esp32s ADXL345调试
1、相关环境及组件
esp32参考前几篇文章。
https://github.com/adafruit/Adafruit_ADXL345
需要补充此库;

https://github.com/adafruit/Adafruit_Sensor
下载Adafruit_Sensor.h,复制到

adxl345是adxl335的升级版,精度更高些。
官网地址:https://www.analog.com/cn/products/adxl345.html#product-documentation
模块比对如下
https://www.analog.com/cn/parametricsearch/11175

ADXL345三轴加速度采用ADXL345芯片,具有体积小,功耗低的特点,
13位数字精度分辨能够测量超过±16g的加速度变换。
信号输出为16位数字输出,可以通过SPI与I2C接口实现信号采集。
ADXL345适用于倾斜角度测量,能够进行静态重力加速度检测。同时也适用于运动状态的追踪,测量运动或冲击过程造成的瞬时加速度。其高分辨率(4mg/LSB)使之能够感应变化小于1°的倾斜角度。
DFrobot的ADXL345三轴加速度计还内置一款LDO模块让你的加速度计能够工作于3.3~6v的工作电压之下。
传感器提供了几个特殊的功能。能够在静态或动态情况下检测是否有运动或停止出现,另外能够感知单轴的加速度值是否超出用户的设定值。检测单击/双击。如果该设备正在下降,能进行自由落体感应检测。这些功能能够被映射到两个中断输出引脚上。
在低功耗模式是用户能够基于ADXL345动作感应,进行电源管理,同时只损耗极低的功耗。
2、连接方式


对应esp32s开发板针脚如图,两个红框内容。

3、核心代码
可自行修改在mcu判断数据后上传给服务器,数据量小适合采用mqtt方式。
//adxl345相关依赖库
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
//变量定义----------------------------bigen
//定义传感器ID,123456序号
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
//变量定义--------------------------------end
//函数定义----------------------------bigen
//显示传感器明细信息
void displaySensorDetails(void)
{
sensor_t sensor;
// 获取传感器信息
accel.getSensor(&sensor);
Serial.println("------------------------------------");
// 传感器名称
Serial.print ("Sensor: "); Serial.println(sensor.name);
// 传感器版本
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
// 传感器ID
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
// 数据最大值
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
// 数据最小值
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
// 解析度
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
//显示传感器数据速率
void displayDataRate(void)
{
Serial.print ("Data Rate: ");
switch (accel.getDataRate())
{
case ADXL345_DATARATE_3200_HZ:
Serial.print ("3200 ");
break;
case ADXL345_DATARATE_1600_HZ:
Serial.print ("1600 ");
break;
case ADXL345_DATARATE_800_HZ:
Serial.print ("800 ");
break;
case ADXL345_DATARATE_400_HZ:
Serial.print ("400 ");
break;
case ADXL345_DATARATE_200_HZ:
Serial.print ("200 ");
break;
case ADXL345_DATARATE_100_HZ:
Serial.print ("100 ");
break;
case ADXL345_DATARATE_50_HZ:
Serial.print ("50 ");
break;
case ADXL345_DATARATE_25_HZ:
Serial.print ("25 ");
break;
case ADXL345_DATARATE_12_5_HZ:
Serial.print ("12.5 ");
break;
case ADXL345_DATARATE_6_25HZ:
Serial.print ("6.25 ");
break;
case ADXL345_DATARATE_3_13_HZ:
Serial.print ("3.13 ");
break;
case ADXL345_DATARATE_1_56_HZ:
Serial.print ("1.56 ");
break;
case ADXL345_DATARATE_0_78_HZ:
Serial.print ("0.78 ");
break;
case ADXL345_DATARATE_0_39_HZ:
Serial.print ("0.39 ");
break;
case ADXL345_DATARATE_0_20_HZ:
Serial.print ("0.20 ");
break;
case ADXL345_DATARATE_0_10_HZ:
Serial.print ("0.10 ");
break;
default:
Serial.print ("???? ");
break;
}
Serial.println(" Hz");
}
//显示重力数据精度范围
void displayRange(void)
{
Serial.print ("Range: +/- ");
switch (accel.getRange())
{
case ADXL345_RANGE_16_G:
Serial.print ("16 ");
break;
case ADXL345_RANGE_8_G:
Serial.print ("8 ");
break;
case ADXL345_RANGE_4_G:
Serial.print ("4 ");
break;
case ADXL345_RANGE_2_G:
Serial.print ("2 ");
break;
default:
Serial.print ("?? ");
break;
}
Serial.println(" g");
}
//初始化串口
void setupSerial() {
// 初始化默认串口
Serial.begin(115200);
}
//初始化传感器
void initSensor() {
// 启动传感器
if (!accel.begin())
{
// 检测不到给予提示,可自行修改信息
Serial.println("no ADXL345 detected ... Check your wiring!");
while (1);
}
//设置传感器精度
accel.setRange(ADXL345_RANGE_16_G);
// displaySetRange(ADXL345_RANGE_8_G);
// displaySetRange(ADXL345_RANGE_4_G);
// displaySetRange(ADXL345_RANGE_2_G);
}
//函数定义--------------------------------end
//主程序----------------------------bigen
void setup(void)
{
// 初始化串口
setupSerial();
delay(1000);
// 初始化传感器
initSensor();
delay(1000);
// 显示传感器明细信息
displaySensorDetails();
// 显示传感器速度
displayDataRate();
// 显示传感器范围
displayRange();
Serial.println("");
}
void loop(void)
{
// 定义x/y/z重力单元值
double Axout, Ayout, Azout;
//定义倾斜度
double theta, psy, phi;
// 定义偏转度
double roll, pitch, yaw;
Serial.println();
// 定义传感器事件
sensors_event_t event;
// 获取传感器数据
accel.getEvent(&event);
//获取x/y/z重力单元值
Axout = event.acceleration.x;
Ayout = event.acceleration.y;
Azout = event.acceleration.z;
Serial.print("Axout = ");
Serial.print(Axout);
Serial.print("\t\t");
Serial.print("Ayout = ");
Serial.print(Ayout);
Serial.print("\t\t");
Serial.print("Azout = ");
Serial.print(Azout);
Serial.print("\t\t");
Serial.println();
//计算偏离角度,公式参考原理说明
theta = atan(Axout / (sqrt((pow (Ayout, 2.0)) + (pow (Azout, 2.0))))) * 57.29577951;
psy = atan(Ayout / (sqrt((pow (Axout, 2.0)) + (pow (Azout, 2.0))))) * 57.29577951;
phi = atan((sqrt((pow (Ayout, 2.0)) + (pow (Axout, 2.0)))) / Azout) * 57.29577951;
Serial.print("theta = ");
Serial.print(theta);
Serial.print("\t\t");
Serial.print("psy = ");
Serial.print(psy);
Serial.print("\t\t");
Serial.print("phi = ");
Serial.print(phi);
Serial.print("\t\t");
Serial.println();
//计算旋转角度,公式参考原理说明
roll = (atan2(Ayout, Azout)) * 57.29577951 + 180;
pitch = (atan2(Azout, Axout)) * 57.29577951 + 180;
yaw = (atan2(Axout, Ayout)) * 57.29577951 + 180;
Serial.print("roll = ");
Serial.print(roll);
Serial.print("\t\t");
Serial.print("pitch = ");
Serial.print(pitch);
Serial.print("\t\t");
Serial.print("pitch = ");
Serial.print(pitch);
Serial.print("\t\t");
Serial.println();
//间隔1秒采集一次
delay(1000);
}
//主程序--------------------------------end
4、测试输出
移动传感器模块效果如下:
theta = 49.58 psy = -26.35 phi = -61.79
roll = 43.20 pitch = 148.17 pitch = 148.17
[17:58:35.016]
Axout = 8.24 Ayout = 3.10 Azout = -4.12
theta = 57.97 psy = 18.60 phi = -64.92
roll = 323.04 pitch = 153.43 pitch = 153.43
[17:58:36.017]
Axout = -0.12 Ayout = -6.16 Azout = -11.14
theta = -0.53 psy = -28.93 phi = -28.94
roll = 28.93 pitch = 89.39 pitch = 89.39
[17:58:37.017]
[17:58:37.027] Axout = -4.82 Ayout = -0.27 Azout = -8.94
theta = -28.33 psy = -1.55 phi = -28.38
roll = 1.76 pitch = 61.65 pitch = 61.65
[17:58:38.026]
Axout = -0.31 Ayout = 1.22 Azout = -9.96
theta = -1.79 psy = 6.95 phi = -7.18
roll = 353.04 pitch = 88.20 pitch = 88.20
[17:58:39.027]
Axout = 1.49 Ayout = 1.14 Azout = -9.73
theta = 8.65 psy = 6.59 phi = -10.91
roll = 353.33 pitch = 98.71 pitch = 98.71
[17:58:40.027]
[17:58:40.037] Axout = 2.79 Ayout = 0.51 Azout = -9.61
theta = 16.14 psy = 2.92 phi = -16.42
roll = 356.96 pitch = 106.16 pitch = 106.16
[17:58:41.039]
Axout = 3.14 Ayout = 0.75 Azout = -9.53
theta = 18.17 psy = 4.25 phi = -18.69
roll = 355.53 pitch = 108.22 pitch = 108.22
[17:58:41.050]
[17:58:42.037]
Axout = 3.33 Ayout = 0.67 Azout = -9.38
theta = 19.53 psy = 3.83 phi = -19.94
roll = 355.93 pitch = 109.58 pitch = 109.58
[17:58:43.037]
[17:58:43.046] Axout = 2.79 Ayout = 0.82 Azout = -9.61
theta = 16.11 psy = 4.71 phi = -16.82
roll = 355.10 pitch = 106.16 pitch = 106.16
[17:58:44.047]
Axout = 1.22 Ayout = 0.67 Azout = -9.92
theta = 6.97 psy = 3.82 phi = -7.96
roll = 356.16 pitch = 96.99 pitch = 96.99
5、nb_iot上报思路
esp32默认3个串口,开发板默认0串口接了usb;

采用uart1跟nb_iot sim7020连接;模块连接
//adxl345相关依赖库
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
//变量定义----------------------------bigen
//定义传感器ID,123456序号
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
//定义通讯串口
HardwareSerial swSer(1);
//定义mqtt服务器ip和端口,ip需要用自己指定域名
extern const char *kMqttServerAddress = "XX.XX.XX.XX";
extern const uint16_t kMqttServerPort = 1883;
//设备mac地址
char Mac_Address[18];
//变量定义--------------------------------end
//函数定义----------------------------bigen
//显示传感器明细信息
void displaySensorDetails(void)
{
sensor_t sensor;
// 获取传感器信息
accel.getSensor(&sensor);
Serial.println("------------------------------------");
// 传感器名称
Serial.print ("Sensor: "); Serial.println(sensor.name);
// 传感器版本
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
// 传感器ID
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
// 数据最大值
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
// 数据最小值
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
// 解析度
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
//显示传感器数据速率
void displayDataRate(void)
{
Serial.print ("Data Rate: ");
switch (accel.getDataRate())
{
case ADXL345_DATARATE_3200_HZ:
Serial.print ("3200 ");
break;
case ADXL345_DATARATE_1600_HZ:
Serial.print ("1600 ");
break;
case ADXL345_DATARATE_800_HZ:
Serial.print ("800 ");
break;
case ADXL345_DATARATE_400_HZ:
Serial.print ("400 ");
break;
case ADXL345_DATARATE_200_HZ:
Serial.print ("200 ");
break;
case ADXL345_DATARATE_100_HZ:
Serial.print ("100 ");
break;
case ADXL345_DATARATE_50_HZ:
Serial.print ("50 ");
break;
case ADXL345_DATARATE_25_HZ:
Serial.print ("25 ");
break;
case ADXL345_DATARATE_12_5_HZ:
Serial.print ("12.5 ");
break;
case ADXL345_DATARATE_6_25HZ:
Serial.print ("6.25 ");
break;
case ADXL345_DATARATE_3_13_HZ:
Serial.print ("3.13 ");
break;
case ADXL345_DATARATE_1_56_HZ:
Serial.print ("1.56 ");
break;
case ADXL345_DATARATE_0_78_HZ:
Serial.print ("0.78 ");
break;
case ADXL345_DATARATE_0_39_HZ:
Serial.print ("0.39 ");
break;
case ADXL345_DATARATE_0_20_HZ:
Serial.print ("0.20 ");
break;
case ADXL345_DATARATE_0_10_HZ:
Serial.print ("0.10 ");
break;
default:
Serial.print ("???? ");
break;
}
Serial.println(" Hz");
}
//显示重力数据精度范围
void displayRange(void)
{
Serial.print ("Range: +/- ");
switch (accel.getRange())
{
case ADXL345_RANGE_16_G:
Serial.print ("16 ");
break;
case ADXL345_RANGE_8_G:
Serial.print ("8 ");
break;
case ADXL345_RANGE_4_G:
Serial.print ("4 ");
break;
case ADXL345_RANGE_2_G:
Serial.print ("2 ");
break;
default:
Serial.print ("?? ");
break;
}
Serial.println(" g");
}
//初始化串口
void setupSerial() {
// 初始化默认串口
Serial.begin(115200);
delay(500);
// 初始化串口1
swSer.begin(115200, SERIAL_8N1, 4, 5);
delay(1000);
}
//初始化传感器
void initSensor() {
// 启动传感器
if (!accel.begin())
{
// 检测不到给予提示,可自行修改信息
Serial.println("no ADXL345 detected ... Check your wiring!");
while (1);
}
//设置传感器精度
accel.setRange(ADXL345_RANGE_16_G);
// displaySetRange(ADXL345_RANGE_8_G);
// displaySetRange(ADXL345_RANGE_4_G);
// displaySetRange(ADXL345_RANGE_2_G);
}
//获取默认mac地址作为设备标示
void getMacAddress() {
uint8_t mac0[6];
// 获取默认mac地址
esp_efuse_mac_get_default(mac0);
// Serial.printf("Default Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac0[0], mac0[1], mac0[2], mac0[3], mac0[4], mac0[5]);
// 把mac地址转成字符串
sprintf (Mac_Address, "%02X%02X%02X%02X%02X%02X", mac0[0], mac0[1], mac0[2], mac0[3], mac0[4], mac0[5]);
}
//连接mqtt服务器
void initMqtt() {
// 发送at判断通讯设备状态
Serial.println("AT\r\n");
swSer.println("AT\r\n");
ShowSerialData();
delay(1000);
// 作业:需要根据at返回状态判断是否执行下一步,如果连不上需要重启,重启采用 ESP.restart()命令
// 建立mqtt通道
Serial.println("AT+CMQNEW=\"" + String(kMqttServerAddress) + "\",\"" + kMqttServerPort + "\",12000,1024\r\n");
swSer.println("AT+CMQNEW=\"" + String(kMqttServerAddress) + "\",\"" + kMqttServerPort + "\",12000,1024\r\n");
ShowSerialData();
delay(1000);
// 在mqtt服务器注册设备
Serial.println("AT+CMQCON=0,3,\"" + String(Mac_Address) + "\",600,0,0\r\n");
swSer.println("AT+CMQCON=0,3,\"" + String(Mac_Address) + "\",600,0,0\r\n");
ShowSerialData();
delay(1000);
}
//发送消息
void sendMqttMsg(String msg) {
//定义消息内容变量
String strMsg;
//定义临时取数据存储
char m[1024] = "";
for (int i = 0; i < msg.length(); i++) {
// 堆栈取数据,转16进制,不足2位左边补0
sprintf (m, "%X", msg[i]);
// 逐一累加到传送字段中
strMsg += m;
}
Serial.println();
Serial.print( "AT+CMQPUB=0,\"acceler_iot/" + String(Mac_Address) + "\",1,0,0," + strMsg.length() + ",\"" + strMsg + "\"\r\n");
swSer.print( "AT+CMQPUB=0,\"acceler_iot/" + String(Mac_Address) + "\",1,0,0," + strMsg.length() + ",\"" + strMsg + "\"\r\n");
ShowSerialData();
delay(1000);
// 需要处理不成功情况
}
//断开连接
void disconnectMqtt() {
// 断开mqtt连接
swSer.println("AT+CMQDISCON=0\r\n");
ShowSerialData();
delay(1000);
}
//输出自定义串口返回信息
void ShowSerialData()
{
while ( swSer.available() != 0 )
Serial.write(swSer.read());
}
//函数定义--------------------------------end
//主程序----------------------------bigen
void setup(void)
{
// 初始化串口
setupSerial();
delay(1000);
// 获取mac地址
getMacAddress();
delay(1000);
// 初始化传感器
initSensor();
delay(1000);
// 显示传感器明细信息
displaySensorDetails();
// 显示传感器速度
displayDataRate();
// 显示传感器范围
displayRange();
Serial.println();
}
void loop(void)
{
// 定义x/y/z重力单元值
double Axout, Ayout, Azout;
//定义倾斜度
double theta, psy, phi;
// 定义偏转度
double roll, pitch, yaw;
Serial.println();
// 定义传感器事件
sensors_event_t event;
// 获取传感器数据
accel.getEvent(&event);
//获取x/y/z重力单元值
Axout = event.acceleration.x;
Ayout = event.acceleration.y;
Azout = event.acceleration.z;
Serial.print("Axout = ");
Serial.print(Axout);
Serial.print("\t\t");
Serial.print("Ayout = ");
Serial.print(Ayout);
Serial.print("\t\t");
Serial.print("Azout = ");
Serial.print(Azout);
Serial.print("\t\t");
Serial.println();
//计算偏离角度,公式参考原理说明
theta = atan(Axout / (sqrt((pow (Ayout, 2.0)) + (pow (Azout, 2.0))))) * 57.29577951;
psy = atan(Ayout / (sqrt((pow (Axout, 2.0)) + (pow (Azout, 2.0))))) * 57.29577951;
phi = atan((sqrt((pow (Ayout, 2.0)) + (pow (Axout, 2.0)))) / Azout) * 57.29577951;
Serial.print("theta = ");
Serial.print(theta);
Serial.print("\t\t");
Serial.print("psy = ");
Serial.print(psy);
Serial.print("\t\t");
Serial.print("phi = ");
Serial.print(phi);
Serial.print("\t\t");
Serial.println();
//计算旋转角度,公式参考原理说明
roll = (atan2(Ayout, Azout)) * 57.29577951 + 180;
pitch = (atan2(Azout, Axout)) * 57.29577951 + 180;
yaw = (atan2(Axout, Ayout)) * 57.29577951 + 180;
Serial.print("roll = ");
Serial.print(roll);
Serial.print("\t\t");
Serial.print("pitch = ");
Serial.print(pitch);
Serial.print("\t\t");
Serial.print("pitch = ");
Serial.print(pitch);
Serial.print("\t\t");
Serial.println();
// 连接mqtt
initMqtt();
// 上报内容合成字符串,用-隔开
Serial.println();
Serial.printf("Axout:%d_Ayout:%d_Azout:%d_theta:%d_psy:%d_phi:%d_roll:%d_pitch:%d_yaw:%d", char(Axout), char(Ayout), char(Azout), char(theta), char(psy), char(phi), char(roll), char(pitch), char(yaw));
Serial.println();
String msg = "-" + String(Axout) + "-" + String(Ayout) + "-" + String(Azout) + "-" + String(theta) + "-" + String(psy) + "-" + String(phi) + "-" + String(roll) + "-" + String(pitch) + "-" + String(yaw);
//上报信息
sendMqttMsg(msg);
//断开mqtt服务
disconnectMqtt();
//间隔5秒采集一次
delay(5000);
}
//主程序--------------------------------end
上报时间可自行调整;


作业:上报正常,接受消息为空,float类型转字符类型,在mqtt传输中有问题。
at 指令的mqtt内容只能接受16进制;
//发送消息
void sendMqttMsg(String msg) {
//定义消息内容变量
String strMsg;
//定义临时取数据存储,做16进制转换
char m[1024] = "";
for (int i = 0; i < msg.length(); i++) {
// 堆栈取数据,转16进制
sprintf (m, "%X", msg[i]);
// 逐一累加到传送字段中
strMsg += m;
}
Serial.println();
Serial.print( "AT+CMQPUB=0,\"acceler_iot/" + String(Mac_Address) + "\",1,0,0," + strMsg.length() + ",\"" + strMsg + "\"\r\n");
swSer.print( "AT+CMQPUB=0,\"acceler_iot/" + String(Mac_Address) + "\",1,0,0," + strMsg.length() + ",\"" + strMsg + "\"\r\n");
ShowSerialData();
delay(1000);
// 需要处理不成功情况
}

效果如图
6、效果比对
需要搭建实验环境比对建立对照组比对数据,才能建立行业的数据标准。
全文完。