用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

点击进入授权页面

只需一步,快速开始

  • QQ空间
  • 回复
  • 收藏
  • TA的每日心情
    奋斗
    2016-8-27 15:32
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    本帖最后由 搬运工 于 2016-6-19 23:31 编辑

    因为Arduino.cc时常访问不了,因此做个资料搬运。但是由于近期101库有跟新,实际操作可能和以下介绍有差别。

    使用CurieIMU+Processing数据可视化
    本教程演示了如何使用Genuino 101的板载六轴加速度计/陀螺仪 来读取加速度计和陀螺仪的X、Y和Z数值。加速度计能够测得开发板的方向,而陀螺仪能够检测开发板的角速度。这样,由加速度计和陀螺仪组成的惯性测量单元(IMU)就能够精确识别开发板的方向。本示例使用了Madgwick滤波算法根据六个轴向数值来计算四个四元数。然后,使用四元数计算欧拉角的三个角参量:章动角、旋进角和自转角,详见 Processing ,这些参数可用于控制物体沿X、Y和Z轴的旋转。

    硬件要求
    Genuino 101 x 1
    CurieIMU库使用了Genuino 101内置的 IMU(加速度计+陀螺仪)。

    说明
    按Genuino 101入门中所述,设置Arduino软件(IDE)。
    连接101和用户电脑。
    启动Arduino软件(IDE),并从“工具 > 开发板” 菜单项中选择Arduino/Genuino 101。
    由开发库管理器中安装Madgwick 库。可打开Arduino软件(IDE),选择"Sketch -> Include Library -> Manage Libraries"。然后搜索'Madgwick' 并直接安装开发库。请参阅开发库安装指导 了解安装和导入开发库的更详细解释。
    下载启动Processing软件 ,并使用如下所示处理代码创建一个文件。
    修改串行端口,使用用户101开发板正在使用的端口号(参阅"处理代码"章节)。
    上传CurieIMU 示例至用户101开发板,请确保开发板保持水平和静止以便进行精确校准。
    几秒钟后,运行Processing代码,调整开发板方向,查看程序对开发板的可视化显示。

    电路图

    Arduino101/genuino101

    Arduino101/genuino101


    工作原理
    Madgwick滤波算法是开源代码,可详见Madgwick的 相关信息和报告。. Madgwick滤波算法由Sebastian Madgwick 在2010年攻读博士学位时开发,该算法主要特点是以较低采样率高效地使用较少计算资源。该算法从陀螺仪和加速度计采集原始数据,并通过计算得到四元数。四元数是包含了分别代表发生旋转数轴的 “x”、“y”、“z”数值和代表围绕相同数轴旋转数值的“ω”数值的四维复数。这些四元数可用于计算欧拉角的三个角参量:章动角、旋进角和自转角;这三个角参量是用于描述一个刚体围绕“x”、“y”和“z”方向的旋转程度,欧拉角由Leonhard Euler在十七世纪提出。可使用 Madgwick报告 中的等式(7)、(8)、(9)来计算章动角、旋进角和自转角,它们的计算函数也被包括在开发库中。

    我们可以使用Arduino/Genuino 101的板载IMU在Processing中创建一个3D显示,它会做出与开发板相同的运动。这是通过Madgwick滤波算法计算得到欧拉角三个角参量实现的。然后通过串口将这些参数发送至Processing并将它们作为Processing rotateX()、rotateY()和rotateZ() 函数的输入角参数。这些函数计算出旋转角度数值,并将刚体沿各自数轴旋转相应角度。

    Arduino代码
    该程序代码使用了CurieIMU库中的功能函数以便从加速度计/陀螺仪采集数据。

    为了在Processing中看到3D显示,Arduino程序必须集成两个主要功能;使用IMU数据和算法计算出章动角、旋进角和自转角数值,并通过串口握手通讯的方式将这些计算数据发送至Processing。

    “在设置过程中应进行校准,可通过将变量calibrateOffsets分别设为1或0来确定是否再次使用校准程序。if calibrateOffsets > 0 然后执行校准程序并读取开发板的初始值,执行内部校准生成每个轴的偏移补偿值。注意:校准过程中用户必须确保开发板处于较好的静止和水平状态,如BMI160数据手册5.2节中所示。''

    首先,我们必须创建一个Madgwick对象来访问开发库Madgwick类中的功能函数。在这里,我们称之为filter:

    [C++] 纯文本查看 复制代码
    Madgwick filter;

    然后,我们可以使用如下CurieIMU库中的函数‘得到’加速度计和陀螺仪的数据:
    [C++] 纯文本查看 复制代码
    CurieIMU.readMotionSensor(ax, ay, az, gx, gy, gz);

    然后,我们可以使用Madgwick库中的功能函数updateIMU()。
    [C++] 纯文本查看 复制代码
    filter.updateIMU(gx / factor, gy / factor, gz / factor, ax, ay, az);
    
    yaw = filter.getYaw();
    roll = filter.getRoll();
    pitch = filter.getPitch();
    


    如代码所示,陀螺仪数值已经一可变因子进行规整,从而方便算法使用。如果不经数值规整,算法输入参数数值过高,那么开发板运动的可视化显示将变得对101的位置变化非常敏感,即把一个小幅运动大幅放大,从而造成“错误的“开发板旋转。可变整数‘因子’可以根据实验效果进行调整以便提高动态显示的性能,它还应随波特率增加而增加。
    然后,可使用如下模块处理串口通讯。首先,检查是否存在由Processing在每个循环结束处发送的输入值“s”。此举可确保Arduino代码不会以超过Processing数据处理能力的频率发送数据,从而导致可视化显示的严重失真。 如果收到一个“s”,那么可通过串口发送数据,数据以逗号分隔以换行结束,以便Processing能够方便地对每个消息进行解析。完整代码可参见页面底部。

    [Java] 纯文本查看 复制代码
    if (Serial.available() > 0) {
        int val = Serial.read();
        if(val == 's')
        {
          Serial.print(yaw);
          Serial.print(",");
          Serial.print(pitch);
          Serial.print(",");
          Serial.println(roll);
        }
       }


    注意,在串口循环打印的gx,gy,gz,ax,az,ay只是用于调试,在和Processing进行通信时必须要注释掉。

    Processing代码

    如果还没有Processing代码,那么首先要做的就是从processing.org 下载最新版的Processing。Processing是一个类似于Arduino的语言,它允许使用者使用类似于void setup() 和 void loop() 的结构来绘制动态图形。如需了解使用Processing的更多信息,请访问他们的 入门指导.

    Processing代码接收到串行端口的的输入数据,经解析后将数据分配给浮点变量yaw、pitch和roll,之后可用作RotateX()、RotateY()和RotateZ() 函数的输入参数。在loop()的每次迭代中,Processing读取和解析串口数据,根据解析数据绘制3D Arduino图像,并通过串口发送一个“s”告知Arduino已准备好接受下一个信息。

    为了让Processing能够从Arduino发送数据的相同端口读取数据,myPort需要被改为用户的串行端口名。在setup()中,这是Serial 的第二个参数。

    [Java] 纯文本查看 复制代码
    myPort = new Serial(this, Serial.list()[0], 9600);


    可通过使用Serial类中的list()功能函数找到正确的端口。方括号内的数字是指串行端口号,它可以使0,1,2等等。如果用户机器上只有一个COM端口可用,那么程序代码可正常运行。作为替代解决方案,用户可直接指定101开发板的“COMx”端口——它在101开发板上主要用于Arduino软件(IDE)的编程开发——对以下代码应做相应注释
    [Java] 纯文本查看 复制代码
    myPort = new Serial(this, Serial.list()[0], 9600);

    对以下代码无需做相应注释

    [Java] 纯文本查看 复制代码
    myPort = new Serial(this, "COM5", 9600);


    其中,“COM5”必须是用户COM端口的正确名称。

    如果有疑问,可在独立的代码中 打印可用串行端口列表 以确定这个名称。

    然后使用功能函数serialEvent()以接受和解析数据。

    [Java] 纯文本查看 复制代码
    void serialEvent()
    {
      message = myPort.readStringUntil(13);
      if (message != null) {
        ypr = split(message, ",");
        yaw = float(ypr[0]);
        pitch = float(ypr[1]);
        roll = float(ypr[2]);
      }
    }

    这个函数可从串行端口不断读取数据直至读到ASCII字符13 (换行符),然后使用split()函数用逗号字符分隔数据。由于我们知道从Arduino发送的数据是遵循“章动角、旋进角和自转角”顺序的,那么我们就可以把每一个字符串转换为一个浮点数,并将它们赋值给String array ypr[]的前三个参数。这样,字符串就转换成了浮点数,并被保存为浮点型变量。Arduino 和Processing的完整代码可访问如下网址。

    代码

    Arduino Code
    [C++] 纯文本查看 复制代码
    /*
      ===============================================
      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: [url=https://github.com/jrowberg/i2cdevlib]https://github.com/jrowberg/i2cdevlib[/url]
    
      ===============================================
      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 <[url=mailto:support@arduino.cc]support@arduino.cc[/url]>
      This example code is in the public domain
      [url=http://arduino.cc/en/Tutorial/Genuino101CurieIMUOrientationVisualiser]http://arduino.cc/en/Tutorial/Ge ... ientationVisualiser[/url]
    */
    
    #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 Code
    [Java] 纯文本查看 复制代码
    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
    }
    打赏作者鼓励一下!
    可以借鉴。但还是楞没看懂
    打赏作者鼓励一下!
    我编译时显示'convertRawAcceleration' was not declared in this scope
    这段有错吗?
    CurieIMU.readMotionSensor(aix, aiy, aiz, gix, giy, giz);
         

         // convert from raw data to gravity and degrees/second units
    //     ax = convertRawAcceleration(aix);
         ax = convertRawAcceleration(aiz);
         //ay = convertRawAcceleration(aiy);
         ay = convertRawAcceleration(aix);
         //az = convertRawAcceleration(aiz);
         az = convertRawAcceleration(aiy);
         //gx = convertRawGyro(gix);
         gx = convertRawGyro(giz);
         //gy = convertRawGyro(giy);
         gy = convertRawGyro(gix);
         //gz = convertRawGyro(giz);
         gz = convertRawGyro(giy);  
    楼主,能不能网盘分享一下processing  (windows),不知为什么官网上总下不下来
    zjy 发表于 2016-12-18 10:09
    楼主,能不能网盘分享一下processing  (windows),不知为什么官网上总下不下来 ...

    https://pan.baidu.com/s/1cyvM4u
    打赏作者鼓励一下!
    青桑 发表于 2016-11-7 23:56
    我编译时显示'convertRawAcceleration' was not declared in this scope
    这段有错吗?
    CurieIMU.readMoti ...

    换最新版本IDE
    打赏作者鼓励一下!
    请问楼主processing代码是自己写的么?
    发新帖
    发表评论
    高级模式  
    您需要登录后才可以回帖 登录 | 立即注册  
    关闭

    推荐主题 上一条 /2 下一条