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:
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?
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.
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.
"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.
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?