You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP-IDF环境下LIS2DW12加速度计转换值偏差10倍问题排查

LIS2DW12加速度计转换值比预期小10倍的排查

我正从Arduino IDE切换到ESP-IDF环境,测试LIS2DW12加速度计。硬件编程相关问题已解决,但转换得到的加速度值比预期小10倍:预期重力加速度约9.81m/s²,实际得到0.98m/s²。该传感器数据为14位值,存储在两个8位寄存器中,我已将量程设为16g,分辨率为13bit(对应8191)。

代码实现

#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");
    
    
}

输出结果

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

疑问:我编写了读取Z轴加速度寄存器并将补码数据转换为[m/s²]值的函数,但结果始终比预期小10倍,请问问题出在哪里?


问题分析与解决

问题出在单位转换环节,你当前的计算仅得到了以g为单位的加速度值,未完成到m/s²的转换。

具体原因:

  1. 计算式 Z= (float)k *16/8191 的结果是以g为单位的加速度,比如输出的-0.98实际是-0.98g。
  2. 1g对应约9.81m/s²,因此需要将结果乘以9.81才能得到正确的m/s²单位值。

修正后的计算式:

Z= (float)k *16/8191 *9.81;

验证:

用测试数据计算:-502 *16/8191 ≈ -0.98g,乘以9.81后得到-0.98*9.81≈-9.61m/s²,与预期重力加速度值一致。

额外提示:

你代码注释中提到的“factor 10 needed?”,这个10是g到m/s²的近似转换(9.81≈10),用10会得到接近真实值的结果但存在小误差,建议使用精确的9.81或传感器手册推荐的转换系数。


内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 20:05:10