Engduino v2.1
|
00001 /** 00002 * \addtogroup EngduinoMagnetometer 00003 * 00004 * This is the driver code for Magnetometer on the Engduino 00005 * In v2.1 this magnetometer is a freescale FXMS3110 00006 * 00007 * @{ 00008 */ 00009 00010 /** 00011 * \file 00012 * Engduino magnetometer driver 00013 * \author 00014 * Engduino team: support@engduino.org 00015 */ 00016 00017 #include "pins_arduino.h" 00018 #include "../Wire/Wire.h" 00019 #include "EngduinoMagnetometer.h" 00020 00021 /*---------------------------------------------------------------------------*/ 00022 /** 00023 * \brief Constructor 00024 * 00025 * C++ constructor for this class. Empty. 00026 */ 00027 EngduinoMagnetometerClass::EngduinoMagnetometerClass() 00028 { 00029 } 00030 00031 /*---------------------------------------------------------------------------*/ 00032 /** 00033 * \brief begin function - must be called before using other functions 00034 * 00035 * This function enables the magnetometer. 00036 * The magnetometer is an I2C device so we initialise the I2C communications, 00037 * make contact with the magnetometer, and check that it's what we think it is. 00038 * 00039 * We set the sampling rate to 10Hz, but where the values are from a heavily 00040 * oversampled set of values 00041 */ 00042 void EngduinoMagnetometerClass::begin() 00043 { uint8_t reg; 00044 00045 // Join I2C bus as master 00046 // 00047 Wire.begin(); 00048 00049 // Check to see that the device is there 00050 // 00051 Wire.beginTransmission(FXMS3110_IIC_ADDRESS); 00052 int error = Wire.endTransmission(); 00053 if (error != 0) { 00054 Serial.println("Error: I2C device not found"); 00055 return; 00056 } 00057 00058 // Check that it's the device we think it is 00059 // 00060 readReg(FXMS3110_WHO_AM_I, ®); 00061 if (reg != FXMS3110) { 00062 Serial.println("Error: Not an FXMS3110"); 00063 return; 00064 } 00065 00066 // Set this to raw mode - no user correction 00067 // and automatically enable reset to deal with big magnetic 00068 // fields 00069 readReg(FXMS3110_CTRL_REG2, ®); 00070 reg |= AUTO_MRST_EN_MASK | RAW_MASK; 00071 writeReg(FXMS3110_CTRL_REG2, ®); 00072 00073 00074 standby(); // Stop the magnetometer 00075 00076 // Set 10Hz data rate = 1280 Hz ADC with 128 times oversampling 00077 readReg(FXMS3110_CTRL_REG1, ®); 00078 reg &= ~(DR_MASK | OS_MASK); 00079 reg |= DATA_RATE_1280_128; 00080 writeReg(FXMS3110_CTRL_REG1, ®); 00081 00082 activate(); // And start it again 00083 } 00084 00085 /*---------------------------------------------------------------------------*/ 00086 /** 00087 * \brief end function - switch off the magnetometer 00088 * 00089 * Send the magnetometer to sleep 00090 * 00091 */ 00092 void EngduinoMagnetometerClass::end() 00093 { 00094 standby(); // Stop the magnetometer 00095 } 00096 00097 00098 /*---------------------------------------------------------------------------*/ 00099 /** 00100 * \brief Read the xyz values from the magnetometer 00101 * \param buf A buffer of floats to put the magnetometer values into 00102 * 00103 * Get the instantaneous magnetometer values for the xyz axes. Convert the 00104 * 16 bit digital value to a float value. 00105 * 00106 */ 00107 void EngduinoMagnetometerClass::xyz(float buf[3]) 00108 { uint8_t reg[6]; 00109 00110 00111 // Check to see if XYZ data is ready to read 00112 readReg(FXMS3110_DR_STATUS, reg); 00113 if (reg[0] & ZYXDR_MASK != 0) { 00114 00115 // Do a multiple read starting with X_MSB 00116 // because this is the first numbered 00117 // Read all the MSBs and LSBs = 6 registers 00118 // 00119 readReg(FXMS3110_OUT_X_MSB, reg, 6); 00120 00121 // The most significant 8 bits are stored 00122 // in the MSB register, the other 8 bits 00123 // the LSB register. The complete 16 bit 00124 // number is stored as 2's complement 00125 // 00126 for (int i = 0; i < 3; i++) { 00127 float f = (reg[2*i] << 8) + reg[2*i+1]; 00128 buf[i] = f; 00129 } 00130 } 00131 00132 } 00133 00134 /*---------------------------------------------------------------------------*/ 00135 /** 00136 * \brief Read the temperature value from the magnetometer 00137 * \return The 8 bit temperature value in 2s complement - values lie between 00138 * -40°C and 125°C, but are uncalibrated. 00139 * 00140 * Get the temperature as measured by the magnetometer - the temperature 00141 * of the die. The register contains the die temperature in degrees C expressed 00142 * as an 8-bit 2's complement number. The sensitivity of the temperature sensor 00143 * is factory trimmed to 1°C/LSB. The temperature sensor offset is not factory 00144 * trimmed and must be calibrated by the user software if higher absolute 00145 * accuracy is required. Note: The register allows for temperature measurements 00146 * from -128°C to 127°C but the output range is limited to -40°C to 125°C. The 00147 * temperature data is updated on every measurement cycle. 00148 * 00149 */ 00150 int8_t EngduinoMagnetometerClass::temperature() 00151 { uint8_t reg; 00152 00153 readReg(FXMS3110_DIE_TEMP, ®); 00154 00155 return reg; 00156 } 00157 00158 00159 /*---------------------------------------------------------------------------*/ 00160 /** 00161 * \brief Activate the sensor 00162 * 00163 * Set the Active bit in System Control Register 1 00164 * 00165 */ 00166 void EngduinoMagnetometerClass::activate() 00167 { uint8_t reg; 00168 00169 readReg(FXMS3110_CTRL_REG1, ®); 00170 reg |= ACTIVE_MASK; 00171 writeReg(FXMS3110_CTRL_REG1, ®); 00172 } 00173 00174 00175 /*---------------------------------------------------------------------------*/ 00176 /** 00177 * \brief Put sensor into standby mode 00178 * 00179 * Clear the Active bit in System Control Register 1 00180 * 00181 */ 00182 void EngduinoMagnetometerClass::standby() 00183 { uint8_t reg; 00184 readReg(FXMS3110_CTRL_REG1, ®); 00185 reg &= ~ACTIVE_MASK; 00186 writeReg(FXMS3110_CTRL_REG1, ®); 00187 } 00188 00189 00190 /*---------------------------------------------------------------------------*/ 00191 /** 00192 * \brief Internal routine to write magnetometer registers 00193 * \param firstReg The first register to write 00194 * \param buf The buffer containing things to write to the registers 00195 * \param nRegs Optional: The number of registers to write - defaults to 1 00196 * 00197 * Do a multiple register write of the FXMS3110 over the I2C bus - where the 00198 * number of registers written might only be one (as it is if the optional 00199 * nRegs parameter is omitted). 00200 * 00201 */ 00202 void EngduinoMagnetometerClass::writeReg(int firstReg, const uint8_t *buf, uint8_t nRegs) 00203 { 00204 // Write out the address of the first register, then the set of values 00205 // for that and all subsequent registers. Release the I2C bus when we're done 00206 // 00207 Wire.beginTransmission(FXMS3110_IIC_ADDRESS); 00208 Wire.write(firstReg); 00209 Wire.write(buf, nRegs); 00210 Wire.endTransmission(); 00211 } 00212 00213 /*---------------------------------------------------------------------------*/ 00214 /** 00215 * \brief Internal routine to read magnetometer registers 00216 * \param firstReg The first register to read 00217 * \param buf The buffer to which to read from the registers 00218 * \param nRegs Optional: The number of registers to read - defaults to 1 00219 * 00220 * Do a multiple register read of the FXMS3110 over the I2C bus - where the 00221 * number of registers read might only be one (as it is if the optional 00222 * nRegs parameter is omitted). 00223 * 00224 */ 00225 void EngduinoMagnetometerClass::readReg(int firstReg, uint8_t *buf, uint8_t nRegs) 00226 { 00227 // Write out the register we'd like to start with reading 00228 // Hold the I2C bus since we're going to read values back 00229 // 00230 Wire.beginTransmission(FXMS3110_IIC_ADDRESS); 00231 Wire.write(firstReg); 00232 Wire.endTransmission(false); 00233 00234 // Read all the registers we're interested in, 00235 // but release the I2C bus when we're done. 00236 // This is determined by the default third 00237 // parameter to requestFrom 00238 // 00239 Wire.requestFrom((uint8_t)FXMS3110_IIC_ADDRESS, nRegs); 00240 00241 int i = 0; 00242 while (Wire.available() && i < nRegs) 00243 buf[i++] = Wire.read(); 00244 } 00245 00246 00247 /*---------------------------------------------------------------------------*/ 00248 /* 00249 * Preinstantiate Objects 00250 */ 00251 EngduinoMagnetometerClass EngduinoMagnetometer = EngduinoMagnetometerClass(); 00252 00253 /** @} */