I'm switching from the Arduino IDE to ESP IDF and I want to test an accelerometer (LIS2DW12). Initially, I had problems with the hardware-related programming. In the meantime I'm getting good values, but I need a factor of 10 for this. It`s a 14 bit value, stored in 2 8bit registers. I've searched some forums and have been working on it for a few days. But I haven't been able to find out, why I'm wrong by a factor of 10. What am I doing wrong? I am grateful for any reference! Register LIS2DW12 Datasheet
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#include "Arduino.h"
#include "string.h"
static const char *TAG = "LIS2DW12: ";
#define I2C_MASTER_SCL_IO 22 /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO 21 /*!< GPIO number used for I2C master data */
#define I2C_MASTER_NUM 1 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000
// Sensor Reg
#define SENSOR_ADDR 0x19 /*!< Slave address of the MPU9250 sensor */
#define WHO_AM_I_REG_ADDR 0x0F /*!< Register addresses of the "who am I" register */
#define Temp_L 0x0D
#define Temp_H 0x0E
#define WhoAmI 0x0F
#define CTRL1 0x20
#define CTRL2 0x21
#define CTRL3 0x22
#define CTRL4 0x23
#define CTRL5 0x24
#define CTRL6 0x25
#define X_LSB 0x28
#define X_MSB 0x29
#define Y_LSB 0x2A
#define Y_MSB 0x2B
#define Z_LSB 0x2C
#define Z_MSB 0x2D
uint16_t X_raw, Y_raw, Z_raw;
float X, Y, Z;
int ix,iy,iz;
void Sensor_data_test(){
byte buf[2];
// read register
register_read(Z_LSB, buf, 2);
Z_raw = buf[1]<<8 | buf[0]; // buf = MSB <<8 | LSB;
// print buffer
Serial.println("Sensor Data:");
Serial.print("buf0: ");Serial.print(buf[0]);
Serial.println();
Serial.print("buf1: ");Serial.print(buf[1]);
Serial.println();
Serial.print("Z uint16_t : ");Serial.print(Z_raw);
Serial.println();
// calculate binary and print
uint16_t Zh = Z_raw;
String hz;
while(Zh!=0)
{
hz=(Zh%2==0 ?"0":"1")+hz;
Zh/=2;
}
Serial.print("Z bin : ");Serial.println(hz);
//calculate 2'er complement
int k = 0;
if(Z_raw & (((uint16_t)0x1) << 15)) //check if binary is negativ
{ //if negativ, do
Z_raw = ~Z_raw; //invert bits
Z_raw = Z_raw + 1; //add one bit
Z_raw = Z_raw >> 2; //shift 2 spaces to the rigt (caused by Sensor register)
k = Z_raw * -1; //save as Integer an reverse sign
}
else{ //if positiv, do
Z_raw = Z_raw >> 2; //shift to spaces to the rigt (caused by Sensor register)
k = Z_raw; //save as Integer
}
if (k){
Serial.print("Z int: ");Serial.print(k);
Serial.println();
}
//acceleration value ============================================
Z= (float)k *16/8191; // factor 10 needed?
Serial.print("Z accel: ");Serial.print(Z);
Serial.println();
}
void Set_Sensor_Config(){
register_write_byte(CTRL1,0x55);
register_write_byte(CTRL2,0x04);
register_write_byte(CTRL3,0x00);
register_write_byte(CTRL4,0x00);
register_write_byte(CTRL5,0x00);
register_write_byte(CTRL6,0x34);
}
void Show_Sensor_Config(){
uint8_t buf[1];
ESP_LOGI(TAG, "LIS12DW Config: ");
register_read(CTRL1, buf, 1);
ESP_LOGI(TAG, "CTRL1 = %X", buf[0]);
register_read(CTRL2, buf, 1);
ESP_LOGI(TAG, "CTRL2 = %X", buf[0]);
register_read(CTRL3, buf, 1);
ESP_LOGI(TAG, "CTRL3 = %X", buf[0]);
register_read(CTRL4, buf, 1);
ESP_LOGI(TAG, "CTRL4 = %X", buf[0]);
register_read(CTRL5, buf, 1);
ESP_LOGI(TAG, "CTRL5 = %X", buf[0]);
register_read(CTRL6, buf, 1);
ESP_LOGI(TAG, "CTRL6 = %X", buf[0]);
}
extern "C" void app_main()
{
Serial.begin(115200);
ESP_ERROR_CHECK(i2c_master_init());
ESP_LOGI(TAG, "I2C initialized successfully");
Set_Sensor_Config();
Show_Sensor_Config();
Sensor_data_test();
ESP_ERROR_CHECK(i2c_driver_delete(I2C_MASTER_NUM));
ESP_LOGI(TAG, "I2C de-initialized successfully");
}
Output:
I (336) LIS2DW12: : LIS12DW Config:
I (336) LIS2DW12: : CTRL1 = 55
I (337) LIS2DW12: : CTRL2 = 4
I (341) LIS2DW12: : CTRL3 = 0
I (344) LIS2DW12: : CTRL4 = 0
I (348) LIS2DW12: : CTRL5 = 0
I (351) LIS2DW12: : CTRL6 = 34
Sensor Data:
buf0: 40
buf1: 248
Z uint16_t : 63528
Z bin : 1111100000101000
Z int: -502
Z accel: -0.98
I (367) LIS2DW12: : I2C de-initialized successfully
I wrote a function that reads out the Z acceleration registers and converts the data into a value [m/s²]. I expect a value of about 9.81 but I get 0.98 (acceleration of gravity).
Edit: I forgot to mention that I set the range to 16g. And the resolution are 13bit (8191).
Z= (float)k *16/8191; // factor 10 needed?
I was about to write that it still doesn't work. But while I was trying to write my questions and formatting my code, I found my mistake. Thanks to deviantgeek for your help. I followed the sample code and finally got it to work.
You cannot/should not approach the matter manually. Because even I can't understand the factors yet. If someone gets an incorrect value, then look at this function "lis2dw12_from_fs2_to_mg". There are various factors that depend, for example, on the range (2g, 4g,...) I used this code as "template": lis2dw12_read_data_single.c
This code works for 16g. It meassures only Z, but the other directions are the same
int32_t accel_z_raw_get(int16_t *val)
{
uint8_t buff[2];
int32_t ret;
if(STATUS & 0x01){ //check if Data ready to read // #define STATUS 0x27
ret = register_read(Z_LSB, buff, 2);
*val = (int16_t)buff[1];
*val = (*val * 256) + (int16_t)buff[0];
}
return ret;
}
float_t lis2dw12_from_fs2_lp1_to_mg(int16_t lsb)
{
return ((float_t)lsb) * 0.488f;
}
static int16_t data_raw_z[1];
static float accel_z_mg[1];
void get_sensor_data(){
char str[25];
accel_z_raw_get(data_raw_z);
accel_z_mg[0] = lis2dw12_from_fs2_lp1_to_mg(data_raw_z[0]);
sprintf((char *)str, "acceleration Z: % 4.2f\t\r\n", accel_z_mg[0]);
puts(str);
}
extern "C" void app_main()
{
Serial.begin(115200);
ESP_ERROR_CHECK(i2c_master_init());
ESP_LOGI(TAG, "I2C initialized successfully");
Set_Sensor_Config();
Show_Sensor_Config();
get_sensor_data();
ESP_ERROR_CHECK(i2c_driver_delete(I2C_MASTER_NUM));
ESP_LOGI(TAG, "I2C de-initialized successfully");
}
The output is: -981.86 That´s correct, because the sensor measures in mg`s. The negativ sign is ok, caus the sensor is upsidedown...
I (336) LIS2DW12-Register: LIS12DW Config:
I (336) LIS2DW12-Register: CTRL1 = 55
I (338) LIS2DW12-Register: CTRL2 = 4
I (342) LIS2DW12-Register: CTRL3 = 0
I (347) LIS2DW12-Register: CTRL4 = 0
I (351) LIS2DW12-Register: CTRL5 = 0
I (355) LIS2DW12-Register: CTRL6 = 34
I (359) LIS2DW12-Register: STATUS = 1
acceleration Z: -981.86
Thank you for your help! This forum is great!