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

news2025/1/10 3:05:51

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");
  else
    Serial.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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/564827.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go学习圣经:队列削峰+批量写入 超高并发原理和实操

说在前面&#xff1a; 本文是《Go学习圣经》 的第二部分。 第一部分请参见&#xff1a;Go学习圣经&#xff1a;0基础精通GO开发与高并发架构&#xff08;1&#xff09; 现在拿到offer超级难&#xff0c;甚至连面试电话&#xff0c;一个都搞不到。 尼恩的技术社群中&#xf…

K近邻算法实现红酒数据集分类

目录 1. 作者介绍2. K近邻算法介绍2.1 K基本原理2.2 算法优缺点 3. KNN红酒数据集分类实验3.1 获取红酒数据集3.2 KNN算法3.3 完整代码 4. 问题分析参考链接&#xff08;可供参考的链接和引用文献&#xff09; 1. 作者介绍 路治东&#xff0c;男&#xff0c;西安工程大学电子信…

面试问题汇总

最近面试了几家公司&#xff0c;对问到的问题汇总一下。 Unity 是左手坐标系还是右手坐标系? 这个题靠记忆答的答错了&#xff0c;是左手坐标系。 大拇指指的方向是X轴&#xff0c;食指指的方向是Y轴方向&#xff0c;中指指的方向Z轴方向。 场景中游戏物体Activity为false,G…

C语言字符串函数和内存函数的介绍与模拟实现

0.前言 C语言中对字符和字符串的处理很是频繁&#xff0c;但是C语言本身是没有字符串类型的&#xff0c;字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数. 1.字符串函数介绍与模拟实现 C语言本身就带有一些库函数&#xff0c;所…

研发工程师玩转Kubernetes——CPU配额

在一个Pod中&#xff0c;可以有多个容器&#xff0c;比如一个主要业务容器和若干辅助业务容器。如果辅助业务容器内程序有问题&#xff0c;导致占用了大量的CPU资源&#xff0c;进而影响了主要业务容器的执行效率&#xff0c;那就需要进行干涉了。本节我们将使用“资源配额”来…

Edgedetect

边缘检测&#xff0c;检测上升沿 对于 8 位矢量中的每个位&#xff0c;检测输入信号何时从一个时钟周期中的 0 变为下一个时钟周期的 1&#xff08;类似于正边沿检测&#xff09;。输出位应在发生 0 到 1 转换后设置周期。 以下是一些示例。为清楚起见&#xff0c;in[1] 和 pe…

Jenkins+GitLab+Docker搭建前端自动化构建镜像容器部署(无本地证书,映射版本)

前言 &#x1f680; 需提前安装环境及知识点&#xff1a; 1、Docker搭建及基础操作 2、DockerFile文件描述 3、Jenkins搭建及基础点 &#x1f680; 目的&#xff1a; 将我们的前端项目打包成一个镜像容器并自动发布部署&#xff0c;可供随时pull访问 一、手动部署镜像及容器 1…

【Linux】线程分离 | 线程库 | C++调用线程 | 线程局部存储

文章目录 1. 线程分离1. 为什么要线程分离&#xff1f;2. 具体使用3. 为什么有时候分离在调用join 会正常运行&#xff1f; 2. 如何理解线程库&#xff1f;如何理解 先描述 在组织&#xff1f; 3. C中使用多线程4. 线程局部存储局部变量全局变量 1. 线程分离 1. 为什么要线程分…

服务器虚拟化部署

服务器虚拟化部署 1、背景2、目的3、环境4、部署4.1、部署VMware ESXi4.1.1、准备工作4.1.2、部署ESXi4.1.3、配置ESXi4.1.4 、部署虚拟机 1、背景 项目上利旧9台服务器&#xff0c;项目需要使用15台服务器&#xff0c;外购已经没有项目硬件采购预算&#xff0c;只能从目前的…

自定义HikariCP连接池

文章目录 一、简介1、概述2、地址 二、配置参数1、Hikari原生参数2、Springboot中参数 三、springboot中使用四、自定义数据源1、各模块2、完整代码3、多数据源 五、多数据源dynamic中使用1、简介2、引入依赖3、参数配置 六、XMind整理 一、简介 1、概述 官方解释&#xff1a…

zabbix 自动发现与自动注册、部署 zabbix 代理服务器及部署 Zabbix 高可用集群

目录 一、zabbix 自动发现二、zabbix 自动注册&#xff08;对于 agent2 是主动模式&#xff09;三、部署 zabbix 代理服务器四、部署 Zabbix 高可用集群五、Zabbix 监控 Windows 系统六、Zabbix 监控 java 应用七、Zabbix 监控 SNMP 一、zabbix 自动发现 zabbix 自动发现&…

Nautilus Chain开启全球行,普及Layer3概念加速其采用

在去年&#xff0c;在 2022 年&#xff0c;Vitalik 进一步提出了 Layer3 的概念与早期形态&#xff0c;期盼弥补目前链体系存在的不足&#xff0c;并为 Layer3 提出了三大目标&#xff0c;即Layer2 用于扩展&#xff0c;Layer3 用于定制功能&#xff0c;如隐私&#xff1b;Laye…

【C++】哈希表特性总结及unordered_map和unordered_set的模拟实现

✍作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;C 文章目录 前言一、哈希表的特性 - 哈希函数和哈希冲突1 哈希函数2. 哈希冲突 二、闭散列的实现 -- 开放地址法1. 定义数据结构2.insert()3.Find()4. Erase()5.仿函数处理key值不能取模无法映射 --- BKDRHash 三、开…

【Linux系列P4】Linux需要什么?编辑器?软件包?一文帮你了解掌握 [yum][vim]———基础开发工具篇

前言 大家好&#xff0c;这里是YY的Linux系列part4&#xff1b;本章主要内容面向接触过Linux的老铁&#xff0c;主要内容含【学习yum工具&#xff0c;进行软件安装】【拓展yum源安装】【掌握vim编辑器使用&#xff0c;基本命令】【命令集】【懒人配置文件安装教程】 在下一章节…

Java高并发编程—可见性与有序性原理

原子性、可见性和有序性是并发编程所面临的三大问题。 Java通过CAS操作已解决了并发编程中的原子性问题&#xff0c;本章为大家介绍Java如何解决剩余的另外两个问题——可见性和有序性。 CPU物理缓存结构 由于CPU的运算速度比主存&#xff08;物理内存&#xff09;的存取速度…

Android系统原理性问题分析 - 多路并发情况下的C/S模型

声明 在Android系统中经常会遇到一些系统原理性的问题&#xff0c;在此专栏中集中来讨论下。Android系统中很多地方都采用了I/O多路复用的机制&#xff0c;为了引出I/O多路复用机制&#xff0c;先来分析多路并发情况下的C/S模型。此篇参考一些博客和书籍&#xff0c;代码基于A…

C++条件变量condition_variable

一、问题 假设没有条件变量&#xff0c;对于一个生产者消费者问题&#xff0c;消费线程在得知队列中没有产品时&#xff0c;将阻塞自己。生产者线程可以给队列中放入产品&#xff0c;但是没有办法激活消费者线程&#xff0c;而消费者线程处于阻塞状态也没有办法自己激活自己。…

RocketMQ 领域模型概述

本文为您介绍 Apache RocketMQ 的领域模型。 Apache RocketMQ 是一款典型的分布式架构下的中间件产品&#xff0c;使用异步通信方式和发布订阅的消息传输模型。通信方式和传输模型的具体说明&#xff0c;请参见下文通信方式介绍和消息传输模型介绍。 Apache RocketMQ 产品具备…

IOS开发指南之自定义TableViewCell使用

演示效果: 1.自定义TableViewCell创建 File->new->File... 在iOS模板中选择Empty来创建一个空的XIB文件,然后点击下一步 输入XIB文件名Cell,然后点击Create创建 创建XIB文件成功后如下: 同时按钮Shift+command+L弹出库,然后输入 table筛选,选择Table View Cell 拖到下…

一文通透spring的初始化

简述 今天重点分析ApplicationContext初始化时做的事情&#xff0c;我们都只到spring是个IOC和AOP容器&#xff0c;那再我们new一个ApplicationContext&#xff0c;spring内部都做了什么&#xff1f;怎么实现的IOC和AOP&#xff1f; 比如说下面这段代码 Configuration Compon…