您现在的位置是:首页 >技术教程 >物联网手势控制小车所遇问题与解决方案网站首页技术教程

物联网手势控制小车所遇问题与解决方案

三点阳 2024-06-24 12:01:01
简介物联网手势控制小车所遇问题与解决方案

LCD1602无法显示问题

问题描述:按照开源社区教程完成LCD1602驱动显示程序的编写,成功点亮屏幕,开启背光,但无法观察到显示数据。

分析过程与解决方案

1.是否IIC地址不对

使用以下代码扫描IIC总线上的设备,发现LCD1602的IIC地址并没有配置错误

#include <Wire.h>
#include <Arduino.h>
void setup(){
  Wire.begin();
  Serial.begin(9600);
  Serial.println("
I2C 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
");
  else
    Serial.println("done
");
  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]='';   //字符串的结束标志位,方便后续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
",hum,tem,dis);
  Number1.print(hum);	//Blinker中BlinkerNumber的对象,用于上传数据至云端
  Number2.print(tem);
  Number3.print(dis);
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。