基于树莓派摄像头的双轮循迹平衡车设计
2019-01-17,,,,
,,,,
(中南民族大学 计算机科学学院,武汉 430074)
引 言
本文所设计的控制系统主要包括平衡与运动控制系统、位置获取与分析系统两个子系统。平衡与运动控制系统以STM32F103单片机为核心处理器,通过姿态传感器MPU6050监测车身所处的俯仰状态和状态变化率,经过PID算法调节,保证小车在按照指令前行的情况下保持平衡;树莓派和摄像头组合充当平衡车的眼睛以获取位置信息。该设计旨在实现双轮小车在直立平衡的状态下,根据树莓派传回的不同数据沿着黑色赛道行驶,以实现自主循迹的功能。在自主循迹的前提下亦可发展无人传输物品,以减少人力的使用。通过对该系统的介绍,重点讲述小车循迹控制算法的实现。
1 双轮平衡车国内外研究现状
1986年,日本电通大学的山滕一雄(Kazuo Yamafuji)教授提出基于倒立摆模型设计自平衡模型的概念,并设计制造了一个两轮共轴、重心在上的自平衡模型。
近十几年来,在双轮自平衡模型的研究上,国内外众多专家和爱好者们取得了一系列的成果,推动了自平衡技术的发展和成熟[1]。2002年,美国Lego公司设计了一款两轮自平衡传感式机器人,简称 Legway[2];2005年,美国Southern Methodist University的David P.Anderson教授设计了一款双轮移动机器模型,取名nBot[3];2007年,深圳固高科技有限公司研制了一款用于教育教学示范的自平衡模型,即GBOT1001机器人[4];2008年,美国Tiger电子公司和日本Sega玩具公司联合推出了AMP[5](Automated Musical Personality)两轮自平衡机器人。
作为科学实验仪器的自平衡模型的涌现,推动两轮机器人学以及相关学科的研究和发展,同时也启发了人们向载人运动方向发展的思路。两轮载人自平衡车具有占地面积小、运动灵活敏捷的特点,由此提供了一种新式交通工具的设计概念。
Segway[6]是第一个推出载人自平衡车品牌并成功推入市场的公司,其由美国著名发明家Dean Kamen 创立,2003年首次推出第一代Segway概念型自平衡车;2005年,中国科学技术大学自动化系和力学系多位教授、博士和研究生研制了自平衡两轮电动代步车Free Mover[7];2008年,日本的丰田公司(TOYOTA)推出了一款两轮个人交通工具Winglet[8];2014年小米科技公司投资ninebot,开始致力于解决5公里或10公里内的短途交通问题;2015年4 月ninebot收购Segway公司,成为全球最大的平衡车公司,同年10月19日,ninebot迷你九号平衡车作为小米生态链公司的一个新领域产品,正式发布。
2 系统整体设计
所设计的双轮小车主要由两大部分组成:第一部分为硬件设计,第二部分为软件设计。其中核心板模块、姿态检测模块、电机驱动板模块、Raspberry Pi高清摄像头板模块和Raspberry Pi3等组成了系统的硬件部分;姿态检测算法、PID算法、通信方案的程序设计、小车循迹控制算法构成了系统的软件部分。小车平衡与控制系统设计过程中涉及的直立行走任务分解、车模直立控制、车模速度控制等借鉴了参考文献[9]。系统的整体框图如图1所示。
图1 系统整体框图
3 双轮平衡车硬件组成
3.1 平衡车车架
平衡车车架由两台42步进电机(含步进电机支架、联轴器)、橡胶轮胎、亚力克载物台、12 V锂电池等组成,12 V锂电池采用DC头作为输出接口,方便电源的插拔。
3.2 核心板模块
核心板模块的主控制器芯片为STM32F103VCT6,其包括板载MCU的基本电路、晶振电路、复位电路、LDO电路、MicroUSB接口,至少支持2路硬件UART、预留8路硬件PWM、支持2路I2C、1路硬件SPI、8路模拟输入;包含8路外部中断;电平标准采用3.3 V。
3.3 姿态检测模块
姿态检测模块主控制器芯片为MPU6050,包含I2C接口、板载LDO电路,其工作电源电压为3.3 V。MPU6050整合了3 轴陀螺仪、3 轴加速计,并含可藉由第二个I2C端口连接其他厂商加速器、磁力传感器或其他传感器的数位运动处理(Digital Motion Processor,DMP)硬件加速引擎,由主要I2C端口以单一数据流的形式向应用端输出完整的9轴融合演算技术InvenSense 的运动处理资料库,可处理运动感测的复杂数据。
3.4 电机驱动板
步进电机驱动模块采用DRV8825方案,其为TI公司生产的一种高电压、大电流步进电机驱动芯片,可实现大电流、快速响应的双极步进电机驱动。DRV8825可以驱动一个两相四线的步进电机,也可以驱动两个直流有刷电机,输入电压为8.2~45 V,最大电流为1.7 A,可以承受2.5 A的瞬间电压,可通过PWM输入来驱动。
3.5 Raspberry Pi高清摄像头板
Raspberry Pi高清 (HD) 摄像头板可连接至 Raspberry Pi,可以创建高清视频和静止摄影。它利用 Sony 的 IMX219PQ 图像传感器提供高速视频成像和高灵敏度。Raspberry Pi 摄像头模块可减少图像污染,如固定模式噪声和拖尾效应。 它还具有自动控制功能,如曝光控制、白平衡和亮度检测。
3.6 Raspberry Pi3
Raspberry Pi型号 B 是信用卡大的计算机板,当添加了键盘、鼠标、显示屏、电源和已安装OS的 MicroSD卡时,可以启动和运行。它是基于微型 ARM的PC,可运行许多通常需要台式PC的应用(如电子表格、文字处理和游戏),它还可播放高清视频。
4 软件设计
4.1 系统流程图
图2 程序流程图
双轮平衡车“跑”起来的过程如图 2所示。首先,初始化各个外设,主函数将一直在 while(1)循环执行。定时器中断每 10 ms 触发一次,从主函数跳到中断回调相应函数,完成数据采集、处理、控制整个过程(首先获取当前小车的姿态即倾角,然后读取树莓派传回的数据,处理完后,更新PID输出,完成电机控制)。执行完立刻返回到上次主函数执行的位置继续执行。
4.2 姿态检测算法
在双轮平衡车姿态检测系统中,MPU6050主要用于获取小车倾斜角和倾斜角的变化率[10],其中加速度计可以精确计算车体静止时的角度;陀螺仪的输出值是旋转角速率,通过角速率对时间积分即可得到角度值,系统采用STM32F103单片机循环采样获取陀螺仪的角速率信息,对采样值进行累加实现积分功能来计算角度值,此方法存在累积误差,为获得可靠的车体倾角值,系统采用卡尔曼滤波对加速度计和陀螺仪的输出值进行融合。
4.3 PID算法
考虑到现在两轮平衡车均采用通过 MPU6050姿态传感器读取小车当前状态,当双轮平衡车的平衡状态被破坏时,系统采用PID控制算法[10],通过整合车体角度、角速度和车体速度等参数值,输出PWM信号驱动电机,产生相应的力矩,使得车体保持动态平衡,其结构框图如图3所示。
图3 PID算法框图
4.4 通信方案的实现与程序设计
利用Raspberry Pi3处理摄像头采集信息,并将处理后的信息以字节形式通过串口传输到STM32F103VCT6。STM32F103VCT6将接收的信息分解成两部分,将字节的最高位作为方向,1表示右,0表示左,低七位表示为速度;停止信息分别为0xff和0x7f,运行期间Raspberry Pi3返回的低七位构成的数值大小范围为0~100,小车初始速度+数值大小×系数等于其中一个轮子的速度,另一个轮子的速度等于小车初始速度-数值大小×系数。
4.5 小车循迹控制
循迹是指小车在白色的纸(地板等)上循黑线行走,本文的循迹是采用摄像头采集图像并分析实线,即用摄像头拍摄白色纸上的黑色引导线,树莓派利用最小二乘法拟合路径[11]得到路径方向和位置,将转弯信息通过串口的方式传送给STM32主控制器,STM32F103VCT6将接收到的数据用于转换为轮子速度和方向的控制。以保证小车能正常沿着黑色引导线行驶。图4为行驶图,黑色为引导线,白色线条为切线,车会沿着切线方向行走如图5所示。
图4 小车行驶图
图5 摄像头拍摄的图片并作出切线
树莓派运行的是基于Debian的树莓派定制系统Raspbian OS,图像处理程序使用Python3.5编写,图像处理逻辑依赖OpenCV2、Numpy、Pyserial实现。
程序首先从摄像头获取图像,由于树莓派性能有限,但又要有较为精确的识别,最后采用160×90的分辨率,最后得到的帧率接近60 fps,保证了小车具有较高的反应速度。
程序再对图像进行隔行扫描,获取每行的路径边缘,取左右边界中心得到小车轨迹中心。最后以水平向右方向为y轴,竖直向下为x轴,建立坐标系,对得到的离散点使用最小二分法进行直线拟合,如图6所示。最小二分法拟合函数参数k、b的计算公式如下:
(1)
(2)
图6 树莓派返回数据生成的表
最后得到直线斜率k,再转换为弧度theta即为小车角度偏移,作为小车方向控制的主要参数。同时,取拟合的直线中点,计算到图像中心的距离dist,作为小车的距离偏移,于是得到小车的转弯结果为:
turn=k1×theta+k2×dist
turn的绝对值为转弯幅度,turn的正负代表转弯方向。最后将turn转化为8位,通过串口传输到STM32主控制器,然后进行相应的转弯控制。
小车循迹程序设计:
'''隔行扫描'''
def getBorder(self, th, row, find_step=2, confidence=2):
size =th.shape
left = 0
right = size[1]
black_count = 0
white_count = 0
black_overed = False
for i in range(0, size[1], find_step):
pixel =th[row][i]
if pixel == 0:
if notblack_overed:
left = i
black_overed = True
elif black_overed:
white_count += 1
if white_count >= confidence:
right =i-confidence*find_step
break
return (left, right)
'''计算最小二分法拟合函数参数k、b,判断轨迹起始、结束点 '''
def minCost(self, th, img):
sum_x2 = 0
sum_x = 0
sum_y = 0
sum_xy = 0
count = 0
size =th.shape
start_point = 0
end_point = size[0]
Xi = []
Yi = []
for i in range(start_point, end_point, 5):
border =self.getBorder(th, i)
l, r = border
if (l == 0 and r == size[1]) or (l == 0 and r == 0):
continue
x =i
y =int((l+r)/2)
Xi.append(x)
Yi.append(y)
Xi =np.array(Xi)
Yi =np.array(Yi)
Para =leastsq(leatsq_error, [1,20], args=(Xi,Yi))
k, b = Para[0]
center_x = int(sum(Xi)/len(Xi))
center_y = int(sum(Yi)/len(Yi))
center = (center_y, center_x)
theta = -math.atan(k)
distance = (center_y - size[1]/2)*200/size[1]
return (theta, distance)