查看: 20305|回复: 15

Arduino/Genuino 101 加速度传感器、陀螺仪传感器开发教程

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

    [LV.5]常住居民I

    发表于 2016-3-1 21:59 | 显示全部楼层 |阅读模式
    惯性测量单元(英文:Inertial measurement unit,简称IMU)是测量物体三轴姿态角(或角速率)以及加速度的装置。
    intel Curie上集成了一个BMI160 IMU,Genuino 101提供了CuireIMU库用于用户读取该传感器的数据。


    This tutorial demonstrates how to make use the Genuino 101's on-board 6-axis accelerometer/gyro to read the X, Y, and Z values of both the accelerometer and the gyroscope. While the accelerometer is able to determine the orientation of the board, the gyroscope measures the angular velocity of the board. Together, the accelerometer and the gyroscope form an Inertial Monitoring Unit (IMU) which can be used to precisely identify the orientation of the board. Madgwick's filter algorithm is used in this example to calculate four quarternions from the 6 axes' values. The quarternions are then used to calculate Euler angles Pitch, Yaw, and Roll, which are received by Processing and used to control the rotation of an object around the X, Y and Z axes.

    Instructions
    • Launch the Arduino software (IDE) and select Arduino/Genuino 101 from the Tools > Board menu.
    • Install the Madgwick library from library manager. To do this, open the Arduino Software (IDE), go to "Sketch -> Include Library -> Manage Libraries". There you can search 'Madgwick' and install the library directly from there. Please see thelibraries installation guide for a more detailed explanation on installing and importing libraries.
    • Download and Launch the Processing software and create a file with the Processing code shown below.
    • Change the Serial port to the one that your 101 is using (see "Processing Sketch" section).
    • Upload the CurieImu example to your 101, making sure that the board is flat and stationery so it can perform the calibration accurately.
    • After a few seconds, run the Processing sketch, adjust the orientation of your board, and watch as the Processing sketch gives a visualisation of your board.
    The Circuit
    image developed using Fritzing.
    How it works
    The Madgwick filter algorithm is open-source and is well documented in Madgwick's information and reports. The Madgwick filter algorithm was developed by Sebastian Madgwick during his PhD in 2010, and is designed to be computationally inexpensive and efficient even at low sampling rates. The algorithm takes raw values from a gyroscope and accelerometer, and uses them to return four quaternions, which are 4-dimensional numbers which contain x, y, and z values to represent the axis around which rotation occurs, as well as a ω value which represents the value of rotation which occurs around the same axis. These quaternions can be used to calculate the Euler angles pitch, yaw, and roll; three angles used to describe the orientation of a rigid body in terms of x,y, and z as presented by Leonhard Euler in the 1700s. The equations (7) (8) (9) in Madgwick's Report are used to calculate the values for pitch, roll, and yaw, and their functions are included within the library.
    We can the Arduino/Genuino 101's on-board IMU to create a 3D representation of the board in Processing, which will move as the board does. This is achieved with the values for Euler angles pitch, roll and yaw obtained by the Madgwick filter algorithm. These values can then be sent via Serial to Processing and used as angle arguments for Processing'srotateX(), rotateY(), and rotateZ() functions. These functions take on argument, an angle in radians, and rotate the object they correspond to around their respective axis by the angle value.
    Arduino Sketch
    The sketch uses functions inside the CurieImu library to get the data from the accelerometer/gyro.
    In order to see a 3D representation in Processing, the Arduino sketch must incorporate two main functionalities; using the IMU data and algorithm to calculate yaw, pitch and roll values, and enabling serial communication in a handshake fashion in order to send those values to Processing.
    A calibration process is implemented during the setup, which can again be used or not by setting the variablecalibrateOffsets to 1 or 0 respectively. The calibration process is then excecuted if calibrateOffsets > 0 and reads the initial values of the board and executes internal calibration to generate an offset compensation value for each axis. Note that the user must keep the board perfectly still and resting horizontally as shown in Section 5.2 of theBMI160 Data Sheet.
    First, we must create a Madgwick object to access the functions from the Madgwick class in the library. Here, we call itfilter:




    We can then 'get' accelerometer and gyroscope data using the following functions from CurieIMU library:

    kittenblock中小学创客名师推荐的图形化编程软件

    CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);



    We can then use the function updateIMU() from the Madgwick library.


    kittenblock中小学创客名师推荐的图形化编程软件

    filter.updateIMU(gx / factor, gy / factor, gz / factor, ax, ay, az);
    
    yaw = filter.getYaw();
    roll = filter.getRoll();
    pitch = filter.getPitch();



    As seen in the code, the gyroscope values have been scaled down by a variable factor so that they fit into a range which works well with the algorithm. Without this scaling, the values which are inputted to the function are too high and the visualisation of the movement of the board becomes very sensitive to small changes of the 101's position, intepreting a slight change as an great change and causing the 'virtual' board to spin. The variable integer 'factor' can be adjusted to experiment with and improve the performance of the dynamic representation, and should also be increased with an increase in baud rate.
    The Serial communication can then be handled with the following block. Firstly, this checks for an incoming value of "s" from the serial which is sent by processing at the end of each loop. This ensures that the Arduino sketch does not send the values more often than Processing can process them which would result an extremely laggy visualisation. If an "s" is received, the values are sent by serial, each seperated with a comma and ending in a new line so that that each message can be parsed easily in Procesing. The full code can be found at the bottom of the page.

    kittenblock中小学创客名师推荐的图形化编程软件

    if (Serial.available() > 0) {
        int val = Serial.read();
        if(val == 's')
        {
          Serial.print(yaw);
          Serial.print(",");
          Serial.print(pitch);
          Serial.print(",");
          Serial.println(roll);
        }
       }


    Note that the serial prints for gx,gy,gz,ax,az,ay are left in loop in comments for debugging and must be commented whilst communicating with Processing.
    Processing Sketch
    If you haven't already, the first thing to do is to download the latest version of Processing from processing.org. Processing is a language similar to Arduino which allows the user to draw dynamic imagery in the familiarvoid setup() and void loop() structure. For more information on using Processing, please visit their Getting Started guide.
    The processing code receives incoming data from the serial port which is parsed and assigned to floats yaw, pitch, and roll, which are then used as arguments in RotateX(), RotateY(), and RotateZ() functions. In each iteration of loop(), Processing reads and parses the serial information, draws a 3D Arduino shape with the parsed values and then sends a "s" via serial to indicate to Arduino that it is ready for more information.
    To enable Processing to read from the same port that Arduino is sending to, myPort needs to be changed to your serial port's name. In setup(), this is the Second parameter of Serial.

    myPort = new Serial(this, Serial.list()[2], 9600);



    The correct port can be found by using the list() function from the Serial class. The number inside the square brackets refers to the number of the serial port, and will be 0, 1, 2, etc. If in doubt, you can print a list of your available serial ports in a separate sketch to determine this number.
    The function serialEvent() is then used to receive and parse data.

    void serialEvent()
    {
      message = myPort.readStringUntil(13);
      if (message != null) {
        ypr = split(message, ",");
        yaw = float(ypr[0]);
        pitch = float(ypr[1]);
        roll = float(ypr[2]);
      }
    }



    This reads from the serial port until ASCII character 13 (new line) and then uses the split() function to seperate the values using the comma character. Since we know that we sent from Arduino in the order yaw, pitch, roll, we can then convert each string to a float and assign them to the first three values in String array ypr[]. The strings are then converted into floats and stored in float variables. The full Arduino and Processing sketches can be seen below.

    Arduino示例程序:

    kittenblock中小学创客名师推荐的图形化编程软件

    /*
      ===============================================
      Example sketch for CurieIMU library for Intel(R) Curie(TM) devices.
      Copyright (c) 2015 Intel Corporation.  All rights reserved.
    
      Based on I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050
      class by Jeff Rowberg: https://github.com/jrowberg/i2cdevlib
    
      ===============================================
      I2Cdev device library code is placed under the MIT license
      Copyright (c) 2011 Jeff Rowberg
    
      Permission is hereby granted, free of charge, to any person obtaining a copy
      of this software and associated documentation files (the "Software"), to deal
      in the Software without restriction, including without limitation the rights
      to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      copies of the Software, and to permit persons to whom the Software is
      furnished to do so, subject to the following conditions:
    
      The above copyright notice and this permission notice shall be included in
      all copies or substantial portions of the Software.
    
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      THE SOFTWARE.
      ===============================================
    
      Genuino 101 CurieIMU Orientation Visualiser
      Hardware Required:
      * Arduino/Genuino 101
    
      Modified Nov 2015
      by Helena Bisby <support@arduino.cc>
      This example code is in the public domain
      http://arduino.cc/en/Tutorial/Ge ... ientationVisualiser
    */
    
    #include <CurieIMU.h>
    #include <MadgwickAHRS.h>
    
    Madgwick filter; // initialise Madgwick object
    int ax, ay, az;
    int gx, gy, gz;
    float yaw;
    float pitch;
    float roll;
    int factor = 800; // variable by which to divide gyroscope values, used to control sensitivity
    // note that an increased baud rate requires an increase in value of factor
    
    int calibrateOffsets = 1; // int to determine whether calibration takes place or not
    
    
    void setup() {
      // initialize Serial communication
      Serial.begin(9600);
    
      // initialize device
      CurieIMU.begin();
      
      if (calibrateOffsets == 1) {
        // use the code below to calibrate accel/gyro offset values
        Serial.println("Internal sensor offsets BEFORE calibration...");
        Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getGyroOffset(X_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getGyroOffset(Y_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getGyroOffset(Z_AXIS)); Serial.print("\t");
        Serial.println("");
    
        // To manually configure offset compensation values, use the following methods instead of the autoCalibrate...() methods below
        //    CurieIMU.setGyroOffset(X_AXIS, 220);
        //    CurieIMU.setGyroOffset(Y_AXIS, 76);
        //    CurieIMU.setGyroOffset(Z_AXIS, -85);
        //    CurieIMU.setAccelerometerOffset(X_AXIS, -76);
        //    CurieIMU.setAccelerometerOffset(Y_AXIS, -235);
        //    CurieIMU.setAccelerometerOffset(Z_AXIS, 168);
    
        //IMU device must be resting in a horizontal position for the following calibration procedure to work correctly!
    
        Serial.print("Starting Gyroscope calibration...");
        CurieIMU.autoCalibrateGyroOffset();
        Serial.println(" Done");
        Serial.print("Starting Acceleration calibration...");
        CurieIMU.autoCalibrateAccelerometerOffset(X_AXIS, 0);
        CurieIMU.autoCalibrateAccelerometerOffset(Y_AXIS, 0);
        CurieIMU.autoCalibrateAccelerometerOffset(Z_AXIS, 1);
        Serial.println(" Done");
    
        Serial.println("Internal sensor offsets AFTER calibration...");
        Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(X_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(Y_AXIS)); Serial.print("\t");
        Serial.print(CurieIMU.getAccelerometerOffset(Z_AXIS)); Serial.print("\t");
        Serial.println("");
      }
    }
    
    void loop() {
      // read raw accel/gyro measurements from device
      CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz); 
    
      // use function from MagdwickAHRS.h to return quaternions
      filter.updateIMU(gx / factor, gy / factor, gz / factor, ax, ay, az);
    
      // functions to find yaw roll and pitch from quaternions
      yaw = filter.getYaw();
      roll = filter.getRoll();
      pitch = filter.getPitch();
      
      // print gyro and accel values for debugging only, comment out when running Processing
      /*
      Serial.print(ax); Serial.print("\t");
      Serial.print(ay); Serial.print("\t");
      Serial.print(az); Serial.print("\t");
      Serial.print(gx); Serial.print("\t");
      Serial.print(gy); Serial.print("\t");
      Serial.print(gz); Serial.print("\t");
      Serial.println("");
      */
    
      if (Serial.available() > 0) {
        int val = Serial.read();
        if (val == 's') { // if incoming serial is "s"
          Serial.print(yaw);
          Serial.print(","); // print comma so values can be parsed
          Serial.print(pitch);
          Serial.print(","); // print comma so values can be parsed
          Serial.println(roll);
        }
      }
    }


    Processing示例程序:

    kittenblock中小学创客名师推荐的图形化编程软件

    import processing.serial.*;
    Serial myPort;
    
    int newLine = 13; // new line character in ASCII
    float yaw;
    float pitch;
    float roll;
    String message;
    String [] ypr = new String [3];
    
    void setup()
    {
      size(600, 500, P3D);
      
      /*Set my serial port to same as Arduino, baud rate 9600*/
      myPort = new Serial(this, Serial.list()[0], 9600); // if you have only ONE COM port active
      //myPort = new Serial(this, "COM5", 9600);  // if you know the 101 COM port
    
      textSize(16); // set text size
      textMode(SHAPE); // set text mode to shape
    }
    
    void draw()
    {
      serialEvent();  // read and parse incoming serial message
      background(255); // set background to white
    
      translate(width/2, height/2); // set position to centre
      
      pushMatrix(); // begin object
      
      rotateX(pitch); // RotateX pitch value
      rotateY(-yaw); // yaw
      rotateZ(-roll); // roll
      
      drawArduino(); // function to draw rough Arduino shape
      
      popMatrix(); // end of object
    
      // Print values to console
      print(pitch);
      print("\t");
      print(roll); 
      print("\t");
      print(-yaw);   
      println("\t");
    
      myPort.write("s"); // write an "s" to receive more data from Arduino
    } 
    
    void serialEvent()
    {
      message = myPort.readStringUntil(newLine); // read from port until new line (ASCII code 13)
      if (message != null) {
        ypr = split(message, ","); // split message by commas and store in String array 
        yaw = float(ypr[0]); // convert to float yaw
        pitch = float(ypr[1]); // convert to float pitch
        roll = float(ypr[2]); // convert to float roll
      }
    }
    void drawArduino() {
      /* function contains shape(s) that are rotated with the IMU */
      stroke(0, 90, 90); // set outline colour to darker teal
      fill(0, 130, 130); // set fill colour to lighter teal
      box(300, 10, 200); // draw Arduino board base shape
    
      stroke(0); // set outline colour to black
      fill(80); // set fill colour to dark grey
    
      translate(60, -10, 90); // set position to edge of Arduino box
      box(170, 20, 10); // draw pin header as box
    
      translate(-20, 0, -180); // set position to other edge of Arduino box
      box(210, 20, 10); // draw other pin header as box
    }


    官方示例:
    https://www.arduino.cc/en/Tutori ... ientationVisualiser


    如果以上内容对你有帮助,你可以通过打赏支持作者
  • TA的每日心情
    无聊
    2017-6-24 14:20
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2016-8-7 10:50 | 显示全部楼层
    本帖最后由 190808149 于 2016-8-7 10:57 编辑

    谢谢奈何,我也按您的参考资料把这个Arduino101与Processing的联动程序调试成功了。

    结果如下:

    Madgwick的程序如上面朋友回复,
    1.积分结果稍显夸张。
    2.板子稳定几秒钟后,姿态根据重力方向融合。会慢慢向正确的状态收敛。这个做的很好。
    打赏
  • TA的每日心情
    慵懒
    2019-5-24 00:00
  • 签到天数: 887 天

    [LV.10]以坛为家III

    发表于 2016-3-1 22:34 | 显示全部楼层
    早知道就兑换 101 了,看起来更高级
    请PY我
  • TA的每日心情
    无聊
    2017-6-24 14:20
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2016-3-17 17:33 | 显示全部楼层
    希望能够读出当前角度等姿态融合数据。
    打赏
  • TA的每日心情
    开心
    2016-7-3 20:19
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2016-5-4 17:19 | 显示全部楼层
    请问大神们CurieIMU.h这个类的源代码在哪里找到?

    点评

    本地libraries目录下就有,当然github上的版本更新 https://github.com/01org/corelibs-arduino101/tree/master/libraries/CurieIMU  详情 回复 发表于 2016-5-4 17:44
  • TA的每日心情
    郁闷
    2018-12-6 22:21
  • 签到天数: 48 天

    [LV.5]常住居民I

     楼主| 发表于 2016-5-4 17:44 | 显示全部楼层
    王老幺 发表于 2016-5-4 17:19
    请问大神们CurieIMU.h这个类的源代码在哪里找到?

    本地libraries目录下就有,当然github上的版本更新 https://github.com/01org/corelib ... /libraries/CurieIMU
    如果以上内容对你有帮助,你可以通过打赏支持作者
  • TA的每日心情
    开心
    2016-7-3 20:19
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2016-5-4 20:08 | 显示全部楼层
    奈何col 发表于 2016-5-4 17:44
    本地libraries目录下就有,当然github上的版本更新 https://github.com/01org/corelibs-arduino101/tree/ ...

    很感谢你,我的IDE库libraries里没有,可能是没有更新的原因吧。谢谢你解决了我的问题

    点评

    C:%users\\AppData\Local\Arduino15\packages\Intel\hardware\arc32\1.0.5\libraries  详情 回复 发表于 2016-5-4 21:06
  • TA的每日心情
    郁闷
    2018-12-6 22:21
  • 签到天数: 48 天

    [LV.5]常住居民I

     楼主| 发表于 2016-5-4 21:06 | 显示全部楼层
    王老幺 发表于 2016-5-4 20:08
    很感谢你,我的IDE库libraries里没有,可能是没有更新的原因吧。谢谢你解决了我的问题 ...

    C:\Users\<username>\AppData\Local\Arduino15\packages\Intel\hardware\arc32\1.0.5\libraries
    如果以上内容对你有帮助,你可以通过打赏支持作者
  • TA的每日心情
    开心
    2016-7-3 20:19
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2016-5-5 16:56 | 显示全部楼层
    奈何col 发表于 2016-5-4 21:06
    C:%users\\AppData\Local\Arduino15\packages\Intel\hardware\arc32\1.0.5\libraries

    谢谢,已找到

    该用户从未签到

    发表于 2016-6-3 13:11 | 显示全部楼层
    101陀螺仪读取的是什么数据啊,加速度,角速度还是其他的

    点评

    两者都有  详情 回复 发表于 2016-6-3 14:18
  • TA的每日心情
    郁闷
    2018-12-6 22:21
  • 签到天数: 48 天

    [LV.5]常住居民I

     楼主| 发表于 2016-6-3 14:18 | 显示全部楼层
    龙宫宝玉 发表于 2016-6-3 13:11
    101陀螺仪读取的是什么数据啊,加速度,角速度还是其他的

    两者都有
    如果以上内容对你有帮助,你可以通过打赏支持作者
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    ESP32 Picoweb教程:提供JSON内容
    ESP32 Picoweb教程:提供J
    简介 在本ESP32教程中,我们将检查如何从Picoweb应用程序中提供JSON内容。有关Picoweb
    ESP32 / ESP8266 MicroPython教程:字符串拆分方法
    ESP32 / ESP8266 MicroPyt
    [/backcolor]引言[/backcolor][/backcolor]这篇ESP32 / ESP8266 MicroPython教程主
    ESP32 Arduino:获取FreeRTOS任务优先级
    ESP32 Arduino:获取FreeRT
    本文主要介绍如何使用ESP32和Arduino环境获取FreeRTOS任务的优先级。 简 介本文主要介
    体验OneNET4.0,一起来拼开发板
    体验OneNET4.0,一起来拼
    一、 活动时间2019年04月09日-2019年6月30日 二、活动链接1.登录Arduino中文社区账
    【原创】 drawbot平面关节scara机械臂写字机 画画机器人直播...
    【原创】 drawbot平面关节
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表