一、小车平台选择
前面已经完成了手机和手机之间的 Wifi 通讯,实现了用一个手机采集图像,并传输到另一个手机上显示,同时实现了双向数据通讯,这样,“带视频监控的Wifi 控制智能小车”基础已经有了,下面就在此基础上实现一个小车的操控。
首先,选择一个小车平台,我所选用的是基于“轮式驱动单元”和舵机组合的单轮驱动小车平台,因为这种驱动方式的小车转向和行走的控制是完全独立的,控制算法比较简单。轮式驱动单元集成了电机PWM驱动和简单的码盘反馈部分,用 TTL 电平的 IO 口可以方便的控制,选择任何一个单片机核心板就可以驱动,无须增加任何额外的部件,简单、方便。
轮式驱动单元的码盘精度虽然一般,只有 2.51mm/脉冲,但为控制行走距离提供了可能,再低精度的码盘也比延时控制精确。
因为是通过 Wifi 用 UDP 协议实现控制,会有丢包和延时的可能,操控命令实时性和可靠性均不高,所以基于这种模式的操控,应尽量采用非连续的操作模式,即一个命令小车只行走一段距离,或者是一个有限的转向,控制端根据反馈确定下一步操作。而不是用一个命令启动小车运行,再根据反馈发送停止命令,这样如果发生丢包或延时,小车的行为将失控。
为了便于交流,选择了最流行的 Arduino Nano 控制板作为驱动板,一方面是编程方便,另一方面Arduino 有现成的舵机驱动函数。
为了便于轮式驱动单元的使用,发挥其全部功能,我尝编写了一个驱动轮式驱动单元的 Arduino 库。不是很完善,欢迎吐槽!不过 Arduino的库编写还是很方便的,赞一个!
因为轮式驱动单元、舵机和Arduino 控制板均可以5V工作,所以选择了手机移动电源作为小车电源,这样充电很方便,电压输出也稳定,还不重复投资^_^
小车部分的详细介绍见前面的博文“单轮驱动小车平台硬件介绍”,此处不再赘述。
二、整体构思
这是用PC作为操控端的 Wifi智能小车框图:
“带视频监控的 Wifi 控制智能小车”系统基本相同,只是将PC机替换为手机。
小车的行为需要经过三个过程实现:
第一步:在操控端手机上产生行为命令,发送给小车上的手机控制端;
第二步:小车上的手机收到命令后,解析并通过蓝牙转发给 Arduino控制板;
第三步:Arduino控制收到命令后,解析,产生实际的操作。
可以附加一个反馈过程:
第一步:Arduino监控小车的执行状态,执行完成后反馈信息给小车上的手机;
第二步:小车上手机收到Arduino的反馈后,转发给操控端手机;
第三步:操控端收到反馈后,确定新的操作命令,开始新一轮操作。
对于一个具体的操作,操控端手机、小车控制端手机及Arduino控制板三部分该如何分工呢?
方案一:将小车上的手机只作为通讯的通道,不承担命令的解析和封装;操控端直接生成 Arduino控制板可以操作的命令,并可以识别Arduino的反馈信息。
方案二:操控端手机生成与具体小车对象无关的行为命令,由小车上的手机解析成Arduino能执行的命令并转发,同时将小车的反馈信息转换成操控端能理解的格式。
方式三:操控端手机生成与具体小车对象无关的行为命令,小车上手机只是转发,Arduino负责解析命令并执行。
方案一的好处是小车上的手机程序比较简单,基本可以不用修改,但操控端的手机和Arduino程序需要不断修改,但从控制逻辑以及面向对象的设计理念来说,有点不合理。
方案二比较符合面向对象设计理念,将小车的行为封装到小车上,操控端发送的是抽象的行为命令,和底层没有关系。这样设计操控端程序可以适应不同的小车对象,小车硬件变化后,只需相应修改小车上的手机程序和Arduino上的程序即可。此时,小车上的手机控制端程序所起的作用类似于中间件,或者硬件适配层(HAL)。
方案三和方案二逻辑上一致,但这样Arduino上的程序压力比较大,基于Arduino的性能特点,比较困难。
所以,确定选择方案二模式,因为控制“单轮驱动小车”是第一步尝试,之后会尝试实现“两轮差分驱动小车”和“三轮全向驱动小车”的Wifi控制,用此方案便于程序的复用。
三、软件构思
因为是验证性的,没有明确的需求和目标,主要是感受一下用手机控制是否可行,关键是基于 Processing 编程,而非标准的 Android 开发环境。通过实践验证一下基于 Processing,手机可以发挥到哪一个程度?可以胜任什么级别的任务?
所以设计会相对简单一些,能找到感觉即可。
3.1 操控端手机程序设计
因为功能主要取决于操控端,所以先构思操控端的程序。
基本功能如下:
手机上显示小车回传的图像,占据主要界面。
显示下端指示程序运行状态,以便判断程序是否死机。
显示上端作为命令发送及执行状态的显示区域。
因为手机显示区域较小,故不再设计操作按钮。初步定义的操作为:
1)按画面上部(1/3)区域,发送小车前进命令,按下时显示行走距离,随着时间增加而增加,释放后发送,暂时不考虑改变速度。最小行走10mm。
2)按画面下部(1/3)区域,小车后退,其余同上。
3)按画面中部右侧,发送小车右转命令,按下时显示转动角度,随着时间增加而增加,最大角度360度,最小转角10度。
4)按画面中部左侧,发送小车左转命令,其余同上。
5)按画面正中,发送停止命令,终止小车目前执行的操作。
除停止命令外,其它命令均执行完成后才能响应下一操作,停止命令可以随时发。
命令帧定义:
帧序号(四字节) 命令字1(保留,一字节) 命令字2(一字节) 命令参数(任意字节,由命令字2确定)。
因为命令是作为UDP数据包的内容,所以无需增加校验信息,直接发送内容即可。
第一步设计的命令:
1)行进: 0x00 0x01 距离(2字节,先低后高) 速度(2字节,先低后高)
距离单位:mm ,数值大于0;
速度单位:mm/s,数值大于0,前进,数值小于0,后退,数值为0,停止;但目前用Arduino控制实现不了调速,暂时解释为PWM百分数。
2)原地转向:0x00 0x02 转角(2字节,先低后高) 速度(2字节,先低后高)
转角单位:度,数值大于0;
速度单位:mm/s,数值大于0,右转,数值小于0,左转,数值为0,停止;但目前用Arduino控制实现不了调速,暂时定义为PWM百分数。
3.2 Arduino控制器程序设计
因为小车上的手机控制端程序完成的是连接操控端和执行端的任务,所以必须先确定执行端的功能,也就是 Arduino 控制板上的程序功能。
Arduino 能力有限,所以只赋予它比较基本的操作,在设计 Arduino 驱动轮式驱动单元库时已经编写了一个程序,可以实现一些基本的行为,暂时不做修改了,等到有了明确的需求或者调试中有明显的不足时再做改进。
简单总结一下Arduino控制板现有的程序功能,主要是控制命令。
目前Arduino支持的控制命令如下:
控制命令帧格式定义:
55 AA 命令字(1字节) 命令参数(5字节)
所有命令均为 8 字节。
初步设计了以下控制命令:
1)电机控制
命令字:0x1
命令参数1: 0x01—— 前进 0x02 —— 后退 0x03 —— 刹车 0x04 —— 惰行
命令参数2: 前进后退命令为 PWM 值 , 0 - 255,数字越大,电机功率越大。
刹车、惰行命令参数 2 为 0。
命令参数3-5:保留
2)行走距离设置
命令字:0x02
命令参数1、2:2字节距离值,单位mm, 先低后高,范围:0 —— 65535mm,距离为 0 持续行走,
命令参数3-5:保留
3)舵机控制命令
命令字:0x03
命令参数1:舵机角度,0 -180 度,254为在当前位置 -2 度,255 为当前位置+2度;
命令参数2-5:保留
4)组合命令:
命令字:0x04
命令参数1:0x01—— 前进 0x02 —— 后退 0x03 —— 刹车 0x04 —— 惰行;
命令参数2:前进后退命令为 PWM 值 , 0 - 255,数字越大,电机功率越大。
刹车、惰行命令参数 2 为 0;
命令参数3、4:2字节距离值,单位mm, 先低后高,范围:0 —— 65535mm,距离为 0 持续行走;
命令参数5:舵机角度,0 -180 度,254为在当前位置 -2 度,255 为当前位置+2度。
行走距离设置可以先发,此命令只是设置一个减计数器加载值,但不触发计数。
只有在设置电机行走命令时,才去读设定值,并将其置入减计数器,触发计数。
如果计数值为“0”,则表示连续运转,直到收到停止命令。
舵机命令收到后即刻执行。
命令有应答帧,4 字节,将命令字高位置“1”
如命令: 55 AA 01 01 80 00 00 00
应答为: 55 AA 81 00
依此类推。
对于小车行走命令,在走完指定距离后再发送一个状态返回帧,告知命令发送方已执行完刚才的命令,便于手机控制端处理后续操作。命令执行结束状态返回帧:
55 AA 80 01 4字节长度
对于舵机操作命令,按转角产生对应延时后发送状态返回帧,告知命令已执行完。状态返回帧:
55 AA 80 03, 4字节长度
3.3 小车上手机控制端程序设计
根据上面两部分程序设计的功能,手机控制端的程序需要完成操控命令的解析,生成相应的Arduino控制命令,发送给Arduino控制器,实现小车运动。
因为操控命令是抽象过的,而Arduino所能接受的命令是最基础的单一操作命令,所以一个操控命令可能需要多个Arduino命令才能实现,并且需要一定的时间。
因此,手机控制端程序考虑用有限状态机模式。
基本状态有:
1)等待操控命令状态
2)解析命令状态
3)发送命令状态
4)等待命令应答状态
5)等待命令执行完成状态
6)返回命令执行完成给操控端
7)等待操控端收到完成信息后的应答
8)回到状态1)
因为要支持停止命令随时终止当前操作,需要考虑不断接收操控命令,如果是停止命令,则改变当前状态,直接处理。
具体的处理流程具体编写时再考虑。
四、综述
上述构思只是针对小车控制的逻辑,这些控制逻辑都是在图像传输的基础上增加的,嵌入在图像收发的过程中,所有的通讯都是以图像传输为基础节拍。
所以,控制命令的实时性也取决于图像传输的帧率,目前设计没有考虑额外的控制命令帧,每传输一帧图像,操控端和控制端交换一次数据和命令。
先按此模式实施,实现后再看效果,以判断这种通讯模式是否合理。
欢迎有兴趣的朋友共同尝试,可以随时交流,共同体验其中的乐趣!