
CW32多玩法平衡车
简介
此平衡车是使用了CW32F030C8T6为主控,主频为64MHZ,在基础的平衡功能上扩展而来有四种玩法:包括蓝牙,语音,避障,跟随。
简介:此平衡车是使用了CW32F030C8T6为主控,主频为64MHZ,在基础的平衡功能上扩展而来有四种玩法:包括蓝牙,语音,避障,跟随。开源协议
:CC BY-NC-SA 4.0
(未经作者授权,禁止转载)描述
多玩法平衡车——基于传统的平衡车之上扩展而来
此车是在基础的平衡功能之上加了许多玩法如蓝牙控制,语音控制,避障控制,跟随控制;集成在一起最终体现出有4种模式:蓝牙模式,语音模式,避障模式和跟随模式。

一、想法起源
在各大视频平台经常刷到双轮的平衡车觉得特别有意思,想着我自己也得做一个属于我的平衡车,但我所想的平衡车不能与他人一样只有平衡功能还想再加上一些更有意思的功能;于是还是继续网上冲浪多看看有哪些有意思的功能适合加在我这个平衡车上,于是在看到许多小车视频后最终确定就加上蓝牙控制,语音控制,避障控制,跟随控制就行了吧;随即分别实现上述功能后,在集合到一起,接下来就是不断调试,经常烧,烧了换,换了烧,最终不断改进终于是成功了,至此现记录下那段难忘的时光。
Ⅰ、语音控制:1.多玩法平衡车语音模式演示_哔哩哔哩_bilibili
Ⅱ、蓝牙控制:2.多玩法平衡车蓝牙模式演示_哔哩哔哩_bilibili
Ⅲ、避障控制:3.多玩法平衡车避障模式演示_哔哩哔哩_bilibili
Ⅳ、跟随控制:4.多玩法平衡车跟随模式演示_哔哩哔哩_bilibili (跟随声源)
二、思路路线
每做一个东西都应该熟悉做这个东西时应该怎么去做,分哪些步骤,有哪些需要注意的;明确这些步骤后才能合理的分配自己的精力去完善每一步。
对此项目我的思路具体分为六步:
Ⅰ、模块移植
1.CW32F030的MCU运用:熟练运用CW32F030C8T6的GPIO,USART,IIC,TIM(后面用的最多)等外设,及其所有的函数API,是后面所有步骤的基础;可以在B站”CW32生态社区“官号进行学习。
2.OLED屏幕驱动:此屏幕驱动芯片为SSD1306,显存大小为128*64bit,0.96寸OLED像素个数就是128*64个,对应的就是每一个位对应每一个像素点;想要在OLED上显示什么数据,使用发送命令函数对一些相应的寄存器进行设置后,再使用发送数据函数就对显存进行操作就行。
3.MPU6050陀螺仪驱动:此传感器需要使用IIC读取数据的函数,与OLED类似,都需要使用发送命令函数对一些相应的寄存器进行设置,使能陀螺仪后再调用数据读取函数就可以读取陀螺仪的原数据(包括三轴的加速度与角速度);想要用在平衡车上需要再对此原数据进行姿态解算才能得到三轴对地的角度,数据处理方法包括“一阶互补过滤+卡尔曼滤波”,“驱动MPU内部的DMP模块直接获取对地角度”此数据才是我们最终要用的。
4.超声波模块驱动:HC-SR04模块是非常常见的超声波测距模块,使用GPIO外设和中断就行,通过IO引脚给个高电平信号发射超声波同时开启中断,定时器,接收到了之后进入中断获取计时数,配合声速是大概340m/s就能计算出距离,凭此写入软件逻辑中。
5.蜂鸣器模块驱动:每款蜂鸣器的驱动都是由一定频率的信号放大输出到蜂鸣器的正极的,信号的占空比决定了声音的响度;常见的一款蜂鸣器频率是2700HZ,只需要使用定时器外设,设置好预分频系数与重装载值就行,根据使能与失能或调节占空比控制响度嵌入到软件逻辑中。
6.红外传感器使用:红外传感器就两个值1和0,初始化IO口,适时读取值就行。
Ⅱ、功能模块学习
1.语音模块选型及其编程方法:使用的语音模块是ASRPRO,存储达4M,自定义词条可达300个;编程环境是天问block,支持图形化编程;后面详解。
2.蓝牙模块使用及其适配软件:使用的蓝牙模块是BT04-E,支持BLE,SPP;传输稳定,距离远,且官方有适配的软件,特别是其中的智能小车组件。
3.思考避障模块在程序中的逻辑嵌入:前面已经驱动过了这里就是完善下测距的逻辑,与红外的配合。
4.麦克风阵列的驱动与使用:使用的是6+1麦克风阵列,通讯协议是IIS(音频专用),驱动的主控是Maix bit使用的是MicroPython函数库;后面详解。
Ⅲ、硬件设计
1.绘制功能模块的外围电路:在实现上述所有功能后,对每个功能需要用到什么类型的引脚,每个引脚需要复用成什么功能掌握的应该都非常清楚了,于是自然而然地在绘制完最小系统后,将每个模块的基本电路画出来后,使用短接符将它们之间的共同引脚连接在一起,或直接使用相同名字,这样网络标识符相同在PCB中也是连接在一起的;
2.需要注意的是:在绘制模块的外围电路时,要注意保持通讯的电平都是一致的3.3V,有些模块既可以5V供电也可以3.3V供电,而且模块自带的电路没有5V转3.3V就有可能烧毁MCU,所以切记一定统一使用3.3V供电。
Ⅳ、程序联调
1.统一框架:设立一个思路层层将上述的功能模块并列的写入到程序框架中,通过什么模块开启和关闭每一种功能。
Ⅴ、完善机械结构
1.将项目做的更完善些:重新拆开优化结构使两轮子轴心一致,高度尽可能小降低重心,定制个亚克力外壳,将外露的导线理顺更加的美观。
Ⅵ、调整参数与PID
1.调PID:在上一步通过完善机械结构确定好重心后,就可以调整PID参数使平衡车达到理想的平衡效果。
2.调速度等参数:调整平衡车在各个模式下的前进速度,后退速度,转弯角度等。
三、具体步骤及其内容
Ⅰ、模块移植
1.CW32F030的MCU运用:此一步骤没有太多好讲的,涉及到自身个人毅力,学习时间的长短等不可控因素;需自身去学习,但其实在此项目中没用多少外设,能熟练运用GPIO,EXTI,USART,SPI就够了(IIC是模拟的);如果没有基础的话最好集中学习。
2.OLED屏幕驱动:
前面说了此屏幕想让它显示我们要显示的数据,需通过IIC协议向其发送命令设置好寄存器,再通过发送数据对OLED的显存进行操作也就是让相应的像素点点亮就行了;
下面来详解一下如何从0到显示一个’1‘出来:
我们所使用的是模拟IIC,意思就是使用GPIO,通过置1置0来模拟IIC中的高低电平,通过改变置1置0的延时时间从而改变IIC的速率;
如图1:

图1这个结构描述了IIC通讯时的基本结构,包含起始位,8位数据,应答位,结束位;此结构也是IIC发送一个8位数据时需要遵循的结构,这也是IIC的特性;我们需要的是使用我们的GPIO通过置1置0以及延时来模拟此IIC的结构,也就是起始位,8位数据,应答位,结束位。
图2:

如图2想要使用我们的GPIO通过置1置0以及延时来模拟此IIC的结构,那么就要了解起始位,8位数据,应答位,结束位的具体结构;可以看到上述协议帧从左往右:START是起始位,想使用GPIO模拟此时序只需让模拟的SDA,SCL全置1然后让SDA置0,SCL暂不用管,延时(或不用延时)一会,再将SCL置0就行了,随后这么一写,封装成一个函数那不就成了吗:

结束位也是一样只需让模拟的SDA,SCL全置0然后让SCL置1,SDA暂不用管,延时(或不用延时)一会,再将SDA置1就行了:

应答信号最为简单,因为不涉及到读取数据所以不需要向对方表明我方有没有读取到数据:

写一个字节就复杂一点点,需要循环8个SCL与SDA,每一个循环都表达一位的数据,也就是向外输出8位,发送一个字节数据:

上述函数一个一个封装起来就相当于是模拟出了起始位,8位数据,应答位,结束位,分别按顺序调用这些个函数就是完整的IIC协议了;要注意的是OLED_SDA_OUT();上述函数中此函数是相当于将IO口配置为推挽输出的,在当前环境下,此函数只需要配置一次就行,因为在需要读取数据时才需要将IO口配置为输入模式。
图3:

如图3在我们模拟出了起始位,8位数据,应答位,结束位后,分别按顺序调用这些个函数就是完整的IIC协议,上述就是两个实例,上面将起始位,8位数据,应答位,结束位按一个顺序分别排列,其中发送的数据0X78,0X00,0X40分别代表OLED的地址,即将写入命令,即将写入数据三种意思;这些数据已经不属于IIC协议的范畴了,不同但符合IIC协议的设备这几个值是不一样的;通过上面的函数写入命令,下面的函数写入数据,OLED就能正常接收到我们发送过去的数据了。
图4:

如图4:上面我们说过使用发送命令函数对一些相应的寄存器进行设置后,再使用发送数据函数就对显存进行操作就行,在我们使用GPIO模拟出了起始位,8位数据,应答位,结束位后,也封装出了发送命令函数和发送数据函数;现在使用发送命令的函数向OLED的寄存器进行一些设置,具体要设置啥得自己翻译去,网上找找肯定也有中文注释,大概就是设置一些像范围,是否反向显示等等;进行完这一步后,就来到了最终的发送数据来显示我们想要的’1‘了。
图5:

如图5这个函数是把我们想要显示的字符与我们向括号填入的字符联系起来的函数,因为假设我们填入’1‘这个字符进去,OLED是不认识的,我们需要给OLED提供一个字库,F8X16[c*16+i]就描述的是8*16像素点大小的字库,里面描述了0-9分别应该怎么显示,字库包含的数据与我们要显示的数据是一 一对应的,字库就是OLED的语言,’1‘属于我们人类的语言。
图6:

就像这个0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,这是OLED认识的’1‘,我们将此6个数据发往OLED那么OLED就会在屏幕上显示为’1‘,中间涉及到一个取模的过程;仔细看看可以看出将此6个字节表达的数据按顺序写成2进制,2进制里所有的’1‘连在一起其实就可以看出里面的数据表达的就是我们人所认识的向右倒地的’1‘。
至此如何从0到显示一个’1‘出来结束。
3.MPU6050陀螺仪驱动:
陀螺仪的IIC驱动与OLED差不多,起始位,8位数据,应答位,结束位都是共用的,区别在于(1)多了一个读取数据的函数,(2)需要等待应答信号,(3)需要发送应答或不应答信号,(4)以及上述讲的陀螺仪的地址,写入命令与写入数据的差别。
图7:

如图7此函数描述了如何从SDA引脚读取8位数据,与IIC的发送8为数据类似,都是需要循环8次;区别在(1)需要提前MPU_SDA_IN();也就是将SDA引脚设置为输入,(2)需要定义一个8位局部变量每读一位数据向左偏移一位以存储起来,循环8次正好储存一整字节,(3)在接收完一个字节后,不论是不是接收到了正确的数据,一定得发送是否应答的信号。
图8.1,8.2,8.3



第一张图是上面所说的描述了需要等待对方是否应答,因为在此种通讯模式下需要反复确认对方是不是在线,有没有正确接收到发过去的数据;第二张与第三张描述了发送应答信号或是不应答信号,应答对方设备就会认为你是正常的会继续发数据,不应答直接结束通讯。
到此之上都是属于IIC的协议层接下来就是设备独有的了。
图9:


图9此两个函数是融入了MPU6050的特性的,从这里就可以看出MPU与OLED使用IIC的不同,OLED发送8位数据0X78,0X00,0X40分别代表OLED的地址,即将写入命令,即将写入数据三种意思;MPU则是((MPU_ADDR<<1)|0),((MPU_ADDR<<1)|1)分别代表写命令和读数据,两者使用IIC的区别一目了然且都完美符合IIC协议;在进行完上面的操作后,就是对设备的相应寄存器进行设置,设置好后就可以读数据了。
图10:

如图10此函数是最终使用IIC的最关键一步,对相应的寄存器进行设置,上面有中文注释是最好的了,看看中文注释大概也能明白每个及寄存器都是怎么设置的;在调用完此函数之后:
图11:


如图11调用此两个函数传入6个指针就能得到三轴的角速度与加速度了,使用变量保存下来这就是原始值了,就可以用这原始值再做处理得到三轴对地角度(使用一阶互补过滤+卡尔曼滤波)去用;或者是我下面要介绍的方法(使用内部DMP库):
1.首先要获取DMP库,这个库比较常见,也可以在我这个工程中复制过去:
添加里面的两个的源文件到工程中,再指定头文件路径到此文件夹;
2.分别点开两个源文件可以看到一些毫秒延时,这部分可能需要你用你定义的毫秒延时函数替换,这是DMP库需要用到的;
3.在定义好了上述所有的读一个字节和写一个字节后,还需要自己去实现两个函数:
uint8_t MPU_Write_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf);
uint8_t MPU_Read_Len(uint8_t addr,uint8_t reg,uint8_t len,uint8_t *buf);这两个函数就是连续写连续读,是DMP库需要用到的,最好将一下几个文件全都移植过去,不然极易出错:

最后全部函数定义好后,调用uint8_t mpu_dmp_get_data(float *pitch,float *roll,float *yaw)函数就可以直接得到三轴对地的角度了,就可以直接使用了。
4.超声波模块驱动:以下的模块就都比较简单了,使用GPIO与TIM就行:

从上面的时序图就可以看到超声波模块是怎么使用的了:
1.初始化发射与接收引脚,初始化定时器,并在初始化时让发射引脚置0;
2.将发射引脚置1延时15us在置0,触发模块内部循环发出超声波脉冲;
3.将接收中断开启,触发方式为上伸沿和下降沿,在中断触发时检测为高电平打开定时器开始计数;
4.当中断再次被触发时检测电平为低时关闭定时器,保留计数,清除计数值;
5.根据设置的重装载值和预分频值求出每一次的时间乘上计数值就是声音在模块与障碍物运动的时间,声速340m/s求出距离。
5.蜂鸣器模块驱动:
常见的蜂鸣器频率为2700HZ,有不同的可问问卖家或数据手册;
1.初始化TIM,使 主频/(预分频系数*自动重装载值) 大概等于2700就行了;
2.设置蜂鸣器占空比,使能定时器就可以响了,改变占空比,就可以改变响度。
6.红外传感器使用:
初始化IO口,开启下降沿中断就行,触发中断后就在中断里处理就行。
Ⅱ、功能模块学习
1.语音模块选型及其编程方法:
选型的话选择了一款常见的可编程语音模块ASRPRO,32位的MCU,RISC内核架构,外围电路只需要加上麦克风和喇叭;
(1)编译环境:直接搜索天问Block下载就行

(2)选择主板,检查串口连接:通过ASRPRO的串口0下载程序,PB5是TX,PB6是RX

(3)界面说明:

(4)打开范例程序,设置编译下载模式:

(5)编译下载范例程序,随后下载成功后按照需要的修改修改随后重新生成模型下载即可:


2.蓝牙模块使用及其适配软件:
使用的蓝牙模块是BT04-E,支持BLE,SPP;传输稳定,距离远,且官方有适配的软件,使用串口通讯就行
其中的智能小车组件刚好可以用:

只需要使用USB转TTL连接上此蓝牙的串口,默认蓝牙串口波特率为9600,通过点击上述的按钮在电脑上打印出来就知道每个按钮对应什么数值了,使用这些数值,配合switch语句点击不同按钮,执行不同的小车向前向后语句,就能轻松使用了。
3.思考避障模块在程序中的逻辑嵌入:
此逻辑在程序中才能体现,后续在程序加上就行。
4.麦克风阵列的驱动与使用:
在此项目中需要的功能是检测声源的方位,驱动主控Maix bit是基于嘉楠堪智科技的边缘智能计算芯片K210(RISC-V架构 64位双核)设计的一款AIOT开发板;
配合6+1麦克风阵列就能检测到6个方向的声源大小,具体步骤:
1.配置开发环境:
(2).MaixPy IDE 安装与使用 - Sipeed Wiki
2.对声源定位例程略微修改下,给即将发出的数据限定一个最小值:

3.使用下载软件uPyLoader将固件中的main.py替换成我们所写的main.py(由声源定位改名而来),就可以使开机直接执行我们所修改的程序。

Ⅲ、硬件设计
硬件设计没有太多好讲的,没有涉及到多少模电数电的多少知识,这里挑选一些注意点讲讲:

此图画的有些随意,但这么画主要就是想看起来功耗分配的清晰,有哪些模块,每个模块都想在不用时使用PMOS与NMOS的结构来断电实现无功耗;
1.12V转5V按照数据手册来画原理图就行,标准的12转5V,但是手册描述的0-15V时电感大小为33uH,0-30V时电感为47uH,于是将电感改成了47uH。
2.USB转串口主要是为了调试语音模块,蓝牙模块,声源定位留的,后面有6路开关分别就是选择这3对功能了。
3.MPU6050电路下的语音+声源定位转接由6P的XH2.54的接口接到扩展板上。
4.然后就是蓝牙模块电路,WS2812,避障及警示电路三种电路都有共同PMOS+NMOS结构,PMOS通常用于上管控制,当时想的就是想要在运行其中一种模式时,其它的模式通过MOS管直接断电实现0功耗,每个MOS管都并联了个小开关也是调试用;
CW32的每个IO引脚内部结构都由保护电路,由上下两个同方向的二极管钳位外部的电压不得大于3.7V左右,不得小于-0.3V左右;
所以想控制5V输入给电路,就是用了这种结构,每个电路都使用了单独的5V转3.3V保证各个电路的3.3V不会互相打扰。
Ⅳ、程序联调
1.确定一个思路将所有功能组织在一个大循环里就行:由于之前我们设置好了MPU6050的寄存器,每10ms会进一次中断,我们借此使整个大循环10MS执行一次,实现这种操作只需要:

设立一个触发标志位,在大循环中判断标志位执行程序即可,由于标志位是每10ms会被置位,主循环执行一遍又是小于10ms的,所以主循环每一个10ms都会被执行一次。
对应的main函数里
这么执行就行。
2.先由三个串口接收函数来确定小车此时的模式,由于使用接收标志位来判断是否有新数据所以标志位就不会被随意误刷新:

3.通过语音模块的接收数据来确定此时模式,并且在另一种模式没有来之前,是不会被改变的。

4.蓝牙模式:

5.跟随模式:先对接收到的5次声源数据进行采集,并进行排序滤波,以此确认真正的声源方向,然后根据声源偏离方向的不同,给左右两个轮子的前进力度都不同:

6.避障模式:可以通过代码看出在测出距离后根据距离的不同控制不一样的速度:

7.语音模式:融合一些时间和速度达到转到相应的角度,代码看一下就知道了,j每加1就相当于以当前的力度执行了10ms,于是以相同力度执行不同时间就可以造成转至不同角度了:

Ⅴ、完善机械结构
重新拆开优化结构使两轮子轴心一致,高度尽可能小降低重心,定制个亚克力外壳,将外露的导线理顺更加的美观。

Ⅵ、调整参数与PID
1.调PID:
四个参数:

(1)全部归零
(2)直立环慢慢增大Kp直至小车低频高幅震荡
(3)直立环慢慢增大Kd直至小车高频低幅震荡
(4)统一乘以0.6-0.8作为最终参数
(5)速度环Kp与Ki之间的大小关系是200倍,Kp可以从0.1慢慢加0.1看看效果,若加速倒下将两系数都加上负号即可,直至理想效果。
2.调速度等参数:
调整上面所说的,如蓝牙模式下的前进后退速度,语音模式下的转弯力度,避障模式下的变速程度等等。
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程工程成员
知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。


评论