Serial Port Transmission Lock Up

I am having a problem where my the serial transmission from my arduino to my computer will freeze at the same point. My code initializes two MPU9250 IMUs that are connected through a TCA9548A multiplexer. This problem did not seem to happen when the multiplexer was not connected and only one IMU was being used. Once multiple are connected via the multiplexer the problem seems to surface. The serial port will get to “TCASc” which part of my first serial print “\nTCAScanner ready!” and then stop sending. It is also somewhat elusive where if the Arduino and the multiplexer are all disconnected and reconnected the problem sometimes wont occur, but if it does it will continue if everything stays connected.

I think it has to do with the multiplexer perhaps switching while the arduino is serially printing and this messing things up, just because I did not see this problem before the multiplexer, but I have not proved this.

#include <Wire.h>
extern "C" { 
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}
#include "MPU9250.h"
#define TCAADDR 0x70

void tcaselect(uint8_t i) {
  if (i > 7) return;
 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission(); 
}

unsigned long time = millis();;
float axb;
float ayb;
float azb;

float gxb;
float gyb;
float gzb;

float mxb;
float myb;
float mzb;
    
// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68
MPU9250 IMU(Wire,0x68);
int status;

void setup() {
  // serial to display data
  Serial.begin(115200);
  while(!Serial) {}

// Check if Multiplexer is working
  Serial.println("\nTCAScanner ready!");
    
    for (uint8_t t=0; t<8; t++) {
      tcaselect(t);
      Serial.print("TCA Port #"); Serial.println(t);
 
      for (uint8_t addr = 0; addr<=127; addr++) {
        if (addr == TCAADDR) continue;
      
        uint8_t data;
        if (! twi_writeTo(addr, &data, 0, 1, 1)) {
           Serial.print("Found I2C 0x");  Serial.println(addr,HEX);
        }
      }
    }
    Serial.println("\ndone");


  // start communication with IMU 1 and initialize
  tcaselect(0);
  status = IMU.begin();
  if (status < 0) {
    Serial.println("IMU initialization unsuccessful");
    Serial.println("Check IMU wiring or try cycling power");
    Serial.print("Status: ");
    Serial.println(status);
    while(1) {}
  }
  // setting the accelerometer full scale range to +/-8G 
  IMU.setAccelRange(MPU9250::ACCEL_RANGE_8G);
  // setting the gyroscope full scale range to +/-500 deg/s
  IMU.setGyroRange(MPU9250::GYRO_RANGE_500DPS);
  // setting DLPF bandwidth to 20 Hz
  IMU.setDlpfBandwidth(MPU9250::DLPF_BANDWIDTH_5HZ);
  // setting SRD to 19 for a 50 Hz update rate
  IMU.setSrd(0);

delay (500);
  Serial.println("IMU1: Start Gyro Calibration");
  status = IMU.calibrateGyro();
  if (status == 1) {
    Serial.println("IMU1: Gyro Calibrated Successfully");
  }
 
gxb = IMU.getGyroBiasX_rads();
gyb = IMU.getGyroBiasY_rads();
gzb = IMU.getGyroBiasZ_rads();

Serial.print("Gyro Bias X: ");
Serial.println(gxb);
Serial.print("Gyro Bias Y: ");
Serial.println(gyb);
Serial.print("Gyro Bias Z: ");
Serial.println(gzb);

  Serial.println("IMU1: Start Accelerometer Calibration");
  status = IMU.calibrateAccel();
    if (status == 1) {
    Serial.println("IMU1: Accelerometer Calibrated Successfully");
  }

axb = IMU.getAccelBiasX_mss();
ayb = IMU.getAccelBiasY_mss();
azb = IMU.getAccelBiasZ_mss();

delay (1000);

//start communication with IMU 2 and initialize
  tcaselect(1);
  status = IMU.begin();
  if (status < 0) {
    Serial.println("IMU initialization unsuccessful");
    Serial.println("Check IMU wiring or try cycling power");
    Serial.print("Status: ");
    Serial.println(status);
    while(1) {}
  }
  // setting the accelerometer full scale range to +/-8G 
  IMU.setAccelRange(MPU9250::ACCEL_RANGE_8G);
  // setting the gyroscope full scale range to +/-500 deg/s
  IMU.setGyroRange(MPU9250::GYRO_RANGE_500DPS);
  // setting DLPF bandwidth to 20 Hz
  IMU.setDlpfBandwidth(MPU9250::DLPF_BANDWIDTH_184HZ);
  // setting SRD to 19 for a 50 Hz update rate
  IMU.setSrd(0);
  \
  Serial.println("IMU2: Start Gyro Calibration");
  status = IMU.calibrateGyro();
  if (status == 1) {
    Serial.println("IMU2: Gyro Calibrated Successfully");
  }
 
gxb = IMU.getGyroBiasX_rads();
gyb = IMU.getGyroBiasY_rads();
gzb = IMU.getGyroBiasZ_rads();

Serial.print("Gyro Bias X: ");
Serial.println(gxb);
Serial.print("Gyro Bias Y: ");
Serial.println(gyb);
Serial.print("Gyro Bias Z: ");
Serial.println(gzb);

Serial.println("IMU2: Start Accelerometer Calibration");
  status = IMU.calibrateAccel();
    if (status == 1) {
    Serial.println("IMU2: Accelerometer Calibrated Successfully");
  }

axb = IMU.getAccelBiasX_mss();
ayb = IMU.getAccelBiasY_mss();
azb = IMU.getAccelBiasZ_mss();

}

void loop() {
  // read the sensor IMU1
  tcaselect(0);
  IMU.readSensor();

  // display the data
  time = millis();
  printIMUData(1);

  // read the sensor IMU2
  tcaselect(1);
  IMU.readSensor();

  // display the data
  time = millis();
  printIMUData(2);
    
  //delay(20);
}

void printIMUData(int IMUnum)
{  
  // After calling update() the ax, ay, az, gx, gy, gz, mx,
  // my, mz, time, and/or temerature class variables are all
  // updated. Access them by placing the object. in front:

  // Use the calcAccel, calcGyro, and calcMag functions to
  // convert the raw sensor readings (signed 16-bit values)
  // to their respective units.

  float accelX = IMU.getAccelX_mss();
  float accelY = IMU.getAccelY_mss();
  float accelZ = IMU.getAccelZ_mss();
  float gyroX = IMU.getGyroX_rads();
  float gyroY =IMU.getGyroY_rads();
  float gyroZ = IMU.getGyroZ_rads();
  float magX = IMU.getMagX_uT();
  float magY = IMU.getMagY_uT();
  float magZ = IMU.getMagZ_uT();

  //Print Format: accelx;accely;accelz;gyrox;gyroy;gyroz;magx;magy;magz
  Serial.println(String(IMUnum) + ";" + String(accelX) + ";" + String(accelY) + ";" + String(accelZ) + 
  ";" + String(gyroX) + ";" + String(gyroY) + ";" + String(gyroZ) + ";" +
  String(magX) + ";" + String(magY) + ";" + String(magZ) + ";" + String(time));
  
}

IMU_Comm_Mult.ino (5.27 KB)

The serial port will get to "TCASc" which part of my first serial print "\nTCAScanner ready!" and then stop sending.

Any time you use Serial.print(), for debugging issues like this, you should use Serial.flush(), to block the code until the data has actually been sent.

Hi Paul, thanks, that does seem to get me a big further. It still will get hung up but at a later point now. If i modify the first section of the code, I will receive the following code.

TCAScanner ready!
TCA Port #0

But it still gets stuck and does not go further

Also when the serial port is cooperating I have been able to run through the entire code without problem.

#include <Wire.h>
extern "C" { 
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}
#include "MPU9250.h"
#define TCAADDR 0x70

void tcaselect(uint8_t i) {
  if (i > 7) return;
 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission(); 
}

unsigned long time = millis();;
float axb;
float ayb;
float azb;

float gxb;
float gyb;
float gzb;

float mxb;
float myb;
float mzb;
    
// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68
MPU9250 IMU(Wire,0x68);
int status;

void setup() {
  // serial to display data
  Serial.begin(115200);
  while(!Serial) {}

// Check if Multiplexer is working
  Serial.println("\nTCAScanner ready!");
  Serial.flush();
    
    for (uint8_t t=0; t<8; t++) {
      tcaselect(t);
      Serial.print("TCA Port #"); 
      Serial.flush();
      Serial.println(t);
      Serial.flush();
 
      for (uint8_t addr = 0; addr<=127; addr++) {
        if (addr == TCAADDR) continue;
      
        uint8_t data;
        if (! twi_writeTo(addr, &data, 0, 1, 1)) {
           Serial.print("Found I2C 0x");  
           Serial.flush();
           Serial.println(addr,HEX);
           Serial.flush();
        }
      }
    }
    Serial.println("\ndone");
Serial.flush();

But it still gets stuck and does not go further

What it does next is try to talk to each address, and get a response. If there is nothing at the address, but everything connected to the I2C bus is connected correctly, the fact that there is no reply is discovered very quickly.

That the process hangs when you try to talk to the first address indicates that the but part of that statement is not true.