[51单片机] HC-SR04超声波测距仪
1、HC-SR04超声波模块工作原理
(1)采用IO口触发测距,给至少10us高电平脉冲;
(2)模块自动发送八个40khz方波,并自主检测是否有电波返回;
(3)当有信号返回时,通过IO口输出一个高电平,高电平的持续时间就是超声波从发送到返回的时间;
(4)测距公式:距离=(高电平时间*声速)/2;
超声波模块的时序图
(5)工作原理分析
英语啥的我也看不懂呐
差不多就是这个意思
2、使用元器件如下
超声波模块和蓝牙模块
加上51单片机后的连接图
3、开始运行时的工作状态
哇哦还是蛮准的嘛,允许一丢丢误差
把障碍物放在距离超声波模块前方的14cm左右(当然放多远是无所谓的,这里就以14cm为例吧!),根据单片机计算出来的值,由蓝牙模块发送到手机上面。
嘿嘿不晓得这样说有没有说清楚,这差不多就是我的理解吧!
这时候要用个手机软件(当然用电脑也是ok的啦,也需要一个蓝牙串口的软件),俺用的是下面这个➡️
偷偷告诉你豌豆荚可以下
4、上主菜
#include <AT89X51.H>
#include <intrins.h>
#include <STDIO.H> //c语言库
#define uchar unsigned char
#define uint unsigned int
#define ECHO P1_1 //echo 接线:模块TRIG接 P1.2 ECH0 接P1.1
#define TRIG P1_0 //trig
unsigned int time=0;
float S=0;
bit flag =0;
void Conut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.87)/100; //算出来是CM
if(flag==1) //超出测量
{
flag=0;
printf("--------\n");
}
printf("S=%5.2fcm\n",S);
}
void delayms(unsigned int ms)
{
unsigned char i=100,j;
for(;ms;ms--)
{
while(--i)
{
j=10;
while(--j);
}
}
}
void zd0() interrupt 1 //T0中断计数器溢出
{
flag=1; //中断溢出标志
}
void StartModule() //T1中断用来扫描
{
int i;
TRIG=1; //启动一次模块
for(i=0;i<21;i++)
{
_nop_();
}
TRIG=0;
}
void main(void) //主工作区
{
TMOD=0x21; //T0为方式1 GATE=1;
SCON=0x50; //SCON是单片机串行口控制寄存器,用于控制串行通信的方式选择、接收和发送,指示串口的状态。
TH1=0xFD;
TL1=0xFD;
TH0=0;
TL0=0;
TR0=1;
ET0=1; //允许T0中断
TR1=1; //开启定时器
TI=1; //TI是串口送数据完成标志
EA=1; //开启总中断
while(1)
{
StartModule(); //启动模块
while(!ECHO); //当ECHO为零时
TR0=1; //开启计数
while(ECHO);//当ECHO为1计数并等待
TR0=0; //关闭计数
Conut(); //计算
delayms(50); //500ms = 0.5s
}
}
下次见
2020.05.16
‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧··END·‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧
附开发全流程:100米±2mm高精度激光测距仪
绝大部分开源项目都是开源PCB和开源代码,好点的再加个结构,但是这些过程是如何从无到有的呢?很少有人会详细解答。
本次工程将手把手教你从硬件选型,原理图PCB,软件编程和结构建模等几个方面,介绍我们开发一个产品的流程。
大概目录如下:
规格书解读、元器件选型:
原理图PCB:
软件编程:
结构建模:
面板绘制:
1.简介
全文8000多字,建议先收藏再查看。
使用PLS-K-100激光测距仪模块+ESP32做MCU,可以实现100米±2mm高精度激光测距,就算是和小米的激光测距仪相比,这个精度也是很高的。
2.了解PLS-K-100激光测距仪模块(花费10~30分钟)
先简单地看看模块的参数。
PLS-K-100具有测量精度高,测量速度快,安装操作简单等特点。
已广泛用于家装测量,工业控制等各领域。
产品特点:
体积小巧重量轻测距距离远,可达100m精度高,最高可达1mm耐高低温-30~+60℃,常温款0-40℃模块图片:
3.元器件选型+MCU选型+编程选型+需求分析+原理图(花费2小时)
这一部分是整个文章最核心部分!
3.1确定核心元器件
首先你需要知道你做的这个东西的核心元器件是什么。
不同的产品可能有不同的核心元器件,复杂的产品甚至是有多个核心元器件。
例如手机的核心元器件就是SOC、蓝牙音响的核心器件是功放和蓝牙芯片,那这要看如何选型,侧重蓝牙芯片还是侧重功放。
像这个激光测距仪的核心元器件就是这个PLS-K-100激光测距仪模块,因为这个模块是串口通讯的,所以MCU只要有串口通信都可以使其工作。其他像电源芯片和MCU都是非核心元器件。
原理图上只需要接到MCU的串口脚即可
这里我使用HDR2.54排针连接到主板,此外还需要接上拉电阻。
3.2预选MCU
因为这个元器件可以通过串口通信然后接收指令和发送测量数据,因此MCU选有串口通信的MCU:ESP32、普通的51单片机、STM32、甚至上树莓派等arm的处理器都是可以的。
但是这都需要功能需求分析后才能选的,这里先告诉大家选用的是ESP32。
3.3选定编程软件
至于选用什么MCU又关系到你选择编程软件的问题,例如STM32,可以支持keil、ST官方的CUBE mx、IAR arm版、VsCode、arduino。ESP32也可以用官方的IDE或者arduino等。
如果是简单地做点东西,我还是更推荐使用arduino。
3.4确定功能需求
那么选好核心器件和MCU后,这两个比较主要的东西基本上是选定了,那么剩下的就是其他需求了。
其他需求指的是什么呢?最简单的就是看系统的输入输出。
我举一些例子:
有无外置电池?是一直插电使用还是随身携带使用?如果有电池需求,那么电池电压选择?电池低于系统电压?需要升压芯片电池高于系统电压?需要降压芯片有无用户输入?如何输入?使用按键还是摇杆?使用鼠标还是键盘?使用触屏还是语音识别?细分一下又可以分为:按键是IO输入还是ADC输入?摇杆是ADC输入还是编码输入?有无用户输出?如何输出?使用屏幕还是LED灯?使用震动还是机械反馈?使用蜂鸣器还是语音播报?这里也可以细分:LED灯是否需要呼吸灯?LED灯有几盏,多的话是否需要译码器?屏幕是否需要驱动芯片又或者直接驱动?3.5先来看看别人是怎么做的
那么我找来了一个优利德的LM150e+ 150m激光测距仪看看。
就看系统的输入输出。输入:两节AAA电池、按键、激光测距模块输出:屏幕显示距离、激光测距模块
在这里激光测距仪是输入也是输出,输出了激光然后输入了激光反馈,因此才测得距离。
看完了别人的那么我们就仿照它来做吧:
3.6确定输入按键
首先输入是肯定用按键,因为这种产品有时你是看不见测量的屏幕,比如测量缝隙的时候你的眼睛就不能盯着触摸屏,如果用触摸屏那不如实体按键来的准确。
然后就是按键数量。优利德的一共有7个按键:
开机兼测量模式的复合按键测量长宽高算体积面积的按键储存按键多组数据加减求和的按键基准切换的按键蜂鸣器开关的关机和清零复合按键那么我们简单点,就要个测量,基准切换,开关机,蜂鸣器开关。
然后我们再加点其他东西,比如说优利德的没有单位切换,那我加一个单位切换。
我想要一个单纯的激光开关,不测量。
我想把测量模式分开。
那么一套下来我们就一共需要至少8个按键:
蜂鸣器开关激光开关基准切换单位切换连续测量单次测量开机关机然后这就有一个问题:
我们电池产品的话要考虑低功耗,所以用按键开关机就要做开机电路,关机电路等,但是想简单点的话直接做一个硬开关,开关电池的供电就好了。
所以以上,就确定要有6个按键,一个开关。
3.7确定屏幕输出
输出用的屏幕可以用彩色屏,1602屏,也可以用OLED,但是这种仪器彩色屏的话成本会高,而1602屏显示的信息就又太少了,果想要经济又实惠,可以用OLED,虽然是单色但也足够。
使用带驱动的模块OLED屏幕,可以用SPI或者IIC通讯,这种不是需要快速显示的,为了节省IO先预选IIC通讯的。
原理图上需要上拉电阻:
3.8确定外围
除了主要的输入输出外,我还需要加入其他外围,方便用户指示或者调试用
3.8.1.蜂鸣器
用于提示用户。需要加三极管驱动
原理图上只需要当下管,IO驱动即可:
3.8.2.激光指示灯
用于提示用户前激光是否打开,不需要用眼睛去看,虽然是二类激光产品,但是看久了还是对眼睛不好。LED想用IO直接驱动:
3.8.3串口输入输出
用于方便调试和升级烧录用(这个前期可以用,后期产品开发成型后可以做空焊),这里就用CH340C把看规格书搭好电路。
需要注意的是V3脚,3.3V直接接3.3V,5V要外接退耦电容。我这里使用的是USB的5V直接供电。
当然如果是STM32可以留JTAG或者SWD,这部分可以等选完MCU再回过来确定,也是可以的。
3.8.4.电池电量和充电指示
如果要使用到电池电量指示那么首先要检测,很明显需要用ADC检测,而充电器是否插入可以用IO或者ADC检测
3.9确定MCU和IO分配
那么输入输出和外围都预选后,就要选择MCU了。实际上确定MCU可以在前面,也可以在这里,这是一个动态调整的过程。比如前面选择了资源较少的MCU,后面需求多了,那么就要更换更大资源的MCU,如果一开始就选很多资源的MCU也是可以的,但是这样就不经济,因此需要结合需求综合的确定出MCU。首先先确定外围,通讯,IO数量:核心,激光测距仪模块:UART蜂鸣器:IO调试:UART按键:IO6或ADC1或ADC*2?电池电量检测:ADC充电器插入检测:ADC或IO?屏幕:IIC或SPI?那么需要一个MCU要有两个UART,ADC1~3路,IO2~8或10,IIC或SPI的最好是硬件的,虽然很多时候软件也能模拟,但是没有硬件效率高。
MCU这部分IO分配需要仔细去看规格书或者IO解读才能知道
传统8051单片机没有硬件IIC,ADC,直接不看
ESP8266 IO不够
经典STM32F103C8T6备选
ESP32 备选
还有很多很多mcu都是可以的,那么MCU满足需求后反过来再看看编程环境和现有的库。3.3节推荐过arduino开发,实际上STM32F103C8T6也是支持arduino的,ESP32也是,都可以使用很多现成的库。不过综合考虑后还是选择ESP32,主要理由是:
现阶段STM32F103C8T6支持arduino不够完善ESP32支持WIFI,后续可以增加联网功能。外围简单,无需晶振然后回过头来在确定按键全部可以用IO,比较好开发,屏幕用IIC
最后就是MCU分配IO了首先先按照那些IO口能输入,能输出,功能复用等先分配
例如ESP32,有些IO是开机会输出PWM啊,或者只能输入不能输出。比如说开机会输出PWM最好就不能接LED啊蜂鸣器的,拉高启动失败就不能接上拉的IOKEY等等,这些都需要做调整。然后除了看以上情况还需要看PCB的布线是否走得通,好不好出现,走不走的顺,走不了只能调换IO,这些是要PCB画到一半再回过头来调整的。
选择好MCU后还需要画上MCU外围,也就是最小系统电路。对于ESP32最小系统基本上就是电源和复位电路了。
当然我集成到CH340自动下载电路了,因此这两个按钮实际上可以省掉
如果是STM32等还需要外围晶振电路
3.8确定电池和电源系统
首先这种手持产品不可能说接着个AC电,TYPE-C5V来用,这样很不方便,因此电池肯定是要有,那选什么电池?选多大的呢?主要还是看各个元器件的输入电压范围。那么我们需要找规格书,那么关于如何找规格书的话有空我可以写个文章单独讲如何找,这里先直接给出来:
MCU:
蜂鸣器:
激光测距模块:
CH340:
OLED屏幕:
以上就是主要元器件的工作电压范围,除了MCU和激光测距模块是在3.3V,其他都可以到3.3~5V。
综合考虑各个系统给定3.3V
然后就是确定电源(电池):如果是一节锂电池(4.2V~3.2V,3.7V额定),那么又有两种方法:
1.是升压到5V然后降压到3.3V
2.是直接降压到3.3V
实际上锂电池大多数情况到后面压降很厉害了,能用的基本都在3.3V以上,考虑到经济和损耗,不如直接降压到3.3V。
那么降压又有DCDC和LDO,这里更推荐使用DCDC,因为大多数LDO需要有0.1~1V的压差才可以使用,例如1V压差需要4.3V才能降压到3.3V,而我们电池电压会波动,所以大多数LDO都用不了,而且我们希望一个电源降压芯片就给整个系统供电,因此使用DCDC效率更高而且电流带载能力越大。
这里使用我经常用的一颗LP3220。
根据数据手册上典型应用图就可以搭出来电路了。
可以带1.2A电流,而且可以低压差甚至无压差输出,例如3.4V输出3.3V,3.3V输出3.3V,当然3.2V不可能输出3.3V,这就需要升降压芯片了,但是这里没有必要用到升降压。
如果是两节锂电池串联(8.4V~6.4V,7.4V额定),那么推荐用DCDC直接到3.3V是最好的,但是两节锂电池又需要考虑电池均衡的问题,还有电池的管理芯片和外围也比单节的多得多,因此不如用单节锂电池。
干电池的话也是可以的,但是自己做DIY的话就不推荐了,要经常买,两节干电池串联实际上只有2.几V的电压,基本上是升压了。
综合考虑下来还是使用单节锂电池最为经济。
3.9电源管理芯片和电源路径管理
选定电池单节锂电池后要考虑充电问题,充电芯片有很多,我这里选的是TP5100,单节充电可以上到2A,不过我选用的是1A电流。
然后要考虑路径管理,很多电池产品例如手机,可以边用边充电,但是考虑到激光测距仪专用性比较强,也不是24小时都要插电用的,更多是手持的时候,因此没做路径管理。当然要做路径管理也是可以的,如下:
边用边充,5V给电池充电同时给系统5V供电,没有5V时用电池供电。
那么到这里元器件选型+MCU选型+编程选型+需求分析+原理图就完了。
4.前期搭建平台验证可行性和调试(花费2小时)
对于上面的MCU和各种选型,我们先可以不着急画PCB。
我先推荐用杜邦线和面包板的方式按照上一步画的原理图先搭建一套简单的平台出来。
好处:
搭出来可以验证电路上原理图上一些问题可以前期先调试软件发PCB后还要等一段时间才会回板,但是这段时间你不可能没事做摆烂因此你可以先用这套平台先调着软件先,你就领先别人一亿年(没错,比赛的时候也是这样,先用平台调软件争取时间,等回板再转到PCB上调)。那么这套平台至少包含:
MCU,可以是核心板,或者开发板。可靠的供电,可以不用上述选到的电源IC,但是一定是要有的,我这里直接用ESP32开发板上AMS1117产生的3.3V核心元器件,也就是激光测距仪,连接到ESP32的串口上。基本输入输出,一个OLED屏幕,按键可以是一个,不用那么多。这是我当时搭建的平台。那么搭建这个平台有什么好处呢?
就是验证过自己的主要的电路是OK的没问题,那么就说明前期画的原理图是没有基本问题的。我不敢打包票说一定没问题,但是大问题是肯定没啥的。
我做的一些项目也是前期搭平台的。
这是今年5月的瑞萨训练营的数据无线采集搭的平台。
当然那次传感器很多,因为核心元器件都是传感器,所以看着接线很乱。
但是至少我搭过平台的项目基本上都是打一次板就全部功能通的。
5.PCB(花费绘制1.5小时,焊接1.5小时)
绘制和焊接PCB要点。
5.1PCB绘制
原理图绘制完成那就是绘制PCB了
这是我的PCB,当然还有很多要优化的地方。
例如ESP32天线处不要铺铜甚至锣空,ESP32的IO不顺,需要调整位置等,不过这些都是小问题。
我们来看看首先要先干什么。
首先是按照结构板框和结构元器件来摆放,例如按键,开关,TYPE-C口位置。
一般流程是板框结构先给出来,但是这里我是现有PCB再有结构的。
如果是现有PCB再有结构的话就特别要注意上面交互元器件的摆放了,要摆放在合适的位置。
由于是做手持产品,因此板能画多小就多小。
我这里先是摆放了六个按键,然后再摆放TYPE-C,再摆放开关和屏幕。
交互元器件定下来后就画上板框大概框住。
然后就大致布局其他元器件。
布局元器件原则就是连接尽量走短,并且留有能够走线的空间。
然后就可以布线了。
布线先走高速差分信号,再走其他小信号,最后再走电源。
我的习惯是这样,后面两个也可以调换,但是一定要先走高速差分信号。
这块板看上去就USB “串口” IIC这几个算是比较高速的了,但只有USB是差分,其他两个也可以走差分。
走好线后调整好各个元器件的丝印,当然也可以全部隐藏,比较漂亮。
在其他空的地方打上地孔,铺上地铜,检查DRC就可以愉快的发板了。
5.2PCB焊接
那么打完板回来就是焊接了
首先我推荐的焊接顺序是:1.TYPE-C座子2.TP5100芯片3.CH340C芯片4.电源芯片LP32205.MCU ESP326.其他贴片物料7.插件物料
为什么会推荐这样的顺序呢?
首先整张板最难焊接的应该就是TYPE-C座子和TP5100芯片了,先焊接比较难的芯片,万一把PCB板弄坏了也没关系,因为没焊其他东西。如果你其他东西全都焊完了,就差这个TYPE-C插座了,但是你一个失手把铜皮扯出来还是怎么样的弄坏了,那真的是寄了。
那么想要避免这种况的发生,那最好的办法就是先焊接这个TYPE-C插座,然后在焊接比较难的,例如TP5100,这是QFN封装的一个芯片,虽然不算难,但是对于新手来说还是有挑战的。
所以一般都是先焊接比较难的又便宜的物料,然后再焊接芯片。
芯片的焊接顺序当然也是有讲究的。
我先焊接了TP5100是因为TP5100便宜,而且比较难焊接。
然后其他芯片都不是很难,但是他有一个价格CH340C芯片的价格是最便宜的,然后是到LP3220,最后是到MCU ESP32。
芯片先从最便宜的开始焊,然后到最贵的,这样就算焊错了也不会有太大损失。
焊接完先上电看看3.3V有没有正常产生就可以了。
电源不短路就是OK,再看看充电是否正常等。
另外就是焊好喇叭后直接焊接OLED屏幕,不用母座对插,这样屏幕不会突出来,可以查看后面装配3D。
按键推荐6x6x13的,这样亚克力是按压装的,看后面装配。
如果按键超过亚克力可以推盖安装,看后面的爆炸图。
6.外壳结构绘制(花费6小时)
本工程将使用SOLIDWORKS进行外壳绘制,外壳文件已经在附件中。
前面讲过一般开发流程都是先有结构再有PCB,然后给出PCB板框,不过我们现在以硬件主导,因此先导入PCB再有结构。
6.1导出PCB 3D
使用嘉立创EDA专业版绘制,选择元器件的时候已经选择了带有3D封装的元器件了:
然后我们到PCB设置板厚。
设置为你打板的厚度,默认1.6mm,这样导出才是板厚1.6mm的。
然后选择导出3D文件。
选择类型选择STEP 对象选择PCB+元件模型。
导出STEP文件。
6.2导入SOLIDWORKS
打开SW后直接选打开。
查看所有类型,选择刚刚导出的文件。然后等待导入SW。
提示没有默认模板,请在设置中选择默认模板。
默认是以装配体形式打开的,PCB和各个元器件是一整个零件
6.3绘制/导入激光测距仪和OLED屏幕和按钮
时间关系已经画好。
配合好PCB的关系即可。
PCB和激光测距仪距离适合即可,不要太多。
OLED和PCB距离5.2,OLED底部PCB应顶住蜂鸣器,蜂鸣器的3D似乎被我搞不见了hhh。
6.4绘制外壳
简单拉个BOX就好了。
沿着PCB和激光测距仪外框框围起来就好啦,激光测距仪记得留螺丝柱固定定位柱记得加加强筋。
PCB板支撑固定也要加倒角加强。
内部做好倒角。
TYPEC做其实可以再收进去一点。
两边缩进,做导轨以放置亚克力,导轨高度应稍高于按键。
那么要注意的点就是这些。
6.5电池和按键
电池仓大小:50x40x5.2可以了。
如果是推盖安装那么按键长度还要再长点,目前淘宝没找到,只能自己画然后打印。
6.6导出外壳3D
可以到三维猴愉快下单了。
6.7绘制亚克力DXF
绘制完外壳要根据滑轨大小制作亚克力大小。
滑轨预留2.25mm,因此亚克力厚度2mm。
长宽83x54.2mm。
留下公差,宽度选择53.5mm,长度可以一样,厚度2mm。
亚克力切掉开关部分和留个按键的键帽直径+0.2~0.3mm即可。
6.8导出亚克力DXF
画完亚克力后需要导出dxf到立创EDA专业版中绘制亚克力图案提供避位。
选中亚克力零件后选择另存为一个零件。
另存为零件得到亚克力的3D。
新建一个工程图。
双击亚克力零件。
选择视图。
便会生成多个视图,我们只需要上面那个即可,我们可以导入到立创EDA里再删除也可以。
我们导出DXF,然后点击选项。
确认输出1:1是激活的。
然后保存即可。
6.9爆炸图
可以做一下爆炸图。
爆炸图演示的是亚克力推盖安装,实际上我是按压安装,这个是看你按钮高度,上面已经说过了,这里不再重复。
爆炸动图
7.亚克力面板(花费30分钟)
先导入DXF。
新建面板文件后选择导入dxf。
选择上一步导入的亚克力DXF。
删掉其他,只保留顶视图投影。
我们就得到外框了。
注意,为了放置比例不对,请先查看一下长宽是否和3D绘制的一样。
然后就可以愉快的画面板了。
中间的控做挖空。
外面做板框即可。
使用立创EDA专业版面板编辑后导出文件到立创面板打样。
8.外壳安装(花费15~30分钟)
1.先接上电池和激光测距仪接线
2.电池后贴双面胶,建议用容易撕下的
3.安装电池,安装时紧贴外壳最后,出线在右下角。上一步不用双面胶也可以用胶布贴紧
4.安装激光测距模块,打上固定螺丝
5.安装主板
6.打上主板固定螺丝
7.安装亚克力,先安装右侧,再用力按压左侧进入凹槽
8.安装轻触开关按钮帽
9.完成
安装完毕
9.代码编写(花费12小时)
软件是整个项目的灵魂,因此设计需要三思
主要分为:1.和激光测距仪的通讯2.按键控制3.OLED显示UI
除了有源码外还有可以直接烧录的bin文件
9.1第三方库
本次工程中使用到第三方库:u8g2。
主要是OLED的UI显示库。
9.2激光测距仪通讯部分
主要是发送控制指令后读取激光模块回传的数据。
发送指令写在了measursend()内
接收和数据处理写在了laserread()内
首先要知道我们激光测距仪是接在ESP32的第二串口
因此需要和第一串口,也就是ch340串口进行区分,不要搞错。
Serial是串口1,连接ch340
Serial2是串口2,连接激光测距仪
9.2.1查看激光测距仪规格书
查看规格书可以看到命令以及对应的指令,返回的数据举例
可以看到发送的指令是固定的,我们只需要用到
单次自动测量连续自动测量打开激光关闭激光退出连续自动测量9.2.2发送指令
把他们存在char里就好了
每个状态用枚举存好
用的时候只需要更改状态即可,然后switch就可以作出动作
9.2.3接收指令
这个就比较麻烦了,因为接收不是固定的
上面规格书提到 前面6位数据都是固定,后面红色为测量距离结果,黄色为质量,最后绿色为校验和
那么我们就建立一个Distance_raw存放
仔细阅读规格书发现,除了返回正常数据,还会返回错误码0XEE
那么我们先判断首位是0XEE还是0XAA
如果是EE那么EE传输的只有8位,因此做校验和只需要取8位即可
然后判断校验和,最后判断返回的错误是什么错误即可
如果是0XAA,也就是正常数据,那么是做的13位校验和
校验和正确后才会拿第6,7,8,9位距离存储位数据做运算,然后再换算出距离,此距离单位是mm。
核心算法是:
Distance_mm = Distance_raw[6] * 16777216 + Distance_raw[7] * 65536 + Distance_raw[8] * 256 + Distance_raw[9];然后再根据Distance_mm 转换出cm和m
最后就是计算出可信度存放到Reliability中。可信度根据“规格书”,可信度越低,质量越高,测量越准确。
9.3按键扫描和激光相互之间的逻辑
我们先定每一个状态
按键对应IO
按键扫描
按键处理
我们先看看简单的处理,比如基准,实际上就是互相切换两种状态。
复杂的像多次测量和单次测量,要单次测量,多次测量和激光开关状态相互配合来判断做处理。
我们先来点简单的一个按键的。
这是单个激光的流程
从关闭状态到打开激光,到关闭激光,再到测量关闭状态,注意,这里的打开激光关闭激光都是发送的指令,只有测量关闭是MCU不发送东西
同样的测量也是,这里自动测量按下第一次实际上只是打开了激光瞄准,再按一次才是测量。
连续测量是从关闭状态到连续测量,然后再退出连续测量,如果不发送退出代码则会一直测量
接着就是单次测量另一个功能,就是长按单次测量,2秒松手后测量,实际上也很简单
打开激光和判断2秒实际上是同时的,打开激光同时已经在计算2秒了
然后就是这三个的相互联动了
如果从其他状态按连续测量,那么都是退出,如果激光打开状态按下测量,无论是单次还是多次,都是打开其测量状态
单次测量进入的打开激光按下多次测量是连续测量
看流程图其实就很容易理解了
那么有个问题,就是单次测量的2秒,我从多次测量开启状态长按单次2秒以上会怎样?从激光打开长按会怎样?
那就要看这个条件是否满足
按键松手前SingleKeyState=0是按下的SingleKeyState=1,和Singlekeyflag=1满足才行
只要按下就Singlekeyflag=1,所以会进入单次测量。
所以这里是有bug,嘿嘿
应该需要再判断是否在多次测量模式或者激光打开模式,那这个留给你们做作业把
9.4蜂鸣器
如果按照我们的顺序执行法,让蜂鸣器IO变高,延迟200ms,然后变低,那么CPU都被蜂鸣器时间占用了,那么最好的方法是使用定时器
但是ESP32用arduino做定时器我似乎遇到了一些问题,定时器开不起来不知道怎么回事那我用另一种方法,就是用millis()
这个函数在开机时就会在跑,我们就判断按下的时候当时的时间,然后加上200ms,然后再获取当前时间,如果当前时间大于按下时间+200ms,那么蜂鸣器已经响了200ms,那么再关闭蜂鸣器就可以了。
这样就不会占用太多CPU资源。
只要蜂鸣器状态开,那么IO变高同时开始计时,然后系统就一直检测当前时间<按下时的时间+200ms,是就复位。
这是不占用CPU资源延时来做的蜂鸣器,当然还是用定时器最简单。
9.5OLED部分
屏幕在这里可以切换0.96或者1.3寸的
中文部分先用取模软件弄好要显示的中文,实际上很多都没用上,因为没做hhh
屏幕代码放在oled()中
大多数是排版的代码。
还有根据状态显示当前状态的图标判断代码
根据单位选择显示不同单位和代为值的代码
这部分较为简单
9.6电池电量检测
这部分做的比较简单,一直没时间优化
核心就是注释的那几个
用满电ADC值和没电ADC值这两个固定的值对比当前的ADC值,计算出当前电压和电量。
当然这里电量是线性的,实际上电池到后面衰减得很快,不是一个线性的过程,但是懒得做优化啦
留给你们作业优化了。
9.7错误代码
我没做,还是留给你们的作业
10.最后
写到这里
已经快赶上一个毕业设计了
甚至多次触发平台字数上限
是一个比较完整的硬件软件结构教程了。
实际上很多东西还是没说到,因为里面实在是有点复杂,不是图文描述能说明的,有补充可以到评论区大家以前讨论哈~
最后感谢星火计划、立创开源社区的白嫖和技术支持
如果你喜欢这个文章,欢迎点赞、关注、转发
我会持续更新优质开源项目!
相关问答
51 单片机 怎么做一个 测距仪 ?用51单片机制作测距仪,最简单的做法是选用一个激光测距模块,这种测距模块是UART接口,单片机可以通过指令,完成激光测距、环境温度测量等。目前常用的激光测...