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

ESP32读取ADXL345无法获取负值的技术求助

解决ESP32上ADXL345无法读取负值的问题

在Arduino UNO上运行ADXL345的I2C代码可正常获取三轴加速度值(示例输出:0.05 0.10 1.01),但移植到ESP32后,输出变为255.89 255.81 0.99,完全无法读取负值,原始数据示例为65000、65000、1。

问题根源

ADXL345输出的是16位有符号整数(int16_t),但ESP32的Wire.read()返回的是无符号8位整数(uint8_t)。直接拼接高低字节时,高位的符号位会被当作无符号位处理,导致负值被错误转换为大的正值(比如-1会被解析为65535)。而Arduino UNO的Wire.read()返回int类型,会自动处理符号扩展,因此不会出现该问题。

修复方案

修改数据类型定义和字节拼接逻辑,确保符号位正确扩展:

  1. 将存储原始三轴数据的变量改为int16_t类型,适配传感器的有符号输出。
  2. 读取字节时,先将uint8_t转换为int8_t,再进行位运算,保证符号扩展正确。
  3. 计算加速度值时,用int16_t直接除以256.0转换为浮点型。

修改后的完整代码

#include <Wire.h>
const int ADXL345 = 0x53; // ADXL345的I2C地址
int16_t X_out, Y_out, Z_out; // 存储原始有符号数据
float X, Y, Z; // 最终加速度值(单位:g)

void setup() {
  Serial.begin(115200);
  Wire.begin();

  // 配置ADXL345数据格式
  Wire.beginTransmission(ADXL345);
  Wire.write(0x31); // 数据格式寄存器
  Wire.write(0x0B);
  Wire.endTransmission();

  // Z轴偏移校准
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20); // Z轴偏移寄存器
  Wire.write(-7);
  Wire.endTransmission();

  // 开启测量模式
  Wire.beginTransmission(ADXL345);
  Wire.write(0x2D); // 电源控制寄存器
  Wire.write(0x08); // 启动测量
  Wire.endTransmission();

  // 设置输出数据速率
  Wire.beginTransmission(ADXL345);
  Wire.write(0x2C); // 速率控制寄存器
  Wire.write(0x09); // 10Hz输出速率
  Wire.endTransmission();

  delay(10);
}

void loop() {
  // 读取加速度数据
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // 从X轴高位寄存器开始读取
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // 读取6个寄存器(每个轴占2个字节)

  // 正确拼接高低字节,处理符号扩展
  X_out = (static_cast<int8_t>(Wire.read())) | (Wire.read() << 8);
  Y_out = (static_cast<int8_t>(Wire.read())) | (Wire.read() << 8);
  Z_out = (static_cast<int8_t>(Wire.read())) | (Wire.read() << 8);

  // 转换为加速度值(±2g范围下,原始值除以256)
  X = X_out / 256.0f;
  Y = Y_out / 256.0f;
  Z = Z_out / 256.0f;

  // 输出结果
  Serial.print(X);
  Serial.print("  ");
  Serial.print(Y);
  Serial.print("  ");
  Serial.println(Z);

  delay(20);
}

关键修改说明

  • X_out、Y_out、Z_out从float改为int16_t,确保存储有符号的原始数据。
  • 拼接字节时使用static_cast<int8_t>(Wire.read())将无符号字节转换为有符号字节,这样高位为1的负值会正确扩展符号位。
  • 除以256时使用256.0f确保浮点运算,避免整数除法导致精度丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:05:23