1

The sample rate of an accelerometer, like an MPU6050, is much faster than the GPS log rate, different technology, different issues. A common GPS Reciver has, approximatly, one second log rate. In my specific case the accelerometer has a 100hz log rate.

With a previous code the gps log rate was slowing down the accelerometer log rate so i thought to introduce two counters:

  • one for the gps
  • one for the accelerometer

What i tried to do was:

  if ((lastLogGPS + LOG_RATE_GPS) <= micros()) {
  //Log accelerometer and gps data
  } else ((  if ((lastLog + LOG_RATE) <= micros()) {
  //Log only Accelerometer data
  }

1. Is that a speed and memory efficient solution? Or better way exist*?

2. During a 60 seconds test the board return me only the accelerometer value, never the satellites informations, i think there are some dumb errors in my code


Thanks for your help :)

This is the void loop section

void loop()
  {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
    Wire.endTransmission(false);
    Wire.requestFrom(MPU,14,true);   // request a total of 14 registers
    AcX=Wire.read()<<8;
    AcX|= Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
    AcY=Wire.read()<<8;
    AcY|=Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
    AcZ=Wire.read()<<8;
    AcZ|=Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
    GyX=Wire.read()<<8;
    GyX|=Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
    GyY=Wire.read()<<8 ;
    GyY|=Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
    GyZ=Wire.read()<<8;
    GyZ|=Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
    if ((lastLogGPS + LOG_RATE_GPS) <= micros()) {
    while (gps.available( gpsPort )) {
    fix = gps.read();  // get the entire fix structure, once per second

    if (logGPSData()) { // Log the GPS data
    SerialMonitor.println( F("GPS logged.") ); // Print a debug message
    } else {// If we failed to log GPS
    // Print an error, don't update lastLog
    SerialMonitor.println( F("Failed to log new GPS data.") );
      }
    }
   lastLogGPS=micros();
  }
  else{ 
    if ((lastLog + LOG_RATE) <= micros()) {

      printImuData(dataFile,lastLog, AcX, AcY, AcZ, GyX, GyY, GyZ);
      dataFile.flush(); 
      }
    lastLog=micros(); 
    }
  } 

This the function that print only the accelerometer informations:

static void printImuData(Print &printer, unsigned long lastLog,
        int16_t AcX, int16_t AcY, int16_t AcZ,
        int16_t GyX, int16_t GyY, int16_t GyZ)
{//Printing the mpu6050 information 

  printer.print("0");   printer.print(",");   //0 longitude
  printer.print("0");   printer.print(",");   //0 latitude
  printer.print("0");   printer.print(",");   //0 altitude
  printer.print("0");   printer.print(",");   //0 speed
  printer.print("0");   printer.print(",");   //0 course
  printer.print("0");   printer.print(",");   //0 date
  printer.print("0");   printer.print(",");   //0 time 
  printer.print("0");   printer.print(",");   //0 satellites
  printer.print(lastLog); printer.print(",");   
  printer.print(AcX);     printer.print(",");
  printer.print(AcY);     printer.print(",");
  printer.print(AcZ);     printer.print(",");
  printer.print(GyX);     printer.print(",");
  printer.print(GyY);     printer.print(",");        
  printer.println(GyZ);  

}

And this is the part for the GPS informations:

byte logGPSData()
{
  if (dataFile.isOpen())
  { // Print longitude, latitude, altitude (in feet), speed (in mph), course
    // in (degrees), date, time, and number of satellites.

    if (fix.valid.location)
      dataFile.print(fix.longitude(), 6);
    dataFile.print(',');
    if (fix.valid.location)
      dataFile.print(fix.latitude(), 6);
    dataFile.print(',');
    if (fix.valid.altitude)
      dataFile.print(fix.altitude() * 3.2808, 1);
    dataFile.print(',');
    if (fix.valid.speed)
      dataFile.print(fix.speed_mph(), 1);
    dataFile.print(',');
    if (fix.valid.heading)
      dataFile.print(fix.heading(), 1);
    dataFile.print(',');

    if (fix.valid.date) {
      dataFile.print( fix.dateTime.full_year() );
      if (fix.dateTime.month < 10)
        dataFile.print( '0' );
      dataFile.print( fix.dateTime.month );
      if (fix.dateTime.date < 10)
        dataFile.print( '0' );
      dataFile.print( fix.dateTime.date );
    }
    dataFile.print(',');

    if (fix.valid.time) {
      if (fix.dateTime.hours < 10)
        dataFile.print( '0' );
      dataFile.print( fix.dateTime.hours );
      if (fix.dateTime.minutes < 10)
        dataFile.print( '0' );
      dataFile.print( fix.dateTime.minutes );
      if (fix.dateTime.seconds < 10)
        dataFile.print( '0' );
      dataFile.print( fix.dateTime.seconds );
    }
    dataFile.print(',');

    if (fix.valid.satellites)
      dataFile.print(fix.satellites);
  dataFile.print(',');  
  dataFile.print(lastLogGPS);  
    dataFile.print(',');
    dataFile.print(AcX);
    dataFile.print(',');
    dataFile.print(AcY);
    dataFile.print(',');
    dataFile.print(AcZ);
    dataFile.print(',');
    dataFile.print(GyX);
    dataFile.print(',');
    dataFile.print(GyY);
    dataFile.print(',');
    dataFile.print(GyZ);

    dataFile.println();
    dataFile.flush(); // make sure the file contains at least this much

    return 1; // Return success
  }

  return 0; // If we failed to open the file, return fail
}

Here a pic of some data returned by Arduino enter image description here

*I need to load easily the *.csv whith the recorded data on matlab so i have some constraints.

  • I'd be tempted to go about this a different way. Check if there is data waiting on the GPS serial port, if so log GPS data. If not assume this is an IMU only time. That way you will log GPS data whenever it is generated even if the GPS rate is set to something other than 1 Hz. Also your GPS data will be at exactly 1 Hz (or whatever rate you set). If you use the arduino clock to time reading GPS data then things will get out of sync over time. You'd need a very long log file for it to matter much but it's good practice to allow for different clocks to be slightly off from each other. – Andrew Jun 19 '17 at 8:28
  • @Andrew I solved moving out of the statement if ((lastLogGPS + LOG_RATE_GPS) <= micros()) { the statement while (gps.available( gpsPort )) { fix = gps.read();, but is very very slow now and is logging at one second rate very useless. By now i can log gps information, but at one second log rate, so i resolved nothing. I attached a string example [link[(imgur.com/a/0CWFc) – Andrea Ciufo Jul 1 '17 at 17:41
1

Ok, I won't recreate your whole code, but here is a logic snippet that you can use.

Let's suppose that you have 2 sensors, sensor1 and sensor2.

sensor1 is read every 10 milliseconds and sensor2 is read every 16 milliseconds.

Here is what you would do:

Make 2 global variables for your timers :

unsigned long timer1 = 0;
unsigned long timer2 = 0;

Then make 2 constants for the frequency, this example will set the frequency in milliseconds.

const int frequency1 = 10;
cosnt int frequency2 = 16;

Then in your void loop, you would do something like this:

void loop () {
    if (timer1 + frequency1 >= millis()
        read(sensor1);
        timer1 = millis();
    }

    if (timer2 + frequency2 >= millis()
        read(sensor2);
        timer2 = millis();
    }
}

This method makes sure that your code isn't going to get stuck anywhere. I would also suggest to remove any while loops because of that danger that it might freeze& your code.

  • Yep i made 2 global variabiles and defined the frequency, but i did not attached that part of code. The While is inside the GPS loop, and Arduino doesn't write any data from the GPS(because It seems is Never satisfied the if condition for the GPS, or another sort of problem). More over i am not sure the GPS will works without the "While" statement, until now or with tinygps or neogps that Command is widey used in the tutorials :) – Andrea Ciufo Jun 18 '17 at 13:00
  • The suggested code will fail after some time, please read the answer to this question and update your code example accordingly. – Patrick Trentin Jun 25 '17 at 7:46
  • @PatrickTrentin : This is a logic snippet, not a full code, we don't write full code for people here on SE. – Dat Ha Jun 25 '17 at 11:14
  • @DatHa are you really arguing that it is fine for an answer on S.E., viewed by who knows how many people, to contain a not-so-obvious implementation bug, especially for the hobbyist audience that is typical for Arduino? – Patrick Trentin Jun 25 '17 at 11:21
  • @PatrickTrentin : my answer is mean't to give a direction, not the full map. Eventually, when they find that problem, they will search that question up and land on the question that you found. I am not arguing that my code is perfect, I'm just saying that this is not mean't to cover all the problems in the world. I can name many more if you really wanted to. But as I said, this is just pointing someone on the right path because here, on SE, we don't write full code for people, no matter what. So either stop complaining or write your own answer. – Dat Ha Jun 25 '17 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.