8 years, 4 months ago.

ADXL313 erronneous data related to Z axis

Hi,

I have written code for the Nucleo-F401RE to read from the ADXL313 accelerometer and print it to a PC via serial. I initially did this with I2C which worked fine, however in my strive for extra speed I have moved to SPI, this is where the issues arise.

At times the data reads normally as can be seen in in the following example:

  • -0.070,-0.383,0.499,1
  • -0.066,-0.381,0.499,1
  • -0.064,-0.381,0.499,1
  • -0.072,-0.377,0.499,1
  • -0.070,-0.400,0.499,1

However at times (it seems when the z axis reading near 0) it will change and give readings of -0.001 on all axis like following:

  • -0.001,-0.001,-0.001,1
  • -0.001,-0.001,-0.001,1
  • -0.001,-0.001,-0.001,1
  • -0.001,-0.001,-0.001,1
  • -0.001,-0.001,-0.001,1

and then at what seems like random; in certain positions it will read -0.503 which is out of bounds of the reading so I have no idea how it gets that?:

  • -0.503,-0.503,-0.503,1
  • -0.503,-0.503,-0.503,1
  • -0.503,-0.503,-0.503,1
  • -0.503,-0.503,-0.503,1
  • -0.503,-0.503,-0.503,1

the limits are 0.5g each way (saturates 0.499 on the positive) Does anyone have any idea what my problem could be related to?

Below I have included a trimmed down version of my code if that helps?

main.cpp mbed code cut down for simplicity

#include "myheader.h"

SPI device(SPI_MOSI, SPI_MISO, SPI_SCK);
DigitalOut CS(SPI_CS);
Serial pc(SERIAL_TX, SERIAL_RX);

char data_read[6];
char data_write[2];
int count = 0;
int flag = 0;

void readSlowAccelero(){
    // Read raw data
    CS = 0;
    device.write(0x80|0x40|DATA_X0);
    for (int i = 0; i<=5; i++){
        data_read[i]=device.write(0x00); // read back 6 data bytes
    }
    CS = 1;
    float X = bytes2val(data_read[1], data_read[0]); //combine the 2 bytes and convert to units of 'g'
    float Y = bytes2val(data_read[3], data_read[2]);
    float Z = bytes2val(data_read[5], data_read[4]);
    pc.printf("%.3f,%.3f,%.3f,%d\r\n", X, Y, Z, flag);
}

int main()
{
    t.start();
    pc.baud(460800);
    CS = 1;
    device.format(8,3); // 8 bit data, Mode 3
    device.frequency(1000000); // 1MHz clock rate
    softReset();
    whoisAccelero();        // Read ID, version and serial numbers
    startAccelerometer();   // Configure the accelerometer sensor device ADXL313
    while(1){
        readSlowAccelero();
    }
}

Function file

#include "myheader.h"

// Function to write a byte (data) to a register (reg)
void write(int reg, int data){
    CS = 0;
    device.write(reg);
    device.write(data);
    CS = 1;;
}

// Reads a register (regi) and prints it to pc serial with a name (regLabel)
void printRegister(int regi, char* regLabel){
    CS = 0;
    device.write(0x80|regi);
    data_read[0] = device.write(0x00);
    CS = 1;
    pc.printf("%s = %#X\r\n", regLabel, data_read[0]);
}

// Performs a soft reset and reports it to PC serial
void softReset(){
    write(SOFT_RESET, RESET_VALUE);
    pc.printf("-----System Reset----- \r\n");
}

// Initialises the accelerometer after this it is in full speed read mode
void startAccelerometer(){
    write(DATA_FORMAT, 0b00000000);
    write(BW_RATE, 0b00001110);
//    write(OFS_Z, 0x80);
    write(POWER_CTL, 0b01001000);
    pc.printf("Accelerometer enabled, testing serial ... \r\n");
    printRegister(XID, "Serial Number");
}

// Returns the 5 ID registers of the accelero as a kind of POST,
// NOTE: Serial number will only take a value after startAccelerometer() is run
void whoisAccelero(){
    printRegister(DEVID_0, "Device ID 0");
    printRegister(DEVID_1, "Device ID 1");
    printRegister(PARTID, "Part ID");
    printRegister(REVID, "Silicon Revision");
    printRegister(XID, "Serial Number");
}

// takes the 2 bytes from reading the data registers and combines them before
// converting into units of "g" - reg0 holds the LSB
float bytes2val(char reg1, char reg0){
    int16_t temporaryX = (reg1 << 8) + reg0;
    return (float)temporaryX / 1024;
}

and for completion here is the header too:

myheader.h

#ifndef FLAGS_H
#define FLAGS_H
#include "mbed.h"

// Variables
static const int RESET_VALUE = 0x52;  // Value to soft reset device
// DEVICE ADDRESS
static const int ALT_WRITE_REG = 0xA6;       // Alternative address + Write
static const int ALT_READ_REG = 0xA7;        // Alternative address + Read
// REGISTER ADDRESS VALUES
static const int DEVID_0 = 0x00;      // Device Analog Devie ID (Read)
static const int DEVID_1 = 0x01;      // Device ADXL313 ID (Read)
static const int PARTID = 0x02;       // Part ID (Read)
static const int REVID = 0x03;        // Silicon revision (Read)
static const int XID = 0x04;          // Semiunique serial number (Read)
static const int SOFT_RESET = 0x18;   // Soft reset (R/W)
// OFFSET REGISTERS (R/W)
static const int OFS_Z = 0x20;    // z-axis offset register
// DATA REGISTERS (Read)
static const int DATA_X0 = 0x32;
// REGISTERS
static const int POWER_CTL = 0x2D;
static const int BW_RATE = 0x2C;
static const int DATA_FORMAT = 0x31;

extern SPI device;
extern Serial pc;
extern DigitalOut myled;
extern DigitalOut CS;

extern char data_read[];
extern char data_write[];

void write(int reg, int data);
void printRegister(int regi, char* regLabel);
void softReset();
void startAccelerometer();
void whoisAccelero();
float bytes2val(char reg1, char reg2);

#endif
Be the first to answer this question.