ADXL Accelerometer SPI Communication Issue

Hi all,

I've been stuck troubleshooting code for an ADXL373 accelerometer communicating through SPI. I get 0 for the acceleration on all 3 axis so I went back to confirming reads from static registers first.

The issue is I always read 0 from those static registers. However, if I switch SPI mode from 0 to 2 or 3, I read non-zero. Those nonzero values though are not the correct reports for the respective registers. (e.g. for the register DEVID_MST, SPI Mode 2 reads 0x0C and Mode 3 reads 0x18 instead of the correct 0x1D). The ADXL373 is supposed to be SPI Mode 0 (CPOL = 0, clock idle low, CPHA = 0, data read on rising edge).

My code is follows the examples from Arduino the Barometric Pressure Sensor and ADXL345, so I'm stumped why I can't establish this simple communication. Is there some configuration or setup step I've overlooked?

ADXL373 Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/adxl373.pdf

// Circuit:
// ADXL373 400g Accelerometer sensor connected to Arduino 2560 Mega Board

// V5: pin 3.3V
// GND: pin GND
// MOSI: pin 51
// MISO: pin 50
// SCLK: pin 52
// CS: pin 53

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

const int CS = 53; //Chip Select (Arduino Mega Pin 53)

/////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Register Addresses ////////////////////////////////

byte AD_ID = 0X00; // Register containing Analog Device ID
byte MEMS_ID = 0x01; // Register containing Analog Device's MEMS ID
byte PART_ID = 0x02; // Register containing Analog Device's Product ID
byte REV_ID = 0x03; // Register containing Analog Device's Revision ID
byte XDATA_H = 0x08; // (0b00001000) X Data Register, High 8 MSB 
byte XDATA_L = 0x09; // (0b00001001) X Data Register, Low 4 MSB 
byte YDATA_H = 0x0A; // (0b00001010) Y Data Register, High 8 MSB 
byte YDATA_L = 0x0B; // (0b00001011) Y Data Register, Low 4 MSB 
byte ZDATA_H = 0x0C; // (0b00001100) Z Data Register, High 8 MSB 
byte ZDATA_L = 0x0D; // (0b00001101) Z Data Register, Low 4 MSB 
byte OFFSET_X = 0x20; // X Data Offset Register, Lower 4 bits
byte OFFSET_Y = 0x21; // Y Data Offset Register, Lower 4 bits
byte OFFSET_Z = 0x22; // Z Data Offset Register, Lower 4 bits
byte TIME_CTRL = 0x3D; // (0b00111101) Timing Control Register -> Select ODR (0b10000000) for 5120 Hz
byte MEASR_CTRL = 0x3E; // (0b00111110) Measurement Control -> Bandwidth set (0b00000100) for 2560 Hz
byte POWER_CTRL = 0x3F; // (0b00111111) Power Control Register -> Op. Mode and HPF off (0b00000111)
const byte WRITE = 0b11111110; // Reads with a 1, high
const byte READ = 0b00000001; // Writes with a 0, low

////////////////////////////////////////////////////////////////////////////////

// Establish variables to identify x, y, and z axis accelerations
int x_axis = 1;
int y_axis = 2;
int z_axis = 3;
int Offset = 0;

void setup() 
{
  SPI.begin(); // Initialize SPI
  SPI.setDataMode(SPI_MODE0);  // CPOL = 0, clock idles low, CPHA = 0, data is clocked on rising edge
  SPI.setBitOrder(MSBFIRST); // Data for the device is sent MSB first, RW is last bit
  Serial.begin(115200);   // Establish a serial connection to display data through terminal
  pinMode(CS, OUTPUT);   // Set CS Pin Direction
  digitalWrite(CS, LOW);
  writeRegister(MEASR_CTRL, 0b00000100); // Set Measurement Mode to 2560Hz bandwidth (0x04)
  writeRegister(POWER_CTRL, 0b00000111); // Set full bandwidth measurement mode, HPF disabled (0x07)
  writeRegister(TIME_CTRL, 0b10000000); // Set ODR to 5120 Hz
  byte ID_Check = readRegister(0x02);
  Serial.println("Binary Read: ");
  Serial.println(ID_Check, BIN);
  Serial.println("Hex Read: ");
  Serial.println(ID_Check, HEX);
  digitalWrite(CS, HIGH);
  delay(1);
}

void loop()
{
  //Serial.print(" x = ");   Commented out until static register read resolved
  //Serial.print(getValue(x_axis));
  //Serial.print(" y = "); 
  //Serial.print(getValue(y_axis));
  //Serial.print(" z = "); 
  //Serial.println(getValue(z_axis));
  //delay(2000);
}

int getValue(int axis)
{
  int AccelData = 0;
  int Offset = 0;
  int high, low; 
  if (axis == 1)
  {
    high = readRegister(XDATA_H);
    low = readRegister(XDATA_L);
  }
  else if (axis == 2)
  {
    high = readRegister(YDATA_H);
    low = readRegister(YDATA_L);
  }
  else if (axis == 3)
  {
    high = readRegister(ZDATA_H);
    low = readRegister(ZDATA_L);
  }
  AccelData = (high << 4) | (low >> 4); // Merge 8 bits from 'high' with upper 4 of 'low' 
  AccelData = (AccelData - Offset)*200; // (Reading-Offset)*ScaleFactor --> 200mg/LSB for ADXL373
  return (AccelData);
}

unsigned int readRegister(byte thisRegister)
{
  byte result = 0;   // predeclare result to return
  // ADXL373 expects the register address in the upper 7 bits of the transmitted byte
  // Shift the register bits left by 1 to apply READ bit:
  thisRegister = thisRegister << 1;
  byte dataToSend = thisRegister | READ; // Combine register address with READ command
  Serial.println("Merged Register w/ READ: ");
  Serial.println(dataToSend, BIN);
  digitalWrite(CS, LOW);  //Set the Chip Select pin low to start an SPI packet
  SPI.transfer(dataToSend);  // Tell device register to read from
  result = SPI.transfer(0x00); // Binary word read
  digitalWrite(CS, HIGH);  //Set CS high to close communcation
  return (result);
}

void writeRegister(byte thisRegister, byte thisValue)
{
 // ADXL373 expects the register address in the upper 7 bits of the transmitted byte
 // Shift the register bits left by 1 bit to apply WRITE bit:
 thisRegister = thisRegister << 1;
 byte dataWrite = thisRegister & WRITE; // Combine the register address and WRITE command
 digitalWrite(CS,LOW); //Set CS pin low to signal SPI packet start
 SPI.transfer(dataWrite); // Transfer the register address, RW
 SPI.transfer(thisValue); // Transfer the value to write 
 digitalWrite(CS,HIGH); //Set the Chip Select pin high to signal the end of an SPI packet.
}

You forgot to post a wiring diagram and a link to the sensor module.

How, exactly, are you handling the rather serious problem of connecting a 5V Arduino to a 3.3V sensor?

That's an error, I have the 3.3V supply connected to the sensor.

The sensor datasheet is linked at the start of the text. I noted the sensor to Arduino Mega connections in those initials lines of the code

If you do not have 5V to 3.3V logic level shifters on the I/O lines, then it will not work at all.

And, you may have actually damaged or destroyed the sensor. It is also possible to damage the Arduino that way.

What is the function then of the 3.3V pin on the Mega board? This has been my first experience with Arduino

The 3.3V pin can be used to power 3.3V devices. It does not release you from the responsibility of making sure that the rest of the connections are compatible.

Many sensor modules sold on the hobby market have the logic level shifters built in, but you MUST make sure that all connections are compatible. Best to use a 3.3V Arduino with a 3.3V sensor, then they can be connected directly.

This is a very common beginner mistake, and we see it every day on the forum.

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