Serial Communication halt

When I run this code serial communication stops suddenly. The IDE shows no errors but the serial monitor stops reading out sensor data or accepting inputs. In addition the serial LEDs on arduino turn off. The error occurs when running code only pulling sensor data but not when running code controlling motors.

// compass stuff
#include <MPU9250_WE.h>
#include <Wire.h>
#define MPU9250_ADDR 0x68
MPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR);
// motor stuff
#include <AFMotor.h>
AF_DCMotor motorA(1);
AF_DCMotor motorB(2);
int lf;
int rf;
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(20);
  // compass stuff
  Wire.begin();
  if(!myMPU9250.init()){
    Serial.println("MPU9250 does not respond");
  }
  else{
    Serial.println("MPU9250 is connected");
  }
  if(!myMPU9250.initMagnetometer()){
    Serial.println("Magnetometer does not respond");
  }
  else{
    Serial.println("Magnetometer is connected");
  }

  Serial.println("Position you MPU9250 flat and don't move it - calibrating...");
  delay(1000);
  myMPU9250.autoOffsets();
  Serial.println("Done!");
  myMPU9250.setSampleRateDivider(5);
  myMPU9250.setAccRange(MPU9250_ACC_RANGE_2G);
  myMPU9250.enableAccDLPF(true);
  myMPU9250.setAccDLPF(MPU9250_DLPF_6);
  myMPU9250.setMagOpMode(AK8963_CONT_MODE_100HZ);
  delay(200); 

  // motors
  motorA.setSpeed(50);
  motorB.setSpeed(50);
  motorA.run(RELEASE);
  motorB.run(RELEASE);
  
  

}

void loop() {
  xyzFloat angles = myMPU9250.getAngles();
  xyzFloat magValue = myMPU9250.getMagValues();
  Serial.print(magValue.x);
  Serial.print(",");
  Serial.print(magValue.y);
  Serial.print(",");
  Serial.print(magValue.z);
  Serial.print(",");
  Serial.print(angles.x);
  Serial.print(",");
  Serial.println(angles.y);

  //motors
  if (Serial.available()>0){
    String ser = Serial.readString();
    String left = (split(ser, '.', 0));
    String right = (split(ser, '.', 1));
      if (ser.length() > 0){
        int lf = left.toInt();
        int rf = right.toInt();
        motorA.setSpeed(lf);
        motorB.setSpeed(rf);
        if (lf > 0){
          motorA.run(BACKWARD);
          }
        if (lf == 0){
          motorA.run(RELEASE);
          }
        if (lf < 0){
          motorA.run(FORWARD);
          }
        if (rf > 0){
          motorB.run(BACKWARD);
          }
        if (rf == 0){
          motorB.run(RELEASE);
          }
        if (rf < 0){
          motorB.run(FORWARD);
          }
    }
  }

  if(!Serial) {  //check if Serial is available... if not,
    Serial.end();      // close serial port
    delay(10);    
    Serial.begin(115200); // reenable serial again
    Serial.println("reset");
  }
  delay(25);
    
}
String split(String data, char separator, int index)
{
    // spliting a string and return the part nr index
    // split by separator
    
    int stringData = 0;        //variable to count data part nr 
    String dataPart = "";      //variable to hole the return text
    
    for(int i = 0; i<data.length()-1; i++) {    //Walk through the text one letter at a time
      
      if(data[i]==separator) {
        //Count the number of times separator character appears in the text
        stringData++;
        
      }else if(stringData==index) {
        //get the text when separator is the rignt one
        dataPart.concat(data[i]);
        
      }else if(stringData>index) {
        //return text and stop if the next separator appears - to save CPU-time
        return dataPart;
        break;
        
      }

    }
    //return text if this is the last part
    return dataPart;
}

Which Arduino board is it ?

its an uno, this is the code that is causing the issues. The this is going through a motor shield

#include <MPU9250_WE.h>
#include <Wire.h>
#define MPU9250_ADDR 0x68
MPU9250_WE myMPU9250 = MPU9250_WE(MPU9250_ADDR);

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
  Wire.begin();
  if(!myMPU9250.init()){
    Serial.println("MPU9250 does not respond");
  }
  else{
    Serial.println("MPU9250 is connected");
  }
  if(!myMPU9250.initMagnetometer()){
    Serial.println("Magnetometer does not respond");
  }
  else{
    Serial.println("Magnetometer is connected");
  }

  Serial.println("Position you MPU9250 flat and don't move it - calibrating...");
  delay(1000);
  myMPU9250.autoOffsets();
  Serial.println("Done!");
  myMPU9250.setSampleRateDivider(5);
  myMPU9250.setAccRange(MPU9250_ACC_RANGE_2G);
  myMPU9250.enableAccDLPF(true);
  myMPU9250.setAccDLPF(MPU9250_DLPF_6);
  myMPU9250.setMagOpMode(AK8963_CONT_MODE_100HZ);
  delay(200);  
}

void loop() {
  xyzFloat angles = myMPU9250.getAngles();
  xyzFloat magValue = myMPU9250.getMagValues();
  Serial.print(magValue.x);
  Serial.print(",");
  Serial.print(magValue.y);
  Serial.print(",");
  Serial.print(magValue.z);
  Serial.print(",");
  Serial.print(angles.x);
  Serial.print(",");
  Serial.println(angles.y);

  
  delay(100);
  
}

Where does it crash?

When something is very wrong with the I2C bus, the Wire library can halt the sketch.
For the Uno, a timeout was added.
You could try to add it:

Wire.begin();
setWireTimeout();

This is the library that you use: https://github.com/wollewald/MPU9250_WE.
Can you give a link to where you bought the MPU-9250 module ?

I'm not sure if the FIFO is used. Looking at the examples, the delay(100) in the loop() should not be a problem.

1 Like

It will crash randomly. Sometimes after outputting only a few lines into the serial monitor and sometimes after a few thousand

You have a conflict with the voltage of the SDA and SCL signals on the I2C bus.
The Arduino Uno has a 5V I2C bus and the sensor has a 3.3V I2C bus.

You can make it (a little) better by lowering the voltage of the Uno board. Can you run it at 4.5V instead of 5.0V ? Power the MPU-9250 with 5V to VCC instead of 3.3V to VCC to increase the signals of SDA and SCL with 0.1V.

Is this the motor shield : https://www.adafruit.com/product/1438.
If that is also connected to the I2C bus, then you chances that you have a problem increase. I checked the schematic, and the PWM chip is connected to the I2C bus with 10k pullup resistors to 5V.

thanks, the motor shield is a v1

This one ? https://learn.adafruit.com/adafruit-motor-shield

1 Like

When I use Wire.setWireTimeout(); in sketch instead of serial communication ending I get the following
23:24:01.061 -> -24.78,-37.13,-53.30,0.02,-0.48
23:24:01.061 -> -24.78,-36.78,-56.00,0.03,-0.47
23:24:01.170 -> 0.00,0.00,0.00,6.50,23.65
23:24:01.281 -> 0.00,0.00,0.00,6.50,23.65
23:24:01.387 -> 0.00,0.00,0.00,6.50,23.65
where the first three zeros are the magnetometer readings and the last two values being the accelerometer angles that stop changing. In addition the serial leds continue blinking.

yes

That is a very old shield. I think the Adafruit started the company with that shield. You can use it with a 12V motor, but not with a 5V motor. But it does not use the I2C bus.

Something seems to be wrong with the I2C bus, but I'm not sure if that is the main problem.
Do you use long wires ? extra pullup resistors ? flat-ribbon cable ?
Do you have a I2C level shifter ?

Please confirm if you use 3.3V to VCC and have changed it to 5V.

sorry, should have included in question. The mpu9250 is being powered by the 3.3 volt supply from a raspberry pi zero. There is a jumper wire joining grounds for i2c communication.

This might solve the issue as the python script I'm using to read data in project should be able to recognise when problem happens and restart serial communication

Then you have not doubled the problems on the I2C bus, but made it almost impossible to work. You have to stop this and make your project in an other way.

If you still want to try to fix this, can you give a schematic or drawing or photo that shows how the Uno, the sensor board and the Raspberry Pi are connected ? Please answer the questions about pullup resistors and flat-ribbon cable.

Just curious... why such a high speed serial? And why the timeout?

Ive no pull-up resistors or ribbon cable. As I'm a new user it won't let me upload schematic but I can try explain.
Sensor SCL and SDA are connected to a4 and a5
Sensor VCC and Ground connected to pi 3.3 V and ground
Pi ground and uno ground connected by jumper wire

added the timeout to see if it would address the problem and the baud rate is just the same one as is used in the example. I've tried changing both but it did not address the issue.

Explanation about the timeout, because they are totally different:

The (not fully documented yet) timeout of the Wire library is a low level timeout for the signals of the I2C bus. I mentioned that in reply #5. I can be used to recover from hardware trouble.

The timeout for the Serial library is only used for the higher level functions, such as parseFloat() and readBytes(). They are actually part of the Stream class. It prevents that such functions wait forever. The default is 1 second.

1 Like