自己与小车可谓有很“深”的渊源了,从小时候玩的四驱车,遥控车,再到大学的调的“循迹小车”,与小车有着不解之缘。因此在之前就萌生了想做一个自己的“智能小车”的念头,但是奈何自己太菜,对单片机软件部分学习的知识很薄弱,虽然能写一些简单的程序,但都是“依托答辩”,所以徒有想法没有实力,就一直搁到现在了,刚好立创开发板开了这个智能小车的训练营(看着很酷,且讲的很受用),跟着学习单片机基础知识的同时,也可以做一辆属于自己的智能小车,这也是做这辆小车的初衷。小车源自训练营,但是要使其成为自己的希望做的智能小车,就需要融入自己的想法,在能做出小车的同时,学习到单片机知识。接下来简单分析一下使用这些模块或者元器件的缘由。
由于这段时间有《专业综合实验》,所以Si24r1和esp01模块还没来得及调,后面就先不介绍这两个,后续做出来了再发。
小车整体,由于想做一个稍微大点的小车,考虑到电路板的电路性能,可以将模块分别放到各个电路板上,节省主板空间,于是选择了用pcb拼出小车整体框架。
小车正面视图
小车左侧视图
小车主板正反面:连接立创开发版,同时大部分功能集中在此板上
小车前面板:连接主板,放屏幕和ws2812彩灯,esp01模块,及连接下底板的超声波模块和前车灯
小车下底板:固定主板,固定电机,并作为小车主体框架;放前车灯和超声波模块
下底板连接板:下底板孔间隙是互相配合的,不需要连接板也可以重叠配合,用螺丝连接,但为了美观性和前后下底板高度一致,便画了这块板
下底板和下底板连接板配合图
关于装配问题:
下底板除了标注部分,不需要处理和焊接
下底板装配好大致是这个样子
主板焊接好后,装配好是这个样子
前面板可以焊的地方都需要焊
其中大部分元器件都能在立创商城上购买,如电阻电容,以及梁山派开发板
梁山派购买链接
另外一部分则需要去某宝购买,购买清单如下
注:原本pcb上画了Tp5100 8.4V电池充电部分(参照技小新),貌似这个芯片有点问题,我也没调出来,就不做介绍了,也不用焊这部分电路。
以下为具体介绍
综合价格和车身大小,及和130减速电机对比后,最后选定用N20作为小车电机。由于N20电机和轮子买了两回,所以觉得买好电机很重要,要么买转速低扭矩大的,要么买转速和扭矩都不错的(理论上转速和扭矩是相反的,转速高扭矩小,但是后面第二次买回来的电机转速和扭矩都很不错,可能是电机动力比较足)。千万不要买转速高扭矩很低的,不然可能就会导致前进和后退没问题,但是不能转弯,这一点是亲身体验过了,而且换轮子也解决不了。这个是第二次买的店N20电机购买链接,虽然是拆机的,但是动力嘎嘎猛。
和电机相比,轮子倒没那么重要,随便哪个店购买都可以。目前我知道的和N20电机配对的有三款轮子,如下图所示分别为:一款直径34mm的薄款轮子,一款直径43mm的厚款轮子,一款直径58mm直径的麦克纳姆轮,相较而言,前两款更便宜,第三款可玩性更多一些。前两款在淘宝上很好找,就不放链接了,随便买都可以;配套N20的麦克纳姆轮比较少,为了方便大家购买,给大家放个链接麦克纳姆轮购买链接
为了方便固定和拆装N20电机,就需要一款电机座,当然也可以永久固定,直接用胶水(虽然可以,但不建议)。由于这个也是淘宝一搜一堆,踩坑的点少,所以没推荐的,不过为了方便大家购买或者参考,也放一个链接N20电机座
采用的模块为Hc05l蓝牙模块,这个没什么限制,随意购买,放个链接供大家参考蓝牙购买链接
这个不是必选项,这个也是和蓝牙一样作为信号接收,控制小车;但是这个模块的遥控距离会远一些,和Nrf2401差不多,而Si24r1是国产的。可以和另一个相同的Si24r1模块配合(手柄遥控部分已画好,由于时间有限,还未调出来,调出来会发后续),由于这个模块不同的店引脚连接不同,所以放个参考链接,如果去别的店买,引脚需要和这个一致。Si24r1参考购买链接
下图是已画的手柄(参考技小新),还在等芯片中.....
用屏幕可以显示电量,小车状态,以及模式。这个屏幕也是随便买,需要注意的是这个是I2C接口,别买成SPI屏就行。屏幕购买参考链接
由于esp01模块,mpu6050等模块购买基本没什么需要注意的,因此就不一 一介绍,下面附上参考链接(仅供参考)
超声波模块:超声波购买参考链接
esp01模块:esp01购买参考链接
mpu6050:mpu6050购买参考链接
M3*6螺丝:M3*6螺丝购买参考链接
M3*26铜柱:M3*26铜柱购买参考链接
RZ7899: RZ7899电机驱动购买参考链接
电池和充电器有很多就不放参考链接了。
主体电路连接,与开发板连接。由于引脚分布太多,在后面会列出具体的引脚连接表
由于单片机不能直接驱动电机,因此需要电机驱动芯片来驱动电机。电机驱动芯片有很多可选项,如RZ7899,TB6612,L298N等等,综合其价格,性价比和体积等因素,最终选择了RZ7899芯片。该芯片可用于驱动普通直流电机和步进电机。电路和程序都比较简单,外围电路简单,元器件少,并且只需要单片机控制两个引脚高低电平的变化,可以实现电机的正转、反转和制动。输入电源电压:3V~25V;最大驱动电流:3A,能满足很多小电机的使用。下面是电路图。其中在BI、FI处接下拉电阻的目的是为了防止主控上电时的干扰电平导致电机转动,BO、FO处并联的电容是为了消除电机转动产生的火花和高频噪声。
拥有一个会放歌的蜂鸣器可是一件很酷的事,小车自然也不能缺少这个“喇叭”;蜂鸣器有两种电路,一种是官方案例的接PNP电路的蜂鸣器,据群友反映上电莫名会发出声音,再加上我一直使用的是NPN电路的蜂鸣器,所以就没有采用那种方案,下图是NPN连接的蜂鸣器电路。只需要控制mos开关的频率即可获得不同的声音(在小车程序里只写了一个频率,所以只有一个音,对蜂鸣器“”放音乐”感兴趣的可以找我要资料)
要想小车电池的使用寿命更长,就需要注意电池的电压大小,不能等电池没电了再充电。因此需要设计一个电压采集电路,再把电量信息显示到屏幕上,方便自己留意到电池电量的多少作出相应的调整。采集电路比较简单,只需要三个电阻分压即可,分压后的最大电压刚好在单片机的测量范围之内 。之所以不能直接用单片机引脚测电池电压的原因是因为单片机的引脚测量电压不能超过3.3V,否则可能会烧坏单片机。
只需要将按键的一端接单片机引脚,一端接地即可,单片机引脚内部上拉,当按键按下,单片机就可以检测到引脚电平的变化。
由于蓝牙与单片机的交流方式是串口通信,因此串口这两根线是需要连接的;其次是电源,它的供电电压是3.3V-6V,这里供电给5V(之前调试的时候由于供电给的3.3V,导致调了半天都调不出来,后面才发现踩了电压的坑)
加这个模块的原因是因为,之前调车的时候都会遇到小车因为两边车速不同(给的相同的PWM值)和其他原因导致小车无法走直线,甚至直接“弯道超车”,偏斜很严重,在学习了一些资料后发现可以利用mpu6050的偏航角来纠正小车的偏斜,结合PID算法可以达到一个不错的效果。这个模块的电路也比较简单,只需要连接4根线,I2C通信。
LED负极接地,正极接单片机引脚,当单片机给LED引脚高电平时,LED灯亮,反之则灭。
由于ws2812为单线数据传输,因此只需要一根信号线传输即可,5V/3.3V供电皆可
和mpu6050一样,也是I2C通信方式
注:在这次项目的前期,自己学习了一下梁山派开发板的基础知识,觉得自己“又行了”(个人觉得里面的知识讲的很基础,也很实用),所以就准备自己先“搓”一份代码,如果搓不出来,就用官方的代码。幸好搓的代码能用,但由于是自己搓的,大部分框架自己做的,可能没有官方那么规范。(仅供大家参考)
引脚分配(目前所用到的)
要让小车动起来,首先要把驱动芯片的代码搓出来,废话不多说,直接上代码(小车电机驱动的代码放在了motor文件夹里)
个人理解:.c用来写具体函数,.h用来放一些定义,和函数的声明等,基本上每用一个外设,相关的库函数都要这么写,一是规范,而是方便引用
对单片机引脚的使用,都需要首先进行初始化,驱动电机也不例外。首先在moto.c里是对引脚的初始化,由于后面会用到pwm输出,因此初始化的时候进行了模式复用。
然后再对引脚对应的pwm通道初始化,为了方便理解和引用,写在了另外一个函数bsp_pwm.c里,里面有对两个定时器不同通道的配置
然后配置每个轮正反转,刹车,熄火功能
再将前面的函数嵌套封装起来,在主函数里面使用就会更简单,引用函数,括号里给一定的数值,小车就可以转动了
在这个软件里可以对蓝牙模块进行配置,主要是主从模式,模块名字,以及波特率,如果蓝牙模块设置的波特率所连单片机的波特率不匹配,就无法进行通信,因此对其配置也很重要;需要将其设为从模式,波特率为9600。在连接电脑之前,先将蓝牙模块与ch340连接,在蓝牙模块中有一个小按键,将HC-05与CH340连接后长按着按钮给模块上电,led灯快闪。
然后再在软件里点击搜索,连接好后,按如下配置
按以上的配置即可,不理解的可以看一下下面这篇文章蓝牙模块配置
下面是程序部分,这部分程序放在了bsp_usart.c里面了,首先是串口引脚配置
然后是数据串口接收
然后就可以在主函数中使用了
下面是使用的蓝牙app软件界面(会放在下面的附件中,需要的可自行下载)
这个模块根据李工的模块移植手册里面的代码是很好移植的,不得不说,那个手册YYDS,有很多模块可以使用。在里面也有dmp库,但是刚上电不知道为什么航向角会发生零漂,而其他两个角不会,但跑直线就需要保证航向角不能出现问题。查了很多资料也不知道怎么解决,在要放弃的时候发现航向角在零漂一定数据后就会稳定在一个数值,后面就比较稳定了。因此等航向角数据稳定后再启动直线行驶程序。
移植的时候最重要的是注意引脚要连正确,否则就用不了
引脚初始化
在主程序里对dmp库初始化
之后就可以在主函数中使用了
由于通过上面得出的航向角会产生零漂,无法直接使用,需要将数据处理一下。经过多组数据分析得出,航向角在上电之后会有一段时间出现零漂,然后稳定在一个值上下零点几左右,而零漂时间不定。所以得出了下面的处理方法,先将得到的航向角转化为整数(因为不转化得到的值是浮点数,用下面的处理方法,很难满足if的条件),再由标志位决定小车是初始化,还是启动。当标志位为零时,就一直进入判断循环,如果第二次减第一次的航向角为零,则说明航向角数据稳定了,此时把目标航向角(小车直线行驶参考角度)改为稳定后的航向角,标志位置1,跳出循环,执行小车直线行驶函数。
小车直线行驶精髓,pid算法,要是小车调整角度时比较快速且稳定,就需要使用pid算法。给左边轮子一个稳定的速度向前行驶,右边的轮子给pid处理过的速度行驶;若小车不发生角度偏移,则pid不会产生效果,即两边的给的速度是一样的,若小车往右偏移,说明左边轮速度比右边快,此时pid算法的处理方式是根据偏差大小按比例增加右边轮的速度,这也就是Kp的作用,Ki是积分系数,主要是是小车行驶更平稳,而Kd的作用则是限幅,避免小车突然增加太多发生震荡(当然Kd大了也会产生震荡),err是偏差,即目标值-实际值,E是对偏差积分,D是用上一次偏差减去此次偏差。
其原理就是根据对测量后的距离,让小车进行前进、后退、停止等操作,也需要使用pid,原理和上面的差不多,需要注意的是,不同小车,不同电压使用相同的pid后效果可能有差异,因此要使其很稳定,可能需要自己微调一些数据。
引脚,定时器初始化
测距原理:通过对超声波发出时间和收到的超声波的时间计算
超声波跟随原理,当小车离目标距离很近的时候,小车后退,当小车距离目标距离很远的时候,小车前进,融合pid算法使小车更稳,此处pid原理和上面直线行驶的pid原理相同。
oled函数有点多,只要能看懂其大致原理,会用就行,首先是对引脚初始化,程序里给了两种I2C输出方式,如果屏幕接的引脚不是单片机的硬件I2C引脚,就需要使用软件I2C,在oled.h里面把宏定义的USE_SOFTWARE 的0该成1即可;如果连接的是单片机的硬件I2C引脚,则两种都可以使用,下图用的是硬件I2C的函数。
下面这些函数只要看懂就会用,而且李工也很贴心,每个函数都有注解,使用方式,方便移植和使用。
清屏函数
字符显示函数
蜂鸣器有有源和无源两种,有源蜂鸣器不要调频率,给个电压就能用(跟点灯一样),所以这里就不过多叙述了;主要讲一下无源蜂鸣器的使用方法,由于无源蜂鸣器直接给电压,它不会响,需要给一定的频率才能响。当然这样使用起来就会麻烦一些,但是也有优点,这样配置,意味着蜂鸣器的音调可调,就可以有其他的玩法,比如放歌,不过这里小车只需要一个音就行了。
还是老规矩,先初始化引脚,开启定时器时钟
下面就是配置定时器和pwm,这个函数可以直接使用,与前面小车pwm配置有一点点区别,小车电机的频率不用改,所以这个函数就只拿来配置一个频率;而在这里的使用是通过改变脉冲值和周期间接改变其频率可以发出不同的音调。
为了把这个弄出来也花了一些时间,本来是参考官方给资料,但是不同的地方写法都有差异,所以就跟着视频敲了代码,一开始用不了,测的值一直在1300左右,后面很玄学又可以用了(可能是没配置好),又去CSDN上找了电压的计算公式,得到了所测的电压。
引脚初始化,ADC采样配置
ADC电压采样:所用的单片机测量电压范围是3.3V(不能超出),采样测出的值从0到4095,而单片机的内部参考电压是3.3V,通俗的讲就是采样值0-4095,对应的就是电压的0-3.3V;因此用采样值除4095就得到了采样值所占4095的百分比,再乘以参考电压就得到了测量的电压。后面那个powervalue是计算电压百分比,方便屏幕显示和查看,不用再去计算还有多少电压没电。理论上根据电阻分压后测到的最大的电压为2.8V(即8.4/3),电池最低使用电压为1.87(5.6/3),根据这两个数据可计算得到电池电压百分比。0.93=2.8-1.83,测到的电池电压合理变动范围,vdd-1.87为所占0.93(电压合理变动范围)的百分比。
再利用定时器6,每5秒更新显示一次电压百分比
按键检测有两种方式,这里也采用了两种方式:外部中断和轮询,由于切换模式需要的优先级更高,同时减少cpu的计算,因此切换模式的按键采用外部中断的方式,而小车的开启和停止按键仅在超声波跟随模式里面,因此需要的优先级低些,且只有进入超声波模式才会执行这个轮询函数,可以有效的避免在其他模式时因为误触启动按键导致小车跑起来。
按键引脚,外部中断初始化
通过外部中断检测按键按下,按下之后切换小车模式
通过轮询方式检测按键按下,按键按下后,可以检测到引脚电压变化。如果在超声波模式中即可由按键改变小车运动状态(启动/停止)
这个灯用起来比较简单,也很好理解只需要理解颜色发送函数,以及更改颜色的方式
首先是引脚初始化,这个数据传输方式对引脚没有特殊要求。
然后是看懂这个函数,有两个参数,第一个参数是灯的位置,如果控制是第一个灯,那这里的参数就填0,如果是第二个就填1,以此类推;第二个参数是灯的颜色,rgb格式每8位控制一个颜色,如0xff0000是红色,0x00ff00是绿色,0x0000ff是蓝色,可以直接去网上找自己喜欢的颜色试试(只需要改0x后面的数据)。
下面是使用案例
定义一个放颜色的数组
对第一个灯每0.1秒换一种颜色
注:由于上传文件大小有限,下面演示视频中,时长最长的那个视频文件被压缩了很多,画质看着有点差,高清的演示视频放B站了智能小车演示
!注意:请使用浏览器自带下载,迅雷等下载软件可能无法下载到有效资源。
欢迎加入EEWorld参考设计群,也许能碰到搞同一个设计的小伙伴,群聊设计经验和难点。 入群方式:微信搜索“helloeeworld”或者扫描二维码,备注:参考设计,即可被拉入群。 另外,如您在下载此设计遇到问题,也可以微信添加“helloeeworld”及时沟通。
EEWorld Datasheet 技术支持