2 ADXL345 accelerometers simultaneously connected in I2C mode

I have connected 2 ADXL345 accelerometers to Arduino Uno in I2C mode simultaneously using 0x1D for one and 0x53 for another by following the link below.

I want to measure accelerations at two different positions having varying accelerations.
I am getting readings from both, however, they are giving the same readings. the code and wiring drawings are as below. please help.

#include<Wire.h>
void writeTo(int device, byte address, byte val) {
   Wire.beginTransmission(device); //start transmission to device 
   Wire.write(address);        // send register address
   Wire.write(val);        // send value to write
   Wire.endTransmission(); //end transmission
}

void readFrom(int device, byte address, int num, byte buff[]) {
  Wire.beginTransmission(device); //start transmission to device 
  Wire.write(address);        //sends address to read from
  Wire.endTransmission(); //end transmission
  
  Wire.beginTransmission(device); //start transmission to device
  Wire.requestFrom(device, num);    // request 6 bytes from device
  
  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  { 
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission
}
#define DEVICE_A (0x1D)    //first ADXL345 device address - accel 2
#define DEVICE_B (0x53)    //second ADXL345 device address - accel 1
#define TO_READ (6)        //num of bytes we are going to read each time (two bytes for each axis)
byte buff[TO_READ] ;      //6 bytes buffer for saving data read from the device

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
  
  //Turning on the both ADXL345s
  writeTo(DEVICE_A, 0x2D, 8);   
  writeTo(DEVICE_B, 0x2D, 8);
}
int regAddress = 0x32;      //first axis-acceleration-data register on the ADXL345
int xa , ya , za ;  
int xb , yb , zb ;
  
void loop()
{  
  readFrom(DEVICE_A, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345  
   //each axis reading comes in 10 bit resolution, ie 2 bytes.  Least Significat Byte first!!
   //thus we are converting both bytes in to one int
  xa = (((int)buff[1]) << 8) | buff[0];   
  xa = xa/256;
  ya = (((int)buff[3])<< 8) | buff[2];
  ya = ya/256;
  za = (((int)buff[5]) << 8) | buff[4];
  za = za/256;
  
  readFrom(DEVICE_B, regAddress, TO_READ, buff); //read the acceleration data from the second ADXL345
  xb = (((int)buff[1]) << 8) | buff[0];   
  xb = xb/256;
  yb = (((int)buff[3])<< 8) | buff[2];
  yb = yb/256;
  zb = (((int)buff[5]) << 8) | buff[4];
  zb = zb/256;

Serial.print("first");
Serial.print(xa);
Serial.print(" ");
Serial.print(ya);
Serial.print(" ");
Serial.print(za);
Serial.print(" ");
Serial.print("\n");  

Serial.print("second");
Serial.print(xa);
Serial.print(" ");
Serial.print(ya);
Serial.print(" ");
Serial.print(za);
Serial.print(" ");
Serial.print("\n"); 
Serial.print("\n"); 
  //It appears that delay is needed in order not to clog the port
  delay(15);
}

When starting out with new I2C devices, you should always check your wiring by running the I2C address scanner program. In this case it should identify two different devices at the expected addresses.

The reason that you are seeing the same values is that you print the values from DEVICE_A twice, and don't print the values from DEVICE_B:

Serial.print("second");
Serial.print(xa);
Serial.print(" ");
Serial.print(ya);
Serial.print(" ");
Serial.print(za);

Notes:

Wire.available() is not required or even useful in the following. Wire.requestFrom() either works, or not. You don't need the final .endTransmission(), either.

  int i = 0;
  while(Wire.available())    //device may send less than requested (abnormal)
  {
    buff[i] = Wire.read(); // receive a byte
    i++;
  }
  Wire.endTransmission(); //end transmission

This example shows how to economically read 3 acceleration values from the related MPU-6050.

 Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 6); // request and fetch data from 6 registers
  int t = Wire.read();
  AcX = (t << 8) | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  t = Wire.read();
  AcY = (t << 8) | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  t = Wire.read();
  AcZ = (t << 8) | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

I ran I2C scanner program, it detects accelerometer with 0x53 register only. I have connected the one with 0x1D mode as per diagram below, with SDO connected to 3V through a separate resistor. is that right?

circuit.png

circuit.png

There should be no resistor between SDO/Alt Address and 3.3V. Here is what the data sheet says:

There are no internal pull-up or pull-down resistors for any unused pins; therefore, there is no known state or default state for the CS or ALT ADDRESS pin if left floating or unconnected. It is required that the CS pin be connected to VDD I/O and that the ALT ADDRESS pin be connected to either VDD I/O or GND when using I2C.

yes, but if I connect it directly all the lights go out, like some short circuit.

Then that module is defective. Those sensors are 3.3V only, and if exposed to 5V, they are instantly destroyed.

The real problem is that you are using the 5V Uno with a 3.3V sensor.

You either need to use a level shifter on the I/O pins to match the voltage levels, or better, use a 3.3V Arduino and connect it directly to the module. You can get 3.3V Pro Mini clones on eBay for $2. Or buy modules with the level shifters built in, from a trustworthy manufacturer.

There are lots of bad tutorials out there, and you had the misfortune of starting with one.

Yes, I am using 3.3V supply from Arduino Uno, did not connect to 5V supply. I don't know where I'm going wrong.

"Lights out" means that sensor is clearly defective, so if you need two, buy another and buy a 3.3V Arduino at the same time. Then you won't have any more problems with interfacing. Or buy accelerometer modules from Pololu or Adafruit that have the 3.3 to 5V level shifters built in. There is no reason to use the ADXL345, as the newer models are always better.

Keep in mind that on a 5V Arduino, the I/O lines are 5V, and when set OUTPUT and HIGH, must never be connected to I/O lines on a 3.3V module.

I2C is a special case (essentially, open drain with pullup resistors) and sometimes, under some circumstances you can get away with doing what that tutorial suggests. But there are too many possibilities for mistakes, so the connections you are using are not recommended.

right did not consider the output from I/O lines. I'll try with new ones, thanks for the help.

The LSM6DS33 is one the best performing consumer grade accelerometers I've used, and the linked module has level shifters, so it will work with either 3.3 or 5V Arduinos.

the I2C scanner program detects 0x1D and 0x53 registers when connected with a logic level converter, but the output still displays the same values for both the accelerometers. Why is this happening?
Can two LSM6DS33 be used simultaneously?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.