查看: 2738|回复: 0

【Arduino101教程】IMU中断检测

[复制链接]
  • TA的每日心情
    郁闷
    2018-12-6 22:21
  • 签到天数: 48 天

    [LV.5]常住居民I

    发表于 2017-3-12 17:35 | 显示全部楼层 |阅读模式
    除了姿态检测外,IMU还可以用于设备运动状态的检测。CurieIMU自带了多种运动状态检测模式,检测到相关状态后,可以生成一个中断事件,并执行相应的中断函数。
    要使用该功能,需要先定义一个中断函数:
      
    static void eventCallback() {
      
    //函数内容
      
    }
      
    中断函数应无参数无返回值。
    与I/O的中断类似,IMU中断同样需要指定中断函数和中断模式。中断函数的设置语句如下:
      
    //设置中断函数
      
    CurieIMU.attachInterrupt(eventCallback);
      
    eventCallback即中断函数名,当中断触发后,会运行该函数名对应的中断函数。
    中断模式设置语句如下:
      
    //设置中断模式
      
    CurieIMU.interrupts(CURIE_IMU_MODE);
      
    其中参数CURIE_IMU_MODE为中断模式,CurieIMU支持的中断模式如表x-xx
      
    中断模式
      
    对应枚举值
    自由落体
    CURIE_IMU_FREEFALL
    震动检测
    CURIE_IMU_SHOCK
    运动检测
    CURIE_IMU_MOTION
    零移检测
    CURIE_IMU_ZERO_MOTION
    计步功能
    CURIE_IMU_STEP
    单击检测
    CURIE_IMU_TAP
    敲击并震动检测
    CURIE_IMU_TAP_SHOCK
    敲击并禁止检测
    CURIE_IMU_TAP_QUIET
    双击检测
    CURIE_IMU_DOUBLE_TAP
    当设定的中断模式被触发后,即会运行中断函数eventCallback
    如果不再需要IMU中断,则可以使用中断分离语句关闭中断功能。语句如下:
      
    CurieIMU.detachInterrupt();
      

    利用CurieIMU中断,我们可检测Genuino101是否在移动的,并得知移动方向。可通过Arduino IDE菜单>文件>示例>CurieIMU> ZeroMotionDetect 打开运动检测示例,示例程序如下:
      
    /*
      
        Copyright (c) 2016 Intel Corporation.   All rights reserved.
      
        See the bottom of this file for full license terms.
      
    */
      
      
    /*
      
        This sketch example demonstrates how the BMI160 accelerometer on the
      
        Intel(R) Curie(TM) module can be used to detect zero motion events
      
    */
      
      
    #include "CurieIMU.h"
      
      
    boolean ledState = false;          // state of the LED
      
    void setup() {
      
       Serial.begin(9600); // initialize Serial communication
      
       while(!Serial) ;    // wait for  serial port to connect.
      
      
       /* Initialise the IMU */
      
       CurieIMU.begin();
      
       CurieIMU.attachInterrupt(eventCallback);
      
      
       /* Enable Zero Motion Detection */
      
       CurieIMU.setDetectionThreshold(CURIE_IMU_ZERO_MOTION, 50);  // 50mg
      
       CurieIMU.setDetectionDuration(CURIE_IMU_ZERO_MOTION, 2);    // 2s
      
       CurieIMU.interrupts(CURIE_IMU_ZERO_MOTION);
      
      
       /* Enable Motion Detection */
      
       CurieIMU.setDetectionThreshold(CURIE_IMU_MOTION, 20);      // 20mg
      
       CurieIMU.setDetectionDuration(CURIE_IMU_MOTION, 10);       // trigger times of consecutive slope  data points
      
       CurieIMU.interrupts(CURIE_IMU_MOTION);
      
      
       Serial.println("IMU initialisation complete, waiting for events...");
      
    }
      
      
    void loop() {
      
       // if zero motion is detected, LED will be turned up.
      
       digitalWrite(13, ledState);
      
    }
      
      
    static void eventCallback(void){
      
       if (CurieIMU.getInterruptStatus(CURIE_IMU_ZERO_MOTION)) {
      
         ledState = true;
      
         Serial.println("zero motion detected...");
      
       }  
      
       if (CurieIMU.getInterruptStatus(CURIE_IMU_MOTION)) {
      
         ledState = false;
      
         if (CurieIMU.motionDetected(X_AXIS, POSITIVE))
      
           Serial.println("Negative motion detected on X-axis");
      
         if (CurieIMU.motionDetected(X_AXIS, NEGATIVE))
      
           Serial.println("Positive motion detected on X-axis");
      
         if (CurieIMU.motionDetected(Y_AXIS, POSITIVE))
      
           Serial.println("Negative motion detected on Y-axis");
      
         if (CurieIMU.motionDetected(Y_AXIS, NEGATIVE))
      
           Serial.println("Positive motion detected on Y-axis");
      
         if (CurieIMU.motionDetected(Z_AXIS, POSITIVE))
      
           Serial.println("Negative motion detected on Z-axis");
      
         if (CurieIMU.motionDetected(Z_AXIS, NEGATIVE))
      
           Serial.println("Positive motion detected on Z-axis");
      
       }  
      
    }
      
    编译上传以上程序,打开串口监视器,并将Genuino 101移动或保持静止,可见串口输出类似信息:

    当Genuino 101静止时,CurieIMU.getInterruptStatus(CURIE_IMU_ZERO_MOTION)会返回true;而运动时,CurieIMU.getInterruptStatus(CURIE_IMU_MOTION)会返回true。而使用CurieIMU.motionDetected(X_AXIS,POSITIVE)可以检测该运动是否延着X轴正方向,如果是该函数会返回true。

    利用IMU的中断检测功能,可以制作一个非接触式开关LED试验。试验代码如下:
      
    #include  "CurieIMU.h"
      
      
    bool  state=false;
      
    void  setup() {
      
      pinMode(13,OUTPUT);
      
      CurieIMU.begin();
      
      CurieIMU.attachInterrupt(eventCallback);
      
      
      // Increase Accelerometer range to allow  detection of stronger taps (< 16g)
      
      CurieIMU.setAccelerometerRange(32);
      
      CurieIMU.setAccelerometerRate(1600);
      
      
      // Reduce threshold to allow detection of  weaker taps (>= 100mg)
      
       CurieIMU.setDetectionThreshold(CURIE_IMU_TAP, 100);
      
      
      // Enable Tap detection
      
      CurieIMU.interrupts(CURIE_IMU_TAP);
      
    }
      
      
    void  loop() {
      
    }
      
      
    static  void eventCallback()
      
    {
      
      if  (CurieIMU.getInterruptStatus(CURIE_IMU_TAP)) {
      
        state =!state;
      
        digitalWrite(13,state);
      
      }
      
    }
      
    编译并上传以上代码后,将Genuino 101平放在桌面上,敲击桌面,即可控制板载LED灯的亮灭。

    相关IMU的应用案例还有很多,如计步器。计步器是基于IMU功能的常见应用,智能手机、智能手表几乎都具备此功能,CurieIMU自带四种记步模式,可以满足多种场合的计步需求。

      
    模式
      
    对应枚举值
    正常模式
    CURIE_IMU_STEP_MODE_NORMAL
    敏感模式
    CURIE_IMU_STEP_MODE_SENSITIVE
    健壮模式
    CURIE_IMU_STEP_MODE_ROBUST
    未知模式
    CURIE_IMU_STEP_MODE_UNKNOWN

    通常使用正常模式即可,语句如下:
      
    // 切换到正常计步模式
      
    CurieIMU.setStepDetectionMode(CURIE_IMU_STEP_MODE_NORMAL);
      
    // 开启计步功能
      
    CurieIMU.setStepCountEnabled(true);
      


    完整示例程序如下:
      
      
    #include "CurieIMU.h"
      
      
    boolean stepEventsEnabeled = true;
      
    long lastStepCount = 0;
      
      
    void setup() {
      
       Serial.begin(9600);
      
       while(!Serial) ;
      
       // 初始化IMU
      
       CurieIMU.begin();
      
       // 切换到正常计步模式
      
       CurieIMU.setStepDetectionMode(CURIE_IMU_STEP_MODE_NORMAL);
      
       // 开启计步功能
      
       CurieIMU.setStepCountEnabled(true);
      
      
       if (stepEventsEnabeled) {
      
         // 关联中断函数
      
    CurieIMU.attachInterrupt(eventCallback);
      
    // 启用步数检测中断
      
         CurieIMU.interrupts(CURIE_IMU_STEP);
      
         Serial.println("IMU initialisation complete, waiting for  events...");
      
      }
      
    }
      
      
    void loop() {
      
       //loop中定时检查步数并输出,而不使用计步事件通知
      
       if (!stepEventsEnabeled) {
      
         updateStepCount();
      
      }
      
       delay(1000);
      
    }
      
      
    static void updateStepCount() {
      
       // 获取步数
      
       int stepCount = CurieIMU.getStepCount();
      
       // 如果步数有更新,则串口输出
      
       if (stepCount != lastStepCount) {
      
         Serial.print("Step count: ");
      
         Serial.println(stepCount);
      
         // 保存步数,用以下一次比较
      
         lastStepCount = stepCount;
      
      }
      
    }
      
      
    static void eventCallback(void) {
      
       if (CurieIMU.stepsDetected())
      
         updateStepCount();
      
    }
      
      
    编译上传以上程序,并打开串口监视器,模拟走路姿势摇动Genuino 101,即可看到串口输出步数信息。

    -------------------------------------------------------------------------------------------------------------
    本教程分为五部分:
    1.配置IMU及获取数据   http://www.arduino.cn/thread-42850-1-1.html
    2.结算AHRS姿态   http://www.arduino.cn/thread-42851-1-1.html
    3.姿态数据可视化   http://www.arduino.cn/thread-42852-1-1.html
    4.IMU中断检测   http://www.arduino.cn/thread-42853-1-1.html
    5.神经元与机器学习   http://www.arduino.cn/thread-42854-1-1.html
    如果以上内容对你有帮助,你可以通过打赏支持作者
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    【人脸识别】ESP-EYE 最新的板子到货了
    【人脸识别】ESP-EYE 最新
    1.我不会编程,最多抄几个一步一步的网络教程。 2.不知道为啥就是超级喜欢电子元件。
    2.4“TFT 触摸屏ILI9341,输入示例程序后能显示画面但是无法...
    2.4“TFT 触摸屏ILI9341,
    各位大神,小弟淘了一块2.4“触摸屏,驱动是ILI9341,集成电路板。 上传示例code
    使用arduino uno用蓝牙碰到温湿度问题
    使用arduino uno用蓝牙碰
    [*]硬件: [Arduino UNO] [*]接入方式: [*]blinker库版本: [最新刚下的] [*]开发环境
    Arduino MEGA 与UNO 通过nRF24L模块通讯
    Arduino MEGA 与UNO 通过n
    之前在深水宝很“实惠”的店铺买了一些原件,随手砍了esp8266以及nRF24L*3 因为缺
    这次做了个8*8的RGB点阵
    这次做了个8*8的RGB点阵
    初次使用贴片,5050RGB用了64个,从设计到布线一次成功,编写了测试程序小灯都没问题
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表