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