2017-11-01 10:16 AM
I have an LIS2DH device in my design and it's working - sort of. I was given some LIS3DH C driver code which I'm using under the advice that the LIS2DH is register-compatible with the LIS3DH.
So my requirement is to take 12-bit X,Y,Z readings ten times per second with a timing loop in my code making other sensor readings interleaved with the accelerometer ones and saving the data to flash memory. The setup code I'm running is listed at the bottom of this post. My timing code sets up a flag called takeAccelSample and, if that's true (which it is 10 times per second), I take a reading using the code also below.
What I observe is that my LIS2DH starts off taking readings and all seems good but, after 3 or 4 thousand samples have been taken, the data turns to junk like 0,0,4 continuously where normal data is 148,-204,12,-148,-212,24, and, occasionally the readings will be -1,-1,-1 or 0,0,0 for the whole dataset like as if the device wan't initialized properly.
I'm sure that I haven't set up the registers correctly and I'm struggling to understand how to configure the LIS2DH registers to do what I want, I don't think I want FIFO because I'm unable to guarantee that the loop timing of my code will match the LIS2DH taking 10 times per second under its own timing loop and I need the data I read to be time-aligned with the other sensor readings. I do have the LIS2DH INT1 pin connected to my microcontroller so I could use that if it helps but I haven't used it yet.
I think it should be possible to ask for a sample as I start my run and then in 0.1 seconds that sample should be ready and I can read and ask for another without having to wait for the result. Can someone please give me advice on how to configure the LIS2DH to read the samples on demand?
Thanks in advance
:)
// +++++++++++++++ Take Accelerometer Samples ++++++++++++++++++++++++++++++
// TM - Take Accelerometer Samples if (takeAccelSample) { // this will be true if recording mode is active response = LIS3DH_GetAccAxesRaw(&data); // TM sample Raw Accel data over SPI if(response==1){ // TM - capture data values rawAccel[0][accelIndx] = data.AXIS_X >> 6; rawAccel[1][accelIndx] = data.AXIS_Y >> 6; rawAccel[2][accelIndx] = data.AXIS_Z >> 6;accelIndx++; // we have to increment the accellerometer index once after capturing the samples takeAccelSample = 0; // clear flag now that sample has been taken } } // end of take accelerometer samples// +++++++++++++++ Accelerometer Setup ++++++++++++++++++++++++++++++
void accelerometerSetup(){ // Set Output Data Rate (ODR) - CTRL_REG1 response = LIS3DH_SetODR(LIS3DH_ODR_10Hz); // sprintf(strMsg1,'T response = %u\r\n', response); SCB_1_UartPutString(strMsg1); if(response==1){ if (verBose) { sprintf(strMsg1,'\n\rSET_ODR_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // Set High Pass Filter (HPF) Mode - CTRL_REG2 response = LIS3DH_SetHPFMode(LIS3DH_HPM_NORMAL_MODE); if(response==1){ if (verBose) { sprintf(strMsg1,'\n\rSET_HPF_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // Set Interrupt Mode response = LIS3DH_SetInt1Pin(LIS3DH_CLICK_ON_PIN_INT1_DISABLE | LIS3DH_I1_INT1_ON_PIN_INT1_ENABLE | LIS3DH_I1_INT2_ON_PIN_INT1_DISABLE | LIS3DH_I1_DRDY1_ON_INT1_ENABLE | LIS3DH_I1_DRDY2_ON_INT1_DISABLE | LIS3DH_WTM_ON_INT1_DISABLE | LIS3DH_INT1_OVERRUN_DISABLE ); if(response==1){ if (verBose) { sprintf(strMsg1,'\n\rSET_Interrupts_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // Set FIFO watermark level response = LIS3DH_SetWaterMark(1); // Set watermark to 1 if(response==1){ if (verBose) { sprintf(strMsg1,'\n\rSET_FIFO_WtrMk_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // Set FIFO mode - CTRL_REG? also enables FIFO? (TM thinks it does) response = LIS3DH_FIFOModeEnable(LIS3DH_FIFO_DISABLE); // (LIS3DH_FIFO_MODE); if(response==1){ if (verBose) { sprintf(strMsg1,'\n\rSET_FIFO_Mode_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // response = LIS3DH_SetBLE(LIS3DH_BLE_LSB); // _LSB or _MSB ??? TM pretty sure it's LSB if(response==1){ if (verBose) { sprintf(strMsg1,'\n\rSET_BLE_Mode_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // Set mode response = LIS3DH_SetMode(LIS3DH_LOW_POWER); if(response==1){ if (verBose) { sprintf(strMsg1,'SET_MODE_OK \n\r'); SCB_1_UartPutString(strMsg1); sprintf(strMsg1,'M response = %u\r\n', response); SCB_1_UartPutString(strMsg1); } } // Set Fullscale to be +- 2g response = LIS3DH_SetFullScale(LIS3DH_FULLSCALE_2); if(response==1){ if (verBose) { sprintf(strMsg1,'SET_FULLSCALE_OK \n\r'); SCB_1_UartPutString(strMsg1); } } // Set axis enable //set axis Enable response = LIS3DH_SetAxis(LIS3DH_X_ENABLE | LIS3DH_Y_ENABLE | LIS3DH_Z_ENABLE); if(response==1){ if (verBose) { sprintf(strMsg1,'SET_AXIS_OK \n\r'); SCB_1_UartPutString(strMsg1); } }}#lis3dh #lis2dh2017-11-02 02:57 AM
Please enable Block Data Update (BDU) so the output registers will not be updated until high and low bytes have been read. If the BDU is not enabled there could be misalignment between Low and High bytes.
I think your solution is OK, but I would recommend to use higher ODR for the LIS2DH that your required timing. Is you select the ODR 10Hz the real ODR can be for example 9.5Hz and then you will read some sample twice.
Concerning the timing, there is also a possibility to define the timing by the sensor. You can enable data ready interrupt and if your microcontroler will receive this interrupt you can read data from both sensors.
2017-11-07 09:06 AM
Miroslav, thanks for the assistance. I changed the ODR to 25 Hz and turned on BDU but there's still an issue. From a power reset, the LIS2DH works but after 20 minutes or so of being polled for and providing X,Y,Z readings ten times per second, the data stream becomes stuck (fixed values which don't change), even when the device is moved around. After I stopped requesting readings today, I issued a 'WhoAmI' query and the LIS2DH responded with 0x33 which is what I expected so it's still responding to SPI requests. I then re-ran the initialization routine and tried more sampling but the LIS2DH still returned the same stuck values as before (32, 244, 16,
32, 244, 16,
32, 244, 16)
continuously. This isn't isolated to a single unit, I have 13 of these devices built and they are all the same although, when they get stuck, they can stick on different values e.g 0,0,4...What can I try next?
2017-11-07 09:31 AM
Do you have any other device or devices connected to the same SPI bus?
Can you please try to read the register CTRL_REG1 (20h) after the device stuck? Or if possible read back all registers to check if something change.
There is rare possibility that the communication with different device on the same SPI bus activate I2C interface of LIS2DH and write some random data to a register.
You can also try to reboot memory content using
CTRL_REG5 (24h) register.
2017-11-07 11:09 AM
There is another device on the SPI bus, a flash memory IC, but they use separate &sharpCS pins which both have pull ups on them. Are you saying that, with the &sharpCS on the LIS2DH in a high state, specific traffic on the data line can be randomly interpreted as I2C data? If that's the case then it might explain what I see but how do I avoid that situation? I will write the routine to read register 20h and get back with you on what I find.
Thanks, Ted
2018-02-08 03:08 PM
Ted
Miroslav is right to enable
Block Data Update (BDU) but also make sure
the XYZDA bit in the STATUS_REG is 1 before doing your raw read. This marks data ready.I had a similar issue although i was using I2C mine seemed to be timing at first, when I started checking the
XYZDA bit before each read things stabilized.