1
\$\begingroup\$

I'm using a Teensy 3.2 to read data from an ADXL375 using SPI. In general the communication is going just fine and I can activate settings etc. However, when I try to read X, Y or Z data it seems like some part of the measurement values are missing.

I'm performing measurements with the ADXL375 and writing the LSB values straight to an SD card, so no conversion to g or anything like that. The accelerometer range goes to +/- 200g, so that should give a max LSB value of about 200*20(scale factor) = +/- 4000 LSB.
During some tests I was swinging the accelerometer with my hand, and tapping it directly with a pen, which gives a momentary high impact. The swinging values are represented well and look credible to me, however the pen tapping values seem to be cut off at precisely 511 LSB, see graphs. That seems incorrect. So why is that?

N.B. The range of the ADXL is fixed to 200 g, so no choice to be made there.

My thinking is that something is going wrong with the conversion of the two ADXL registers (two's complement) to form a single number. This is the conversion I'm doing (i.e. I'm reading out the FIFO in one go):

void ADXL375::saveFIFO(){
    int fifo_index;
    int16_t x, y, z;
    fifo_index=0;
//    readFrom(DEVICE,ADXL375_INT_SOURCE_REG,1,buff);


    for(int i=0;i<32;i++){
        multiByteReadSPI(ADXL375_DATAX0_REG, 6, bufferSPI); //read the acceleration data from the ADXL375 
        x = (((uint16_t)bufferSPI[1]) << 8) | (uint16_t)bufferSPI[0];
        y = (((uint16_t)bufferSPI[3]) << 8) | (uint16_t)bufferSPI[2];
        z = (((uint16_t)bufferSPI[5]) << 8) | (uint16_t)bufferSPI[4];

        // Serial.print(bufferSPI[5], BIN); Serial.println(bufferSPI[4], BIN); // z
        // Serial.print(bufferSPI[1], BIN); Serial.print(","); Serial.println(bufferSPI[0], BIN);  // x 

        if (x & 0x8000){ // Check if the binary number is negative, by checking whether left most bit is 1 or not. 
            // If negative, then perform not operation and add one to get magnitude 
            x = ~x + 1; 
            x = - x; 
        } 
        if (y & 0x8000){ // Check if the binary number is negative, by checking whether left most bit is 1 or not. 
            // If negative, then perform not operation and add one to get magnitude 
            y = ~y + 1; 
            y = - y; 
        } 
        if (z & 0x8000){ // Check if the binary number is negative, by checking whether left most bit is 1 or not. 
            // If negative, then perform not operation and add one to get magnitude 
            z = ~z + 1; 
            z = - z; 
        } 

        
        lastFiFo[fifo_index]    =   newistFiFo[fifo_index];
        newistFiFo[fifo_index]  =   x;
        fifo_index++;
        lastFiFo[fifo_index]    =   newistFiFo[fifo_index]; 
        newistFiFo[fifo_index]  =   y;
        fifo_index++;
        lastFiFo[fifo_index]    =   newistFiFo[fifo_index]; 
        newistFiFo[fifo_index]  =   z;
        fifo_index++;
        // debugPrint(x); // debugPrintln(", Saving fifo"); 

                // x = (((int16_t)bufferSPI[1]) << 8) | bufferSPI[0];
        // y = (((int16_t)bufferSPI[3])<< 8) | bufferSPI[2];
        // z = (((int16_t)bufferSPI[5]) << 8) | bufferSPI[4];
        // scaleXYZ(&x,&y,&z);

    }

 }

This is the SPI Multibyte Read function I'm using:

void ADXL375::multiByteReadSPI(uint8_t regAddr, uint8_t numberOfBytes, uint8_t *dataBuffer){


    SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE3));

    digitalWrite(_chipSelectPin,LOW);

    uint8_t readMBaddr; 

    if (numberOfBytes > 1){ // for an actual multibyte read
        readMBaddr = 0b11000000 | regAddr; //  From left to right: read (1),  yes multibyte (1), and then a bunch of zeros
    }
    else{ // for single byte read 
        readMBaddr = 0b10000000 | regAddr; //  From left to right: read (1),  not multibyte (0), and then a bunch of zeros
    }

    SPI.transfer(readMBaddr);

    for (uint8_t k = 0; k < numberOfBytes; k++ ){
      dataBuffer[k] = SPI.transfer(SPI_DUMMY_VALUE);
    }

    digitalWrite(_chipSelectPin,HIGH);

    SPI.endTransaction();

}

enter image description here enter image description here I also had a look whether the SPI transfer are okay. The image shows one multibyte read, consisting of a command byte on the far left, and then 6 read bytes after that. Nothing out of the ordinary there. enter image description here

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

I found the answer. Turns out the datasheet of the ADXL375 is wrong, and the user can actually change the range themselves (even though the datasheet says you can't). In my case, the range was unintentionally set to 25 g (instead of 200 g). See below the full explanation by bvn123 - which was posted in 2017, yet Analog Devices has still not updated the datasheet.

I use ADXL345 and ADXL375 under a uC software, which was written for ADXL345.

The Datasheet for ADXL345 says about ±2g/±4g/±8g/±16g ranges and corresponding to these ranges 10/11/12/13bits resolutions.

The Datasheet for ADXL375 shows only one range ±200g and 13bits resolution. .

Inspite of the ADXL375 Datasheet's info, that Register 0x31 only state for bits D3:D2:D1:D0 is 1n11 (D3 is the Full resolution bit, D1:D0 are the Range bits), the ADXL375 reacts for D1:D0 and D3 change in the Register 0x31 the same way, as the ADXL345,

So, in reality ADXL375 also provides 4 ranges (±25g/±50g/±100g/±200g).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.