I2C Confusion: Two devices with the same serial (grove 6-axis)

Hey,

I'm quite new to arduino - I have a little experience in general programming, and a lot of experience in Max MSP (which I was aiming to defer most of my programming to).
I have a problem which is melting my brain right now. I'm using 3 grove 6-axis per Arduino Mega, with the Grove shield. For one Grove, I'm using the following code:

//#include <SPI.h>
#include <Wire.h>  
#include <Arduino_LSM6DS3.h>
#include <MadgwickAHRS.h>
#include <Math.h>
#include "SparkFunLSM6DS3.h"

LSM6DS3 myIMU(I2C_MODE, 0x6A);
float pitchFilteredOld;
Madgwick filter;
const float sensorRate = 1004.00;

void setup() {
  Serial.begin(9600);
  if (myIMU.begin() != 0) {
        Serial.println("Device error");
    } else {
        Serial.println("Device OK!");
    }
  filter.begin(sensorRate);
  Serial.println("Setup complete!");
}  
void loop() {
  float xAcc, yAcc, zAcc;
  float xGyro, yGyro, zGyro;
  float roll, pitch, heading;
  if(IMU.accelerationAvailable() && IMU.gyroscopeAvailable()){
    IMU.readAcceleration(xAcc, yAcc, zAcc);
    IMU.readGyroscope(xGyro, yGyro, zGyro); 
    filter.updateIMU(xGyro, yGyro, zGyro, xAcc, yAcc, zAcc);
    // pitch = filter.getPitch();
    // float pitchFiltered = 0.1 * pitch + 0.9 * pitchFilteredOld; // low pass filter
    //Serial.println("pitch: " + String(pitchFiltered));
    //pitchFilteredOld = pitchFiltered;
    Serial.print(xAcc, 4);
    Serial.print(" ");
    Serial.print(yAcc, 4);
    Serial.print(" ");
    Serial.print(zAcc, 4);
    Serial.print(" ");
    Serial.print(xGyro, 4);
    Serial.print(" ");
    Serial.print(yGyro, 4);
    Serial.print(" ");
    Serial.println(zGyro, 4);
  }
}

I'm sure there are a number of unnecessary things in here, but my main problem is this: at the beginning I define the register:
LSM6DS3 myIMU(I2C_MODE, 0x6A);
All of the sensors have the same register, so how can I determine which I am reading from in my code?

Thanks!

AFAIR you can change that address by jumpers or wires to Vcc and GND on the board.

Hi, @doomspeak
Welcome to the froum.

Can you please post a link to specs/data of your IMU?

If it is the one I have found the I2C address does not seem address configurable.

Google;

arduino 2 i2c devices same address

It may help you.

Tom... :smiley: :+1: :coffee: :australia:

Hey,
Sorry, I was trying to find someone who could explain it to me like I'm five. I tried searching the forum but the explanations were unclear to me.
The spec sheet is here -

Shield:

I was told that it is possible, or that they can shift addresses but I wasn't clear on how.

@DrDiettrich
How do I understand that within the serial input though?
(also thanks!)

See in the sensor data sheet Table 2 pin# 1 and Table 9 ** SDO/SA0.**
This pin allows to toggle the module address between 0x6A and 0x6B.

Hi,

Where?
(From @doomspeak link.)

Tom... :smiley: :+1: :coffee: :australia:

Last row, pin SA0. Too many edits :frowning:

1 Like

If you do not use the Arduino LSM6DS3 library, then please remove: #include <Arduino_LSM6DS3.h>
I think that you can remove #include <Math.h> as well.

If you have two devices with the same address on the I2C bus the devices will both respond to a query. That means both will be talking at the same time. As with people the combination of two responses is unintelligible.

Oh and it might damage the groove device outputs.

The accelerometer specification states:

The Slave ADdress (SAD) associated to the LSM6DS3 is 110101xb. The SDO/SA0 pin can
be used to modify the less significant bit of the device address. If the SDO/SA0 pin is
connected to the supply voltage, LSb is ‘1’ (address 1101011b); else if the SDO/SA0 pin is
connected to ground, the LSb value is ‘0’ (address 1101010b). This solution permits to
connect and address two different inertial modules to the same I2C bus.

So the best you can do is have two devices on the I2C bus. This leaves the SPI bus your only option.

So I was thinking it might be possible to toggle them using the CS pin

Screenshot 2021-12-06 at 20.02.20

When I would have a number of devices on the I2C bus and just read through in a loop like:

Device 1 = 1
Device 2.....n = 0 
Serial.read();
delay(100); 
Device 2 = 1
Device 1....n (excluding 2) = 0 
Serial.read();
delay(100);
etc.....

obviously this is not code, but is something in this principle possible?

There is a well known trick when a sensor has two I2C addresses.

It goes like this:
Keep all the sensors at 0x6B, they are inactive.
Connect digital output pins to the SDO of the sensors. For 8 sensors, 8 digital output pins are required.
Bring one sensor to 0x6A with the digital pin and use the code for 0x6A.
When ready, put it back at 0x6B.
Do that for each sensor.

Sometimes it works, sometimes not. Sometimes it is mentioned in the datasheet that it is allowed.

Warning : You may not connect a digital output of the Arduino Mega 2560 board to a 3.3V sensor ! The Arduino Mega 2560 board can output up to 40mA with a digital pin. If you put 5V 40mA into a pin of the LSM6DS3 sensor, then it will be damaged.

1 Like

I'm guessing this must use a software I2C?

Hi,
This is also a good method, used it a number of times.
URL included in the image.

Tom.... :grinning: :+1: :coffee: :australia:

Hi @TomGeorge I have seen that you posted that circuit a number of times and I wanted to say something about it. I hope you don't mind that I do that here.

I can see that it will work, but it is not a "good" method.
In a standard I2C bus, the SCL signal can go high and low without having any effect, as long as SDA stays high, since SDA initiates a START condition. That means the SCL signal can be shared for multiple I2C buses and the SCL can even be used for other things.

In that circuit, the SDA is shared and the SCL is kept low for the unused sensor. I think that those signals are not allowed for the I2C bus and I think that the behavior is undefined.
The hardware logic of the sensors should be able to always detect a START and STOP condition, so it should work. But it can not be guaranteed.

The circuit makes use of the fact that the SCL is almost never a bidirectional signal and that the I2C bus is a open-drain bus. It is therefor not possible to share the SCL and keep the unused SDA high with a few diodes.

Hi, @Koepel
No problem, I use it for simple systems, so any serious bidirectional comms is not needed.

Tom... :grinning: :+1: :coffee:

@Tom, thanks for that, it looks like a solution - is this expandable up to 4-6 devices, or just for two?
Do you know if there is any example code for this?

For more devices, get a I2C multiplexer: https://www.adafruit.com/product/2717.
The command to select one of the (sub) I2C buses is also send over I2C. So the two I2C pins is all that is needed.

If the library is simple and easy to change, then it is possible to use a software I2C library. With a shared SCL pin, it needs 7 digital pins for 6 devices.

This is probably a good idea, I was just avoiding spending more money if there was an actual workaround, but probably in the long run it will save energy. Thanks!

The I2C multiplexer is the workaround that avoids spending too much time and money :wink:

Hi,

The diagram I posted has a URL at the top, that should give you the info your need.

Tom... :grinning: :+1: :coffee: :australia: