机器人姿态(21):姿态试验(续)

MCU这端增加了pitch/yar/roll角度的计算,PC这端用LabVIEW动画显示姿态。

一、

姿态试验

二、

姿态试验

三、

这里是视频

机器人姿态(19):姿态试验

简单试验系统:MCU采用号称最强51的STC-12c5a,一路串口用于蓝牙数据通信,一个定时器资源获取闭环周期。IMU采用九轴MPU9150,IIC总线。无线透传采用蓝牙4.0的CC2540,工作于从模式。PC端插一块CC2540转串口,工作于主模式。上位软件使用LV,接收数据,绘制波形。框图如下:

试验框图

有五组角度:

试验效果都差不多:

各个角度都差不多

手摇从0~+180度~-180度~+180度~-180度, 红线不知道:

两个周期

静止20来分钟,好像陀螺仪漂移很大,不知道:

长时间漂移

机器人姿态(17):安卓系统重力感应App开发

现在的手机都具有传感器,也基本都有低功耗蓝牙。利用加速度计可以写一些游戏,例如桌面台球等等手机小游戏。再加上蓝牙就可以做一些硬件设备,例如体感控制器,挥挥手就可以控制灯泡鼠标,等等。程序实现上,重力感应比较简单,蓝牙BLE相对复杂。

  • 重力感应

Android从SDK1.5开始就支持重力传感器,也称为加速度传感器。这个传感器可以检测手机姿态,手机反转倾斜程度可以由传感器检测到,类似三轴加速度计MPU-3050。

这个主要包括传感器扫描和一个回调函数:

//变量

private SensorManager sm;
private Sensor sensor;
private SensorEventListener mySensorListener;

//ͨ通过服务得到传感器管理对象
sm = (SensorManager) MainActivity.ma.getSystemService(Service.SENSOR_SERVICE);
sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到重力传感器实例

mySensorListener = new SensorEventListener() {

public void onSensorChanged(SensorEvent event) {
//传感器获取值发生改变,在此处理
x = event.values[0]; //手机横向翻滚,x>0左翻,x<0右翻
y = event.values[1]; //手机纵向翻滚,y>0后翻,y<0前翻
z = event.values[2]; //屏幕朝向上下,z>0朝上,z<0 朝下

//传感器的精度发生改变时响应此函数
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}

sm.registerListener(mySensorListener, sensor, SensorManager.SENSOR_DELAY_FASTEST);
//第一个参数是传感器监听器,第二个是需要监听的传感实例

以上x/y/z单位是重力加速度m/s^-2。

重力加速度传感器

  • 蓝牙通讯

这个主要包括设备扫描、交互控制、基础服务三部分

  1. 设备扫描

一、设备扫描

private BluetoothManager mBluetoothManager;

private BluetoothAdapter mBluetoothAdapter;
private DeviceListAdapter mDeviceListAdapter;//设备列表

private BluetoothDevice mBluetoothDevice;//设备

  1. 交互控制

//变量
private ExpandableListView mGattServicesList;//服务列表
private BluetoothLeService mBluetoothLeService;//服务

private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics;//特征列表

private BluetoothGattCharacteristic mNotifyCharacteristic;//特征

private final ServiceConnection mServiceConnection = new ServiceConnection() {…

//实例化ServiceConnection接口;重写onServiceConnected和onServiceDisconnected…

public void onServiceConnected(ComponentName componentName, IBinder service){

BluetoothLeService mBluetoothLeService =;//在这初始化这个关键服务类

private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {…

//处理蓝牙服务触发的事件

displayGattServices(mBluetoothLeService.getSupportedGattServices());

displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));

//可以设置一个按钮主动发送字符出去用于测试

mBluetoothLeService.sendSetting();

… …

public void onCreate(Bundle savedInstanceState) {…

Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);//在onCreate()里新建Intent

bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);//并绑定服务

//注意后面需要unbindService

 

protected void onResume() {…

registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());//注册分发事件的receiver,注意后面需要unregisterReceiver

boolean result = mBluetoothLeService.connect(mDeviceAddress);//建立服务

private void displayGattServices(List<BluetoothGattService> gattServices) {//示例

 

List<BluetoothGattService> gattServices;

//服务的gat列表

ArrayList<HashMap<String, String>>
gattServiceData;

//服务的MAP表

 

ArrayList<ArrayList<BluetoothGattCharacteristic>>;//特征的gat列表们

ArrayList<ArrayList<HashMap<String, String>>>
gattCharacteristicData;//特征的MAP表们

 

for (BluetoothGattService gattService : gattServices) {

//对于每项的gat服务

HashMap<String, String> newServiceData;

//对应该项的MAP服务

 

–ArrayList<BluetoothGattCharacteristic> newgattCharas;//特征的gat表们

–ArrayList<HashMap<String, String>> newCharacteristicGroupData;//特征的MAP表们

for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {

  1. 基础服务

//GATT负责BLE连接读写属Profile通用规范。Service是Characteristic的集合,例如一个“Heart Rate Monitor”的service可能包含多个Characteristics,其中一个Characteristic可能叫做“heart rate measurement”。Characteristic为一个数据类型,包括一个value以及零到多个对此value的描述(Descriptor),Descriptor对Characteristic的描述一般例如范围、计量单位等。

//变量

private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;

private BluetoothGatt mBluetoothGatt;

private int mConnectionState = STATE_DISCONNECTED;

//需要注意一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回,例如discoverServices与onServicesDiscovered回调。例如readCharacteristic要在onCharacteristicRead里面。setCharacteristicNotification要在onCharacteristicChanged里面。 writeCharacteristic会到onCharacteristicWrite里面。

//操作的回调函数CB。重写接收到的消息的处理。

private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

//—1—状态改变

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

if (newState == BluetoothProfile.STATE_CONNECTED) {

–String intentAction = ACTION_GATT_CONNECTED;

–broadcastUpdate(intentAction);//广播意图,在交互控制里面处理

mBluetoothGatt.discoverServices();//发起活动,在交互控制里面处理

//—2—发现服务

public void onServicesDiscovered(BluetoothGatt gatt, int status) {

broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);//广播意图,在交互控制里面处理

//寻找服务之后,我们就可以和设备进行通信,比如下发配置值,获取设备电量什么的

//—3—读取到值

public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {

if (characteristic.getUuid().toString().equals(“00002a19-0000-1000-8000-00805f9b34fb”)){//根据UUID来判断读到的是什么值

broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic););//广播意图,在交互控制里面处理

//—4—收到上报值

public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) {

//—5—特征被写

public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status)

{

//根据 characteristic.getValue()来判断是哪个值发送成功了

//比如连接上设备之后有一大串命令需要下发,调用多次写命令, 这样需要判断是不是所有命令都成功了

//操作的主动方法。常规用到的有:connect,discoverServices,disconnect,readCharacteristic,setCharacteristicNotification,getServices

//—1—connect

public boolean connect(final String address) {

mBluetoothGatt = device.connectGatt(this, false, mGattCallback);//连接成功,到回调onConnectionStateChange

//—2—disconnect

public void disconnect() {

//—3—read

public void readCharacteristic(BluetoothGattCharacteristic characteristic) {

mBluetoothGatt.readCharacteristic(characteristic);

//—4—读操作示例

public void readBatrery(){

//—5—写操作示例
public void sendSetting(){

  • 读写示例

//中心设备向外围设备的写入命令字

public void WriteSetting(){
BluetoothGattService sendService
= mBluetoothGatt.getService(UUID.fromString(“0000fff0-0000-1000-8000-00805f9b34fb”));
//此处的0000180f…取决于询问硬件
if(sendService!=null) {
BluetoothGattCharacteristic sendCharacteristic
= sendService.getCharacteristic(UUID.fromString(“0000fff1-0000-1000-8000-00805f9b34fb”));
//此处的0000180f…取决于询问硬件
if(sendCharacteristic!=null) {
sendCharacteristic.setValue //(new byte[] { 0x01,0x02,0x03  });
(new byte[]  {0x24,0x4d,0x3c,} );//命令字
mBluetoothGatt.writeCharacteristic(sendCharacteristic);//写命令到设备,

}

//中心设备向外围设备的读取信息

低功耗蓝牙4.0BLE通讯

机器人姿态(15):安卓系统无线通讯App开发

  • 无线通讯

小车、平衡车、飞行器等,出于调试和使用目的,需要不依赖线缆连接的通讯功能。这个通常是手机。

小车或飞行器的MCU本身提供的是串口,如果需要无线的数据转发,要用到数据透传。所谓透传, 就是MCU把数据通过串口经由透传模块以无线电波而非线缆连接的形式传递出去。

T宝有很多现成模块:蓝牙透传(10米),wifi透传(100米),远距离的有2.4g透传(10km),目前常用的是蓝牙。

  • 蓝牙透传

蓝牙透传常见的有两种:一种使用BC417芯片的是蓝牙2.0版本,一般手机蓝牙都支持;另一种使用CC2540芯片的是蓝牙4.0版本,也就是BLE:Bluetooth Low Energy,要求手机硬件在4.0以上同时要求Android4.3(API level 16)以上,这样才支持BLE协议。

只要把这种模块的Rx/Tx连接到MCU相应串口的Rx/Tx,同时接好VCC/GND,就可以正常工作。

  • 手机程序

检验是否工作有两种方式:一个是在手机安装蓝牙App,通过App可以接收到发来的串口数据;一种是在PC机另安装一个蓝牙透传模块,也可以接收到数据。

要注意的地方,是在通过AT-command修改透传模块的波特率的时候,要注意以0x0A/0x0D结尾。

安卓App程序,整体很简单。

注意不要操作常规Services和Characteristics,只要根据UUID判断出硬件的蓝牙特征码,然后操作特征码即可。

Setting: 9600, Both NL and CR.
AT
OK
AT+BAUD=?
OK:BAUD=9600
AT+NAME=?
OK:NAME=LanQianTech
AT+ROLE=?
OK:ROLE=S
M: 主设备
S: 从设备

常见的问题,一般是App软件中的特征码和硬件模块的特征码不匹配,那么通信不成功。