Go Down

Topic: i2c bus failed(ADXL355、MPU9250) (Read 394 times) previous topic - next topic

henry321yu

May 23, 2019, 11:02 am Last Edit: May 24, 2019, 04:10 am by henry321yu
Hi hi there,
I'm a rookie programmer.Had a big problem :o  :o

I have been trying to connect two accelerometers (ADXL355, mpu9250 or mpu6050) to the nano via the I2C interface and save them to the SD card.
But i2c reading always fails, I also tried to use the WSwire function library, only the fact that the program is not stuck, but still not successful.
Let me first say that I use mpu9250 to read gyroscopes and magnetometers, but first try to communicate and find big problems..
Mpu6050 is only for testing.

The situation is like this, as long as the i2c port of both chips is connected to nano, the program will run very slowly (about two seconds to read the data), and the data is a fixed error value.
If one of the i2c pins is unplugged, the other party will return to normal and log at normal speed(100hz).
However, I have also tested two accelerometers separately and only wrote one of them, and of course, it is successful. but...
If I insert the pin of adxl355 while reading mpu9250 or mpu6050, the program still will return to the fault state (slow, data error), and it will remain fault state after reset.
In turn, testing the ADXL355, inserting mpu9250 or mpu6050 will have no effect.

After trying, there is a way for the ADXL355 to not affect the mpu6050, that is, to run at 10hz, and only write the program of mpu6050.
But it can only run for about 20 seconds, and as long as the mpu6050 is moved, it will fail again..

So I still haven't reached a conclusion. I can only guess that the ADXL355 is not working properly with other I2c interface?
I thought it might be a memory problem, I changed to mega2560, but the situation remains the same..
No matter whether I have connected to the sd module or not, it has no effect.

I can't try mpu9250 and mpu6050 at the same time, because the address is the same.
I can't seem to change the AD0 of the mpu9250 so that its address becomes 0x69.
Because this chip's AD0 is connected to GND(link below)

btw,why not try spi? here's my post



My connection:

accelerometers:
vcc:3.3V
scl:scl
sda:sda
gnd:gnd

sd module:
vcc:5v
cs:cs(10 or 53)
sclk:sclk
miso:miso
mosi:mosi
gnd:gnd

files:
adxl355 datasheet
EVAL-ADXL355 User Guide
mpu9250 datasheet
9dof razor imu m0 schematic
9DoF Razor IMU M0 Introduction



results(wiring both)


if only connect to ADXL355


if only connected to MPU9250


connect the ADXL355 when testing the MPU9250 (three axes become -0.0156)


mpu6050 10hz




:smiley-confuse:
My code is attached~

Code: [Select]

#include <SD.h>
#include <SPI.h>
#include <WSWire.h>

const int SD_CS = 53; // Pin 10 on Arduino Uno
const int acc_I2c = 0x1D; //
const int IMU_I2c = 0x68; //
const int led = 4; //
long values[20], t[9];
double x, y, z, x1, y1, z1, c;
File test0;

void setup() {
  Serial.begin(115200);
  Wire.begin();
  TWBR = 12;

  if (!SD.begin(SD_CS)) {
    Serial.println("Card failed, or not present");
  }
  pinMode(SD_CS, OUTPUT);

  //adxl355 setting
  writeRegister(POWER_CTL, 0x00);  // writing 0 to to enable sensor
  writeRegister(RANGE, 0xC1);
  writeRegister(SELF_TEST, 0x00);  // writing 3 to to enable
  delay(200);
 
  //imu setting
  //writeRegister1(PWR_MGMT_1, 0x80); //reset
  writeRegister1(PWR_MGMT_2, 0x00);
  writeRegister1(PWR_MGMT_1, 0x01); //enable all axis
  //writeRegister1(ACCEL_CONFIG, 0xE0); // Accel self-test

  delay(200);
  //digitalWrite(SD_CS, LOW);
  test0 = SD.open("test0.txt", FILE_WRITE);
  if (test0) {
    Serial.println("writing");
    //test0.print("666666");
    //test0.close(); // close the file
  }
  // if the file didn't open, print an error:
  else {
    Serial.println("error opening test.txt");
    //return;
  }
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);



  delay(200);
}
void loop() {

  acc_data();

  Serial.print(x, 5);
  Serial.print(", ");
  Serial.print(y, 5);
  Serial.print(", ");
  Serial.print(z, 5);
  Serial.print(",     ");
  //delay(200);
  imu_data();

  Serial.print(x1, 5);
  Serial.print(", ");
  Serial.print(y1, 5);
  Serial.print(", ");
  Serial.print(z1, 5);
  Serial.print('\n'); 
  delay(5);

  if (!test0) {
    test0 = SD.open("test0.txt", FILE_WRITE);
    Serial.println("file opened");
  }
  if (test0) {
    Serial.println("writing");
    digitalWrite(led, HIGH);
    test0.print(x, 5);
    test0.print(", ");
    test0.print(y, 5);
    test0.print(", ");
    test0.print(z, 5);
    test0.print(",     ");
    test0.print(x1, 5);
    test0.print(", ");
    test0.print(y1, 5);
    test0.print(", ");
    test0.println(z1, 5);
    test0.close(); // close the file
  }
  // if the file didn't open, print an error:
  else {
    Serial.println("error opening test.txt");
  }
  delay(5);
  digitalWrite(led, LOW);
}

void writeRegister(int reg, int data) {
  Wire.beginTransmission(acc_I2c);
  Wire.write(reg);
  Wire.write(data);
  Wire.endTransmission();
}

int readRegister(int reg) {
  Wire.beginTransmission(acc_I2c);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom(acc_I2c, 1);
  if (Wire.available() <= 1) {
    return Wire.read();
  }
  Wire.endTransmission();
}

void writeRegister1(int reg1, int data1) {
  Wire.beginTransmission(IMU_I2c);
  Wire.write(reg1);
  Wire.write(data1);
  Wire.endTransmission();
}

int readRegister1(int reg1) {
  Wire.beginTransmission(IMU_I2c);
  Wire.write(reg1);
  Wire.endTransmission();
  Wire.requestFrom(IMU_I2c, 0x80);
  if (Wire.available() <= 0x80) {
    return Wire.read();
  }
  Wire.endTransmission();
}

void acc_data() {
  values[0] = readRegister(XDATA3);
  values[1] = readRegister(XDATA2);
  values[2] = readRegister(YDATA3);
  values[3] = readRegister(YDATA2);
  values[4] = readRegister(ZDATA3);
  values[5] = readRegister(ZDATA2);

  values[6] = readRegister(XDATA1);
  values[7] = readRegister(YDATA1);
  values[8] = readRegister(ZDATA1);

  t[0] = readRegister(TEMP2);
  t[1] = readRegister(TEMP1);

  x = (values[0] << 12) + (values[1] << 4) + (values[6] >> 4);
  y = (values[2] << 12) + (values[3] << 4) + (values[7] >> 4);
  z = (values[4] << 12) + (values[5] << 4) + (values[8] >> 4);

  if (x >= 0x80000) {
    x = x - (2 * 0x80000);
  }
  if (y >= 0x80000) {
    y = y - (2 * 0x80000);
  }
  if (z >= 0x80000) {
    z = z - (2 * 0x80000);
  }

  c = (t[0] << 8) + t[1];
  c = ((1852 - c) / 9.05) + 25.7;

  x = x * 0.0000039;
  y = y * 0.0000039;
  z = z * 0.0000039;
}

void imu_data() {
  values[10] = readRegister1(ACCEL_XOUT_H);
  values[11] = readRegister1(ACCEL_XOUT_L);
  values[12] = readRegister1(ACCEL_YOUT_H);
  values[13] = readRegister1(ACCEL_YOUT_L);
  values[14] = readRegister1(ACCEL_ZOUT_H);
  values[15] = readRegister1(ACCEL_ZOUT_L);

  x1 = (values[10] << 8) + values[11];
  y1 = (values[12] << 8) + values[13];
  z1 = (values[14] << 8) + values[15];

  if (x1 >= 0x8000) {
    x1 = x1 -  0x10000;
  }
  if (y1 >= 0x8000) {
    y1 = y1 -  0x10000;
  }
  if (z1 >= 0x8000) {
    z1 = z1 -  0x10000;
  }

  x1 = x1/0x4000;
  y1 = y1/0x4000;
  z1 = z1/0x4000;
}

Idahowalker

#1
May 23, 2019, 04:24 pm Last Edit: May 23, 2019, 04:34 pm by Idahowalker
Have you tried, with only one device connected, running an I2C scanner, and noting the I2C address, removing the scanned device, after powering down, add in the next device, running the I2C scanner, noting the device address, and on and on till all the devices are scanned and their address are noted? With that info you can determine if you are having I2C address conflicts and adjust accordingly.

Also have you determined if each device has its own pull ups or does each device require pullups.

And are you running mixed voltage devices? Meaning some devices work with 3.3V and some work with 5V but output 3.3V signals and so on and so mixed?

As a note the MPU9250 can be run on the SPI buss. I run several MPU9250's at 10MhZ. On one of my projects I run a MPU9250 and two MLX90393 SPI devices.

You might, also, consider reading the multi devices in a round robin fashion. Say you have devices A, B, and C. The first call to the do the device A thing starts the show. When the thing is done with device A, the device A function calls device B, the device B function does its thing and then calls device C to do its thing, when device C is done it calls the device A function.


If each device works great when running separate but FUBAR when ran with other devices, look for some conflict.

Each SPI device has to have its own CS pin, you can use quite a number of CS pins, with a Mega.

Such as:
Code: [Select]
#define csPinMLX90393_0 32
#define csPinMLX90393_1 5
#define spiCLK 25 //
#define spiMOSI 26 //
#define spiMISO 27 //
#define MLX90393int_0 18
#define MLX90393int_1 4
spi_device_handle_t _hMLX90393_0;
spi_device_handle_t _hMLX90393_1;

JohnRob

I had a similar problem, my code was missing a Wire.begin statement.
I thought it was called by the library but it was not.

I was using a Pro Mini board.

Please do not PM me with thread based messages.  If your thoughts are worth responding,  the group should benefit from your insight.

henry321yu

#3
May 24, 2019, 03:20 am Last Edit: May 30, 2019, 04:28 am by henry321yu
Have you tried, with only one device connected, running an I2C scanner, and noting the I2C address, removing the scanned device, after powering down, add in the next device, running the I2C scanner, noting the device address, and on and on till all the devices are scanned and their address are noted? With that info you can determine if you are having I2C address conflicts and adjust accordingly.
Yes,i tried.I using the address it appeared.
ADXL355:0x1D
MPU9250、6050:0x68

Also have you determined if each device has its own pull ups or does each device require pullups.
IMU m0(mpu9250) had 4.7k pull-up resistors you can see at the file 9dof razor imu m0 schematic

And are you running mixed voltage devices? Meaning some devices work with 3.3V and some work with 5V but output 3.3V signals and so on and so mixed?
The sensors all work with 3.3v except sd card module.But i've tried test with sd card module removed  still the same.


You might, also, consider reading the multi devices in a round robin fashion. Say you have devices A, B, and C. The first call to the do the device A thing starts the show. When the thing is done with device A, the device A function calls device B, the device B function does its thing and then calls device C to do its thing, when device C is done it calls the device A function.
You mean like adxl355(); and mpu9250();? thats what i'm doing now.My code is attached.

henry321yu

#4
May 24, 2019, 03:47 am Last Edit: May 24, 2019, 03:48 am by henry321yu
I thought it was called by the library but it was not.
sory i don't understand.what's that mean?
I had Wire.begin in void setup().

Go Up