查看: 2827|回复: 2

【Arduino 101】结合IMU和BLE的计步服务

[复制链接]
  • TA的每日心情
    开心
    2017-7-3 15:02
  • 签到天数: 56 天

    [LV.5]常住居民I

    发表于 2017-5-15 22:14 | 显示全部楼层 |阅读模式
    概述:
          作为可穿戴芯片,首先应该能完成的就是计步服务。CurieIMU库提供了计步功能的函数,BLE GATT服务里也提供了 "Running Speed and Cadence" (跑步速度与节奏) 服务,但具体如何把IMU和BLE结合起来,完成一个完整的计步服务,例程里并没有。本帖提供一个完整的,结合IMU和BLE的计步服务。
    效果图.jpeg

    图:达到的效果


    目的:
          使用Arduino 101,编写使用IMU计步,使用BLE传输数据的程序。并使用手机APP NRF toolbox显示计步数据。



    需要:
           硬件需要:Arduino 101、手机
           软件需要:Arduino 101 2.x+库、NRF toolbox(一款手机上的多功能BLE服务获取APP)
           知识储备:查询GATT服务、使用Arduino 101编写GATT服务

    下载NRF toolbox可以去奈何大大的帖子:http://www.arduino.cn/thread-22901-1-1.html

    编写Arduino 101的GATT服务可以参考我的帖子:http://www.arduino.cn/thread-42927-1-1.html



    编程思路:
    1、使用IMU完成计步
           使用IMU计步非常简单,只需要调用现成的函数。首先,在setup()函数里,需要初始化设置CurieIMU为计步模式:
    [mw_shl_code=cpp,true]CurieIMU.begin();
      CurieIMU.setStepDetectionMode(CURIE_IMU_STEP_MODE_NORMAL);
    CurieIMU.setStepCountEnabled(true);[/mw_shl_code]然后CurieIMU就会自动完成计步,你随时可以调用以下函数获取当前累计步数:[mw_shl_code=cpp,true]CurieIMU.getStepCount();[/mw_shl_code]仅仅获取累计步数是不行的,因为接下来我们会看到BLE RSC服务需要传送的数据是“每分钟步数”,我们设法在Curie上完成这个数据的计算。方法很简单,每4分钟运行一次loop函数,获取新的步数并减去旧的步数,得到4秒内计步的数值。然后乘以15,就是每分钟步数。


    2、查询计步相关的GATT服务
           BLE计步服务是 "Running Speed and Cadence" (RSC) ,蓝牙官网对该服务描述请参考:
    https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.running_speed_and_cadence.xml

            如果不明白如何查询GATT服务,或查到了不知道如何编写相应的Arduino程序,可以参考我的这篇帖子:
    编写Arduino 101的GATT服务可以参考我的帖子:http://www.arduino.cn/thread-42927-1-1.html

           我们看到,在RSC服务提供了众多服务数据,包括行走速度、每步长度、每分钟步数等。因为我们只有Curie自带的加速度计陀螺仪,无法测出这么多数据,因此我们只计算每分钟步数,其他数据统统置0。
           仔细阅读RSC服务的要求后,得到编程思路如下:程序要建立一个UUID为0x1814的RSC服务、一个UUID为0x2A53的CSC Measurement特征、一个UUID为0x2A54的CSC Feature特征。其中CSC Feature特征包括2字节,我们让它恒为0。CSC Measurement特征包括4字节(最短情况下):第一字节为控制字符Flags,我们让它恒为0;中间2字节是行走速度,我们让它恒为0;后1字节是每分钟步数,我们使用计算出的每分钟步数数据,不断地更新它。




    代码:
    [mw_shl_code=cpp,true]#include <CurieIMU.h>
    #include <CurieBLE.h>

    BLEPeripheral blePeripheral;

    // Running Speed and Cadence (RSC) 服务: UUID=1814
    // 完整的RSC服务字段描述请见 https://www.bluetooth.com/specif ... rsc_measurement.xml
    BLEService RSC("1814");
    // RSC Feature 特征:UUID=2A54,Property=Read,数据长度=2 (因此直接使用Short类型)
    BLEShortCharacteristic RSCFeature("2A54", BLERead);
    // RSC Measurement 特征:UUID=2A53,Property=Notify,数据长度=4Byte
    BLECharacteristic RSCMeasure("2A53", BLENotify , 4);

    void setup() {
      // 初始化BLE
      blePeripheral.setLocalName("Curie");
      blePeripheral.setAdvertisedServiceUuid(RSC.uuid());
      blePeripheral.addAttribute(RSC);
      blePeripheral.addAttribute(RSCFeature);
      blePeripheral.addAttribute(RSCMeasure);
      blePeripheral.begin();
      RSCFeature.setValue(0);

      // 初始化IMU为计步模式并开始计步
      CurieIMU.begin();
      CurieIMU.setStepDetectionMode(CURIE_IMU_STEP_MODE_NORMAL);
      CurieIMU.setStepCountEnabled(true);
    }

    // 每 INTERVAL 秒,BLE发送一次数据
    #define INTERVAL 4

    void loop() {
      // RSC Measurement 特征 的4Byte发送缓冲区
      static uint8_t data[4] = {0,0,0,0};
      // 上一次计步的步数,即INTERVAL秒前的计步步数
      static uint32_t lastStepCnt=0;
      // 每分钟步数
      static uint8_t spm;

      // 每分钟步数 = (此次计步步数-INTERVAL秒前的计步步数) * 每分钟60秒 / INTERVAL
      spm = (CurieIMU.getStepCount() - lastStepCnt) * 60 / INTERVAL;
      
      lastStepCnt = CurieIMU.getStepCount();

      // 根据RSC的字段描述
      // RSC Measurement 特征的第三字节为每分钟步数
      // 在仅有加速度计陀螺仪的情况下,仅能完成计步
      // 而其他字段,Curie缺乏相关传感器无法测量,因此保持为0
      data[3] = spm;
      
      // 更新RSC Measurement
      RSCMeasure.setValue(data,4);

      // 等待INTERVAL秒
      delay(INTERVAL*1000);
    }[/mw_shl_code]



    程序测试:
             首先,你需要一个装有NRF toolbox的手机,下载NRF toolbox可以去奈何大大的帖子:http://www.arduino.cn/thread-22901-1-1.html
             上传代码到Arduino 101后,打开NRF toolbox,点击RSC,在下方点击Connect,选择"Curie"进行连接,然后带着Arduino 101走几步路,就可以看到手机屏幕上的计步数据更新。
    流程.jpg

    图:程序测试流程





  • TA的每日心情
    开心
    2019-7-17 13:13
  • 签到天数: 264 天

    [LV.8]以坛为家I

    发表于 2017-5-16 16:14 | 显示全部楼层
    感谢灯灯师兄分享。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    热门推荐

    新设计的一款遥控播放音乐机器人
    新设计的一款遥控播放音乐
    近期设计的一款遥控播放音乐歌曲的机器人终于完工了,DF mini mp3模块是真的强大。sol
    ESP8266物联网创意点阵时钟,女朋友看了都想要!
    ESP8266物联网创意点阵时
    [md]本文作者:默 & 铁熊 前段时间我在网上看到了一款很有意思的点阵时钟,它可以
    按键中断无法触发
    按键中断无法触发
    如题,按键中断无法触发,设成电平变化触发中断程序,但是flag的状态一直不变 void
    【原创】全球最小口袋3D打印机mini one直播教程贴
    【原创】全球最小口袋3D打
    最近闲得蛋疼,没事搞个掌上3D打印机,先放效果图吧。 搞了半天,终于能正常打印,
    OLED心率示波仪
    OLED心率示波仪
    在ARDUINO UNO开发板上插上一片0.96寸OLED显示屏并上传已下简单的程序就能构成一个OLE
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表