A hello world for inertial sensors

Dependencies:   FXAS21000 FXOS8700Q mbed

Fork of FRDM-STBC-AGM01 by angus taggart

main.cpp

Committer:
Elecia
Date:
2015-06-30
Revision:
4:5ab2bb2f062b
Parent:
3:123b546e4a5c

File content as of revision 4:5ab2bb2f062b:

/* Copyright (c) 2010-2011 mbed.org, MIT License
*
* 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.
*/

/* This project was created by Elecia White of Embedded.fm and Logical Elegance using hardware
*  supplied by element14. It uses 
*    * a FRDM-KL05Z board (http://www.newark.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=15003&langId=-1&urlRequestType=Base&partNumber=53W2646&storeId=10194)
*    * an IMU sensor toolbox shield (http://www.newark.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=15003&langId=-1&urlRequestType=Base&partNumber=30Y6365&storeId=10194)
*    * a momentary button connected to A5 and ground
* Together, these create a sort of "hello world" for the accelerometer, gyro, and magnetometer so 
* people can see what each sensor does.
*
* On boot, the system will have no LED running though it will be outputting IMU
* data on the serial port available from USB (115200, 8, None, 1).
*
* Press the button to go into accelerometer demo mode. The LED will come on and 
* tell you upon which axis it feels gravity (red = X, green = Y, blue = Z). 
* As you move it, the LED will change. If you jiggle it, you can see the light 
* change in intensity. A gentle toss up might lead to a dark sensor at the top 
* of the arc (free fall!). And if you tap on the device, you will likely see a 
* brighter flare of the LED: accelerometers do really well with tap detection.
* 
* Press the button again to get into gyro demo mode. The LED will go off until 
* you turn the unit. Spinning it around one axis is the obvious mechanism. But 
* try swinging it back and forth in different direction. Look at the joints on 
* your arm, what colors do you see when you move (and how consistently)? 
* 
* Press the button again to go into the North Star mode. Remember, it might light 
* your way home, but only if you and it are pointed in the same direction.
*
* For more information, see the element14 post: http://www.element14.com/community/community/designcenter/kinetis_kl2_freedom_board/blog/2015/06/30/brave-new-hello-world
*
*/
#include "mbed.h"
#include "FXOS8700Q.h"
#include "FXAS21000.h"
#include "led.h"
#include "Adafruit_9DOF.h"
#include "northStarFuncs.h"
#include "button.h"

#define ACCEL_FLOAT_TO_MG_INT (1000.0F) // G to mG
#define PI_F 3.14159265
#define DEGREES_TO_MRADS       (1000.0*(2.0*PI_F/360.0))

FXOS8700Q_acc combo_acc(D14, D15, FXOS8700CQ_SLAVE_ADDR0);
FXOS8700Q_mag combo_mag(D14, D15, FXOS8700CQ_SLAVE_ADDR0);
FXAS21000 gyro(D14, D15);

Serial pc(USBTX, USBRX);
SMART_LED  smartLed(LED1, LED2, LED3);
DigitalIn  gButton(A5, PullUp);

typedef struct {
    int16_t a[NUM_AXIS];         //  3D accelerometer data in 0.001 G (milliGs)
    int16_t m[NUM_AXIS];            //  3D magnetometer data in 0.001 gauss (milliGauss)
    int16_t g[NUM_AXIS];            //  3D angular rate darta in degrees per second
} tImuData;


// UpdateLeds uses the inertial data to set the LED (according to the current mode).
// It alsu updates the current mode when the button is pressed
int UpdateLed(tImuData *imuData)
{
  static eModes gMode = OFF;
  uint8_t r = 0, b = 0, g = 0;
  int delayMs = 10;

  switch (gMode) {
  case ACCEL:
    // the color brightness is the abs value of the direction,
    // scaled to one G
    r = conditionAccels(imuData->a[X]);
    g = conditionAccels(imuData->a[Y]);
    b = conditionAccels(imuData->a[Z]);
    delayMs = 10; // 100 Hz readings on the accel
    break;
  case MAG:
     tOrientation orientation;
     if (fusionGetOrientation(imuData->a, imuData->m, &orientation)) {
        // N = white, E = green, W = red, S = dark
        r = conditionMags(orientation.heading, -45.0, 120.0);
        g = conditionMags(orientation.heading, 45.0, 120.0);
        b = conditionMags(orientation.heading, 0.0, 120.0);        
    } else{
        printf("orientation failed\r\n");
    }
    delayMs = 20; // 50 Hz readings on the mag
    break;
  case GYRO:
    // scale the brightness to the motion being 
    // experienced, where X = R, Y = B, Z = G
    r = conditionGyros(imuData->g[X]);
    g = conditionGyros(imuData->g[Y]);
    b = conditionGyros(imuData->g[Z]);
    delayMs = 10;
    break;
  default:
    r = g = b = 0;
    delayMs = 10;
    break;
  }
  if (debounceButtonPress(gButton)) { 
     printf("Button pressed from %d", gMode);
     gMode = changeMode(gMode);
     printf(" to new mode %d\r\n", gMode);
  }  
  smartLed.set(r, g, b);
  return (delayMs);
}

int main()
{        
    pc.baud(115200);    
    
    float gyro_data[3];
    MotionSensorDataUnits adata;
    MotionSensorDataUnits mdata;
    printf("\r\nStarting\r\n\r\n");

    combo_acc.enable();
    combo_mag.enable();
    printf("FXOS8700 Combo mag = %X\r\n", combo_mag.whoAmI());
    printf("FXOS8700 Combo acc = %X\r\n", combo_acc.whoAmI());
    printf("FXAS21000 Gyro = %X\r\n", gyro.getWhoAmI());
        
    while(1) {
        tImuData imuData;
        combo_acc.getAxis(adata);
        imuData.a[X] = adata.x * ACCEL_FLOAT_TO_MG_INT;
        imuData.a[Y] = adata.y * ACCEL_FLOAT_TO_MG_INT;
        imuData.a[Z] = adata.z * ACCEL_FLOAT_TO_MG_INT;
        printf("FXOS8700 Acc:   X:%6.3f Y:%6.3f Z:%6.3f\r\n", adata.x, adata.y, adata.z);
        
        combo_mag.getAxis(mdata); // data in mGauss already
        imuData.m[X] = mdata.x;
        imuData.m[Y] = mdata.y;
        imuData.m[Z] = mdata.z;
        printf("FXOS8700 Mag:   X:%6.2f Y:%6.2f Z:%6.2f\r\n", mdata.x, mdata.y, mdata.z);
        
        gyro.ReadXYZ(gyro_data);
        imuData.g[X] = gyro_data[0] * DEGREES_TO_MRADS;
        imuData.g[Y] = gyro_data[1] * DEGREES_TO_MRADS;
        imuData.g[Z] = gyro_data[2] * DEGREES_TO_MRADS;
        printf("FXAS21000 Gyro: X:%6.2f Y:%6.2f Z:%6.2f\r\n", gyro_data[0], gyro_data[1], gyro_data[2]);        
        printf("\r\n");
        
        int delayMs = UpdateLed(&imuData);
        wait_ms(delayMs); 
    }
}