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

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