Engduino v2.1
|
00001 /** 00002 * \addtogroup EngduinoAccelerometer 00003 * 00004 * This is the driver code for Accelerometer on the Engduino 00005 * In v1.0 this accelerometer is a freescale MMA8652 00006 * 00007 * @{ 00008 */ 00009 00010 /** 00011 * \file 00012 * Engduino accelerometer driver 00013 * \author 00014 * Engduino team: support@engduino.org 00015 */ 00016 00017 #include "pins_arduino.h" 00018 #include "../Wire/Wire.h" 00019 #include "EngduinoAccelerometer.h" 00020 00021 /*---------------------------------------------------------------------------*/ 00022 /** 00023 * \brief Constructor 00024 * 00025 * C++ constructor for this class. Empty. 00026 */ 00027 EngduinoAccelerometerClass::EngduinoAccelerometerClass() 00028 { 00029 } 00030 00031 /*---------------------------------------------------------------------------*/ 00032 /** 00033 * \brief begin function - must be called before using other functions 00034 * 00035 * This function enables the accelerometer. 00036 * The accelerometer is an I2C device so we initialise the I2C communications, 00037 * make contact with the accelerometer, and check that it's what we think it is. 00038 * 00039 * We set the accelerometer to its 2G range, and don't use a FIFO. Other options 00040 * are possible, but will need to be implemented in this driver. 00041 * 00042 */ 00043 void EngduinoAccelerometerClass::begin() 00044 { uint8_t reg; 00045 00046 // Join I2C bus as master 00047 // 00048 Wire.begin(); 00049 00050 // Check to see that the device is there 00051 // 00052 Wire.beginTransmission(MMA865x_IIC_ADDRESS); 00053 int error = Wire.endTransmission(); 00054 if (error != 0) { 00055 Serial.println("Error: I2C device not found"); 00056 return; 00057 } 00058 00059 // Check that it's the device we think it is 00060 // 00061 readReg(MMA865x_WHO_AM_I, ®); 00062 if (reg != 0x5A) { 00063 Serial.println("Error: Not an MMA8652"); 00064 return; 00065 } 00066 00067 // Set up the parameters we'd like to have 00068 // +-2g and 50Hz 00069 // 00070 standby(); // Stop the accelerometer 00071 00072 // Set to 2g 00073 readReg(MMA865x_XYZ_DATA_CFG, ®); 00074 reg &= ~FS_MASK; 00075 reg |= FULL_SCALE_2G; 00076 writeReg(MMA865x_XYZ_DATA_CFG, ®); 00077 00078 // And 50Hz data rate 00079 readReg(MMA865x_CTRL_REG1, ®); 00080 reg &= ~DR_MASK; 00081 reg |= DATA_RATE_50HZ; 00082 writeReg(MMA865x_CTRL_REG1, ®); 00083 00084 activate(); // And start it again 00085 } 00086 00087 /*---------------------------------------------------------------------------*/ 00088 /** 00089 * \brief end function - switch off the button 00090 * 00091 * Send the accelerometer to sleep 00092 * 00093 */ 00094 void EngduinoAccelerometerClass::end() 00095 { 00096 standby(); // Stop the accelerometer 00097 } 00098 00099 00100 /*---------------------------------------------------------------------------*/ 00101 /** 00102 * \brief Read the xyz values in g from the accelerometer 00103 * \param buf A buffer of floats to put the accelerometer values in g into 00104 * 00105 * Get the instantaneous accelerometer values for the xyz axes. Convert the 00106 * 12 bit digital value to a float value that is expressed in g. 00107 * 00108 */ 00109 void EngduinoAccelerometerClass::xyz(float buf[3]) 00110 { uint8_t reg[6]; 00111 00112 // Check to see if XYZ data is ready to read 00113 readReg(MMA865x_STATUS_00, reg); 00114 if (reg[0] & ZYXDR_MASK != 0) { 00115 00116 // Do a multiple read starting with X_MSB 00117 // because this is the first numbered 00118 // Read all the MSBs and LSBs = 6 registers 00119 // 00120 readReg(MMA865x_OUT_X_MSB, reg, 6); 00121 00122 // Now convert the value to g. 00123 // At 2g full scale, 1g = 1024 counts 00124 // The most significant 8 bits are stored 00125 // in the MSB register, the other 4 bits 00126 // are in the top of the LSB register, making 00127 // the number a factor of 16 too big. The 00128 // complete 12 bit number is stored as 00129 // 2's complement 00130 // 00131 for (int i = 0; i < 3; i++) { 00132 float f = (reg[2*i] << 8) + reg[2*i+1]; 00133 f = f / (16 * 1024); // Put the number into the right range 00134 buf[i] = f; 00135 } 00136 00137 // TODO: Could take the cailbration (offset) 00138 // registers into account 00139 // 00140 } 00141 } 00142 00143 /*---------------------------------------------------------------------------*/ 00144 /** 00145 * \brief Read the raw xyz values from the accelerometer 00146 * \param buf A buffer of uint16s to hold the 12 bit raw accelerometer values 00147 * 00148 * Get the instantaneous accelerometer values for the xyz axes. We return the 00149 * raw values without converting them into g. To convert to g, if we are using 00150 * a 2G scale, then simply divide by 16384 00151 * 00152 */ 00153 void EngduinoAccelerometerClass::xyzRaw(uint16_t buf[3]) 00154 { uint8_t reg[6]; 00155 00156 // Check to see if XYZ data is ready to read 00157 readReg(MMA865x_STATUS_00, reg); 00158 if (reg[0] & ZYXDR_MASK != 0) { 00159 00160 // Do a multiple read starting with X_MSB 00161 // because this is the first numbered 00162 // Read all the MSBs and LSBs = 6 registers 00163 // 00164 readReg(MMA865x_OUT_X_MSB, reg, 6); 00165 00166 // Just return raw values 00167 // 00168 for (int i = 0; i < 3; i++) 00169 buf[i] = (reg[2*i] << 8) + reg[2*i+1]; 00170 00171 // TODO: Could take the cailbration (offset) 00172 // registers into account 00173 // 00174 } 00175 } 00176 00177 /*---------------------------------------------------------------------------*/ 00178 /** 00179 * \brief Activate the sensor 00180 * 00181 * Set the Active bit in System Control Register 1 00182 * 00183 */ 00184 void EngduinoAccelerometerClass::activate() 00185 { uint8_t reg; 00186 00187 readReg(MMA865x_CTRL_REG1, ®); 00188 reg |= ACTIVE_MASK; 00189 writeReg(MMA865x_CTRL_REG1, ®); 00190 } 00191 00192 00193 /*---------------------------------------------------------------------------*/ 00194 /** 00195 * \brief Put sensor into standby mode 00196 * 00197 * Clear the Active bit in System Control Register 1 00198 * 00199 */ 00200 void EngduinoAccelerometerClass::standby() 00201 { uint8_t reg; 00202 00203 readReg(MMA865x_CTRL_REG1, ®); 00204 reg &= ~ACTIVE_MASK; 00205 writeReg(MMA865x_CTRL_REG1, ®); 00206 } 00207 00208 00209 /*---------------------------------------------------------------------------*/ 00210 /** 00211 * \brief Internal routine to write accelerometer registers 00212 * \param firstReg The first register to write 00213 * \param buf The buffer containing things to write to the registers 00214 * \param nRegs Optional: The number of registers to write - defaults to 1 00215 * 00216 * Do a multiple register write of the MMA8652 over the I2C bus - where the 00217 * number of registers written might only be one (as it is if the optional 00218 * nRegs parameter is omitted). 00219 * 00220 */ 00221 void EngduinoAccelerometerClass::writeReg(int firstReg, const uint8_t *buf, uint8_t nRegs) 00222 { 00223 // Write out the address of the first register, then the set of values 00224 // for that and all subsequent registers. Release the I2C bus when we're done 00225 // 00226 Wire.beginTransmission(MMA865x_IIC_ADDRESS); 00227 Wire.write(firstReg); 00228 Wire.write(buf, nRegs); 00229 Wire.endTransmission(); 00230 } 00231 00232 /*---------------------------------------------------------------------------*/ 00233 /** 00234 * \brief Internal routine to read accelerometer registers 00235 * \param firstReg The first register to read 00236 * \param buf The buffer to which to read from the registers 00237 * \param nRegs Optional: The number of registers to read - defaults to 1 00238 * 00239 * Do a multiple register read of the MMA8652 over the I2C bus - where the 00240 * number of registers read might only be one (as it is if the optional 00241 * nRegs parameter is omitted). 00242 * 00243 */ 00244 void EngduinoAccelerometerClass::readReg(int firstReg, uint8_t *buf, uint8_t nRegs) 00245 { 00246 // Write out the register we'd like to start with reading 00247 // Hold the I2C bus since we're going to read values back 00248 // 00249 Wire.beginTransmission(MMA865x_IIC_ADDRESS); 00250 Wire.write(firstReg); 00251 Wire.endTransmission(false); 00252 00253 // Read all the registers we're interested in, 00254 // but release the I2C bus when we're done. 00255 // This is determined by the default third 00256 // parameter to requestFrom 00257 // 00258 Wire.requestFrom((uint8_t)MMA865x_IIC_ADDRESS, nRegs); 00259 00260 int i = 0; 00261 while (Wire.available() && i < nRegs) 00262 buf[i++] = Wire.read(); 00263 } 00264 00265 00266 /*---------------------------------------------------------------------------*/ 00267 /* 00268 * Preinstantiate Objects 00269 */ 00270 EngduinoAccelerometerClass EngduinoAccelerometer = EngduinoAccelerometerClass(); 00271 00272 /** @} */