Question
Hello, I have question regarding LIS3DH sensor. I'd like to read raw X, Y and Z data and plot current position.
Desired behavior is shown on the first attachment (mma8451_sensor). When I read and parse LIS3DH data it seems that data are fluctuating(lis3dh_sensor) and cannot remain stable. Could you help me what am I doing wrong ?
bool LIS3DH_Init(void)
{
uint8_t tx_data[STD_TWO_BYTE_SIZE] = {0};
uint8_t ctrl_reg1_val = LIS3DH_CTRL1_DEFAULT_POWER_DOWN_VAL;
uint8_t ctrl_reg2_val = LIS3DH_FDS_ENABLE;
uint8_t ctrl_reg4_val = (LIS3DH_BDU_ENABLED | LIS3DH_RESOLUTION_2G);
if (false == read_who_am_i())
{
return false;
}
/* Writing to CTRL_REG1 register to enable low power mode and set measurement frequency */
tx_data[0] = LIS3DH_ADDR_CTRL_REG1;
tx_data[1] = ctrl_reg1_val;
CoM_i2c_write(LIS3DH_ADDR, &tx_data[0], STD_TWO_BYTE_SIZE, false);
/* Writing to CTRL_REG2 register to enable high pass filter */
tx_data[0] = LIS3DH_ADDR_CTRL_REG2;
tx_data[1] = ctrl_reg2_val;
CoM_i2c_write(LIS3DH_ADDR, &tx_data[0], STD_TWO_BYTE_SIZE, false);
/* Writing to CTRL_REG4 register to disable high-resolution mode and enable block data update feature */
tx_data[0] = LIS3DH_ADDR_CTRL_REG4;
tx_data[1] = ctrl_reg4_val;
CoM_i2c_write(LIS3DH_ADDR, &tx_data[0], STD_TWO_BYTE_SIZE, false);
/* Dummy read to force the HP filter to current acceleration value */
uint8_t dummy_reference_reg = LIS3DH_ADDR_REFERENCE;
uint8_t dummy_reference_val = 0x00;
CoM_i2c_write(LIS3DH_ADDR, &dummy_reference_reg, STD_ONE_BYTE_SIZE, true);
CoM_i2c_read(LIS3DH_ADDR, &dummy_reference_val, STD_ONE_BYTE_SIZE);
if (NRF_SUCCESS != change_mode(HIGH_RESOLUTION_MODE))
return false;
return true;
}/* Change mode of the LIS3DH chip */
static uint32_t change_mode(lis3dh_mode mode)
{
uint8_t ctrl_reg1_val = 0x00;
uint8_t ctrl_reg4_val = 0x00;
uint8_t reg;
if (mode > HIGH_RESOLUTION_MODE)
{
NRF_LOG_RAW_INFO("[ERROR] lis3dh unsupported mode request");
return NRF_ERROR_NOT_SUPPORTED;
}
/* Read current configuration */
reg = LIS3DH_ADDR_CTRL_REG1;
CoM_i2c_write(LIS3DH_ADDR, ®, STD_ONE_BYTE_SIZE, true);
CoM_i2c_read(LIS3DH_ADDR, &ctrl_reg1_val, STD_ONE_BYTE_SIZE);
reg = LIS3DH_ADDR_CTRL_REG4;
CoM_i2c_write(LIS3DH_ADDR, ®, STD_ONE_BYTE_SIZE, true);
CoM_i2c_read(LIS3DH_ADDR, &ctrl_reg4_val, STD_ONE_BYTE_SIZE);
/* Clear the ODR related bits */
ctrl_reg1_val &= 0x0F;
switch(mode)
{
case POWER_DOWN_MODE:
{
//ToDo
break;
}
case LOW_POWER_MODE:
{
/* Enable LPen bit in CTRL_REG1
* Decrase ODR value
* Disable HR bit in CTRL_REG4
*/
ctrl_reg1_val = LIS3DH_CTRL1_DEFAULT_LOW_POWER_VAL;
ctrl_reg4_val &= ~LIS3DH_HIGH_RES_ENABLE;
break;
}
case HIGH_RESOLUTION_MODE:
{
/* Disable LPen bit in CTRL_REG1
* Increase ODR value
* Enable HR bit in CTRL_REG4
*/
ctrl_reg1_val &= ~LIS3DH_LOW_POWER_ENABLE;
ctrl_reg1_val |= LIS3DH_MODE_50HZ;
ctrl_reg4_val |= LIS3DH_HIGH_RES_ENABLE;
break;
}
case NORMAL_MODE:
default:
{
/* Disable LPen bit in CTRL_REG1
* Increase ODR value
* Disable HR bit in CTRL_REG4
*/
ctrl_reg1_val &= ~LIS3DH_LOW_POWER_ENABLE;
ctrl_reg1_val |= LIS3DH_MODE_50HZ;
ctrl_reg4_val &= ~LIS3DH_HIGH_RES_ENABLE;
break;
}
}
/* Update power mode */
uint8_t tx_data[STD_TWO_BYTE_SIZE] = {0};
tx_data[0] = LIS3DH_ADDR_CTRL_REG1;
tx_data[1] = ctrl_reg1_val;
CoM_i2c_write(LIS3DH_ADDR, &tx_data[0], STD_TWO_BYTE_SIZE, false);
tx_data[0] = LIS3DH_ADDR_CTRL_REG4;
tx_data[1] = ctrl_reg4_val;
CoM_i2c_write(LIS3DH_ADDR, &tx_data[0], STD_TWO_BYTE_SIZE, false);
return NRF_SUCCESS;
}void LIS3DH_Read_Data(uint8_t *data, uint8_t len)
{
//int16_t x, y, z;
uint8_t raw_data[STD_XYZ_AXIS_DATA_LEN];
uint8_t reg = LIS3DH_STATUS;
uint8_t status = 0x00;
/* Read current status */
CoM_i2c_write(LIS3DH_ADDR, ®, STD_ONE_BYTE_SIZE, true);
CoM_i2c_read(LIS3DH_ADDR, &status, STD_ONE_BYTE_SIZE);
if (!(status & LIS3DH_ZYX_OR))
{
NRF_LOG_RAW_INFO("[WARN] lis3dh_status no data\r\n");
return;
}
/* Read XYZ data */
reg = (LIS3DH_OUT_X_L | LIS3DH_READ_AUTO_INCREMENT);
CoM_i2c_write(LIS3DH_ADDR, ®, STD_ONE_BYTE_SIZE, true);
CoM_i2c_read(LIS3DH_ADDR, &raw_data[0], STD_XYZ_AXIS_DATA_LEN);
/* x = raw_data[0];
x |= ((uint16_t)raw_data[1]) << 8;
y = raw_data[2];
y |= ((uint16_t)raw_data[3]) << 8;
z = raw_data[4];
z |= ((uint16_t)raw_data[5]) << 8;
*/
data[0] = raw_data[1];
data[1] = raw_data[0];
data[2] = raw_data[3];
data[3] = raw_data[2];
data[4] = raw_data[5];
data[5] = raw_data[4];
}Plotted stuff is:
LOG("x: %d\r\n", (data[2] << 8) | data[3]);
LOG("y: %d\r\n", (data[4] << 8) | data[5]);
LOG("z: %d\r\n", (data[6] << 8) | data[7]);
BR,
Jakub
