• Android互动设计-蓝牙遥控自走车iTank


    一、让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();
        }
    }
    
  • 相关阅读:
    TCP/IP 协议体系结构模型
    A*算法详解
    导航规划之CH算法介绍
    Crp(customizable route planning) 算法介绍
    机器学习面试题总结(笔记)
    机器学习面试问题总结
    机器学习面试常见问题
    seata-微服务集成seata
    seata-部署seata连接nacos
    Sentinel授权规则-规则管理三种模式
  • 原文地址:https://www.cnblogs.com/sirius-swu/p/6687980.html
Copyright © 2020-2023  润新知