HW Serial - i2C timing issue; (was: I2C and serial input to serial output)

Hello folks,

I still have a problem with reading data from HW serial and i2C on a MEGA.

The code appended is running for some time (approx. 30 sec to minutes) before it hangs. Output data is correct, the MEGA just freezes. It looks like problems are somehow building up over time, terminal output first stops for a few hundred ms (several times) and then resumes before it finally completely hangs.

The strings to be transferred are relatively long (see log.txt), my impression is, the code is somehow choking up (buffers?!). What can I do to debug, or - more likely - to fix my broken code?

Matthias

The GPS is sending its data w/o being asked every second

log.txt (6.14 KB)

MPU9250_NMEA.txt (8.46 KB)

      if (outputhdm = true) {
      if (outputhdt = true) {
      if (outputrot = true) {
      if (outputshr = true) {

Why? Most people would be using ==.

Hi,

because -monkey see, monkey do-. My programming skills don't suggest to change code from a reputable source - unfortunately.

I anyhow made the modifications - no change in behavior of the code.

regards Matthias

  while (imu->IMURead()) {

Does that function ever return false?

    if (++loopCount >= 10)
      continue;

Explain this. I would never do something like this, so I don't understand why you do.

Hi Paul,

as mentioned before, I've copy/pasted the code from
a) http://kingtidesailing.blogspot.de/2015/09/how-to-make-nmea-0183-tilt-compensated.html (see IMU_Source; too long for inline display)
its is based on the
https://github.com/richards-tech/RTIMULib
RTIMULib.

From the forum here I've modified the "readserial" code and added it after a).

b) Serial Input Basics - updated - Introductory Tutorials - Arduino Forum

  // read serial1 (GPS)
  // code from https://forum.arduino.cc/index.php?topic=396450.0
  
  recvWithStartEndMarkers();
  showNewData();

}



// Functions


void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '

Due to my limited programming skills, I cannot comment about code a).
b) is somewhat comprehensible to me.

What I can say is that a) is running flawlessly without b) and vice versa.
So with just one device (GPS or IMU) connected, everything works fine. As soon as I try to read from both devices, the problems do start.

Regarding your first question:

  while (imu->IMURead()) {

I did not receive any error message.

Any further thoughts?

regards Matthias

IMU_Source.txt (7.49 KB);
  //char endMarker = '>';
  char endMarker = '\n';
  char rc;

while (Serial1.available() > 0 && newData == false) {
    rc = Serial1.read();

if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("$");
    Serial.println(receivedChars);
    newData = false;
  }
}


Due to my limited programming skills, I cannot comment about code a). 
b) is somewhat comprehensible to me. 

What I can say is that a) is running flawlessly without b) and vice versa.
So with just one device (GPS or IMU) connected, everything works fine. As soon as I try to read from both devices, the problems do start. 

Regarding your first question:

§DISCOURSE_HOISTED_CODE_1§


I did not receive any error message.

Any further thoughts?

regards Matthias

[IMU_Source.txt|attachment](upload://s8dcQSpxPLmAJkMTkUGcWrRvHGD.txt) (7.49 KB)

Due to my limited programming skills, I cannot comment about code a).

You could Serial.print() a statement that indicates that the function succeeded.

b) is somewhat comprehensible to me.

What it does is skip the body of the while loop after 10 iterations, but keep reading the IMU. Personally, that doesn't make sense to me. Change the continue; to break;, to see what happens.

Paul,

the IMU gets initialized correctly.

   // Checking the IMU, if it fails, simply restarting the connection seems to work sometimes  
   if ((errcode = imu->IMUInit()) < 0) {  
     Serial.print("Failed to init IMU: "); Serial.println(errcode);  
   }  
   if (imu->getCalibrationValid())  
     Serial.println("Using compass calibration");  
   else  
     Serial.println("No valid compass calibration data");

I'm getting no Error Message here and the message "Using compass calibration". Furtheron correct IMU data is delivered which does change with movements of the device.

with "comprehensible" code I was referring to the "readserial" code from the forum. I don't see a x10 times loop there.

I think you are referring to the IMU code

 if (++loopCount >= 10)
      continue;

The author is mentioning in his blog that the IMU "runs at 10 times per second, but only prints a sentence once per second".
C++ code is a closed book for me, so my assumption was, he is reading the IMU 10 times before continuing.

As a test, I have physically disconnected the IMU and the GPS during runtime (one at a time). Again, the system works fine (only delivering data from the connected device). It does not freeze (freeze means no activity in serial terminal, TX Led on MEGA dead).

I'm guessing there is a conflict between the two. As the code now runs sequentially (does it?), my reasoning is that there is a problem in buffers or joint memory. If an output buffer would be overwritten, this should result in bogus data (shouldn't it?). So from my perspective the error should be caused somewhere on the "read" side.
Is there a buffer I need to clear or something similar?

big ???

Matthias

The author is mentioning in his blog that the IMU "runs at 10 times per second, but only prints a sentence once per second".

That would imply that 9 times out of 10, the data is discarded. I see no reason to do that. If you don't need the IMU data, and all the stuff done with the data, don't read it.

I also do not see that just skipping the body of the while statement is useful. It will simply come back to the top, read the data, increment the counter, and see that it needs to skip the body again. And again, and again...

Using the blink without delay technique to read the data when needed is going to be far better than using that while loop.

Since you ARE having timing issues, anything that looks like blocking code is suspect. And that while loop sure looks like blocking code.