Adxl345 spi with mini d1 esp32

I am trying to read acceleration values using SPI with maximum speed and sampling rate.
After stuffing the internet, I got this library, but it does not give output as expected.
The code and the output is

#include <SPI.h>
// Ctrl + T for autoformat
#define CS 5              // Chip select
// AND W ADDR
#define WRITEBYTE 0x00
#define READBYTE 0x80
// Set 2nd MSB for Multi-Byte mode

// figure out speed at which sensor updates and samples
// and speed at which we poll for those
// as well as the SPI transfer speeds

// ADXL(R/W, REG, DATA)
// return 1 for write, could even do a read to check successful write
// ADXL.read

void initialise()
{
  Serial.begin(2000000);
  SPI.begin();
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  while (!Serial);
  Serial.println("Initialized");
}

void registerWrite(byte Address, byte data)  {
  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));
  digitalWrite(CS, LOW);
  SPI.transfer(Address | WRITEBYTE);
  SPI.transfer(data);
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

uint8_t registerRead(byte Address) {
  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));
  digitalWrite(CS, LOW);
  SPI.transfer(Address | READBYTE);
  uint8_t data = SPI.transfer(0x00);
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
  return data;
}

void setup() {
  initialise();
  // Configure chip
  registerWrite(0x31, 0x00);            // Enter 4-wire SPI mode
  Serial.print("Reg0x31: "); Serial.println(registerRead(0x31));
  // Read & print DEVICE ID
  Serial.print("DEVICE ID: "); Serial.println(registerRead(0x00));
  // SET RES AND G-RANGE HERE
  registerWrite(0x2D, 0x08);            // Exit standby mode
}

float acceleration(char axis) {
  // Pass axis to registerRead (ASCII with offset)
  // Either do a switch or make sure user cant access
  // Out of bounds
  
  // Try to only use one variable<-- change int16 to float?
  
  int16_t DATAn = (registerRead(axis-(189-axis)) << 8);   // Hi
  DATAn |= registerRead(axis-(190-axis));                 // Lo
  // Divide value by the LSB/g(256 for 2g at 10-bit res)
  float nAccel = DATAn / 256.0;
  // Then times by Earth accel due to gravity (9.807m/s^2)
  nAccel *= 9.807;
  return nAccel;
}

void loop() {
   Serial.print(acceleration('x'));
Serial.print(',');   
  Serial.print(acceleration('y'));
  Serial.print(',');
  Serial.println(acceleration('z'));
  delay(500);
}

// Able to change data update speed, G-range, resolution etc settings
// Add way to calibrate/offset

// IF 8 bit storage is recycled after the hi & lo byte are combined:
// Read xData store high and low byte
// Read yData store high and low byte
// Read zData store high and low byte

// Combine high and low byte 

// Convert to m/s^2
// ========================================

// Either do all axis at one time using a for loop OR
// one at a time 

// There are a few combinations of when registers should 
// Be read and when the numbers should be processed 
// The reason is to avoid other axis' registers changing value
// While processing/reading the current axis

// ADXL.read(x);
// ADXL.settings();

// Check if ADXL is ther by reading ID

// Shouldnt max accel be 1g?

The output is

18:30:42.957 -> -9.19,3.60,-1.11
18:30:43.457 -> -9.04,3.52,-0.96
18:30:43.957 -> -9.19,3.60,-1.03
18:30:44.454 -> -9.19,3.60,-1.03
18:30:44.953 -> -9.04,3.41,-1.19
18:30:45.433 -> -9.19,3.68,-0.96
18:30:45.918 -> -9.19,3.52,-1.19
18:30:46.451 -> -9.19,3.60,-1.19
18:30:46.939 -> -9.04,3.52,-1.03
18:30:47.455 -> -9.19,3.60,-1.19
18:30:47.933 -> -9.04,3.60,-1.11
18:30:48.441 -> -9.04,3.52,-1.11
18:30:48.948 -> -9.04,3.68,-0.96
18:30:49.460 -> -9.19,3.60,-1.19
18:30:49.957 -> -9.19,3.60,-1.03
18:30:50.457 -> -9.04,3.68,-1.11
18:30:50.950 -> -9.04,3.60,-0.96
18:30:51.434 -> -9.04,3.52,-1.11
18:30:51.933 -> -9.19,3.52,-1.19
18:30:52.440 -> -9.19,3.60,-0.96
18:30:52.955 -> -8.96,3.60,-1.19
18:30:53.449 -> -9.19,3.60,-1.00
18:30:53.925 -> -9.04,3.41,-1.11
18:30:54.433 -> -9.04,3.52,-1.00
18:30:54.937 -> -9.04,3.60,-1.00

What is the expected value? Looks okey to me.

I am thinking of how to increase the number of samples per second. I have altered the code and increased the data rate to 3200Hz, yet no changes.

From the serial monitor above, I achieved 2 samples per second.

void loop() {
   Serial.print(acceleration('x'));
Serial.print(',');   
  Serial.print(acceleration('y'));
  Serial.print(',');
  Serial.println(acceleration('z'));
  delay(10);
}

When I reduced the delay to 10, I achieved 80 samples per second.

I will kindly appreciate any inputs or suggestions

The first suggestion is that You post the full test code.

2 Mega bit per second. Is that in use?

#include <SPI.h>
// Ctrl + T for autoformat
#define CS 5              // Chip select
// AND W ADDR
#define WRITEBYTE 0x00
#define READBYTE 0x80
// Set 2nd MSB for Multi-Byte mode

// figure out speed at which sensor updates and samples
// and speed at which we poll for those
// as well as the SPI transfer speeds

// ADXL(R/W, REG, DATA)
// return 1 for write, could even do a read to check successful write
// ADXL.read



void initialise()
{
  Serial.begin(2000000);
  SPI.begin();
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  while (!Serial);
  Serial.println("Initialized");
}

void registerWrite(byte Address, byte data)  {
  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));
  digitalWrite(CS, LOW);
  SPI.transfer(Address | WRITEBYTE);
  SPI.transfer(data);
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

uint8_t registerRead(byte Address) {
  SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));
  digitalWrite(CS, LOW);
  SPI.transfer(Address | READBYTE);
  uint8_t data = SPI.transfer(0x00);
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
  return data;
}

void setup() {
  initialise();
  // Configure chip
  registerWrite(0x31, 0x00);            // Enter 4-wire SPI mode
  Serial.print("Reg0x31: "); Serial.println(registerRead(0x31));
  // Read & print DEVICE ID
  Serial.print("DEVICE ID: "); Serial.println(registerRead(0x00));
  // SET RES AND G-RANGE HERE
  registerWrite(0x2D, 0x08);            // Exit standby mode
}

float acceleration(char axis) {
  // Pass axis to registerRead (ASCII with offset)
  // Either do a switch or make sure user cant access
  // Out of bounds
  
  // Try to only use one variable<-- change int16 to float?
  
  int16_t DATAn = (registerRead(axis-(189-axis)) << 8);   // Hi
  DATAn |= registerRead(axis-(190-axis));                 // Lo
  // Divide value by the LSB/g(256 for 2g at 10-bit res)
  float nAccel = DATAn / 256.0;
  // Then times by Earth accel due to gravity (9.807m/s^2)
  nAccel *= 9.807;
  return nAccel;
}

void loop() {
   Serial.print(acceleration('x'));
Serial.print(',');   
  Serial.print(acceleration('y'));
  Serial.print(',');
  Serial.println(acceleration('z'));
  delay(10);
}

// Able to change data update speed, G-range, resolution etc settings
// Add way to calibrate/offset

// IF 8 bit storage is recycled after the hi & lo byte are combined:
// Read xData store high and low byte
// Read yData store high and low byte
// Read zData store high and low byte

// Combine high and low byte 

// Convert to m/s^2
// ========================================

// Either do all axis at one time using a for loop OR
// one at a time 

// There are a few combinations of when registers should 
// Be read and when the numbers should be processed 
// The reason is to avoid other axis' registers changing value
// While processing/reading the current axis

// ADXL.read(x);
// ADXL.settings();

// Check if ADXL is ther by reading ID

// Shouldnt max accel be 1g? 

Changing the Serial.begin did not affect the number of samples

The delay(10);// 10 milliseconds lower the sample rate to below 100 Hz.
The execution of the code take some little time and Serial.print uses some time.

One Idea: Declare a number of unsigned long var1, var2, var3, ....
Register the microSeconds() value between interesting code lines.
At the end of loop use serial.println(var1); Serial.println(var2) etc.

Then You can find out how the different code lines affect the cycle time.

#include <SPI.h>

// Define ADXL345 register addresses
#define ADXL345_DEVID       0x00
#define ADXL345_DATAX0      0x32
#define ADXL345_DATAX1      0x33
#define ADXL345_DATAY0      0x34
#define ADXL345_DATAY1      0x35
#define ADXL345_DATAZ0      0x36
#define ADXL345_DATAZ1      0x37

// Initialize SPI pins
#define ADXL345_CS          5
#define ADXL345_SCK         18
#define ADXL345_MOSI        23
#define ADXL345_MISO        19

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  
  // Initialize SPI communication
  SPI.begin(ADXL345_SCK, ADXL345_MISO, ADXL345_MOSI, ADXL345_CS);
  SPI.setClockDivider(SPI_CLOCK_DIV2);  // Set SPI clock speed to 20 MHz

  // Configure ADXL345
  writeRegister(ADXL345_DEVID, 0x00);    // Read device ID
  writeRegister(0x2C, 0x0A);             // Set data rate to 3200Hz
  writeRegister(0x31, 0x00);             // Set range to +/-2g
  writeRegister(0x2D, 0x08);             // Enable measurement mode
}

void loop() {
  // Read accelerometer data
  int16_t x = readRegister16(ADXL345_DATAX0);
  int16_t y = readRegister16(ADXL345_DATAY0);
  int16_t z = readRegister16(ADXL345_DATAZ0);
  
  // Print data to serial monitor
  Serial.print("X: ");
  Serial.print(x);
  Serial.print(", Y: ");
  Serial.print(y);
  Serial.print(", Z: ");
  Serial.println(z);
  
  // Wait for 1/3200 seconds (sampling period)
  delayMicroseconds(313);
}

// Write a value to an ADXL345 register
void writeRegister(uint8_t reg, uint8_t value) {
  digitalWrite(ADXL345_CS, LOW);
  SPI.transfer(reg);
  SPI.transfer(value);
  digitalWrite(ADXL345_CS, HIGH);
}

// Read a 16-bit value from two consecutive ADXL345 registers
int16_t readRegister16(uint8_t reg) {
  int16_t value;
  digitalWrite(ADXL345_CS, LOW);
  SPI.transfer(reg | 0x80);    // Set read bit
  value = SPI.transfer(0);
  value |= (int16_t)SPI.transfer(0) << 8;
  digitalWrite(ADXL345_CS, HIGH);
  return value;
}

I wondered why the output read 0 0 0 on the serial monitor

This is the serial monitor output

08:18:01.098 -> X: 0, Y: 0, Z: 0
08:18:01.098 -> X: 0, Y: 0, Z: 0
08:18:01.130 -> X: 0, Y: 0, Z: 0
08:18:01.162 -> X: 0, Y: 0, Z: 0
08:18:01.162 -> X: 0, Y: 0, Z: 0
08:18:01.194 -> X: 0, Y: 0, Z: 0
08:18:01.194 -> X: 0, Y: 0, Z: 0
08:18:01.226 -> X: 0, Y: 0, Z: 0
08:18:01.258 -> X: 0, Y: 0, Z: 0
08:18:01.258 -> X: 0, Y: 0, Z: 0
08:18:01.289 -> X: 0, Y: 0, Z: 0
08:18:01.289 -> X: 0, Y: 0, Z: 0
08:18:01.322 -> X: 0, Y: 0, Z: 0
08:18:01.322 -> X: 0, Y: 0, Z: 0
08:18:01.353 -> X: 0, Y: 0, Z: 0
08:18:01.386 -> X: 0, Y: 0, Z: 0
08:18:01.386 -> X: 0, Y: 0, Z: 0
08:18:01.417 -> X: 0, Y: 0, Z: 0
08:18:01.417 -> X: 0, Y: 0, Z: 0
08:18:01.450 -> X: 0, Y: 0, Z: 0
08:18:01.482 -> X: 0, Y: 0, Z: 0
08:18:01.482 -> X: 0, Y: 0, Z: 0
08:18:01.513 -> X: 0, Y: 0, Z: 0
08:18:01.513 -> X: 0, Y: 0, Z: 0
08:18:01.546 -> X: 0, Y: 0, Z: 0

The code is reading zeroes from the ADXL345.

Yes, please. When I use the previous code, it works fine. I am just curious to know. Thanks

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