2. 北京邮电大学 电子工程学院, 北京 100876
2. School of Electronic Engineering, Beijing University of Posts and Telecommunications, Beijing 100876, China
随着经济与科技的快速发展, 机器人技术正在逐步普及, 在各行各业得到了较多应用. 在社会上的部分岗位中, 机器人已经可以完全替代人类. 当前对于四轮简易机器人, 即智能小车的开发仍是大学生创新创业训练、各类大赛的热点题目, 相关技术资料较为丰富, 文献[1]对无线遥控智能小车进行了介绍. 对于小车的轮子电机控制硬件设计, 在文献[2]中给出了描述. 对于小车的PID控制软件设计, 在文献[3]中给出了介绍. 本文借鉴智能小车相关文献和大赛, 如恩智浦杯[4]、博创杯等比赛成果用到的开发技术, 进行具有计算机视觉人脸识别功能的无线遥控智能小车的技术实践. 本文采用基于ARM[5]和嵌入式Linux系统的方案实现属于简易机器人的四轮智能小车, 较传统单片机的解决方案, 其智能性和扩展性较高. 较同类基于ARM和嵌入式Linux的解决方案, 其主要特点在于基于OpenCV实现了一定的人脸识别功能.
本文中手机可以通过传统“按键动作”发送命令, 也可以通过较为新颖的“重力感应动作”发送命令, 提高了无线遥控的用户体验和乐趣. 在手机和小车之间组建无线网络, 通过Android智能手机的APP发送无线遥控命令, 手机可以通过按键动作发送命令也可以通过重力感应动作发送命令. 重力感应指的是手机上的重力传感器能够根据手机的不同摆放状态获得不同的数据, ARM芯片通过WiFi模块接收命令并进行相应的操作控制, 如小车的前进、后退、转弯、旋转、停车等.
1 关键技术 1.1 智能小车系统架构如图1, 无线遥控小车架构由车轮、小车底板、电机、电池、OK6410 ARM开发板[6](带S3C6410处理器)、WiFi模块(SDIO接口)、USB摄像头、速度传感器、Android手机客户端组成.
1.2 关键技术概述
使用的关键技术包括: 基于重力传感器的智能手机无线遥控、WiFi/Socket套接字[7]通信、计算机视觉人脸检测算法、PID控制算法[8]等.
如图2, 基于Android智能手机中的重力传感器实现重力感应[9], 需要首先得到x、y、z三轴的加速度的值. 该值包含了地心引力的影响, 如当将手机放在水平桌面上时, x轴默认值为0, y轴默认值为0, z轴默认值为9.81. 将手机向左倾斜时, x轴的值为正. 将手机向右倾斜时, x轴的值为负. 将手机向前倾斜时, y轴的值为负. 将手机向后倾斜时, y轴的值为正.
利用传感器技术获得手机状态后, 还要将与状态对应的命令通过专门的通信技术发送给小车(如手机左倾代表遥控小车左转). ARM开发板与智能手机之间采取C/S架构的WiFi/Socket (套接字)技术进行互联通信. 其中ARM板上运行着Socket服务器, 负责驱动WiFi模块并获取Android智能手机客户端发送来的数据命令包, 然后把命令解析出来, 通过GPIO端口把控制信息传送给小车底板, 小车底板中的驱动电路接收到控制信号, 做出相应的操作驱动电机改变车轮运动状态, 从而达到无线遥控小车运动的目的. ARM小车上运行Socket服务端程序, 设置WiFi模块为热点模式, 手机上安装Socket通信客户端APP, 使手机连接到ARM小车WiFi热点, 打开手机APP, 设置相应的服务端IP和端口号, 设置发送的命令. 控制端手机APP(Socket通信客户端)发送命令数据包, 手机APP发送指令数据包分为两种方式: 屏幕按键、重力感应. 屏幕按键操作是用户按住APP的前、后、左、右键发送相应的数据包命令; 重力感应操作是用户在手机APP上选择重力感应模式, 通过把手机前倾、后倾、左倾、右倾完成数据包命令的发送. ARM小车服务端接收到数据包后, 对数据包进行解析, 然后执行相应的操作, 如前进、后退、左转、右转、左旋、右旋、停车等.
人脸识别用到的人脸检测算法是采用Adaboost学习算法[10], 它把一些比较弱的分类方法级联整合在一起, 组合出新的很强的分类措施. 采用比例积分微分(Proportion Integral Differential, PID)控制算法控制小车的车轮转速, 确保其直线行走和准确转弯. 关于人脸检测算法和PID控制算法将在软件设计与实现小节详细描述.
2 硬件设计过程与方法 2.1 关键器件选型小车采用四个驱动车轮, 四个轮子都安装了直流电机, 大大增加了地面的阻力. 四个轮子和电机都是同种型号的, 各个轮子几乎没有差别, 在相同供电的情况下, 小车运动时, 小车的重力中心在小车底盘中心, 由于四个轮子都可以单独控制, 小车运动时很难跑偏. 当然四个驱动轮使得小车有更快的速度, 当小车停止时, 由于四个轮子都不转, 直接增大了摩擦力, 小车很快就能停下, 这个小车底盘性能较好, 满足本小车的需求[11]. 四驱小车速度达到了预期要求, 在小车执行直行、转弯、旋转等动作时更便于控制.
S3C6410芯片是三星公司的ARM11架构处理器, 本文选用的中国飞凌公司的OK6410开发板采用了S3C6410为主控芯片, 功能强大, 便于用户二次开发[3]. WiFi模块较蓝牙模块的通信距离更远, 更适合无线遥控, 因此选用飞凌公司基于RTL8189ES型号的WiFi模块[6], 该模块通过SDIO接口与板子连接. 选用普通USB接口的摄像头, 通过USB口与板子连接.
2.2 电机及其驱动电路
选择了4个130直流电机, 130电机惯量适中. 小车的轮子由四个电机构成, 且每个电机都可以单独控制, 即四轮驱动. 小车的转向是通过轮子的差速实现的, 即左右两个轮子存在速度差时, 小车就能实现转弯. 假如左边两个轮子的速度比右边两个轮子的快, 那么小车会偏向右; 同理, 左边两个轮子比右边两个轮子速度慢, 那么小车就会偏左. 由于四个轮子的130电机需要差速转弯, 转向时轮子与地面有很大的阻力, 使用的电流比较大, 实际测量, 小车在走直线时需要600–850 mA的电流, 转向时需要提供的电流约为1.2–1.5 A. 130直流电机工作电压在3–9 V之间, 实际选取6 V左右, 此时小车状态较好.
四个直流电机选用双L298N电机驱动模块[8]驱动, 两个电机分别驱动左右两对轮子. L298N芯片是ST公司制作的, 并且工艺稳定性高, 其原理图如图3, 能够直接驱动4路3–16 V直流电机. 电机驱动电路输入接口的GND与OK6410开发板的GND连在一起, 电机供电电池的GND和驱动电路输出接口的GND连在一起, 保证逻辑电平的统一. 制作了专门的排线以连接ARM开发板与电机驱动电路.
电机驱动电路的输入端有8个管脚(IN1~IN8), 分别连接OK6410板子的8个引出的预留给用户的GPIO管脚, 这8个GPIO管脚分别连接驱动电路的IN1~IN8输入管脚, 对应驱动电路的8路输出端口OUT1~OUT8, 以控制车轮旋转方向(使轮子正转、反转、不转). 基于S3C6410处理器的定时器内部中断, 由软件模拟产生GPIO管脚上的PWM波, 可为左右两对车轮的电机提供PWM信号, 以控制车轮转速(在左右两对轮子之间形成速度差, 使小车利用差速转弯). 除了上述8个作为输出端口的GPIO管脚, 板子还有另外2个GPIO管脚作为输入端口, 分别连接速度传感器的输出管脚, 以达到测速目的.
如表1, 驱动电路输出端的8路输出端口分别连接4个车轮的电机(每个电机需要2根接线, 4个电机共需8根线, 分别接8个输出端口). 以左上电机为例: 当OUT1、OUT2同为高电平或低电平时, 左上电机不转; 当OUT1为低电平, OUT2为高电平时, 左上电机正转; 当OUT1为高电平, OUT2为低电平时, 左上电机反转. 其他3个电机的控制以此类推.
3 软件设计过程与方法
在PC机安装虚拟机软件, 虚拟机内安装的是Ubuntu 12.04, 安装ARM交叉编译器、QT Creator IDE(用于开发QT程序, QT是嵌入式Linux系统的一种图形化用户界面, 类似于PC Windows系统中的桌面[6]). OK6410板子中烧录Linux 3.0.1版本的内核.
3.1 GPIO驱动程序与车轮控制三星S3C6410芯片包含187个多功能输入/输出端口管脚, 而小车的控制采用OK6410开发板预留的用户端口中的10路GPIO, 分别为GPC0~GPC7(输出由软件模拟的PWM波)、GPP8~GPP9(输入端口, 分别检测由速度传感器产生的关联左右两对轮子转速的外部中断). 以GPC寄存器的配置为例, GPCCON、GPCDAT、GPCPUD、GPCCONSLP、GPCPUDSLP, 这五个控制寄存器都属于端口GPC控制寄存器. 寄存器GPC的端口都有多种的配置方式, 包括输入、输出、外部中断等, 在小车控制中需要把GPIO端口配置为输出模式, 具体配置见表2. 此时GPC7~0的管脚状态与GPCDAT的低八位[7:0]相应的位状态相同, GPP9、GPP8的管脚状态与GPPDAT的中间两位[9:8]相应的位状态相同[12].
在GPIO的驱动中, 首先要编写驱动的入口函数和卸载函数[13], 驱动的入口函数为mygpio_init(), 卸载函数为mygpio_exit(), 打开设备的函数为mygpio_open(), 控制设备的函数为mygpio_ioctl(). 在mygpio_open()函数中, 首先要进行地址映射, 内核中访问IO内存之前, 只知道它们的物理地址, 不能使用软件直接访问, 调用ioremap()将设备物理地址映射为虚拟地址, 然后根据虚拟地址范围去访问IO资源. mygpio_ioctl()函数可以控制每一个车轮的转动状态.
小车的实际速度有时不稳定, 不能直接线性调速, 且小车的四个轮子的直流电机也存在微小的差异, 使得小车轮子之间的转速有差异. 为此, 本设计采用PID(Proportion Integral Differential, 比例积分微分)控制算法控制小车的车轮转速, 确保其直线行走和准确转弯. 采用定时器来模拟四路PWM(Pulse Width Modulation, 脉冲宽度调制)来控制四个直流电机的转速. PID一般包括两种: 位置式PID和增量式PID, 在小车控制中一般采用增量式, 本文采用的就是这种方式.
计算机控制是经过采样后的数字化控制, 这种控制必须按照采样时间点的偏差计算控制量, 无法输出连续的模拟控制量, 因此积分项和微分项是不能被直接使用的, 而是要先进行处理, 使之离散化. 其离散化处理的方法为: 以T为采样周期, k为采样序号, 则离散采样时间kT对应着连续时间t, 用求和代替积分, 用后向差分代替微分, 则离散化的PID表达式近似如下:
$uk = Kp[ek + T/Ti \times \sum\limits_{j = 0}^k {ej} + Td \times (ek - ek - 1)/T]$ | (1) |
式(1)中, ek为输入的控制误差, uk为输出, Kp为比例系数, Ti与积分时间相关, Td为微分时间常数. 所谓增量式PID是指数字控制器的输出只是控制量的增量, 增量式PID控制算法可以得到控制器的第k–1个采样时刻的输出值为:
${\rm{u}}k - 1 = Kp[ek - 1 + T/Ti \times \sum\limits_{j = 0}^{k - 1} {ej} + Td \times (ek - 1 - ek - 2)/T]$ | (2) |
将(1)与(2)相减并整理, 就可以得到增量式PID控制算法公式为:
$\begin{array}{l}\Delta {\rm{u}}k = uk - uk - 1\\ = Kp[ek - ek - 1 \!+\! T/Ti \times ek \!+\! Td(ek - 2ek - 1 \!+\! ek - 2)/T]\\ = Aek + Bek - 1 + Cek - 2\end{array}$ | (3) |
其中
$\begin{split}& A = K{\rm{p}}(1 + T/Ti + Td/T) \\ & B = Kp(1 + 2Td/T) \\ & C = KpTd/T \end{split} $ | (4) |
由式(3)可以看出, 如果计算机控制系统采用恒定的采用周期T, 只要确定了A、B、C的值, 并使用时间上前后三次测量的目标速度与实际速度的偏差值ek、ek-1、ek-2, 就可以求出控制量的增量△uk. 小车的车轮转速采样周期为100 ms, 由PID算法得出A、B、C三个参数, 按照△uk来增大或减小输出PWM波的占空比, 从而调整车轮转速.
3.2 视频采集与人脸识别摄像头与ARM开发板通过USB口连接. 在ARM开发板上, 采用V4L2(Video for Linux 2)API[14]进行打开摄像头等操作, 并基于Open CV 2.0开源计算机视觉代码包[15]处理视频数据. 使用QT界面程序显示采集到的视频并进行人脸检测.
开发时发现Open CV的打开摄像头的接口函数在ARM开发板上不能正常运行, 故采用Linux中的V4L2接口来配合编写摄像头程序, 其中包括: 打开摄像头、初始化摄像头、采集视频帧、停止采集视频帧、卸载摄像头设备、获取视频帧、关闭摄像头等. 获取到摄像头视频后, 把视频进行压缩, 从而提高人脸检测的速度, 在视频流中进行人脸检测, 然后恢复原图像的大小, 使用Open CV函数进行图像格式转换并把视频显示在QT界面程序中. 在人脸检测中, 如果检测到人脸, 则在图像中以人脸为中心, 围绕着人脸画出一个方框来标注人脸, 如图4.
利用Open CV中支持的人脸检测方法实现人脸识别: 首先利用样本的Haar特征进行分类训练, 获得级联boosted分类器, 进而获得级联分类器类CascadeClassifier, 使用该类对视频流中的目标进行检测. 检测时需要加载XML分类器文件("haarcascade_frontalface_alt.xml"). 在程序中构造了一个detectAndDisplay()函数, 对在视频流中读取的每一帧图像进行检测. 该函数主要是将每一帧图像转换为灰度图像, 然后进行直方图均衡化, 然后找出人脸区域; 最后显示人脸目标: 定出人脸区域后, 以人脸为中心画出一个方框, 如图4.
3.3 软件主流程
软件主流程如图5, 整体为C/S架构, 小车做服务端, 手机做客户端, 两者之间采取WiFi/Socket技术进行通信. 其中小车部分为多线程结构, 主线程负责视频采集与人脸识别, 次线程负责小车控制.
4 实践遇到的主要问题、解决方法和经验体会首先, 使用OpenCV的函数调用摄像头在虚拟机中的Linux中可以正常运行, 没有问题存在, 但是当把程序移植到ARM开发板的嵌入式Linux系统中时, 会出现段错误, 主要是OpenCV的相关函数出现问题. 比如其中一个出现问题的函数是cvCreateCameraCapture(), 调试时发现运行到这里就出现错误了. 采取的措施是避开使用OpenCV的函数打开摄像头, 采用V4L2来打开摄像头, 使用OpenCV的函数来处理图像, 问题成功解决.
另外, 在QT调用OpenCV的功能调试时调试时间较长, 发现导致问题的因素大都是某些细节没有处理好, 但初次实践者较易忽略. 笔者经过实践解决了问题, 总结经验如下: 在QT程序中, 需要把OpenCV的动态链接库路径加入到工程中, 并在ARM开发板中把所有的链接库(*.so)文件添加, 此时需要保证路径和PC机上的一致. 如果出现在ARM上运行的程序提示找不到链接库, 可能是由于链接库路径太长.
5 结论
本文研制的小车实物如图6. 经过实测, 小车各项功能达到了预期设计目标, 运行稳定, 小车可被手机无线遥控, 并支持视频采集与人脸检测, 有效遥控距离为60米左右, 在防爆、救援、养老等领域具有较好的应用价值. 比如, 小车可在人类视野内被遥控进入危险的人类不便进入的区域, 以进行识别、救援、排爆等任务. 将来考虑实现其他计算机视觉算法, 并增加语音识别等功能.
[1] |
朱丹峰, 葛主冉, 林晓雷. 基于Android平台的无线遥控智能小车. 电子器件, 2013, 36(3): 408-412. DOI:10.3969/j.issn.1005-9490.2013.03.027 |
[2] |
宋洪慧, 李春芾, 朱江. 智能小车直流电机驱动电路设计. 机电技术, 2015(6): 84-87. DOI:10.3969/j.issn.1672-4801.2015.06.028 |
[3] |
隋妍. 基于数字PID的智能小车的控制. 数字技术与应用, 2012(6): 3, 6. |
[4] |
全国大学生智能汽车竞赛秘书处. 全国大学生" 恩智浦杯”智能汽车竞赛官网. http://www.smartcar.au.tsinghua.edu.cn.
|
[5] |
ARM Limited. ARM architecture reference manual. ARM Limited, 2005, 23-37. |
[6] |
飞凌嵌入式. OK6410-A Linux使用手册. http://www.forlinx.com.
|
[7] |
Stevens WR, Fenner B, Rudoff AM. UNIX网络编程: 卷1: 套接字联网API. 北京: 人民邮电出版社, 2015.
|
[8] |
刘金琨. 先进PID控制MATLAB仿真. 3版. 北京: 电子工业出版社, 2011.
|
[9] |
丁山. Android程序设计教程. 北京: 机械工业出版社, 2015.
|
[10] |
曹莹, 苗启广, 刘家辰, 等. AdaBoost算法研究进展与展望. 自动化学报, 2013, 39(6): 745-758. |
[11] |
迎创电子. 初始ZK-4WD小车机器人. http://www.mcustudio.com.cn.
|
[12] |
飞凌嵌入式. OK6410-A开发板硬件手册. http://www.forlinx.com.
|
[13] |
宋宝华. Linux设备驱动开发详解. 2版. 北京: 人民邮电出版社, 2010.
|
[14] |
王飞, 孔聪. 基于V4L2的Linux摄像头驱动的实现. 电子科技, 2012, 25(2): 86-87, 92. DOI:10.3969/j.issn.1001-9146.2012.02.022 |
[15] |
Laganiere R. OpenCV2计算机视觉编程手册. 张静, 译. 北京: 科学出版社, 2013.
|