微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 基于CC2640蓝牙4.2的智能健身自行车(附带简易APP)(结项)

基于CC2640蓝牙4.2的智能健身自行车(附带简易APP)(结项)

时间:10-02 整理:3721RD 点击:

经过一个多星期的开发测试,智能自行车的开发终于进入了尾声。昇润科技的SDK大大简化了开发时间,使得开发者能快速、高效的完成开发,同时也能保证设备的低功耗与强鲁棒性。


下面为目前已完成进度:

实现了对自行车的测速功能。

实现了对心率粗略的测量,在传感器佩戴良好的情况下,可以实现较精确的对心率的测量。

实现了数据定时回传功能,配合对应开发的APP可实现实时速度显示。

APP开发完成,可实现连接或断开设备、读取所需数据并显示。


首先说下测速原理。


室内自行车的转盘上我放置了两个强磁铁,其经过霍尔元件时会触发中断。CC2640每两秒统计一次中断触发次数,同时根据外径计算出当前对应的速度。设备安置如下:



计算速度的代码如下:


很简单的计算,半径单位为厘米,周长 C = 2*Pi*R,如果放了一个磁铁那么计数器Counter与周长的乘积就应该除以二。得到了当前速度(m/ms),将其换算成km/h,即为CurrentSpeed。


心率测量的计算算法稍微麻烦一点,我分成心率检出跟心率计数两个部分来说明。


心率检出:

首先说下采样速率,100hz,速率不太高,勉强够用,速度越快精度越高。


采样得到的图像近似如下图:



首先交代下状态:

依次为:低于平均,高于平均且上升,高于平均且下降。

  1. typedef enum {BelowAverage,AboveAverageRising,AboveAverageFalling}HeartBeatSituation;

复制代码

我们可以看到心跳的最高电平很高,其他的都不算太高。首先进行500次采样,对采集得到的电压取平均值作为阈值。

ADC采样得到的电压低于阈值,则置状态:BelowAverage;

若其高于阈值,则与采样得到的最高电平(HeartBeatsPeak,默认为0)比较,若高于,则置状态AboveAverageRiseing,并修改最高电平数值;若低于,则置AboveAverageFalling。

当其再次低于阈值时,判断其状态,若其为AboveAverageFalling,或者最高电平(HeartBeatsPeak)不为0,则判定一次心跳(可看成下降沿触发中断)。若不是,则置状态:BelowAverage。


这就完成了心率检出。


对应实现的代码如下:

  1. void BeatsCaculate(uint16_t Level)
  2. {
  3.   if(SampleCounter != -1)
  4.   {
  5.     return ;
  6.   }
  7.   if(Level <= AverageLevel)
  8.   {
  9.     if(HeartBeatStatues == AboveAverageFalling || HeartBeatsPeak)
  10.     {
  11.       HeartBeatsCounter ++;
  12.     }
  13.     HeartBeatStatues = BelowAverage;
  14.     HeartBeatsPeak = 0;
  15.   }
  16.   else
  17.   {
  18.     if(HeartBeatsPeak < Level)
  19.     {
  20.       HeartBeatStatues = AboveAverageRising;
  21.       HeartBeatsPeak = Level;
  22.     }
  23.     else
  24.     {
  25.       HeartBeatStatues = AboveAverageFalling;
  26.     }
  27.   }
  28. }

复制代码

心率计数:

这个跟上面相比,我现在的处理方法就很简单很粗糙了。

我使用的方案主要有两套,最开始的一种方法是维护一个四元素队列,每秒动态的替换心率数据,使用最小二乘法拟合线形回归方程,对其进行积分来得到每分钟的心率。但这个因为前一级心率检出的效果严重依赖佩戴方式,所得到的效果并不好。


现在采用的方法很简单,对其采样5s,把得到的心率总数乘以12,即计算出当前的心率速度。虽然跟随性不太好,但准确性还是可以的。


数据回传就不多说了,很简单,Set一下就OK的。

App方面需要讲的就太多了。

我刚进入App开发不久,所以这次没有使用昇润科技提供的安卓代码,而是选择自己造了一遍轮子进而了解下App的开发过程。


首先是获取权限并开启蓝牙。

获取权限:

  1. if (!App.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
  2.             throw new RuntimeException("Don't support BLE.");
  3.         }

复制代码

开启蓝牙:

  1. bluetoothManager = (BluetoothManager) ParentActivity.getSystemService(Context.BLUETOOTH_SERVICE);
  2.         mBluetoothAdapter = bluetoothManager.getAdapter();
  3.         if (!mBluetoothAdapter.isEnabled()) {
  4.             if(mBluetoothAdapter.enable())
  5.             {
  6.                 Toast.makeText(ParentActivity,"蓝牙打开成功!",Toast.LENGTH_SHORT).show();
  7.                 while(!mBluetoothAdapter.isEnabled())
  8.                 {
  9.                     ThreadSleep(10);
  10.                 }
  11.             }
  12.             else
  13.             {
  14.                 Toast.makeText(ParentActivity,"蓝牙打开失败!",Toast.LENGTH_SHORT).show();
  15.                 return;
  16.             }
  17.         }

复制代码

之后是连接BLE设备。

  1. public void ConnectDevices(BluetoothDevice[] Device, String TargetMAC) {
  2.         if (!isConnect) {
  3.             for (BluetoothDevice Dev : Device) {
  4.                 if (Dev.getAddress().equals(TargetMAC)) {
  5.                     mBluetoothGatt =  Dev.connectGatt(ParentActivity, false, new BluetoothGattCallback() {
  6.                         @Override
  7.                         public void onCharacteristicRead(BluetoothGatt gatt,
  8.                                                          BluetoothGattCharacteristic characteristic, int status)
  9.                         {
  10.                             DataRead = characteristic.getValue();
  11.                             ReadyToRead.release(1);
  12.                         }
  13.                         @Override
  14.                         public void onServicesDiscovered(BluetoothGatt gatt, int status)
  15.                         {
  16.                             BLEService = gatt.getServices();
  17.                         }
  18.                         @Override
  19.                         public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
  20.                             switch (newState) {
  21.                                 case BluetoothProfile.STATE_CONNECTED:
  22.                                     mBluetoothGatt.discoverServices();
  23.                                     isConnect = true;
  24.                                     break;
  25.                                 case BluetoothProfile.STATE_DISCONNECTED:isConnect = false;
  26.                                     break;
  27.                                 default:
  28.                                     break;
  29.                             }
  30.                         }
  31.                     });
  32.                 }
  33.             }
  34.         }
  35.     }

复制代码


最后就是从设备读取数据了。

  1. public byte[] GetData(BluetoothGattCharacteristic characteristic)
  2.     {
  3.         if(mBluetoothGatt.readCharacteristic(characteristic))
  4.         {
  5.             try {
  6.                 ReadyToRead.acquire();
  7.             }
  8.             catch (InterruptedException e){}
  9.             return DataRead;
  10.         }
  11.         return null;
  12.     }

复制代码

下面放出演示图:

前三张为心率数据发送。因为实在是无法一边拿着板子一边握着传感器一边截图一边蹬车,所以只能分开来进行演示。

UUID为00001002那个即为对应接收的。


      

      

  


下面四张为float型的当前速度,直接在App转成float即可。只要他是按照IEE754就OK(基本都按照吧……)。



      

      

   

最后一张为停止踩单车后的数据。



下面为APP获取数据的演示。









全部代码传于百度盘:

链接:http://pan.baidu.com/s/1kUXsXr5 密码:kzkv


PS:App需要先连接设备后再读取数据,否则会闪退……(没做异常处理……原谅我……)

PS:连接的设备的MAC在程序里写死了……(原谅我)

PS:安卓版本需要5.1以上。


以上。


不错的文档,值得收藏

好详细,收了。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top