![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Drivers for the mini robot designed for Princeton's MAE 433 course.
Dependencies: mbed-dsp mbed-rtos mbed
Dependents: MAE433_Library_Tester RobotBalancerv2
Diff: FXOS8700CQ.cpp
- Revision:
- 0:9afc272fa65f
- Child:
- 3:72db173215c7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FXOS8700CQ.cpp Fri Jun 24 21:03:20 2016 +0000 @@ -0,0 +1,147 @@ +/** + * @file FXOS8700CQ.cpp + * @date June 5th, 2016 + * @author Weimen Li + * @brief Source file for FXOS8700CQ driver. + */ + +#include <FXOS8700CQ/FXOS8700CQ.hpp> + +// These defines are extracted from Page. 25 of the datasheet, Rev. 7.0. +// FXOS8700CQ I2C address +const uint8_t FXOS8700CQ_SLAVE_ADDR = 0x1C; // with pins SA1=1, SA0=0, preshifted + +// FXOS8700CQ internal register addresses +const char FXOS8700CQ_STATUS = 0x00; +const char FXOS8700CQ_OUT_X_MSB = 0x01; +const uint8_t FXOS8700CQ_WHOAMI = 0x0D; +const uint8_t FXOS8700CQ_XYZ_DATA_CFG = 0x0E; +const uint8_t FXOS8700CQ_CTRL_REG1 = 0x2A; +const uint8_t FXOS8700CQ_CTRL_REG2 = 0x2B; +const uint8_t FXOS8700CQ_CTRL_REG4 = 0x2D; /// Interrupt enable register. +const uint8_t FXOS8700CQ_CTRL_REG5 = 0x2E; /// Interrupt pin register. +const uint8_t FXOS8700CQ_M_CTRL_REG1 = 0x5B; +const uint8_t FXOS8700CQ_M_CTRL_REG2 = 0x5C; +const uint8_t FXOS8700CQ_WHOAMI_VAL = 0xC7; + +// Other defines: +static const uint32_t I2CFastModeHz = 400000; +static const uint32_t I2CNormalModeHz = 100000; +static const uint32_t I2CSuperSlowModeHz = 25000; + +FXOS8700CQ::FXOS8700CQ(PinName SDA, PinName SCL, PinName INT1, PinName INT2, AccelerometerSensitivity setting) +: I2CObj(SDA, SCL), dataReadyInt(INT2), accelSensitivitySetting(setting), + accelInt2Float((accelSensitivitySetting == TWO) ? 1. / 4096. : + (accelSensitivitySetting == FOUR) ? 1. / 2048. : 1. / 1024.), + xOffset(0), yOffset(0), zOffset(0) +{ + + // Set the bus to operate in fast or normal mode. + I2CObj.frequency(I2CFastModeHz); + + // Following routine is based off of manufacturer's datasheet example. + // Create a buffer to hold information to be transfered. + char dataPacket[64]; + + /* Reset the device, placing it into standby mode, to set registers. */ + // standby + // [6] = reset = 1; + dataPacket[0] = FXOS8700CQ_CTRL_REG2; // First byte is register address. + dataPacket[1] = 0b01000000; // Second byte is data - bit 6 set to 1 means reset. + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, dataPacket, 2); + // Wait 2 ms for the reset to take place. + wait_ms(2); + //I2CObj.stop(); + + /* Configure the device to send an interrupt when data is ready. */ + //[7-1]: Disable all other interrupt sources. + //[0]: Enable data-ready interrupt with 1. + dataPacket[0] = FXOS8700CQ_CTRL_REG4; // First byte is register address. + dataPacket[1] = 0b00000001; + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, dataPacket, 2); + //I2CObj.stop(); + /* Configure the data-ready interrupt to be on INT2 Pin. */ + //[7-1]: Other interrupt source pin assignment - we don't care because we only use the data ready interrupt. + //[0]: Set to 0 for data-ready interrupt to be on INT2. + dataPacket[0] = FXOS8700CQ_CTRL_REG5; // First byte is register address. + dataPacket[1] = 0b00000000; + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, dataPacket, 2); + //I2CObj.stop(); + + /* Disable the magnetometer. */ + // write 0001 1111 = 0x1F to magnetometer control register 1 + // [7]: m_acal=0: auto calibration disabled + // [6]: m_rst=0: no one-shot magnetic reset + // [5]: m_ost=0: no one-shot magnetic measurement + // [4-2]: m_os=111=7: 8x oversampling (for 200Hz) to reduce magnetometer noise + // [1-0]: m_hms=00=0: only set the accelerometer to be active. + dataPacket[0] = FXOS8700CQ_M_CTRL_REG1; // First byte is register address. + dataPacket[1] = 0b00011100; // Second byte is data. + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, dataPacket, 2); + //I2CObj.stop(); + + + /* Configure the device to disable the high-pass filter and + * use the setrange. + */ + // [7]: reserved + // [6]: reserved + // [5]: reserved + // [4]: High pass filter filter disabled with 0. + // [3]: reserved + // [2]: reserved + // [1-0]: fs=10 for accelerometer range of +/-8g range with 0.976mg/LSB + uint8_t fs = + (accelSensitivitySetting == TWO) ? 0b00 : + (accelSensitivitySetting == FOUR) ? 0b01 : + 0b10; + dataPacket[0] = FXOS8700CQ_XYZ_DATA_CFG; // First byte is register address. + dataPacket[1] = 0b00000000 | fs; // Second byte is data. + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, dataPacket, 2); + //I2CObj.stop(); + /* + * Set the device out of standby mode. + */ + // [7-6]: aslp_rate=00 // Sleep mode output data rate is 50 Hz. + // [5-3]: dr=000 for 800Hz data rate in accelerometer only mode. + // [2]: lnoise=... for non-low noise mode (Low noise only possible for 2 g or 4 g accelerometer range.) + // [1]: f_read=0 for normal 16 bit reads + // [0]: active=1 to take the part out of standby and enable sampling + uint8_t lNoise = (accelSensitivitySetting != EIGHT) ? 0b100 : 0b000; + dataPacket[0] = FXOS8700CQ_CTRL_REG1; // First byte is register address. + dataPacket[1] = 0b00000001 | lNoise; // Second byte is data. + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, dataPacket, 2); + //I2CObj.stop(); + + // Attach the data-ready interrupt to a member interrupt handler. + // Interrupts are active-low by default. + dataReadyInt.fall(this, &FXOS8700CQ::dataReadyISR); + +} + +FXOS8700CQ::~FXOS8700CQ() { + // TODO Auto-generated destructor stub +} + +void FXOS8700CQ::readAccelerometer(float *xAccel, float *yAccel, float *zAccel) { + // In case an interrupt occurs in the middle of our write, we spin while the data is not consistent. + while((*xAccel != lastxAccel) || (*yAccel != lastyAccel) || (*zAccel != lastzAccel)) { + *xAccel = lastxAccel; + *yAccel = lastyAccel; + *zAccel = lastzAccel; + } +} + +void FXOS8700CQ::dataReadyISR(void) { + char inputBuffer[7]; + I2CObj.write(FXOS8700CQ_SLAVE_ADDR, &FXOS8700CQ_STATUS, 1); + // Read the accelerometer values back from the slave. + I2CObj.read(FXOS8700CQ_SLAVE_ADDR, inputBuffer,7); + + // copy the 14 bit accelerometer byte data into 16 bit words + lastxAccel = accelInt2Float * ((int16_t) ((inputBuffer[1] << 8) | inputBuffer[2]) >> 2) - xOffset; + lastyAccel = accelInt2Float * ((int16_t) ((inputBuffer[3] << 8) | inputBuffer[4]) >> 2) - yOffset; + lastzAccel = accelInt2Float * ((int16_t) ((inputBuffer[5] << 8) | inputBuffer[6]) >> 2) - zOffset; +} + +