LCD1602无法显示问题
问题描述:按照开源社区教程完成LCD1602驱动显示程序的编写,成功点亮屏幕,开启背光,但无法观察到显示数据。
分析过程与解决方案:
1.是否IIC地址不对
使用以下代码扫描IIC总线上的设备,发现LCD1602的IIC地址并没有配置错误
#include <Wire.h>
#include <Arduino.h>
void setup(){Wire.begin();Serial.begin(9600);Serial.println("\nI2C Scanner");
}
void loop(){byte error, address;int nDevices;Serial.println("Scanning...");nDevices = 0;for (address = 1; address < 127; address++ ){// The i2c_scanner uses the return value of// the Write.endTransmisstion to see if// a device did acknowledge to the address.Wire.beginTransmission(address);error = Wire.endTransmission();if (error == 0){Serial.print("I2C device found at address 0x");if (address < 16)Serial.print("0");Serial.print(address, HEX);Serial.println(" !");nDevices++;}else if (error == 4){Serial.print("Unknow error at address 0x");if (address < 16)Serial.print("0");Serial.println(address, HEX);}}if (nDevices == 0)Serial.println("No I2C devices found\n");elseSerial.println("done\n");delay(5000); // wait 5 seconds for next scan
}
2.硬件电路是否连接错误
检查原理图后,发现IIC模块背部有调光旋钮,使用螺丝刀旋转该旋钮,背光减弱,可以正常观察到显示的数据,代码并没有错误,最后问题成功解决。
手势识别问题
问题描述:通过DMP库读取MPU6050的姿态角后,通过上位机观察陀螺仪翻转时的姿态数据,发现当向后翻转时,姿态角数据反向增大后,再逐渐恢复正常值,现象如下图黄线所示:
这不利于设置阈值判定手势。
解决方案:通过与同伴交流,发现应该在陀螺仪初始化时将其正向放置,即遵循电路板上丝印进行静止初始化,即可实现,向后翻转,数据直接增大至稳定值。
通讯延时问题
问题描述:使用UDP进行两块ESP32间的通信,但控制延时较大,且发送数据过快时,会出现更大的延时。
解决方案:
1.通讯方式选择
ESP32中的UDP通信原理是将自己作为UDP服务器,并通过调用库函数实现数据传输。但UDP处于计算机网络中的传输层(第四层),通信双方每次传输均需要两次数据封装与解封操作。经过仔细阅读任务文档,发现了多ESP32的通讯实例:https://randomnerdtutorials.com/esp-now-many-to-one-esp32/。该方法通过ESP私有协议ESP-NOW完成通信,传输时只需要知晓一方的MAC地址即可完成双向通信,这意味着该协议处于数据链路层,减少了数据封装过程,因此通讯速率有所提升。经测试,从UDP更换为ESP-NOW通信后,通信延时减少了一秒。
2.数据发送频率
原始代码中,在遥控端,每隔100ms发送一次控制数据。
当无线通讯(ESP32间通讯)速率大于串口转发速率时,会导致遥控端发送的控制数据在小车端的ESP32和Arduino间堆积,即数据占满了串口缓存区。由于串口读取数据较慢,会导致实时的控制指令无法被实时接收,由此产生控制延时。于是减少控制数据的发送频率,通过判定上一次控制指令与当前指令是否相同来决定是否发送数据,若相同,则不发送,若不同,则发送数据。
修改后,控制延时大幅减小,能实现控制延时在1秒内。
字符串传输与解析
问题描述:Arduino需要向ESP32传输温度、湿度、距离数据,实现数据上云。
解决方案:确定通讯协议如下:A[温度数据],[湿度数据],[距离数据]F,如温度23摄氏度,湿度40%,距离50厘米即可传输字符串:A23,40,50F。其中字母A和F是数据标志位。
最终Arduino的数据发送代码段如下:
Serial.print('A');Serial.print(humidity);Serial.print(',');Serial.print(temperature);Serial.print(',');Serial.print(distance);Serial.print('F');
其中humidity,temperature, distance为获取的传感器数据。
ESP32端先接收数据到receive字符串数组中,然后使用strtok,atoi,atof函数将字符串中的传感器数据转换为float和int型。整体处理代码如下
//接收数据if(Serial2.available()){while(Serial2.available())//读完串口中的所有数据{receive[i++]=Serial2.read();}/***调试用***/Serial.println("I receive this:");Serial.println(receive);i=0; //清零,方便下一次读取数据Serial.println("I split this:");//处理数据data_process(receive);}//data_process函数原型如下void data_process(char *data){int i=0,j=0;while(data[i]!='A'){i++;}while(data[j]!='F'){j++;}data[j]='\0'; //字符串的结束标志位,方便后续strtok准确地分离数据char *p;const char *d = ",";//分离字符数据p = strtok((data+i+1),d);float hum = atof(p);p = strtok(NULL,d);float tem = atof(p);p = strtok(NULL,d);int dis = atoi(p);Serial.printf("%f,%f,%d\n",hum,tem,dis);Number1.print(hum); //Blinker中BlinkerNumber的对象,用于上传数据至云端Number2.print(tem);Number3.print(dis);
}