Engduino v2.1
EngduinoMagnetometer.cpp
Go to the documentation of this file.
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, &reg);
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,  &reg);
00070         reg |= AUTO_MRST_EN_MASK | RAW_MASK;
00071         writeReg(FXMS3110_CTRL_REG2, &reg);
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, &reg);
00078         reg &= ~(DR_MASK | OS_MASK);
00079         reg |= DATA_RATE_1280_128;
00080         writeReg(FXMS3110_CTRL_REG1, &reg);
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, &reg);
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,  &reg);
00170         reg |= ACTIVE_MASK;
00171         writeReg(FXMS3110_CTRL_REG1, &reg);
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,  &reg);
00185         reg &= ~ACTIVE_MASK;
00186         writeReg(FXMS3110_CTRL_REG1, &reg);
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 /** @} */