|
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 /* @} */