Craig Evans
/
2645_FXOS8700CQ_Functions
Sample code for interfacing with FXOS8700CQ with I2C functions
main.cpp@0:7489bca92308, 2017-01-31 (annotated)
- 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?
User | Revision | Line number | New 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,®,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,®,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 | } |