Sample code for interfacing with FXOS8700CQ with I2C functions

Dependencies:   mbed

Committer:
eencae
Date:
Tue Jan 31 19:07:30 2017 +0000
Revision:
0:7489bca92308
Child:
1:7f3b2be90495
Example code for interfacing with FXOS8700CQ using I2C functions.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
eencae 0:7489bca92308 1 /* K64F Accelerometer & Magnetometer
eencae 0:7489bca92308 2
eencae 0:7489bca92308 3 Sample code for reading data from on-board FXOS8700CQ sensor
eencae 0:7489bca92308 4
eencae 0:7489bca92308 5 Craig A. Evans
eencae 0:7489bca92308 6 Jan 2017
eencae 0:7489bca92308 7
eencae 0:7489bca92308 8 */
eencae 0:7489bca92308 9
eencae 0:7489bca92308 10 #include "mbed.h"
eencae 0:7489bca92308 11
eencae 0:7489bca92308 12 ///////////// defines //////////////////////////////////
eencae 0:7489bca92308 13
eencae 0:7489bca92308 14 // mbed API uses 8-bit addresses so need to left-shift 7-bit addresses by 1
eencae 0:7489bca92308 15 #define FXOS8700CQ_ADDR (0x1D << 1) // for K64F board
eencae 0:7489bca92308 16 // values from 13.2 datasheet
eencae 0:7489bca92308 17 #define FXOS8700CQ_STATUS 0x00
eencae 0:7489bca92308 18 #define FXOS8700CQ_WHO_AM_I 0x0D
eencae 0:7489bca92308 19 #define FXOS8700CQ_XYZ_DATA_CFG 0x0E
eencae 0:7489bca92308 20 #define FXOS8700CQ_CTRL_REG1 0x2A
eencae 0:7489bca92308 21 #define FXOS8700CQ_M_CTRL_REG1 0x5B
eencae 0:7489bca92308 22 #define FXOS8700CQ_M_CTRL_REG2 0x5C
eencae 0:7489bca92308 23 #define FXOS8700CQ_WHO_AM_I_VAL 0xC7
eencae 0:7489bca92308 24 #define FXOS8700CQ_READ_LEN 13
eencae 0:7489bca92308 25
eencae 0:7489bca92308 26 // struct to hold 6 DOF values
eencae 0:7489bca92308 27 struct Data {
eencae 0:7489bca92308 28 float ax;
eencae 0:7489bca92308 29 float ay;
eencae 0:7489bca92308 30 float az;
eencae 0:7489bca92308 31 float mx;
eencae 0:7489bca92308 32 float my;
eencae 0:7489bca92308 33 float mz;
eencae 0:7489bca92308 34 };
eencae 0:7489bca92308 35
eencae 0:7489bca92308 36 ////////// mbed API objects ////////////////////////////
eencae 0:7489bca92308 37
eencae 0:7489bca92308 38 // I2C connection for FXOS8700CQ accelerometer/magnetometer
eencae 0:7489bca92308 39 I2C fxos8700cq(I2C_SDA,I2C_SCL); // PTE25/PTE24
eencae 0:7489bca92308 40
eencae 0:7489bca92308 41 //////// function prototypes ///////////////////////////
eencae 0:7489bca92308 42 // setup accelerometer/magnetometer
eencae 0:7489bca92308 43 void init_fxos8700cq();
eencae 0:7489bca92308 44 // i2c primitive functions
eencae 0:7489bca92308 45 void send_byte_to_reg(char byte,char reg);
eencae 0:7489bca92308 46 char read_byte_from_reg(char reg);
eencae 0:7489bca92308 47 void read_bytes_from_reg(char reg,int number_of_bytes,char bytes[]);
eencae 0:7489bca92308 48 // FXOS8700CQ values
eencae 0:7489bca92308 49 Data get_values();
eencae 0:7489bca92308 50
eencae 0:7489bca92308 51 ///////// functions ////////////////////////////////////
eencae 0:7489bca92308 52
eencae 0:7489bca92308 53 int main()
eencae 0:7489bca92308 54 {
eencae 0:7489bca92308 55 printf("K64F FXOS8700CQ Example Code\n\n");
eencae 0:7489bca92308 56 init_fxos8700cq();
eencae 0:7489bca92308 57
eencae 0:7489bca92308 58 while(1) {
eencae 0:7489bca92308 59
eencae 0:7489bca92308 60 Data values = get_values();
eencae 0:7489bca92308 61
eencae 0:7489bca92308 62 float mag_h = sqrt(values.mx*values.mx+
eencae 0:7489bca92308 63 values.my*values.my+
eencae 0:7489bca92308 64 values.mz*values.mz);
eencae 0:7489bca92308 65
eencae 0:7489bca92308 66 printf("Mag = %f\n",mag_h);
eencae 0:7489bca92308 67
eencae 0:7489bca92308 68 //printf("ax = %f ay = %f az = %f | mx = %f my = %f mz = %f\n"
eencae 0:7489bca92308 69 // ,values.ax, values.ay, values.az
eencae 0:7489bca92308 70 // ,values.mx, values.my, values.mz);
eencae 0:7489bca92308 71
eencae 0:7489bca92308 72 wait(1.0);
eencae 0:7489bca92308 73 }
eencae 0:7489bca92308 74
eencae 0:7489bca92308 75 }
eencae 0:7489bca92308 76
eencae 0:7489bca92308 77 // gets the status, acceleration and magnetometer data
eencae 0:7489bca92308 78 Data get_values()
eencae 0:7489bca92308 79 {
eencae 0:7489bca92308 80 printf("Reading values...");
eencae 0:7489bca92308 81 // 13 bytes - status plus 6 channels (2 bytes each)
eencae 0:7489bca92308 82 // x,y,z for accelerometer and magnetometer
eencae 0:7489bca92308 83 char data[FXOS8700CQ_READ_LEN];
eencae 0:7489bca92308 84 read_bytes_from_reg(FXOS8700CQ_STATUS,FXOS8700CQ_READ_LEN,data);
eencae 0:7489bca92308 85
eencae 0:7489bca92308 86 // copy the 14 bit accelerometer byte data into 16 bit words
eencae 0:7489bca92308 87 int acc_x = (int16_t)(((data[1] << 8) | data[2]))>> 2;
eencae 0:7489bca92308 88 int acc_y = (int16_t)(((data[3] << 8) | data[4]))>> 2;
eencae 0:7489bca92308 89 int acc_z = (int16_t)(((data[5] << 8) | data[6]))>> 2;
eencae 0:7489bca92308 90
eencae 0:7489bca92308 91 // copy the magnetometer byte data into 16 bit words
eencae 0:7489bca92308 92 int mag_x = (int16_t) (data[7] << 8) | data[8];
eencae 0:7489bca92308 93 int mag_y = (int16_t) (data[9] << 8) | data[10];
eencae 0:7489bca92308 94 int mag_z = (int16_t) (data[11] << 8) | data[12];
eencae 0:7489bca92308 95
eencae 0:7489bca92308 96 Data values; // struct to hold values
eencae 0:7489bca92308 97
eencae 0:7489bca92308 98 // 0.488 mg/LSB in 4 g mode (8.1 data sheet)
eencae 0:7489bca92308 99 values.ax = 0.488e-3*acc_x;
eencae 0:7489bca92308 100 values.ay = 0.488e-3*acc_y;
eencae 0:7489bca92308 101 values.az = 0.488e-3*acc_z;
eencae 0:7489bca92308 102
eencae 0:7489bca92308 103 // the magnetometer sensitivity is fixed at 0.1 μT/LSB
eencae 0:7489bca92308 104 values.mx = 0.1e-6*mag_x;
eencae 0:7489bca92308 105 values.my = 0.1e-6*mag_y;
eencae 0:7489bca92308 106 values.mz = 0.1e-6*mag_z;
eencae 0:7489bca92308 107
eencae 0:7489bca92308 108 printf("Done.\n");
eencae 0:7489bca92308 109
eencae 0:7489bca92308 110 return values;
eencae 0:7489bca92308 111 }
eencae 0:7489bca92308 112
eencae 0:7489bca92308 113 /// primitive i2c functions ////
eencae 0:7489bca92308 114
eencae 0:7489bca92308 115 // sends a byte to a specific register
eencae 0:7489bca92308 116 void send_byte_to_reg(char byte,char reg)
eencae 0:7489bca92308 117 {
eencae 0:7489bca92308 118 char data[2];
eencae 0:7489bca92308 119 data[0] = reg;
eencae 0:7489bca92308 120 data[1] = byte;
eencae 0:7489bca92308 121 // send the register address, followed by the data
eencae 0:7489bca92308 122 int nack = fxos8700cq.write(FXOS8700CQ_ADDR,data,2);
eencae 0:7489bca92308 123 if (nack)
eencae 0:7489bca92308 124 error("No ACK"); // if we don't receive acknowledgement, flash error message
eencae 0:7489bca92308 125 }
eencae 0:7489bca92308 126
eencae 0:7489bca92308 127 // reads a byte from a specific register
eencae 0:7489bca92308 128 char read_byte_from_reg(char reg)
eencae 0:7489bca92308 129 {
eencae 0:7489bca92308 130 int nack = fxos8700cq.write(FXOS8700CQ_ADDR,&reg,1,true); // send the register address to the slave
eencae 0:7489bca92308 131 // true as need to send repeated start condition (5.10.1 datasheet)
eencae 0:7489bca92308 132 // http://www.i2c-bus.org/repeated-start-condition/
eencae 0:7489bca92308 133 if (nack)
eencae 0:7489bca92308 134 error("No ACK"); // if we don't receive acknowledgement, flash error message
eencae 0:7489bca92308 135
eencae 0:7489bca92308 136 char rx;
eencae 0:7489bca92308 137 nack = fxos8700cq.read(FXOS8700CQ_ADDR,&rx,1); // read a byte from the register and store in buffer
eencae 0:7489bca92308 138 if (nack)
eencae 0:7489bca92308 139 error("No ACK"); // if we don't receive acknowledgement, flash error message
eencae 0:7489bca92308 140
eencae 0:7489bca92308 141 return rx;
eencae 0:7489bca92308 142 }
eencae 0:7489bca92308 143
eencae 0:7489bca92308 144 // reads a series of bytes, starting from a specific register
eencae 0:7489bca92308 145 void read_bytes_from_reg(char reg,int number_of_bytes,char bytes[])
eencae 0:7489bca92308 146 {
eencae 0:7489bca92308 147 int nack = fxos8700cq.write(FXOS8700CQ_ADDR,&reg,1,true); // send the slave write address and the configuration register address
eencae 0:7489bca92308 148 // true as need to send repeated start condition (5.10.1 datasheet)
eencae 0:7489bca92308 149 // http://www.i2c-bus.org/repeated-start-condition/
eencae 0:7489bca92308 150
eencae 0:7489bca92308 151 if (nack)
eencae 0:7489bca92308 152 error("No ACK"); // if we don't receive acknowledgement, flash error message
eencae 0:7489bca92308 153
eencae 0:7489bca92308 154 nack = fxos8700cq.read(FXOS8700CQ_ADDR,bytes,number_of_bytes); // read bytes
eencae 0:7489bca92308 155 if (nack)
eencae 0:7489bca92308 156 error("No ACK"); // if we don't receive acknowledgement, flash error message
eencae 0:7489bca92308 157
eencae 0:7489bca92308 158 }
eencae 0:7489bca92308 159
eencae 0:7489bca92308 160 /// init functions /////
eencae 0:7489bca92308 161
eencae 0:7489bca92308 162 // based on 13.4 in datasheet - 200 Hz hybrid mode (both acc and mag)
eencae 0:7489bca92308 163 void init_fxos8700cq()
eencae 0:7489bca92308 164 {
eencae 0:7489bca92308 165 printf("Initialising....\n");
eencae 0:7489bca92308 166
eencae 0:7489bca92308 167 // i2c fast-mode - 10.1.1 data sheet
eencae 0:7489bca92308 168 fxos8700cq.frequency(400000);
eencae 0:7489bca92308 169
eencae 0:7489bca92308 170 // the device has an ID number so we check the value to ensure the correct
eencae 0:7489bca92308 171 // drive is on the i2c bus
eencae 0:7489bca92308 172 char data = read_byte_from_reg(FXOS8700CQ_WHO_AM_I);
eencae 0:7489bca92308 173 if (data != FXOS8700CQ_WHO_AM_I_VAL) { // if correct ID not found, hang and flash error message
eencae 0:7489bca92308 174 error("Not correct ID");
eencae 0:7489bca92308 175 }
eencae 0:7489bca92308 176
eencae 0:7489bca92308 177 printf("Read correct WHO_AM_I value: 0x%X\n",data);
eencae 0:7489bca92308 178
eencae 0:7489bca92308 179 // write 0000 0000 = 0x00 to accelerometer control register 1 to place
eencae 0:7489bca92308 180 // FXOS8700CQ into standby
eencae 0:7489bca92308 181 // [7-1] = 0000 000
eencae 0:7489bca92308 182 // [0]: active=0
eencae 0:7489bca92308 183 data = 0x00;
eencae 0:7489bca92308 184 send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
eencae 0:7489bca92308 185
eencae 0:7489bca92308 186 // write 0001 1111 = 0x1F to magnetometer control register 1
eencae 0:7489bca92308 187 // [7]: m_acal=0: auto calibration disabled
eencae 0:7489bca92308 188 // [6]: m_rst=0: no one-shot magnetic reset
eencae 0:7489bca92308 189 // [5]: m_ost=0: no one-shot magnetic measurement
eencae 0:7489bca92308 190 // [4-2]: m_os=111=7: 8x oversampling (for 200Hz) to reduce magnetometer noise
eencae 0:7489bca92308 191 // [1-0]: m_hms=11=3: select hybrid mode with accel and magnetometer active
eencae 0:7489bca92308 192 data = 0x1F;
eencae 0:7489bca92308 193 send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG1);
eencae 0:7489bca92308 194
eencae 0:7489bca92308 195 // write 0010 0000 = 0x20 to magnetometer control register 2
eencae 0:7489bca92308 196 // [7]: reserved
eencae 0:7489bca92308 197 // [6]: reserved
eencae 0:7489bca92308 198 // [5]: hyb_autoinc_mode=1 to map the magnetometer registers to follow
eencae 0:7489bca92308 199 // the accelerometer registers
eencae 0:7489bca92308 200 // [4]: m_maxmin_dis=0 to retain default min/max latching even though not used
eencae 0:7489bca92308 201 // [3]: m_maxmin_dis_ths=0
eencae 0:7489bca92308 202 // [2]: m_maxmin_rst=0
eencae 0:7489bca92308 203 // [1-0]: m_rst_cnt=00 to enable magnetic reset each cycle
eencae 0:7489bca92308 204 data = 0x20;
eencae 0:7489bca92308 205 send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG2);
eencae 0:7489bca92308 206
eencae 0:7489bca92308 207 // write 0000 0001= 0x01 to XYZ_DATA_CFG register
eencae 0:7489bca92308 208 // [7]: reserved
eencae 0:7489bca92308 209 // [6]: reserved
eencae 0:7489bca92308 210 // [5]: reserved
eencae 0:7489bca92308 211 // [4]: hpf_out=0
eencae 0:7489bca92308 212 // [3]: reserved
eencae 0:7489bca92308 213 // [2]: reserved
eencae 0:7489bca92308 214 // [1-0]: fs=01 for accelerometer range of +/-4g range with 0.488mg/LSB
eencae 0:7489bca92308 215 data = 0x01;
eencae 0:7489bca92308 216 send_byte_to_reg(data,FXOS8700CQ_XYZ_DATA_CFG);
eencae 0:7489bca92308 217
eencae 0:7489bca92308 218 // write 0000 1101 = 0x0D to accelerometer control register 1
eencae 0:7489bca92308 219 // [7-6]: aslp_rate=00
eencae 0:7489bca92308 220 // [5-3]: dr=001 for 200Hz data rate (when in hybrid mode)
eencae 0:7489bca92308 221 // [2]: lnoise=1 for low noise mode
eencae 0:7489bca92308 222 // [1]: f_read=0 for normal 16 bit reads
eencae 0:7489bca92308 223 // [0]: active=1 to take the part out of standby and enable sampling
eencae 0:7489bca92308 224 data = 0x0D;
eencae 0:7489bca92308 225 send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
eencae 0:7489bca92308 226
eencae 0:7489bca92308 227 printf("Initialisation complete!\n");
eencae 0:7489bca92308 228
eencae 0:7489bca92308 229 }