Teensy4.1 SPI pins not working with ADXL345

New_bee

Active member
I have tried different libraries , and the used the pinout as described in the manual. when I use with other board it works well.

HTML:
#include <SPI.h>

#define CS_PIN 10  // Chip Select Pin for ADXL345

// ADXL345 Register Addresses
#define ADXL345_DEVID 0x00
#define ADXL345_POWER_CTL 0x2D
#define ADXL345_DATA_FORMAT 0x31
#define ADXL345_DATAX0 0x32
#define ADXL345_DATA_RATE 0x2C

// ADXL345 Data Rate Codes
#define ADXL345_DATA_RATE_3200 0x0F

// ADXL345 Range Codes
#define ADXL345_RANGE_4G 0x01

SPISettings adxlSpiSettings(8000000, MSBFIRST, SPI_MODE3);

void setup() {
  Serial.begin(2000000);

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);
  SPI.begin();

  // Check if ADXL345 is connected
  if (readRegister(ADXL345_DEVID) != 0xE5) {
    Serial.println("ADXL345 not connected!");
    while (1)
      ;
  }

  // Set data rate to 3200 Hz
  writeRegister(ADXL345_DATA_RATE, ADXL345_DATA_RATE_3200);

  // Set range to ±4g and enable FULL_RES
  writeRegister(ADXL345_DATA_FORMAT, 0x08 | ADXL345_RANGE_4G);

  // Set the ADXL345 to measurement mode
  writeRegister(ADXL345_POWER_CTL, 0x08);
}



void loop() {
  int16_t x, y, z;

  // Read acceleration data
  readAcceleration(&x, &y, &z);

  // Convert raw acceleration data to m/s^2
  float x_accel_m_s2 = x * 3.9 / 1000.0 * 9.80665;
  float y_accel_m_s2 = y * 3.9 / 1000.0 * 9.80665;
  float z_accel_m_s2 = z * 3.9 / 1000.0 * 9.80665;


  Serial.print("X: ");
  Serial.print(x_accel_m_s2);
  Serial.print(" m/s^2, Y: ");
  Serial.print(y_accel_m_s2);
  Serial.print(" m/s^2, Z: ");
  Serial.print(z_accel_m_s2);
  Serial.println(" m/s^2");

  delay(10);
}

void writeRegister(byte reg, byte value) {
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x40);
  SPI.transfer(value);
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();
}

byte readRegister(byte reg) {
  byte value;
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x80);
  value = SPI.transfer(0x00);
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();
  return value;
}

void readAcceleration(int16_t* x, int16_t* y, int16_t* z) {
  byte buffer[6];
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(ADXL345_DATAX0 | 0x80 | 0x40);
  for (int i = 0; i < 6; i++) {
    buffer[i] = SPI.transfer(0x00);
  }
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();

  *x = ((int16_t)buffer[1] << 8) | buffer[0];
  *y = ((int16_t)buffer[3] << 8) | buffer[2];
  *z = ((int16_t)buffer[5] << 8) | buffer[4];
}

and the output is

HTML:
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2

I aslo tried ADXL345_WE library to no avail
 
I have tried different libraries , and the used the pinout as described in the manual. when I use with other board it works well.

HTML:
#include <SPI.h>

#define CS_PIN 10  // Chip Select Pin for ADXL345

// ADXL345 Register Addresses
#define ADXL345_DEVID 0x00
#define ADXL345_POWER_CTL 0x2D
#define ADXL345_DATA_FORMAT 0x31
#define ADXL345_DATAX0 0x32
#define ADXL345_DATA_RATE 0x2C

// ADXL345 Data Rate Codes
#define ADXL345_DATA_RATE_3200 0x0F

// ADXL345 Range Codes
#define ADXL345_RANGE_4G 0x01

SPISettings adxlSpiSettings(8000000, MSBFIRST, SPI_MODE3);

void setup() {
  Serial.begin(2000000);

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);
  SPI.begin();

  // Check if ADXL345 is connected
  if (readRegister(ADXL345_DEVID) != 0xE5) {
    Serial.println("ADXL345 not connected!");
    while (1)
      ;
  }

  // Set data rate to 3200 Hz
  writeRegister(ADXL345_DATA_RATE, ADXL345_DATA_RATE_3200);

  // Set range to ±4g and enable FULL_RES
  writeRegister(ADXL345_DATA_FORMAT, 0x08 | ADXL345_RANGE_4G);

  // Set the ADXL345 to measurement mode
  writeRegister(ADXL345_POWER_CTL, 0x08);
}



void loop() {
  int16_t x, y, z;

  // Read acceleration data
  readAcceleration(&x, &y, &z);

  // Convert raw acceleration data to m/s^2
  float x_accel_m_s2 = x * 3.9 / 1000.0 * 9.80665;
  float y_accel_m_s2 = y * 3.9 / 1000.0 * 9.80665;
  float z_accel_m_s2 = z * 3.9 / 1000.0 * 9.80665;


  Serial.print("X: ");
  Serial.print(x_accel_m_s2);
  Serial.print(" m/s^2, Y: ");
  Serial.print(y_accel_m_s2);
  Serial.print(" m/s^2, Z: ");
  Serial.print(z_accel_m_s2);
  Serial.println(" m/s^2");

  delay(10);
}

void writeRegister(byte reg, byte value) {
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x40);
  SPI.transfer(value);
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();
}

byte readRegister(byte reg) {
  byte value;
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x80);
  value = SPI.transfer(0x00);
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();
  return value;
}

void readAcceleration(int16_t* x, int16_t* y, int16_t* z) {
  byte buffer[6];
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(ADXL345_DATAX0 | 0x80 | 0x40);
  for (int i = 0; i < 6; i++) {
    buffer[i] = SPI.transfer(0x00);
  }
  digitalWrite(CS_PIN, HIGH);
  SPI.endTransaction();

  *x = ((int16_t)buffer[1] << 8) | buffer[0];
  *y = ((int16_t)buffer[3] << 8) | buffer[2];
  *z = ((int16_t)buffer[5] << 8) | buffer[4];
}

and the output is

HTML:
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2
X: 0.00 m/s^2, Y: 0.00 m/s^2, Z: 0.00 m/s^2

I aslo tried ADXL345_WE library to no avail

HTML:
/***************************************************************************
* Example sketch for the ADXL345_WE library
*
* This sketch shows how use SPI for the basic data sketch. Please apply the 
* same steps in the other sketches if you want to use SPI.  
*  
* Further information can be found on:
* https://wolles-elektronikkiste.de/adxl345-teil-1 (German)
* https://wolles-elektronikkiste.de/en/adxl345-the-universal-accelerometer-part-1 (English)
* 
***************************************************************************/

#include<ADXL345_WE.h>
#include<SPI.h>
#define CS_PIN 10   // Chip Select Pin
// In case you want to change the default SPI pins (e.g. for ESP32), uncomment and adjust:
  #define MOSI_PIN 11
  #define MISO_PIN 12
  #define SCK_PIN 13

bool spi = true;    // flag indicating that SPI shall be used

/* There are three ways to create your ADXL345 object in SPI mode:
 * ADXL345_WE myAcc = ADXL345_WE(CS_PIN, spi)     -> uses SPI, spi is just a flag, see SPI example
 * ADXL345_WE myAcc = ADXL345_WE(&SPI, CS_PIN, spi) -> uses SPI / passes the SPI object, spi is just a flag, see SPI example
 * ADXL345_WE myAcc = ADXL345_WE(&SPI, CS_PIN, spi, MOSI_PIN, MISO_PIN, SCK_PIN) -> like the latter, but also changes the SPI pins  
 */

ADXL345_WE myAcc = ADXL345_WE(CS_PIN, spi);

void setup(){
  Serial.begin(9600);
  Serial.println("ADXL345_Sketch - Basic Data");
  if(!myAcc.init()){
    Serial.println("ADXL345 not connected!");
  }

/* You can set the SPI clock speed. Default is 8 MHz. */
//  myAcc.setSPIClockSpeed(4000000);
   


  myAcc.setDataRate(ADXL345_DATA_RATE_1600);
  delay(100);
  Serial.print("Data rate: ");
  Serial.print(myAcc.getDataRateAsString());

/* In full resolution the size of the raw values depend on the
    range: 2g = 10 bit; 4g = 11 bit; 8g = 12 bit; 16g =13 bit;
    uncomment to change to 10 bit for all ranges. 
 */
  // myAcc.setFullRes(false);

 
  myAcc.setRange(ADXL345_RANGE_4G);
  Serial.print("  /  g-Range: ");
  Serial.println(myAcc.getRangeAsString());
  Serial.println();

/* Uncomment to enable Low Power Mode. It saves power but slightly
    increases noise. LowPower only affetcs Data Rates 12.5 Hz to 400 Hz.
*/
  // myAcc.setLowPower(true);
}


void loop() {
  xyzFloat raw = myAcc.getRawValues();
  xyzFloat g = myAcc.getGValues();
  
  Serial.print("Raw-x = ");
  Serial.print(raw.x);
  Serial.print("  |  Raw-y = ");
  Serial.print(raw.y);
  Serial.print("  |  Raw-z = ");
  Serial.println(raw.z);

  Serial.print("g-x   = ");
  Serial.print(g.x);
  Serial.print("  |  g-y   = ");
  Serial.print(g.y);
  Serial.print("  |  g-z   = ");
  Serial.println(g.z);

  Serial.println();
  
  delay(100);
  
}
 
Have you seen this? It might help.

Looks like the Sparkfun version of it that Paul's is forked from, has been updated with Paul's changes and a few more since then.

https://github.com/sparkfun/SparkFun_ADXL345_Arduino_Library

As for your code, wondering if maybe the Teensy code is too fast for the device. In particular in places like:
Code:
  SPI.beginTransaction(adxlSpiSettings);
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(reg | 0x40);
If maybe there needs to be a short delay between when the CS_PIN is selected and the first transfer.
You might experiement adding short delay between the two. I would probably start off with something like:
Code:
  digitalWrite(CS_PIN, LOW);
  delay(1);
  SPI.transfer(reg | 0x40);
And if that makes a difference, then try something like: delayMicrosconds(500);
and if that works, try smaller number... until you find maybe the minimal amount needed to still be reliable.

But sorry just guessing here.
 
Back
Top