Drivers for the mini robot designed for Princeton's MAE 433 course.

Dependencies:   mbed-dsp mbed-rtos mbed

Dependents:   MAE433_Library_Tester RobotBalancerv2

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;
+}
+
+