美文网首页
IMU通过BLE传输

IMU通过BLE传输

作者: 背着蘑菇的鸡蛋 | 来源:发表于2016-05-10 11:42 被阅读0次
    /*
       This library is free software; you can redistribute it and/or
       modify it under the terms of the GNU Lesser General Public
       License as published by the Free Software Foundation; either
       version 2.1 of the License, or (at your option) any later version.
    
       This library is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       Lesser General Public License for more details.
    
       You should have received a copy of the GNU Lesser General Public
       License along with this library; if not, write to the Free Software
       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    
    */
    
    /*
       This sketch example demonstrates how to collect Inertial
       Measurement Unit(IMU) accelerometer and gyroscope data and then
       transmit that data using the on board Bluetooth Low Energ(BLE)
       capability of the Arduino/Genuino 101.
    
       This sketch is based on the IMU acceleromter and gyroscope examples
       sketches found at: https://www.arduino.cc/en/Reference/CurieIMU
    
       
    */
    
    #include "CurieIMU.h"
    #include <CurieBLE.h>
    
    /**
    * BLE Initialization Code
    *
    */
    BLEPeripheral blePeripheral;       // BLE Peripheral Device (the board you're programming)
    
    /** 
     *  Inertial Measurement Unit(IMU) Service - somewhat surprisely I could not find a standard IMU
     *  service on the Bluetooth SIG website(https://www.bluetooth.com/develop-with-bluetooth). So I 
     *  used an online uuid generator(http://www.itu.int/en/ITU-T/asn1/Pages/UUID/uuids.aspx) to 
     *  create this uuid. You are welcome to use it or make your own. Keep in mind that custom service 
     *  uuid must always be specified in 128 bit format as seen below.
    */ 
    BLEService imuService("917649A0-D98E-11E5-9EEC-0002A5D5C51B"); // Custom UUID
    
    /** 
     *  Accelerometer & Gyroscope Characteristics - these are simple variations on the service uuid from 
     *  above. 
     *  
     *  A float in C takes up 4 bytes of space. We will send the x, y and z components of both the
     *  accelerometer and gyroscope values. The byte length of 12 is specified as the last value
     *  passed in the function here. Float data is stored in memory as little endian. There are many
     *  good tutorials on little and big endian, here is a link to one of them:
     *  (https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html).
     *  BLE limits us to 20 bytes of data to transmit. Therefore we cannot send all 6 floats using one 
     *  characteristics. So we will create one characteristic for each main element of the IMU.
     *  
     *  The appButtonCharacteristic will allow us to recieve button inputs from the mobile app. Since
     *  a single byte can represent 256 values, we could in principle differentiate among a minimum
     *  of 256 buttons!
    */
    BLECharacteristic imuAccCharacteristic("917649A1-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLENotify, 12 );
    BLECharacteristic imuGyroCharacteristic("917649A2-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLENotify, 12 );
    BLEUnsignedCharCharacteristic appButtonCharacteristic("917649A7-D98E-11E5-9EEC-0002A5D5C51B", BLERead | BLEWrite );
    
    BLEDescriptor imuAccDescriptor("2902", "block");
    BLEDescriptor imuGyroDescriptor("2902", "block");
    
    /** 
     *  Define pins, connect your LEDs to the appropriate pins as defined below. These pins are 
     *  not required for the demo to function and therefore the circuit to connect them
     *  are not necessary.
    */
    #define BLE_CONNECT 3 // This pin will service as a hardware confirmation of the BLE connection
    #define INDICATOR_LEDA 4 // This pin will be used to debug input buttons from mobile app
    
    
    /**
    * The union directive allows 3 variables to share the same memory location. Please see the 
    * tutorial covering this project for further discussion of the use of the union
    * directive in C.
    *
    */
     union 
     {
      float a[3];
      unsigned char bytes[12];      
     } accData;
    
     union 
     {
      float g[3];
      unsigned char bytes[12];         
     } gyroData;
     
    void setup() {
    
      // initialze serial port for debugging communications
      Serial.begin(9600); // initialize Serial communication
      while (!Serial);    // wait for the serial port to open
     
      Serial.println("Arduino101/IntelCurie/Accelerometer/Evothings Example Started");
      Serial.println("Serial rate set to 9600");
      
      // initialize IMU
      // Serial.println("Initializing IMU device...");
      CurieIMU.begin();
    
      // Set the accelerometer range to 2G
      CurieIMU.setAccelerometerRange(2);
    
      // Set the accelerometer range to 250 degrees/second
      CurieIMU.setGyroRange(250);
    
      // prepare & initiazlie BLE
      // enable LED pins for output.
      pinMode(BLE_CONNECT, OUTPUT);
      pinMode(INDICATOR_LEDA, OUTPUT);
    
      blePeripheral.setLocalName("imu");
      blePeripheral.setAdvertisedServiceUuid(imuService.uuid());  // add the service UUID
      blePeripheral.addAttribute(imuService);   
      blePeripheral.addAttribute(imuAccCharacteristic);
      blePeripheral.addAttribute(imuAccDescriptor);
      blePeripheral.addAttribute(imuGyroCharacteristic);
      blePeripheral.addAttribute(imuGyroDescriptor);
      blePeripheral.addAttribute(appButtonCharacteristic);
    
    
      // All characteristics should be initialized to a starting value prior
      // using them.
      const unsigned char initializerAcc[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
      const unsigned char initializerGyro[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
     
      imuAccCharacteristic.setValue( initializerAcc, 12);
      imuGyroCharacteristic.setValue( initializerGyro, 12 );
      appButtonCharacteristic.setValue(0);
      
      blePeripheral.begin();
    }
    
    void loop() {
      
      int axRaw, ayRaw, azRaw;         // raw accelerometer values
      int gxRaw, gyRaw, gzRaw;         // raw gyro values
      
    
      // ?: Would there be an eficiency gained by declaring these outside the loop?
    
      // Here we connect oth central, your mobile device!
      BLECentral central = blePeripheral.central();
      if (central) {
        
        Serial.print("Connected to central: "); Serial.println(central.address());
        // It does not matter f you connect this LED or not, it is up to you.
        digitalWrite(BLE_CONNECT, HIGH);
    
    
        /**
         * All processing occurs in the context of an active BLE connection. 
        */
        while (central.connected()) {
          
        
          // read raw accelerometer measurements from device
          CurieIMU.readAccelerometer(axRaw, ayRaw, azRaw);
    
         /** 
          *  convert the raw accelerometer data to G's and assign them to the elements of
          *  the float array in the union representing the accelerometer data.
         */
         
    
          accData.a[0] = convertRawAcceleration(axRaw);
          accData.a[1] = convertRawAcceleration(ayRaw);
          accData.a[2] = convertRawAcceleration(azRaw);
    
          
          // read raw gyro measurements from device
         CurieIMU.readGyro(gxRaw, gyRaw, gzRaw);
    
         
        /** 
          *  convert the raw gyro data to degrees/second and assign them to the elements of
          *  the float array in the union representing the gyroscope data.
         */
         
         gyroData.g[0] = convertRawGyro(gxRaw);
         gyroData.g[1] = convertRawGyro(gyRaw);
         gyroData.g[2] = convertRawGyro(gzRaw);
         
         
         // These statements are for debugging puposes only and can be commented out to increae the efficiency of the sketch.
         Serial.print( "(ax,ay,az): " ); 
         Serial.print("("); Serial.print(accData.a[0]); Serial.print(","); Serial.print(accData.a[1]); Serial.print(","); Serial.print(accData.a[2]); Serial.print(")");Serial.println();
         Serial.print( "(gx,gy,gz): " ); 
         Serial.print("("); Serial.print(gyroData.g[0]); Serial.print(","); Serial.print(gyroData.g[1]); Serial.print(","); Serial.print(gyroData.g[2]); Serial.print(")");Serial.println();
         
         
          
         /**
          * The following two statements have the potential to cuase the most confusion. Please see the tutorial for
          * more on this.
          * What we are doing here is casting our union variables into a pointer of unsigned characters in
          * order to allow us to pass the array of bytes to the setValue() function.
         */
         unsigned char *acc = (unsigned char *)&accData;
         unsigned char *gyro = (unsigned char *)&gyroData;
    
    
          /**
           * Setting the values here will cause the notification mechanism on the moible app 
           * side to be enacted.
          */
         imuAccCharacteristic.setValue( acc, 12 );
         imuGyroCharacteristic.setValue( gyro, 12 );
          
      
         /**
          * When a button is pressed on the mobile app, the value of the characteristic is changed and
          * sent over BLE to the arduino/genuino101. A change in the characteristic is indicated
          * by a true value from the written() function and the value transmitted from the button 
          * on the mobile app is read here with the value() function.
          * The values change here essentially do nothing but print out a line to the serial port.
          * You can make them do anything here.
          * 
         */    
         if ( appButtonCharacteristic.written() ) {
    
            int appButtonValue = appButtonCharacteristic.value();
    
            switch(appButtonValue) {
    
              case 0:
                Serial.println( "App Input Value(0): " + appButtonValue );
                break;
              case 1:
                Serial.println( "App Input Value(1): " + appButtonValue );
                break;
              case 2:  
                 Serial.println( "App Input Value(2): " + appButtonValue );
                break;  
            }
            
          }
          
          
        } // while central.connected  
      } // if central
    } // end loop(){}
    
    
    /**
     * The follwing functions are taken directly from the accelerometer
     * and gyroscope demo apps.
    */
    
    float convertRawAcceleration(int aRaw) {
      // since we are using 2G range
      // -2g maps to a raw value of -32768
      // +2g maps to a raw value of 32767
      
      float a = (aRaw * 2.0) / 32768.0;
    
      return a;
    }
    
    float convertRawGyro(int gRaw) {
      // since we are using 250 degrees/seconds range
      // -250 maps to a raw value of -32768
      // +250 maps to a raw value of 32767
      
      float g = (gRaw * 250.0) / 32768.0;
    
      return g;
    }
    

    相关文章

      网友评论

          本文标题:IMU通过BLE传输

          本文链接:https://www.haomeiwen.com/subject/uzcyrttx.html