Mindstorms 3rd Party ROBOTC Drivers RobotC
[Home] [Download] [Submit a bug/suggestion] [ROBOTC Forums] [Blog] [Support this project]

mindsensors-imu.h

Go to the documentation of this file.
00001 /*!@addtogroup mindsensors
00002  * @{
00003  * @defgroup MSIMU AbsoluteIMU Sensor
00004  * Mindsensors AbsoluteIMU Sensor (MSIMU) driver
00005  * @{
00006  */
00007 
00008 /*
00009  * $Id: mindsensors-imu.h 133 2013-03-10 15:15:38Z xander $
00010  */
00011 
00012 #ifndef __MSIMU_H__
00013 #define __MSIMU_H__
00014 /** \file mindsensors-imu.h
00015  * \brief Mindsensors AbsoluteIMU Sensor driver
00016  *
00017  * mindsensors-imu.h provides an API for the Mindsensors AbsoluteIMU Sensor.
00018  *
00019  * Changelog:
00020  * - 0.1: Initial release
00021  *
00022  * Credits:
00023  * - Big thanks to Mindsensors for providing me with the hardware necessary to write and test this.
00024  *
00025  * License: You may use this code as you wish, provided you give credit where its due.
00026  *
00027  * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 3.59 AND HIGHER. 
00028 
00029  * \author Xander Soldaat (xander_at_botbench.com)
00030  * \date 23 August 2012
00031  * \version 0.1
00032  * \example mindsensors-imu-test1.c
00033  * \example mindsensors-imu-test2.c
00034  * \example mindsensors-imu-test3.c
00035  */
00036 
00037 #pragma systemFile
00038 
00039 #ifndef __COMMON_H__
00040 #include "common.h"
00041 #endif
00042 
00043 #define MSIMU_IMU_I2C_ADDR            0x22  /*!< IMU I2C address */
00044 
00045 #define MSIMU_REG_CMD                 0x41  /*!< Command register */
00046 
00047 #define MSIMU_REG_TILT_ALL_AXES       0x42  /*!< All Axes for Tilt */
00048 #define MSIMU_REG_ACC_ALL_AXES        0x45  /*!< All Axes for Accel */
00049 #define MSIMU_REG_COMPASS_HEADING     0x4B  /*!< Compass heading */
00050 #define MSIMU_REG_COMPASS_ALL_FIELDS  0x4D  /*!< All magnetic fields for compass */
00051 #define MSIMU_REG_GYRO_ALL_AXES       0x53  /*!< All Axes for Gyro */
00052 #define MSIMU_REG_GYRO_FILTER         0x5A  /*!< Filter level for Gyro */
00053 
00054 #define MSIMU_CMD_COMPASS_START_CAL   0x43  /*!< Accelerometer 2G range */
00055 #define MSIMU_CMD_COMPASS_STOP_CAL    0x63  /*!< Accelerometer 2G range */
00056 
00057 #define MSIMU_CMD_ACC_RANGE_2G        0x31  /*!< Accelerometer 2G range */
00058 #define MSIMU_CMD_ACC_RANGE_4G        0x32  /*!< Accelerometer 4G range */
00059 #define MSIMU_CMD_ACC_RANGE_8G        0x33  /*!< Accelerometer 8G range */
00060 #define MSIMU_CMD_ACC_RANGE_16G       0x34  /*!< Accelerometer 16G range */
00061 
00062 #define MSIMU_GYRO_FILTER_NONE        0     /*!< Gyro filter level: none */
00063 #define MSIMU_GYRO_FILTER_LEVEL_1     1     /*!< Gyro filter level: 1 */
00064 #define MSIMU_GYRO_FILTER_LEVEL_2     2     /*!< Gyro filter level: 2 */
00065 #define MSIMU_GYRO_FILTER_LEVEL_3     3     /*!< Gyro filter level: 3 */
00066 #define MSIMU_GYRO_FILTER_LEVEL_4     4     /*!< Gyro filter level: 4 (default) */
00067 #define MSIMU_GYRO_FILTER_LEVEL_5     5     /*!< Gyro filter level: 5 */
00068 #define MSIMU_GYRO_FILTER_LEVEL_6     6     /*!< Gyro filter level: 6 */
00069 #define MSIMU_GYRO_FILTER_LEVEL_7     7     /*!< Gyro filter level: 7 (highest) */
00070 
00071 
00072 #define MSIMU_TILT_X_AXIS           MSIMU_REG_TILT_X_AXIS
00073 #define MSIMU_TILT_Y_AXIS           MSIMU_REG_TILT_Y_AXIS
00074 #define MSIMU_TILT_Z_AXIS           MSIMU_REG_TILT_Z_AXIS
00075 
00076 #define MSIMU_ACC_X_AXIS            MSIMU_REG_ACC_X_AXIS
00077 #define MSIMU_ACC_Y_AXIS            MSIMU_REG_ACC_Y_AXIS
00078 #define MSIMU_ACC_Z_AXIS            MSIMU_REG_ACC_Z_AXIS
00079 
00080 #define MSIMU_GYRO_X_AXIS           MSIMU_REG_GYRO_X_AXIS
00081 #define MSIMU_GYRO_Y_AXIS           MSIMU_REG_GYRO_Y_AXIS
00082 #define MSIMU_GYRO_Z_AXIS           MSIMU_REG_GYRO_Z_AXIS
00083 
00084 tByteArray MSIMU_I2CRequest;    /*!< Array to hold I2C command data */
00085 tByteArray MSIMU_I2CReply;      /*!< Array to hold I2C reply data */
00086 
00087 bool _MSIMUsendCMD(tSensors link, ubyte cmd);
00088 bool MSIMUreadTiltAxes(tSensors link, int &_x, int &_y, int &_z);
00089 bool MSIMUreadGyroAxes(tSensors link, int &_x, int &_y, int &_z);
00090 bool MSIMUreadAccelAxes(tSensors link, int &_x, int &_y, int &_z);
00091 bool MSIMUreadMagneticFields(tSensors link,  int &_x, int &_y, int &_z);
00092 int MSIMUreadHeading(tSensors link);
00093 bool MSIMUsetGyroFilter(tSensors link, ubyte level);
00094 
00095 
00096 /**
00097  * Send a command to the sensor
00098  *
00099  * Note: this is an internal function and should be called directly
00100  * @param link the port number
00101  * @param cmd the command to be sent
00102  * @return true if no error occured, false if it did
00103  */
00104 bool _MSIMUsendCMD(tSensors link, ubyte cmd)
00105 {
00106         MSIMU_I2CRequest[0] = 3;                        // Message size
00107   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00108         MSIMU_I2CRequest[2] = MSIMU_REG_CMD;  // Register address
00109         MSIMU_I2CRequest[3] = cmd;  // command
00110 
00111   return writeI2C(link, MSIMU_I2CRequest);
00112 }
00113 
00114 
00115 /**
00116  * Read all three tilt axes
00117  * @param link the port number
00118  * @param _x data for x axis in degrees per second
00119  * @param _y data for y axis in degrees per second
00120  * @param _z data for z axis in degrees per second
00121  * @return true if no error occured, false if it did
00122  */
00123 bool MSIMUreadTiltAxes(tSensors link, int &_x, int &_y, int &_z){
00124         MSIMU_I2CRequest[0] = 2;                        // Message size
00125   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00126         MSIMU_I2CRequest[2] = MSIMU_REG_TILT_ALL_AXES;  // Register address
00127 
00128   if (!writeI2C(link, MSIMU_I2CRequest, MSIMU_I2CReply, 3))
00129     return false;
00130 
00131   _x = (MSIMU_I2CReply[0] >= 128) ? (int)MSIMU_I2CReply[0] - 256 : (int)MSIMU_I2CReply[0];
00132   _y = (MSIMU_I2CReply[1] >= 128) ? (int)MSIMU_I2CReply[1] - 256 : (int)MSIMU_I2CReply[1];
00133   _z = (MSIMU_I2CReply[2] >= 128) ? (int)MSIMU_I2CReply[2] - 256 : (int)MSIMU_I2CReply[2];
00134 
00135   return true;
00136 }
00137 
00138 
00139 /**
00140  * Read all three axes of the gyro
00141  * @param link the port number
00142  * @param _x data for x axis in degrees per second
00143  * @param _y data for y axis in degrees per second
00144  * @param _z data for z axis in degrees per second
00145  * @return true if no error occured, false if it did
00146  */
00147 bool MSIMUreadGyroAxes(tSensors link, int &_x, int &_y, int &_z){
00148         MSIMU_I2CRequest[0] = 2;                        // Message size
00149   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00150         MSIMU_I2CRequest[2] = MSIMU_REG_GYRO_ALL_AXES;  // Register address
00151 
00152   if (!writeI2C(link, MSIMU_I2CRequest, MSIMU_I2CReply, 6))
00153     return false;
00154 
00155   _x = MSIMU_I2CReply[0] + ((int)(MSIMU_I2CReply[1]<<8));
00156   _y = MSIMU_I2CReply[2] + ((int)(MSIMU_I2CReply[3]<<8));
00157   _z = MSIMU_I2CReply[4] + ((int)(MSIMU_I2CReply[5]<<8));
00158   return true;
00159 }
00160 
00161 
00162 /**
00163  * Read all of the accelerometer axes
00164  * @param link the port number
00165  * @param _x variable to hold X axis data
00166  * @param _y variable to hold Y axis data
00167  * @param _z variable to hold Z axis data
00168  * @return true if no error occured, false if it did
00169  */
00170 bool MSIMUreadAccelAxes(tSensors link, int &_x, int &_y, int &_z){
00171         MSIMU_I2CRequest[0] = 2;                        // Message size
00172   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00173         MSIMU_I2CRequest[2] = MSIMU_REG_ACC_ALL_AXES;  // Register address
00174 
00175   if (!writeI2C(link, MSIMU_I2CRequest, MSIMU_I2CReply, 6))
00176     return false;
00177 
00178   _x = MSIMU_I2CReply[0] + ((int)(MSIMU_I2CReply[1]<<8));
00179   _y = MSIMU_I2CReply[2] + ((int)(MSIMU_I2CReply[3]<<8));
00180   _z = MSIMU_I2CReply[4] + ((int)(MSIMU_I2CReply[5]<<8));
00181   return true;
00182 }
00183 
00184 
00185 
00186 /**
00187  * Read all the magnetic field strengths
00188  * @param link the port number
00189  * @param _x variable to hold X axis data
00190  * @param _y variable to hold Y axis data
00191  * @param _z variable to hold Z axis data
00192  * @return true if no error occured, false if it did
00193  */
00194 bool MSIMUreadMagneticFields(tSensors link, int &_x, int &_y, int &_z){
00195         MSIMU_I2CRequest[0] = 2;                        // Message size
00196   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00197         MSIMU_I2CRequest[2] = MSIMU_REG_ACC_ALL_AXES;  // Register address
00198 
00199   if (!writeI2C(link, MSIMU_I2CRequest, MSIMU_I2CReply, 6))
00200     return false;
00201 
00202   _x = MSIMU_I2CReply[0] + ((int)(MSIMU_I2CReply[1]<<8));
00203   _y = MSIMU_I2CReply[2] + ((int)(MSIMU_I2CReply[3]<<8));
00204   _z = MSIMU_I2CReply[4] + ((int)(MSIMU_I2CReply[5]<<8));
00205 
00206   return true;
00207 }
00208 
00209 
00210 /**
00211  * Read the current magnetic compass heading
00212  * @param link the port number
00213  * @return the current heading
00214  */
00215 int MSIMUreadHeading(tSensors link)
00216 {
00217         MSIMU_I2CRequest[0] = 2;                        // Message size
00218   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00219         MSIMU_I2CRequest[2] = MSIMU_REG_COMPASS_HEADING;  // Register address
00220 
00221   if (!writeI2C(link, MSIMU_I2CRequest, MSIMU_I2CReply, 2))
00222     return 0;
00223 
00224   return MSIMU_I2CReply[0] + ((int)(MSIMU_I2CReply[1]<<8));
00225 }
00226 
00227 
00228 /**
00229  * Set the level of filtering of the Gryo readings.
00230  * @param link the port number
00231  * @param level the level of filtering (0-7) where 0 is none and 7 is the highest amount of filtering, 4 is the default level.
00232  * @return true if no error occured, false if it did
00233  */
00234 bool MSIMUsetGyroFilter(tSensors link, ubyte level)
00235 {
00236         MSIMU_I2CRequest[0] = 3;                        // Message size
00237   MSIMU_I2CRequest[1] = MSIMU_IMU_I2C_ADDR;      // I2C Address
00238         MSIMU_I2CRequest[2] = MSIMU_REG_GYRO_FILTER;  // Register address
00239         MSIMU_I2CRequest[3] = level;  // filtering level
00240 
00241   return writeI2C(link, MSIMU_I2CRequest);
00242 }
00243 
00244 #endif // __MSIMU_H__
00245 
00246 /*
00247  * $Id: mindsensors-imu.h 133 2013-03-10 15:15:38Z xander $
00248  */
00249 /* @} */
00250 /* @} */