Genuino 101 & GPS & IMU & barometer & SD card (GPS problem)

Hi all,

I have been working on a project with the aim of connecting Genuino 101 to GPS Neo6m, barometer BMP 180, integrated IMU and sd card reader/writer.
Since the IMU loop is working with a 25Hz frequency one loop takes 40k us.
The time needed to calculate angles is relatively low around 140us and time needed for barometer depends on the settings.
So far code achieves data writing (on SD card) with frequency of 25Hz for both angles and barometer/temperature readings (Max time of loop is 20k us). So there is plenty of time for other readings as well and some steps require less time than others since barometer reading is not taken every loop.
The problem comes when i have implemented the code for GPS readings.

The code added for GPS in a loop uses SoftwareSerial(9600) communication (Only one available for 101):

if (Gps_serial.available()){
        char c = Gps_serial.read();
        if (c>31){
          g_buffer[g_buffer_used] = c; // store it
          g_buffer_used++;
          g_buffer[g_buffer_used] = 0;
        } else
        if (c==13) {    // end of sentence! So parse it
          ParseNMEAString();
          g_buffer_used = 0;
          g_buffer[0] = 0;
       }
      }
      if (g_update_clock == true){
        /*file.print(time_a);
        file.print(" "); 
        file.print("GPS ");
        file.print(g_alt);
        file.print(" ");
        file.print(g_lat);
        file.print(" ");
        file.println(g_long);*/
        g_update_clock = false;
        }

(If i try the code for GPS alone while only Serial printing data it works very fine and does the job for only ~10k us for the data i want to extract from it, ex. latitude longitude altitude.)

I have also tried the code from NeoGps library but the problem is the same.
What happens is that simply after running, the code stops/breaks/crashes (stops further calculations) when i implement the code above for GPS readings with all the other sensors. I have a feeling that the problem is coming from Software Serial readings. I am not sure i clearly understand Software Serial communication but i have the feeling that it interrupts everything else when GPS becomes available to send data.

Any kind of advice/suggestion/explanation/solution is very welcome.

Thank you!

We'll need to see the entire sketch, because there is no problem with that snippet of code. As you said,

nikolaineda:
If I try the code for GPS alone while only Serial printing data it works very fine and does the job for only ~10k us for the data i want to extract from it, ex. latitude longitude altitude.

You are only showing us the code that you know is working. If it is larger than 9KB, you can attach it to your post instead of embedding it.

10ms is a very long time, so there is lots of room for improvement. NeoGPS processes a GPS sentence in about 800us. It's even faster if you only want lat, lon and alt.

BTW, the 101 has two serial ports: Serial (via USB) and Serial1 (pins 0 & 1). Maybe you don't need SoftwareSerial.

Cheers,
/dev

Hi, thanks for the reply.

Here are the codes.
First one uses void ParseNMEAString() (you will find this function at the bottom of the code) function to read chosen line and data from GPS output.
The second code uses NMEAGPS library from NeoGps.

As mentioned, if i run the codes for only GPS data both codes work very well. However when implemented in attached programs, the loop stops very quickly after start, probably as soon as GPS becomes available.

You will find the calling for GPS after printing of BMP and angle values in the void loop section.

Thanks again for helping.

Sensor_data_recorde_101_withGPS.ino (14.4 KB)

Sensor_data_recorde_101_withGPS_v2.ino (11.5 KB)

Can you hook the GPS to pins 0 & 1 and use Serial1?

If you look at the NeoGPS examples, they all check gps.available every time through loop. You have nested that test inside your 40ms if test. This means you are reading GPS character only once every 40ms. Not good.

The attached program moves the gps.available test to the top of loop. If no characters are available, it quickly skips to testing the 40ms interval. If there are characters available, they get parsed.

Sometimes, enough characters have been parsed that an entire fix becomes available (once per second). Then the fix is read and altitude is written to your file (if it's valid).

The second problem is that the temperature function and the read_pressure function are blocking. They wait 5ms and 14ms for the sensor.

You need to split those routines into two steps each: the first half of the routine requests the conversion; the second half (called later) reads the result. Then the 40ms "cycle" will have 4 "early" steps, as a little state machine (see attached).

Cheers,
/dev

Sensor_data_recorde_101_withGPS_v2a.ino (11.8 KB)

Hi,

Thank you so much it works now very well (even the time for each loop is reduced!!), this is awesome, i am really motivated with your approach to learn more about state machine!!

Cheers! :slight_smile:

I just realized there is a bug. It is possible that a GPS fix could become available when the file is closed (i.e., when i==0). Then it would try to write the altitude to the closed file.

If you close & re-open the file when i==99, it would always leave the file open:

   // print the heading, pitch and roll
    float roll    = filter.getRoll();
    float pitch   = filter.getPitch();
    float heading = filter.getYaw(); 

    file.print(time_a);
    file.print(" ");  
    file.print("IMU ANGLES ");
    file.print(roll);  
    file.print(" ");
    file.println(pitch); 
    file.print(time_a);
    file.print(" ");     
    file.print("BMP ");
    file.print(P); 
    file.print(" ");
    file.println(T); 


    i++;                                   // povecaj inkrement iteratora
  
    /***********************************************************/
    // ako je 99 - ti ciklus zatvori fajl i resetuj iterator
    if (i==99) {
      //file.close();
      //file=SD.open("TEST_SD.TXT", O_APPEND | O_WRITE);
      file.flush(); // faster than close/open?
      i=0;
    } else if ((i % 10) == 9) {
      state = REQUEST_TEMP;
    }

I think closing and re-opening is slower than calling file.flush().

Yes you are right i will implement this modification as well.
Thank you so much! :slight_smile: