FINAL VERSION

Dependencies:   mbed

Committer:
jamesheavey
Date:
Thu May 09 14:36:51 2019 +0000
Revision:
140:d8634e76ecce
Parent:
15:b867a6620f96
Final Submission. I have read and agreed with Statement of Academic Integrity.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jamesheavey 15:b867a6620f96 1 /* FXOS8700CQ Library
jamesheavey 15:b867a6620f96 2
jamesheavey 15:b867a6620f96 3 Sample code from ELEC2645 - demonstrates how to create a library
jamesheavey 15:b867a6620f96 4 for the K64F on-board accelerometer and magnetometer
jamesheavey 15:b867a6620f96 5
jamesheavey 15:b867a6620f96 6 (c) Craig A. Evans, University of Leeds, Jan 2017
jamesheavey 15:b867a6620f96 7
jamesheavey 15:b867a6620f96 8 */
jamesheavey 15:b867a6620f96 9
jamesheavey 15:b867a6620f96 10 #include "FXOS8700CQ.h"
jamesheavey 15:b867a6620f96 11
jamesheavey 15:b867a6620f96 12 // constructor is called when the object is created - use it to set pins and frequency
jamesheavey 15:b867a6620f96 13 FXOS8700CQ::FXOS8700CQ(PinName sda, PinName scl)
jamesheavey 15:b867a6620f96 14 {
jamesheavey 15:b867a6620f96 15 i2c = new I2C(sda,scl); // create new I2C instance and initialise
jamesheavey 15:b867a6620f96 16 }
jamesheavey 15:b867a6620f96 17
jamesheavey 15:b867a6620f96 18 // destructor is called when the object goes out of scope
jamesheavey 15:b867a6620f96 19 FXOS8700CQ::~FXOS8700CQ()
jamesheavey 15:b867a6620f96 20 {
jamesheavey 15:b867a6620f96 21 delete i2c; // free memory
jamesheavey 15:b867a6620f96 22 }
jamesheavey 15:b867a6620f96 23
jamesheavey 15:b867a6620f96 24 // based on 13.4 in datasheet - 200 Hz hybrid mode (both acc and mag)
jamesheavey 15:b867a6620f96 25 void FXOS8700CQ::init()
jamesheavey 15:b867a6620f96 26 {
jamesheavey 15:b867a6620f96 27 // i2c fast-mode - 10.1.1 data sheet
jamesheavey 15:b867a6620f96 28 i2c->frequency(400000); // I2C Fast Mode - 400kHz
jamesheavey 15:b867a6620f96 29
jamesheavey 15:b867a6620f96 30 // the device has an ID number so we check the value to ensure the correct
jamesheavey 15:b867a6620f96 31 // drive is on the i2c bus
jamesheavey 15:b867a6620f96 32 char data = read_byte_from_reg(FXOS8700CQ_WHO_AM_I);
jamesheavey 15:b867a6620f96 33 if (data != FXOS8700CQ_WHO_AM_I_VAL) { // if correct ID not found, hang and flash error message
jamesheavey 15:b867a6620f96 34 error("Incorrect ID!");
jamesheavey 15:b867a6620f96 35 }
jamesheavey 15:b867a6620f96 36
jamesheavey 15:b867a6620f96 37 // write 0000 0000 = 0x00 to accelerometer control register 1 to place
jamesheavey 15:b867a6620f96 38 // FXOS8700CQ into standby
jamesheavey 15:b867a6620f96 39 // [7-1] = 0000 000
jamesheavey 15:b867a6620f96 40 // [0]: active=0
jamesheavey 15:b867a6620f96 41 data = 0x00;
jamesheavey 15:b867a6620f96 42 send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
jamesheavey 15:b867a6620f96 43
jamesheavey 15:b867a6620f96 44 // write 0001 1111 = 0x1F to magnetometer control register 1
jamesheavey 15:b867a6620f96 45 // [7]: m_acal=0: auto calibration disabled
jamesheavey 15:b867a6620f96 46 // [6]: m_rst=0: no one-shot magnetic reset
jamesheavey 15:b867a6620f96 47 // [5]: m_ost=0: no one-shot magnetic measurement
jamesheavey 15:b867a6620f96 48 // [4-2]: m_os=111=7: 8x oversampling (for 200Hz) to reduce magnetometer noise
jamesheavey 15:b867a6620f96 49 // [1-0]: m_hms=11=3: select hybrid mode with accel and magnetometer active
jamesheavey 15:b867a6620f96 50 data = 0x1F;
jamesheavey 15:b867a6620f96 51 send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG1);
jamesheavey 15:b867a6620f96 52
jamesheavey 15:b867a6620f96 53 // write 0010 0000 = 0x20 to magnetometer control register 2
jamesheavey 15:b867a6620f96 54 // [7]: reserved
jamesheavey 15:b867a6620f96 55 // [6]: reserved
jamesheavey 15:b867a6620f96 56 // [5]: hyb_autoinc_mode=1 to map the magnetometer registers to follow
jamesheavey 15:b867a6620f96 57 // the accelerometer registers
jamesheavey 15:b867a6620f96 58 // [4]: m_maxmin_dis=0 to retain default min/max latching even though not used
jamesheavey 15:b867a6620f96 59 // [3]: m_maxmin_dis_ths=0
jamesheavey 15:b867a6620f96 60 // [2]: m_maxmin_rst=0
jamesheavey 15:b867a6620f96 61 // [1-0]: m_rst_cnt=00 to enable magnetic reset each cycle
jamesheavey 15:b867a6620f96 62 data = 0x20;
jamesheavey 15:b867a6620f96 63 send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG2);
jamesheavey 15:b867a6620f96 64
jamesheavey 15:b867a6620f96 65 // write 0000 0001= 0x01 to XYZ_DATA_CFG register
jamesheavey 15:b867a6620f96 66 // [7]: reserved
jamesheavey 15:b867a6620f96 67 // [6]: reserved
jamesheavey 15:b867a6620f96 68 // [5]: reserved
jamesheavey 15:b867a6620f96 69 // [4]: hpf_out=0
jamesheavey 15:b867a6620f96 70 // [3]: reserved
jamesheavey 15:b867a6620f96 71 // [2]: reserved
jamesheavey 15:b867a6620f96 72 // [1-0]: fs=01 for accelerometer range of +/-4g range with 0.488mg/LSB
jamesheavey 15:b867a6620f96 73 data = 0x01;
jamesheavey 15:b867a6620f96 74 send_byte_to_reg(data,FXOS8700CQ_XYZ_DATA_CFG);
jamesheavey 15:b867a6620f96 75
jamesheavey 15:b867a6620f96 76 // write 0000 1101 = 0x0D to accelerometer control register 1
jamesheavey 15:b867a6620f96 77 // [7-6]: aslp_rate=00
jamesheavey 15:b867a6620f96 78 // [5-3]: dr=001 for 200Hz data rate (when in hybrid mode)
jamesheavey 15:b867a6620f96 79 // [2]: lnoise=1 for low noise mode
jamesheavey 15:b867a6620f96 80 // [1]: f_read=0 for normal 16 bit reads
jamesheavey 15:b867a6620f96 81 // [0]: active=1 to take the part out of standby and enable sampling
jamesheavey 15:b867a6620f96 82 data = 0x0D;
jamesheavey 15:b867a6620f96 83 send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
jamesheavey 15:b867a6620f96 84
jamesheavey 15:b867a6620f96 85 }
jamesheavey 15:b867a6620f96 86
jamesheavey 15:b867a6620f96 87 Data FXOS8700CQ::get_values()
jamesheavey 15:b867a6620f96 88 {
jamesheavey 15:b867a6620f96 89 // 13 bytes - status plus 6 channels (2 bytes each)
jamesheavey 15:b867a6620f96 90 // x,y,z for accelerometer and magnetometer
jamesheavey 15:b867a6620f96 91 char data[FXOS8700CQ_READ_LEN];
jamesheavey 15:b867a6620f96 92 read_bytes_from_reg(FXOS8700CQ_STATUS,FXOS8700CQ_READ_LEN,data);
jamesheavey 15:b867a6620f96 93
jamesheavey 15:b867a6620f96 94 // copy the 14 bit accelerometer byte data into 16 bit words
jamesheavey 15:b867a6620f96 95 int acc_x = (int16_t)(((data[1] << 8) | data[2]))>> 2;
jamesheavey 15:b867a6620f96 96 int acc_y = (int16_t)(((data[3] << 8) | data[4]))>> 2;
jamesheavey 15:b867a6620f96 97 int acc_z = (int16_t)(((data[5] << 8) | data[6]))>> 2;
jamesheavey 15:b867a6620f96 98
jamesheavey 15:b867a6620f96 99 // copy the magnetometer byte data into 16 bit words
jamesheavey 15:b867a6620f96 100 int mag_x = (int16_t) (data[7] << 8) | data[8];
jamesheavey 15:b867a6620f96 101 int mag_y = (int16_t) (data[9] << 8) | data[10];
jamesheavey 15:b867a6620f96 102 int mag_z = (int16_t) (data[11] << 8) | data[12];
jamesheavey 15:b867a6620f96 103
jamesheavey 15:b867a6620f96 104 Data values; // struct to hold values
jamesheavey 15:b867a6620f96 105
jamesheavey 15:b867a6620f96 106 // 0.488 mg/LSB in 4 g mode (8.1 data sheet)
jamesheavey 15:b867a6620f96 107 values.ax = 0.488e-3*acc_x;
jamesheavey 15:b867a6620f96 108 values.ay = 0.488e-3*acc_y;
jamesheavey 15:b867a6620f96 109 values.az = 0.488e-3*acc_z;
jamesheavey 15:b867a6620f96 110
jamesheavey 15:b867a6620f96 111 // the magnetometer sensitivity is fixed at 0.1 μT/LSB
jamesheavey 15:b867a6620f96 112 values.mx = 0.1e-6*mag_x;
jamesheavey 15:b867a6620f96 113 values.my = 0.1e-6*mag_y;
jamesheavey 15:b867a6620f96 114 values.mz = 0.1e-6*mag_z;
jamesheavey 15:b867a6620f96 115
jamesheavey 15:b867a6620f96 116 return values;
jamesheavey 15:b867a6620f96 117 }
jamesheavey 15:b867a6620f96 118
jamesheavey 15:b867a6620f96 119 void FXOS8700CQ::send_byte_to_reg(char byte,char reg)
jamesheavey 15:b867a6620f96 120 {
jamesheavey 15:b867a6620f96 121 char data[2];
jamesheavey 15:b867a6620f96 122 data[0] = reg;
jamesheavey 15:b867a6620f96 123 data[1] = byte;
jamesheavey 15:b867a6620f96 124 // send the register address, followed by the data
jamesheavey 15:b867a6620f96 125 int nack = i2c->write(FXOS8700CQ_ADDR,data,2);
jamesheavey 15:b867a6620f96 126 if (nack)
jamesheavey 15:b867a6620f96 127 error("No acknowledgement received!"); // if we don't receive acknowledgement, send error message
jamesheavey 15:b867a6620f96 128
jamesheavey 15:b867a6620f96 129 }
jamesheavey 15:b867a6620f96 130
jamesheavey 15:b867a6620f96 131 // reads a byte from a specific register
jamesheavey 15:b867a6620f96 132 char FXOS8700CQ::read_byte_from_reg(char reg)
jamesheavey 15:b867a6620f96 133 {
jamesheavey 15:b867a6620f96 134 int nack = i2c->write(FXOS8700CQ_ADDR,&reg,1,true); // send the register address to the slave
jamesheavey 15:b867a6620f96 135 // true as need to send repeated start condition (5.10.1 datasheet)
jamesheavey 15:b867a6620f96 136 // http://www.i2c-bus.org/repeated-start-condition/
jamesheavey 15:b867a6620f96 137 if (nack)
jamesheavey 15:b867a6620f96 138 error("No acknowledgement received!"); // if we don't receive acknowledgement, send error message
jamesheavey 15:b867a6620f96 139
jamesheavey 15:b867a6620f96 140 char rx;
jamesheavey 15:b867a6620f96 141 nack = i2c->read(FXOS8700CQ_ADDR,&rx,1); // read a byte from the register and store in buffer
jamesheavey 15:b867a6620f96 142 if (nack)
jamesheavey 15:b867a6620f96 143 error("No acknowledgement received!"); // if we don't receive acknowledgement, send error message
jamesheavey 15:b867a6620f96 144
jamesheavey 15:b867a6620f96 145 return rx;
jamesheavey 15:b867a6620f96 146 }
jamesheavey 15:b867a6620f96 147
jamesheavey 15:b867a6620f96 148 // reads a series of bytes, starting from a specific register
jamesheavey 15:b867a6620f96 149 void FXOS8700CQ::read_bytes_from_reg(char reg,int number_of_bytes,char bytes[])
jamesheavey 15:b867a6620f96 150 {
jamesheavey 15:b867a6620f96 151 int nack = i2c->write(FXOS8700CQ_ADDR,&reg,1,true); // send the slave write address and the configuration register address
jamesheavey 15:b867a6620f96 152 // true as need to send repeated start condition (5.10.1 datasheet)
jamesheavey 15:b867a6620f96 153 // http://www.i2c-bus.org/repeated-start-condition/
jamesheavey 15:b867a6620f96 154
jamesheavey 15:b867a6620f96 155 if (nack)
jamesheavey 15:b867a6620f96 156 error("No acknowledgement received!"); // if we don't receive acknowledgement, send error message
jamesheavey 15:b867a6620f96 157
jamesheavey 15:b867a6620f96 158 nack = i2c->read(FXOS8700CQ_ADDR,bytes,number_of_bytes); // read bytes
jamesheavey 15:b867a6620f96 159 if (nack)
jamesheavey 15:b867a6620f96 160 error("No acknowledgement received!"); // if we don't receive acknowledgement, send error message
jamesheavey 15:b867a6620f96 161
jamesheavey 15:b867a6620f96 162 }
jamesheavey 15:b867a6620f96 163
jamesheavey 15:b867a6620f96 164 float FXOS8700CQ::get_roll_angle()
jamesheavey 15:b867a6620f96 165 {
jamesheavey 15:b867a6620f96 166 Data values = get_values();
jamesheavey 15:b867a6620f96 167 float roll_rad = atan2(values.ay,values.az);
jamesheavey 15:b867a6620f96 168 return roll_rad*(360/3.14159265);
jamesheavey 15:b867a6620f96 169 }
jamesheavey 15:b867a6620f96 170
jamesheavey 15:b867a6620f96 171 float FXOS8700CQ::get_pitch_angle()
jamesheavey 15:b867a6620f96 172 {
jamesheavey 15:b867a6620f96 173 Data values = get_values();
jamesheavey 15:b867a6620f96 174 float pitch_rad = atan2(-values.ax,sqrt((values.ay * values.ay) + (values.az * values.az)));
jamesheavey 15:b867a6620f96 175 return pitch_rad*(360/3.14159265);
jamesheavey 15:b867a6620f96 176 }