App Inventor开发乐高EV3控制程序



App Inventor开发乐高EV3控制程序。

一、问题

EV3是乐高推出的最新一代MINDSTROMS可编程智能机器人产品,而MIT App Inventor目前版本中的LEGO MINDSTORMS类组件主要是针对乐高的上一代产品NXT提供的,经实际编程测试发现,利用现有这些组件无法实现对新版EV3的相关控制功能。通过对照分析App Inventor和EV3的源代码,初步认定问题是由NXT与EV3间底层通信协议版本不兼容造成的,因此,要使用App Inventor开发EV3控制程序只能绕开现有组件通过其他途径实现。
 
二、分析
通过分析EV3虚拟机的部分源码,可知新版通信协议支持系统指令(System Command)和直接指令(Direct Command)等两种不同特性的指令类型,其中,直接指令可以通过远程调用虚拟机的底层字节码实现对EV3部件(电机、传感器等)的直接控制,而无需智能块本机的其他应用程序配合,并且针对不同类型的通信平台(蓝牙、WiFi、USB等),都采用了统一的协议形式。因此,我们可以利用App Inventor现有的蓝牙组件,以直接指令的方式实现对EV3的远程控制。
 
从数据格式看,EV3通信协议采用了字节码封装的形式,与智能块底层的虚拟机指令基本对应,并且制定了一套完备的指令和部件编码规范,包括指令类型、名称、参数以及部件连接端口、类别等,这一方面使得远程控制功能的开发难度极大降低,同时也使远程应用可具有与本机程序同等的控制能力,而且可以实现应用在不同平台系统间的移植和扩展,比如将一些本机应用的功能移植到远端的安卓设备上来。另外,控制指令的发送以及应答数据的返回采取了异步的形式,也都使App Inventor现有蓝牙组件的能力完全胜任对控制功能的实现要求。
三、思路
 
首先参照EV3通信协议、字节码说明及编码规范,将EV3的底层控制指令封装为App Inventor应用内的相关过程块(Procedures),如对应于电机控制的opOUTPUT_POWER、opOUTPUT_START和对应于传感器数据采集的opINPUT_READ等,然后根据不同的控制功能要求,在相关的UI事件块中进行组合调用。
 
安卓应用与EV3智能块的通信连接则由App Inventor的蓝牙客户端组件(BluetoothClient)实现,为了简化逻辑,各控制功能过程块可直接通过蓝牙客户端发送指令信息(Direct Command),同样,对指令应答返回信息的处理也由各功能单元直接通过蓝牙客户端获取。
 
四、实现
 
对EV3的控制一般包括建立连接、发送指令、读取数据等三个基本过程,就我们所要实现的功能来说,就是首先建立与EV3智能块间的蓝牙连接,然后向其发出启动电机或采集数据的指令,最后读取EV3传回的传感器数据,实现对其的监测。在此基础上,我们可进一步构筑和实现更为复杂的控制功能及应用。
 
1、建立连接
 
App Inventor通过BluetoothClient组件建立安卓手机与EV3间的蓝牙连接,首先要通过BluetoothClient的AddressesAndNames属性获得可连接的设备列表,从中选取EV3所对应的地址和名称,这通常都是通过ListPicker组件的选取功能来实现的。
App <wbr>Inventor开发乐高EV3控制程序初试

然后再通过BluetoothClient的Connect方法建立与所选EV3智能块设备间的连接,根据连接情况进行相应的初始化设置。
App <wbr>Inventor开发乐高EV3控制程序初试
2、发送指令
EV3直接控制指令(Direct Command)一般采用字节码串的形式,可以想象成是一连串挨在一起的、固定大小的格子,即
 
| 字节0 | 字节1 | 字节2 | 字节3 | 字节4 | 字节5 |…| 字节n |
 
其中,字节0-1为指令长度,字节2-3为消息计数器,字节4为指令类型(0×80为不需返回信息的指令,如启动电机,0×00为需返回信息的指令,如读传感器),字节5-6为全局和本地变量字节数,主要用于存储返回信息等。这七个字节构成各类控制指令通用的头信息格式,而从字节7开始,则为与特定控制指令相关的字节串,与EV3虚拟机中的字节码定义有关,一般包括指令码、参数和返回变量等,如启动端口A所连接电机的指令定义是opOUTPUT_START,LC0(0),LC0(0×01),则相应的字节串为A60001,其中0xA6即为该指令对应的字节编码,0×01则为端口A的编码,具体的指令定义及相应的编码设定可查阅EV3的源码文件,此处不再赘述。
为实现与EV3间的通信信息传输,我们需要利用BluetoothClient的Send…方法将不同指令所对应的字节码逐个发送出去,对应直接控制指令(Direct Comand),EV3一旦收到指令即刻产生相应动作。以下我们给出与示例相关的opOUTPUT_POWER、opOUTPUT_START、opOUTPUT_STOP以及opINPUT_READ等指令的实现代码,为便于说明代码没有进行优化,仅供参考。
App <wbr>Inventor开发乐高EV3控制程序初试App <wbr>Inventor开发乐高EV3控制程序初试App <wbr>Inventor开发乐高EV3控制程序初试App <wbr>Inventor开发乐高EV3控制程序初试
关于opINPUT_READ过程块需要注意的是,这里没有将全部的参数都提取出来,其中最重要的是传感器的类型和模式参数,为测试方便,我们将其硬编码为端口默认的红外传感器和近距检测模式,更详细的说明和设定也请参照EV3相关源码。
3、读取数据
EV3的返回数据也采用字节码串的形式,和控制指令的格式基本类似,其字节0-1为返回信息的长度,字节2-3为消息计数器,字节4为返回类型(0×02为对直接指令的应答,0×04为应答失败),从字节5开始则为具体的应答数据,即读取指令中所设定的全局变量值,我们也将其转换为对应的App Inventor过程块,如图所示。
App <wbr>Inventor开发乐高EV3控制程序初试
五、示例
示例一的功能是控制EV3小车向前行进,需同时驱动两个大型电机一起转动,其中的关键是端口的设定,当驱动单电机转动时,我们一般会将过程块的port参数设为对应的端口值,而当驱动多电机时则应将port参数设为多个电机对应的端口值之和,如BC口电机同时转动,则port值为6,而如果还要让位于端口A的中型电机也同时转动,则port值设为7等等,限于篇幅,这里只给出了BC口电机同时转动的例子,并且省略了界面设定的相关内容。依照此例,应该很容易开发出左右转向、后退等其他功能,因此也不再赘述。
App <wbr>Inventor开发乐高EV3控制程序初试

 
示例二的功能为读取EV3红外传感器(连接在端口4上)所采集到的前方障碍物距离数值,并将其显示在用户界面中。根据EV3的相关技术说明,此数值应为70厘米范围内的百分数换算值。另外,对于读取时间的控制,这里简单采用了App Inventor的Clock组件及其Timer方法,间隔设定为1s。
App <wbr>Inventor开发乐高EV3控制程序初试

附件:项目源码