一、让Android与外部的设备互动
iTank智能型移动平台基本款简介
iTank智能型移动平台是一台履带车,车体上方的控制板有一颗微处理器,我们可以通过它的UART或是I2C接口下达指令来控制iTank:
在控制板上具备有UART插座,可搭配使用F1611A蓝牙无线传输模块从手机端以蓝牙连接来远程控制iTank:
UART插座会将蓝牙模块的UART接口连接到控制板上微处理器的UART接口,在手机端通过蓝牙与蓝牙模块连接后,就相当于建立一条无线传输通道,连接手机与控制板的UART接口,即可从手机送出指令给控制板上的微处理器来控制iTank。
1、复制链接库文件:将FlagAPI.jar导入项目;
2、加入蓝牙权限:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tw.com.flag.ch16_itankled" > <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
3、导入FlagAPI的类:
4、创建蓝牙对象:
5、管理蓝牙连接:
6、处理蓝牙事件:
package tw.com.flag.ch16_itankled; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextView; import tw.com.flag.api.FlagBt; import tw.com.flag.api.OnFlagMsgListener; public class MainActivity extends AppCompatActivity implements OnFlagMsgListener { FlagBt bt; //声明蓝牙对象 TextView txv; byte[] ledCmd ={ //点亮 LED0 的指令 (byte)0xFF,(byte)0xFF, (byte)0x03,(byte)0x00,(byte)0x02, (byte)0xFF,(byte)0xFF,(byte)0x00 }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.setRequestedOrientation( // 让手机屏幕保持直立模式 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); txv = (TextView)findViewById(R.id.txv); bt = new FlagBt(this); // 创建蓝牙对象 } public void onDestroy() { bt.stop(); // 确保程序结束前会停止蓝牙连接 super.onDestroy(); } public void connect(View v) { if(!bt.connect()) // 选取已配对设备进行连接 txv.setText("找不到任何已配对设备"); } public void quit(View v) { bt.stop(); finish(); } @Override public void onFlagMsg(Message msg) { switch(msg.what) { case FlagBt.CONNECTING: // 尝试与已配对设备连接 txv.setText("正在连接到:" + bt.getDeviceName()); break; case FlagBt.CONNECTED: // 与已配对设备连接成功 txv.setText("已连接到:" + bt.getDeviceName()); bt.write(ledCmd); // 送出点亮 LED0 的指令 break; case FlagBt.CONNECT_FAIL: // 连接失败 txv.setText("连接失败!请重连"); break; case FlagBt.CONNECT_LOST: // 当前连接意外中断 txv.setText("连接中断!请重连"); break; } } }
二、点亮iTank控制板上的LED灯
iTank控制板上有两颗LED,分别标示为LED0与LED1:
点亮LED的指令:
要点亮控制板上的LED,手机端程序可以通过蓝牙传递一下8个字节长度的指令(均为十六进制数值):
FF FF 03 00 data FF FF 00
其中,data是1个字节的数据,由其中的4个比特控制两个LED:
LED | 对应的控制位 |
LED0 | bit4 + bit0 |
LED1 | bit5 + bit1 |
两个比特的组合值会决定对应的LED状态:
bits组合值 | LED状态 |
00 | 变暗 |
01 | 变亮 |
10 | 保持当前状态 |
11 | 不合法的指令,舍弃不处理 |
因此,要点亮LED1,就必须传送一下指令:
FF FF 03 00 02 FF FF 00
三、手机蓝牙遥控iTank
传送特定格式的指令,FlagAPI中已经为iTank定制了一个好用的类,即FlagTank,提供了一些便利的方法可以控制iTank:
FlagTank类提供的方法:
moveF() | 前进 |
moveB() | 后退 |
moveL() | 左转 |
moveR() | 右转 |
stop() | 停止 |
move(int direction) | 根据参数指定的方向移动 |
其中,move方法的direction参数:
1 | 2 | 3 |
左前 | 前进 | 右前 |
4 | 5 | 6 |
左转 | 停止 | 右转 |
7 | 8 | 9 |
左后 | 后退 | 右后 |
package tw.com.flag.ch16_itankled; import android.content.pm.ActivityInfo; import android.os.Bundle; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextView; import tw.com.flag.api.FlagBt; import tw.com.flag.api.FlagTank; import tw.com.flag.api.OnFlagMsgListener; public class MainActivity extends AppCompatActivity implements OnFlagMsgListener { FlagBt bt; //声明蓝牙对象 FlagTank tank; //声明 iTank 对象 TextView txv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.setRequestedOrientation( // 让手机屏幕保持直立模式 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); txv = (TextView)findViewById(R.id.txv); bt = new FlagBt(this); // 创建蓝牙对象 tank = new FlagTank(bt); // 创建 iTank 对象 } public void onDestroy() { bt.stop(); // 确保程序结束前会停止蓝牙连接 super.onDestroy(); } public void connect(View v) { if(!bt.connect()) // 选取已配对设备进行连接 txv.setText("找不到任何已配对设备"); } public void quit(View v) { bt.stop(); finish(); } @Override public void onFlagMsg(Message msg) { switch(msg.what) { case FlagBt.CONNECTING: // 尝试与已配对设备连接 txv.setText("正在连接到:" + bt.getDeviceName()); break; case FlagBt.CONNECTED: // 与已配对设备连接成功 txv.setText("已连接到:" + bt.getDeviceName()); break; case FlagBt.CONNECT_FAIL: // 连接失败 txv.setText("连接失败!请重连"); break; case FlagBt.CONNECT_LOST: // 当前连接意外中断 txv.setText("连接中断!请重连"); break; } } public void forward(View v) { tank.moveF(); } public void backward(View v) { tank.moveB(); } public void left(View v) { tank.moveL(); } public void right(View v) { tank.moveR(); } public void stop(View v) { tank.stop(); } }