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

hitechnic-compass.h

Go to the documentation of this file.
00001 /*!@addtogroup HiTechnic
00002  * @{
00003  * @defgroup htmc Compass Sensor
00004  * HiTechnic Compass Sensor
00005  * @{
00006  */
00007 
00008 /*
00009  * $Id: hitechnic-compass.h 133 2013-03-10 15:15:38Z xander $
00010  */
00011 
00012 /** \file hitechnic-compass.h
00013  * \brief HiTechnic Magnetic Compass Sensor Driver
00014  *
00015  * hitechnic-compass.h provides an API for the HiTechnic Magnetic Compass Sensor.
00016  *
00017  * Changelog:
00018  * - 0.1: Initial release
00019  * - 0.2: Added SMUX functions
00020  * - 0.3: Removed HTMC_SMUXData, reuses HTMC_I2CReply to save memory
00021  * - 0.4: Replaced hex values in calibration functions with #define's
00022  * - 0.5: Replaced functions requiring SPORT/MPORT macros
00023  * - 0.6: simplified relative heading calculations - Thanks Gus!
00024  * - 0.7: Changed to new SMUX support system\n
00025  *        Merged target functions with optional heading argument.
00026  *
00027  * License: You may use this code as you wish, provided you give credit where its due.
00028  *
00029  * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 3.59 AND HIGHER. 
00030 
00031  * \author Xander Soldaat (xander_at_botbench.com)
00032  * \date 18 January 2011
00033  * \version 0.7
00034  * \example hitechnic-compass-test1.c
00035  * \example hitechnic-compass-test2.c
00036  * \example hitechnic-compass-SMUX-test1.c
00037  */
00038 
00039 #pragma systemFile
00040 
00041 #ifndef __COMMON_H__
00042 #include "common.h"
00043 #endif
00044 
00045 // I2C address + registers
00046 #define HTMC_I2C_ADDR       0x02  /*!< HTMC I2C device address */
00047 #define HTMC_MODE           0x41  /*!< HTMC Mode control */
00048 #define HTMC_HEAD_U         0x42  /*!< HTMC Heading Upper bits */
00049 #define HTMC_HEAD_L         0x43  /*!< HTMC Heading Lower bit */
00050 
00051 // I2C commands
00052 #define HTMC_MEASURE_CMD    0x00  /*!< HTMC measurement mode command */
00053 #define HTMC_CALIBRATE_CMD  0x43 /*!< HTMC calibrate mode command */
00054 
00055 bool HTMCstartCal(tSensors link);
00056 bool HTMCstopCal(tSensors link);
00057 int HTMCreadHeading(tSensors link);
00058 int HTMCreadRelativeHeading(tSensors link);
00059 int HTMCsetTarget(tSensors link, int offset = 0);
00060 
00061 #ifdef __HTSMUX_SUPPORT__
00062 int HTMCreadHeading(tMUXSensor muxsensor);
00063 int HTMCreadRelativeHeading(tMUXSensor muxsensor);
00064 int HTMCsetTarget(tMUXSensor muxsensor, int offset = 0);
00065 
00066 tConfigParams HTMC_config = {HTSMUX_CHAN_I2C, 2, 0x02, 0x42}; /*!< Array to hold SMUX config data for sensor */
00067 #endif // __HTSMUX_SUPPORT__
00068 
00069 tByteArray HTMC_I2CRequest;       /*!< Array to hold I2C command data */
00070 tByteArray HTMC_I2CReply;         /*!< Array to hold I2C reply data */
00071 
00072 int target[][] = {{0, 0, 0, 0},   /*!< Offsets for the compass sensor relative readings */
00073                   {0, 0, 0, 0},
00074                   {0, 0, 0, 0},
00075                   {0, 0, 0, 0}};
00076 
00077 
00078 /**
00079  * Start the calibration. The sensor should be rotated a little more than 360 along the
00080  * horizontal plane in no less than 20 seconds.  After the sensor has been rotated,
00081  * call HTMCstopCal() to set the sensor back in measurement mode and save the
00082  * calibration data.  This calibration data is stored in the sensor until the
00083  * next calibration.
00084  * @param link the HTMC port number
00085  * @return true if no error occured, false if it did
00086  */
00087 bool HTMCstartCal(tSensors link) {
00088   memset(HTMC_I2CRequest, 0, sizeof(tByteArray));
00089 
00090   HTMC_I2CRequest[0] = 3;                   // Number of bytes in I2C command
00091   HTMC_I2CRequest[1] = HTMC_I2C_ADDR;       // I2C address of compass sensor
00092   HTMC_I2CRequest[2] = HTMC_MODE;           // Set write address to sensor mode register
00093   HTMC_I2CRequest[3] = HTMC_CALIBRATE_CMD;  // The calibration mode command
00094 
00095   // Start the calibration
00096   return writeI2C(link, HTMC_I2CRequest);
00097 }
00098 
00099 
00100 /**
00101  * Stop the calibration. This should be called no less than 20 seconds after
00102  * HTMCstartCal() and only if the sensor has been rotated more than 360 degrees
00103  * @param link the HTMC port number
00104  * @return true if no error occured, false if it did
00105  */
00106 bool HTMCstopCal(tSensors link) {
00107   memset(HTMC_I2CRequest, 0, sizeof(tByteArray));
00108 
00109   HTMC_I2CRequest[0] = 3;                 // Number of bytes in I2C command
00110   HTMC_I2CRequest[1] = HTMC_I2C_ADDR;     // I2C address of compass sensor
00111   HTMC_I2CRequest[2] = HTMC_MODE;         // Set write address to sensor mode register
00112   HTMC_I2CRequest[3] = HTMC_MEASURE_CMD;  // The measurement mode command
00113 
00114   // Stop the calibration by setting the mode register back to measurement.
00115   // Read back the register value to check if an error has occurred.
00116   if (!writeI2C(link, HTMC_I2CRequest, HTMC_I2CReply, 1))
00117     return false;
00118 
00119   // The register is equal to 2 if the calibration has failed.
00120   if (HTMC_I2CReply[0] == 2)
00121     return false;
00122 
00123   return true;
00124 }
00125 
00126 
00127 /**
00128  * Return the current absolute heading
00129  * @param link the HTMC port number
00130  * @return heading in degrees (0 - 359) or -1 if an error occurred.
00131  */
00132 int HTMCreadHeading(tSensors link) {
00133   memset(HTMC_I2CRequest, 0, sizeof(tByteArray));
00134 
00135   HTMC_I2CRequest[0] = 2;               // Number of bytes in I2C command
00136   HTMC_I2CRequest[1] = HTMC_I2C_ADDR;   // I2C address of compass sensor
00137   HTMC_I2CRequest[2] = HTMC_HEAD_U;     // Set write address to sensor mode register
00138 
00139   if (!writeI2C(link, HTMC_I2CRequest, HTMC_I2CReply, 2))
00140     return -1;
00141 
00142   // Result is made up of two bytes.  Reassemble for final heading.
00143   return (HTMC_I2CReply[0] * 2) + HTMC_I2CReply[1];
00144 }
00145 
00146 
00147 /**
00148  * Return the current absolute heading
00149  * @param muxsensor the SMUX sensor port number
00150  * @return heading in degrees (0 - 359) or -1 if an error occurred.
00151  */
00152 #ifdef __HTSMUX_SUPPORT__
00153 int HTMCreadHeading(tMUXSensor muxsensor) {
00154   memset(HTMC_I2CReply, 0, sizeof(tByteArray));
00155 
00156   if (HTSMUXSensorTypes[muxsensor] != HTSMUXSensorCustom)
00157     HTSMUXconfigChannel(muxsensor, HTMC_config);
00158 
00159   if (!HTSMUXreadPort(muxsensor, HTMC_I2CReply, 2)) {
00160     return -1;
00161   }
00162 
00163   // Result is made up of two bytes.  Reassemble for final heading.
00164   return (HTMC_I2CReply[0] * 2) + HTMC_I2CReply[1];
00165 }
00166 #endif // __HTSMUX_SUPPORT__
00167 
00168 
00169 /**
00170  * Return the current relative heading, value between -179 and 180
00171  * @param link the HTMC port number
00172  * @return relative heading in degrees or -255 if an error occurred.
00173  */
00174 int HTMCreadRelativeHeading(tSensors link) {
00175 
00176   // The black voodoo magic code below is courtsey of Gus from HiTechnic.
00177   int _tmpHeading = HTMCreadHeading(link) - target[link][0] + 180;
00178   return (_tmpHeading >= 0 ? _tmpHeading % 360 : 359 - (-1 - _tmpHeading)%360) - 180;
00179 }
00180 
00181 
00182 /**
00183  * Return the current relative heading, value between -179 and 180
00184  * @param muxsensor the SMUX sensor port number
00185  * @return relative heading in degrees or -255 if an error occurred.
00186  */
00187 #ifdef __HTSMUX_SUPPORT__
00188 int HTMCreadRelativeHeading(tMUXSensor muxsensor) {
00189 
00190   // The black voodoo magic code below is courtsey of Gus from HiTechnic.
00191   int _tmpHeading = HTMCreadHeading(muxsensor) - target[SPORT(muxsensor)][MPORT(muxsensor)] + 180;
00192   return (_tmpHeading >= 0 ? _tmpHeading % 360 : 359 - (-1 - _tmpHeading)%360) - 180;
00193 
00194   // return ((HTMCreadHeading(muxsensor) - target[SPORT(muxsensor)][MPORT(muxsensor)] + 540) % 360 - 180);
00195 }
00196 #endif
00197 
00198 
00199 /**
00200  * Set the value for the offset to be used as the new zero-point
00201  * for the relative heading returned by HTMCreadRelativeHeading()
00202  * @param link the HTMC port number
00203  * @param offset to be used to calculate relative heading (0-360 degrees).  If unspecified, uses current heading.
00204  * @return the current target heading
00205  */
00206 int HTMCsetTarget(tSensors link, int offset) {
00207   target[link][0] = (offset != 0) ? offset : HTMCreadHeading(link);
00208   return target[link][0];
00209 }
00210 
00211 
00212 /**
00213  * Set the value for the offset to be used as the new zero-point
00214  * for the relative heading returned by HTMCreadRelativeHeading()
00215  * @param muxsensor the SMUX sensor port number
00216  * @param offset to be used to calculate relative heading (0-360 degrees).  If unspecified, uses current heading.
00217  */
00218 #ifdef __HTSMUX_SUPPORT__
00219 int HTMCsetTarget(tMUXSensor muxsensor, int offset) {
00220   target[SPORT(muxsensor)][MPORT(muxsensor)] = (offset != 0) ? offset : HTMCreadHeading(muxsensor);
00221   return target[SPORT(muxsensor)][MPORT(muxsensor)];
00222 }
00223 #endif // __HTSMUX_SUPPORT__
00224 
00225 /*
00226  * $Id: hitechnic-compass.h 133 2013-03-10 15:15:38Z xander $
00227  */
00228 /* @} */
00229 /* @} */