硬件是软件运行的基础,因此有必要建立良好的硬件系统供软件的运行。因此,针对通信功能的蓝牙模块、制动功能的电机模块和测距功能的超声波模块三大模块,建立电路连接,提供电路连接图,并编写程序。
本文也提供部分代码,代码虽然都是核心代码但不能够独立运行。程序都附注释,有一丢丢开发基础都能看懂。希望看官能有所思考后取得所需代码,而不是无脑的复制粘贴。完整代码参考这里。且代码仅以我的接线方式为标准。
通信功能
通信功能选取了HC-05蓝牙模块,某购物平台25RMB左右。对于Arduino而言,还是能很轻易的做到Arduino与HC-05蓝牙模块的连接。连接的电路图如下所示:
- 5V连接VCC,GND相互连接构成回路
- HC-05的发射端TXD连接Arduino的接收端RXD
- HC-05的接收端RXD连接Arduino的发射端TXD
- 以此来构成通信的回路。
但需要注意的是,在给Arduino烧录程序时,需要断开Arduino与HC-05的RXD和TXD连接。否则Arduni的TXD和RXD处于连接状态而非悬空状态时,程序无法烧录。(也可能是我用Vscode做IDE的原因)
PC向Arduino发送数据
而在完成电路的连接后,需要编写程序来测试连接是否正确。首先Arduino处于接收端,电脑处于发送端。接通电路,电脑开启蓝牙并连接。对于接收端,当available()返回值大于0时,表明串口有数据发送到Arduino,此时调用read方法读取即可。
1 | void setup() |
而在发送端,选择了使用python作为发射信号和读取信号的工具。借助pyserial串口,很容易实现这个功能。(pip install pyserial)
1 | import serial |
至于为什么要用b""
这样的形式,因为serial这个库发送和读取的数据都是字节类型。蓝牙HC-05的使用是我经历的最难的一部分,主要的坑是:只有在程序连接蓝牙时才算连接,而仅仅在Win10蓝牙中连接是不够的。
Arduino向PC发送数据
首先来看Arduino端的程序,一般是调用println方法完成发送,调用flush方法等待数据的发送完毕。
1 | void setup() |
而在python端完成读取数据的功能:
1 | import serial |
同样读取的数据为字节类型,通常为这样的格式:
1 | b'1\r\n' |
所以可以str(data[2:-5])这样取出其中的数值部分。
测距功能
选用了HC-SR04模块作为超声测距模块,购物平台5RMB左右。超声波测距的原理较为简单,首先发送特定频率的声波,在接收对应频率的声波。记录声波传输的时间,再结合声波传输的速度,很容易得到当前与障碍物的距离。测距原理图如下所示:
而具体到硬件而言,测距方法如下。HC-SR04有两个喇叭,Trig发送声波,Echo接收声波。Trig是启动信号引脚,使用的时候先给他10us以上的高电平,再拉低,SR04就会发送八个40khz的超声波。此时对Echo拉低。然后就开始等待Echo啥时候变高了我们就开始计时 (开始接收到反馈的声波), 直到他变低为止 (声波接收完毕),当它变低的时候,我们就可以根据这个时间计算距离了。
这个时间是声波在空气中传播的时间,因为是往返的,所以计算过程需要除以2,变成单程的时间,再将这个单程时间乘以声速即340米/秒,得到的就是从当前位置到对面障碍物的距离。因此,得到的电路连接方式如下:
也很容易得到相应的程序,但也有相关的注意事项:
- 使用pulseIn函数记录Echo持续高电平的时间即可。
- 在完成一次测距后一定要延时一秒左右。因为程序的执行速度和硬件的执行速度是不一样的,程序执行完了要缓一缓,等待硬件执行完。不延时的情况下HC-SR04是不能工作的。
1 | int trigBack = 2; |
制动功能
车辆最基本的功能还是实现前进、后退、左转和右转,而这些功能的实现离不开电机模块。选用的电机模块是HC02-48,便宜到忘记了它的价格。但是Arduino不能直接驱动HC02-48电机完成工作,因为驱动电机需要较大电流,而Arduino的作用在于高低电平的控制而不是电流的输出。Arduino的IO口输出电流在40mA左右,无法驱动最低要求150mA的电机。因此需要借助电机驱动模块L298N来放大驱动电流。
L298N驱动直流电机时可选择任何额定电压在4.8~35V和电流小于2A范围内的电机。而HC02-48电机的工作电压在3-6V,且L298N的输出电流恰好能驱动电机模块,因此在硬件层面可完成驱动。这个好像也很便宜,大约10RMB左右。
将L298N的四个入口引脚IN1,IN2,IN3和IN4接Arduino的控制引脚,此时Out1,Out2连接一个电机,Out3,Out4出口引脚连接另外的电机。通过对4个入口引脚赋值来更改出口引脚的电平输出,进而控制电机的正反转,完成前进、后退和转向的功能。此外可以通过总开关ENA,ENB两个使能端控制两个电机能否转动和转速。电路连接方式下:
而L298N的+12V和GND接口,需要单独的电池供电。正如上文所说,Arduino的核心功能是控制电平的输出而不是提供电压,因此仅将Arduino的IO口和L298N的使能端连接即可,L298N的供电部分需要另外的电池。
转速调节
在倒车的过程中,车辆不能够以过高的速度倒车,否则容易发生碰撞。因此,需要PWM调制的手段将车速给降下来。想必在做的看官应该不是自动化专业的,所以我准备通俗的解释PWM的含义:
- 在一个时间段内,一直给电机供电,那么电机会持续转动,此时是满电的输出;
- 在一个时间段内,一半的时间供电,一半的时间不供电,那么电机只会在一半的时间内转动,此时的速度会低于满电输出;
- 在一个时间段内,75%的时间不供电,25%的时间供电,那么电机会在1/4的时间内转动,此时速度会更低;
- 如果将一个时间段取极限无限的减小,那么电机就是时而供电时而没电,此时便会减速。如下图所示:
而在Arduino实现这个并不是很难,只需要调用analogWrite方法对L298N的使能端进行PWM调制即可。其中,analogWrite方法接收一个参数,参数的取值范围是[0, 255],取值越大,输出电压越大,电机转速越快。代码如下:
1 | // 定义两个电机驱动的使能端 |
需要注意的是:电机的实际转速不仅和参数speed有关,还和供电的电压有关。即使speed的取值为255,但电池没电了,电机还是会转的很慢。
电机转动
在能够对电机的转速进行调节后,下一步就是实现电机的转动了:
- 四个电机都向前转,那么车辆会向前行进;
- 四个电机都向后转,那么车辆会向后行进;
- 左侧的电机向前转,右侧的电机向后转,那么车辆会向右行进;
- 左侧的电机向后转,右侧的电机向前转,那么车辆会向左行进;
仅需要digitalWrite方法对电机两侧输入不同的电平即可完成电机的转动,因此代码如下:
1 | // 右前轮 ----------------------------------------- |
当然,电平高低的输出需要根据实际的接线情况来判断。
供电系统
全部系统的供电系统分为两部分,一个是给Arduino供电,一个是给L298N电机供电。
对于给Arduino供电,我选择了使用电源接口为Arduino供电。通过此方法为Arduino开发板供电时,直流电源电压为9V ~ 12V,买一个9V电池和转接线即可。使用低于9V的电源电压可能导致Arduino工作不稳定,使用高于12V电源电压存在着毁坏Arduino开发板的风险。
对于给L298N供电,选择的是3.7V 18650可充电锂电池,在配一个电池盒即可。电池盒要求是串联的,而不是并联,否则电压不够。将电池盒自带的红色线与L298N的+12V连接,将黑色线与L298N的GND连接即可完成电机部分的供电。
结语
接线并不是很复杂,我都是用的杜邦线接起来的,大胆的去尝试就好了。有问题也欢迎在下方留言,毕竟计算机搞这些可能也是一头雾水,上文都是我一点点摸索出来的经验。