ADXL313 Outputs Zero Data at High ODR (0,0,0)

Hello all, thanks for looking at this post. This is my first electronics project, and I am looking for some input on why I am getting irregular, blank data (output is simply 0,0,0) from my ADXL313 boards from time to time.

The Story: I am currently working on building an accelerometer tool where an Arduino Uno collects data from three individual ADXL313 eval boards and sends that data to a host computer serially. For this prototype setup, the Arduino samples all three ADXL313 boards sequentially at 1000 Hz via SPI communication, then the Arduino does some calculations, and then it sends that data immediately to a serial COM port on the computer (I use puTTY to see the data). I use a timer counter interrupt to initiate the accelerometer sampling routine, so there are instances where the Arduino cannot send the desired data fast enough before the next interrupt is triggered, but that is a separate issue for later.

The Problem: My problem is that there are times where everything runs smoothly, where the data is displayed nicely on the terminal emulator, but then I will reprogram the Arduino with virtually identical code (only change what values are sent serially, no change in number of bytes sent) and I now get data which is extremely noisy because every second or third sample only displays "0,0,0" for x,y,z acceleration, which is clearly a bug and not normal. Sometimes, I only get a stream of zeros!

Has anyone seen this issue before and been able to pin point the root cause? It does not seem like it would be due to a faulty chip, since I am using three of them and they all experience the same symptoms.

The Details: Here is a summary of the ADXL313 parameters (each of the three programmed the same):

  • Full resolution mode, +/- 2 g range, right justified data
  • ODR at 3200 Hz
  • SPI clock at 5 MHz
  • Basic operation: no FIFO, always in measurement mode
  • Multiple byte read every 1 ms (1000 Hz sample rate)
  • idk what else is relevant here...

Any and all help is most appreciated! I can upload parts of my firmware code if you need more information from me to help figure out my issue. I have been stumped by this for a bit over two weeks now, but I will let you all know if I have progress on my own. Thanks.

-Victor

  • 0
    •  Analog Employees 
    on Jan 7, 2016 3:35 AM

    Hi Victor,

    Thank you for your post and for the detailed explanation.  I agree that if the only thing that you changed was your code, it is hard to implicate the ADXL313 as the root cause.  Are you able to restore normal operation by going back to your old code?  Normally, stuff like this happens when the timing is violated or there are other functional issues with the communication protocol. We will keep thinking about this, but you might want to check this blog post out for general ideas:

    Connecting to Smart Sensors, it Takes More Than Code

    Perhaps it might be worth exploring the new value that are going into the ADXL313?  

    I hope that this helps!

    NevadaMark

  • Hi Victor,

    May be you can post the ADXL313 related schmatics and initialization code here, we can help you to review. It looks like your signal chain is ADXL313->SPI->MCU->UART->PC->APP show the real time output. I would suggest you to read DEVID_0, DEVID_1, PARTID every 1ms and send them to App to see whether you can still see 0x00, if so, that should be not related to ADXL313 configuration, but may related to unstable SPI communication, or unstable UART communication. Just my two cents.

    BR

    Neil

  • Hello NevadaMark,

    Firstly, my sincere apologies for my delayed response. You were prompt with your comment, and I appreciate that.

    Secondly, to answer your first question, no, I am not able to reliably restore normal operation when I go back to my "old" code. The only difference between the "new" and "old" firmware on the Arduino is the variable I pass to the "Serial.print()" command; the set up and algorithms are identical. Sometimes the data is normal, other times it is irregular as described above.

    Admittedly, I have not revisited this issue since I posted this thread in January. I will review the blog you posted, which hopefully provides insight into my problem. Also, I will be replying to neilzhao below now.

    Thanks,

    Victor

  • Hello neilzhao,

    Thank you very much for your comment, I am very sorry for not following it up promptly. I really like the debug technique you suggested (reading DEVID and PARTID), so that will be the first approach I take when I pick up this project again (while will be soon!)

    The schematic I have does not provide much information, it only shows the 4-wire SPI connection between the Arduino and three ADXL313 eval boards, and the power and ground buses. Below is a snippet of my Arduino code that initializes the SPI protocol and the accelerometers (header file for register definitions not shown). Sorry if the formatting is strange, I am copying/pasting out of the Arduino IDE.

    // PREAMBLE

         #include <SPI.h>

         SPISettings settings(5000000, MSBFIRST, SPI_MODE3);

         const uint8_t CS_1 = 7;

         const uint8_t CS_2 = 6;

         const uint8_t CS_3 = 5;

    // SETUP()

         SPI.begin();

         // Set up the three Chip Select pins to be a outputs from the Arduino.

        pinMode(CS_1, OUTPUT);

        pinMode(CS_2, OUTPUT);

        pinMode(CS_3, OUTPUT);

         // Before communication starts, the Chip Select pin needs to be set high as to

         // not invoke the accelerometers.

        digitalWrite(CS_1, HIGH);

        digitalWrite(CS_2, HIGH);

        digitalWrite(CS_3, HIGH);

         // Prepare bit masks for configuring the ADXL345 registers appropriately. Refer to

         // ADXL313_Registers.h in this sketch for register and bit definitions.

        uint8_t maskBandWidth   = ADXL313_DATARATE_3200_HZ;

       

        uint8_t maskPowerCtl    = (1 << ADXL313_BIT_I2C_DISABLE) |

                                  (1 << ADXL313_BIT_MEASURE);

                                 

        uint8_t maskDataFormat  = (1 << ADXL313_BIT_FULL_RES) |

                                  (ADXL313_RANGE_2_G);

         // Put ADXL313 into a high ODR of ~3200Hz.

        writeRegisters(ADXL313_REG_BW_RATE, maskBandWidth);

         // Put ADXL313 into Measurement Mode.

        writeRegisters(ADXL313_REG_POWER_CTL, maskPowerCtl);

           

         // Put both ADXL345 into +/- 2g range, 4-wire SPI, and full res mode.

        writeRegisters(ADXL313_REG_DATA_FORMAT, maskDataFormat);

    // LOOP()

         // Timing of these commands is controlled by a Timer Interrupt (not shown)

         readRegister(ADXL313_REG_DATAX0, NUMBYTES, values, CS_1);

         readRegister(ADXL313_REG_DATAX0, NUMBYTES, values, CS_2);

         readRegister(ADXL313_REG_DATAX0, NUMBYTES, values, CS_3);

    // FUNCTIONS writeRegisters() and readRegister()

    void writeRegisters(uint8_t registerAddress, uint8_t value)

    {

        SPI.beginTransaction(settings);

        digitalWrite(CS_1, LOW);

        SPI.transfer(registerAddress);

        SPI.transfer(value);

        digitalWrite(CS_1, HIGH);

        SPI.endTransaction();

        // Initiate an SPI communication instance with the second accelerometer...

        SPI.beginTransaction(settings);

        digitalWrite(CS_2, LOW);

        SPI.transfer(registerAddress);

        SPI.transfer(value);

        digitalWrite(CS_2, HIGH);

        SPI.endTransaction();

        // Initiate an SPI communication instance with the third accelerometer...

        SPI.beginTransaction(settings);

        digitalWrite(CS_3, LOW);

        SPI.transfer(registerAddress);

        SPI.transfer(value);

        digitalWrite(CS_3, HIGH);

        SPI.endTransaction();

    }

    void readRegister(uint8_t registerAddress, uint8_t numBytes, uint8_t* values,

                      uint8_t device)

    {

        // Since we're performing a read operation, the most significant bit of the

        // register address should be set.

        uint8_t address = registerAddress | (1 << 7);

        // If we're doing a multi-byte read, bit 6 needs to be set as well.

        if (numBytes > 1)

        {

            address = address | (1 << 6);

        }

        // Open communication with the device.

        SPI.beginTransaction(settings);

        // Set the specified Chip select pin low to start an SPI packet.

        digitalWrite(device, LOW);

        // Transfer the starting register address that needs to be read.

        SPI.transfer(address);

        // Continue to read registers until we've read the number specified, storing the

        // results to the input buffer.

        for (uint8_t i = 0; i < numBytes; i++)

        {

            values[i] = SPI.transfer(0x00); // Sending nothing means SPI.transfer() only

                                            // returns data from device.

        }

        // Set the Chips Select pin high to end the SPI packet.

        digitalWrite(device, HIGH);

        // Close SPI communication.

        SPI.endTransaction();

    }

    I know this is a wall of Arduino code that isn't really interesting, but hopefully it confirms that I am setting up the SPI protocol correctly. If necessary, I can post lines from my ADXL313 register header file.

    Thanks so much for the help and insight,

    Victor

  • 0
    •  Analog Employees 
    on Jun 9, 2016 6:19 PM

    Hi,

    I have not reviewed the code, but agree with Mark's earlier comment that when 0's are occurring, it is likely a timing issue.  As the title of the question suggests, are you getting different results when the ODR is changed?  What happens?  Are you polling a Data_Ready Signal through one of the interrupt pins to ensure new data is ready when you are trying to read it from the device?