Sample code for interfacing with FXOS8700CQ with I2C functions

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* K64F Accelerometer & Magnetometer
00002 
00003 Sample code for reading data from on-board FXOS8700CQ sensor
00004 
00005 Craig A. Evans
00006 Jan 2017
00007 
00008 */
00009 
00010 #include "mbed.h"
00011 
00012 ///////////// defines //////////////////////////////////
00013 
00014 // mbed API uses 8-bit addresses so need to left-shift 7-bit addresses by 1
00015 #define FXOS8700CQ_ADDR   (0x1D << 1)    // for K64F board
00016 // values from 13.2 datasheet
00017 #define FXOS8700CQ_STATUS 0x00
00018 #define FXOS8700CQ_WHO_AM_I 0x0D
00019 #define FXOS8700CQ_XYZ_DATA_CFG 0x0E
00020 #define FXOS8700CQ_CTRL_REG1 0x2A
00021 #define FXOS8700CQ_M_CTRL_REG1 0x5B
00022 #define FXOS8700CQ_M_CTRL_REG2 0x5C
00023 #define FXOS8700CQ_WHO_AM_I_VAL 0xC7
00024 #define FXOS8700CQ_READ_LEN 13
00025 
00026 // struct to hold 6 DOF values
00027 struct Data {
00028     float ax;
00029     float ay;
00030     float az;
00031     float mx;
00032     float my;
00033     float mz;
00034 };
00035 
00036 ////////// mbed API objects ////////////////////////////
00037 
00038 // I2C connection for FXOS8700CQ accelerometer/magnetometer
00039 I2C fxos8700cq(I2C_SDA,I2C_SCL);  // PTE25/PTE24
00040 
00041 //////// function prototypes ///////////////////////////
00042 // setup accelerometer/magnetometer
00043 void init_fxos8700cq();
00044 // i2c primitive functions
00045 void send_byte_to_reg(char byte,char reg);
00046 char read_byte_from_reg(char reg);
00047 void read_bytes_from_reg(char reg,int number_of_bytes,char bytes[]);
00048 // FXOS8700CQ values
00049 Data get_values();
00050 
00051 ///////// functions ////////////////////////////////////
00052 
00053 int main()
00054 {
00055     printf("K64F FXOS8700CQ Example Code\n\n");
00056     init_fxos8700cq();
00057 
00058     while(1) {
00059         
00060         Data values = get_values();
00061         
00062         printf("ax = %f ay = %f az = %f | mx = %f my = %f mz = %f\n"
00063                ,values.ax, values.ay, values.az
00064               ,values.mx, values.my, values.mz);
00065         
00066         wait(1.0);
00067     }
00068 
00069 }
00070 
00071 // gets the status, acceleration and magnetometer data
00072 Data get_values()
00073 {
00074     printf("Reading values...");
00075     // 13 bytes - status plus 6 channels (2 bytes each)
00076     // x,y,z for accelerometer and magnetometer
00077     char data[FXOS8700CQ_READ_LEN];
00078     read_bytes_from_reg(FXOS8700CQ_STATUS,FXOS8700CQ_READ_LEN,data);
00079 
00080     // copy the 14 bit accelerometer byte data into 16 bit words
00081     int acc_x = (int16_t)(((data[1] << 8) | data[2]))>> 2;
00082     int acc_y = (int16_t)(((data[3] << 8) | data[4]))>> 2;
00083     int acc_z = (int16_t)(((data[5] << 8) | data[6]))>> 2;
00084 
00085     // copy the magnetometer byte data into 16 bit words
00086     int mag_x = (int16_t) (data[7] << 8) | data[8];
00087     int mag_y = (int16_t) (data[9] << 8) | data[10];
00088     int mag_z = (int16_t) (data[11] << 8) | data[12];
00089 
00090     Data values;  // struct to hold values
00091 
00092     // 0.488 mg/LSB in 4 g mode (8.1 data sheet)
00093     values.ax = 0.488e-3*acc_x;
00094     values.ay = 0.488e-3*acc_y;
00095     values.az = 0.488e-3*acc_z;
00096 
00097     // the magnetometer sensitivity is fixed at 0.1 μT/LSB
00098     values.mx = 0.1e-6*mag_x;
00099     values.my = 0.1e-6*mag_y;
00100     values.mz = 0.1e-6*mag_z;
00101 
00102     printf("Done.\n");
00103 
00104     return values;
00105 }
00106 
00107 /// primitive i2c functions ////
00108 
00109 // sends a byte to a specific register
00110 void send_byte_to_reg(char byte,char reg)
00111 {
00112     char data[2];
00113     data[0] = reg;
00114     data[1] = byte;
00115     // send the register address, followed by the data
00116     int nack = fxos8700cq.write(FXOS8700CQ_ADDR,data,2);
00117     if (nack)
00118         error("No ACK");  // if we don't receive acknowledgement, flash error message
00119 }
00120 
00121 // reads a byte from a specific register
00122 char read_byte_from_reg(char reg)
00123 {
00124     int nack = fxos8700cq.write(FXOS8700CQ_ADDR,&reg,1,true);  // send the register address to the slave
00125     // true as need to send repeated start condition (5.10.1 datasheet)
00126     // http://www.i2c-bus.org/repeated-start-condition/
00127     if (nack)
00128         error("No ACK");  // if we don't receive acknowledgement, flash error message
00129 
00130     char rx;
00131     nack = fxos8700cq.read(FXOS8700CQ_ADDR,&rx,1);  // read a byte from the register and store in buffer
00132     if (nack)
00133         error("No ACK");  // if we don't receive acknowledgement, flash error message
00134 
00135     return rx;
00136 }
00137 
00138 // reads a series of bytes, starting from a specific register
00139 void read_bytes_from_reg(char reg,int number_of_bytes,char bytes[])
00140 {
00141     int nack = fxos8700cq.write(FXOS8700CQ_ADDR,&reg,1,true);  // send the slave write address and the configuration register address
00142     // true as need to send repeated start condition (5.10.1 datasheet)
00143     // http://www.i2c-bus.org/repeated-start-condition/
00144 
00145     if (nack)
00146         error("No ACK");  // if we don't receive acknowledgement, flash error message
00147 
00148     nack = fxos8700cq.read(FXOS8700CQ_ADDR,bytes,number_of_bytes);  // read bytes
00149     if (nack)
00150         error("No ACK");  // if we don't receive acknowledgement, flash error message
00151 
00152 }
00153 
00154 /// init functions /////
00155 
00156 // based on 13.4 in datasheet - 200 Hz hybrid mode (both acc and mag)
00157 void init_fxos8700cq()
00158 {
00159     printf("Initialising....\n");
00160 
00161     // i2c fast-mode - 10.1.1 data sheet
00162     fxos8700cq.frequency(400000);
00163 
00164     // the device has an ID number so we check the value to ensure the correct
00165     // drive is on the i2c bus
00166     char data = read_byte_from_reg(FXOS8700CQ_WHO_AM_I);
00167     if (data != FXOS8700CQ_WHO_AM_I_VAL) { // if correct ID not found, hang and flash error message
00168         error("Not correct ID");
00169     }
00170 
00171     printf("Read correct WHO_AM_I value: 0x%X\n",data);
00172 
00173     // write 0000 0000 = 0x00 to accelerometer control register 1 to place
00174     // FXOS8700CQ into standby
00175     // [7-1] = 0000 000
00176     // [0]: active=0
00177     data = 0x00;
00178     send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
00179 
00180     // write 0001 1111 = 0x1F to magnetometer control register 1
00181     // [7]: m_acal=0: auto calibration disabled
00182     // [6]: m_rst=0: no one-shot magnetic reset
00183     // [5]: m_ost=0: no one-shot magnetic measurement
00184     // [4-2]: m_os=111=7: 8x oversampling (for 200Hz) to reduce magnetometer noise
00185     // [1-0]: m_hms=11=3: select hybrid mode with accel and magnetometer active
00186     data = 0x1F;
00187     send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG1);
00188 
00189     // write 0010 0000 = 0x20 to magnetometer control register 2
00190     // [7]: reserved
00191     // [6]: reserved
00192     // [5]: hyb_autoinc_mode=1 to map the magnetometer registers to follow
00193     // the accelerometer registers
00194     // [4]: m_maxmin_dis=0 to retain default min/max latching even though not used
00195     // [3]: m_maxmin_dis_ths=0
00196     // [2]: m_maxmin_rst=0
00197     // [1-0]: m_rst_cnt=00 to enable magnetic reset each cycle
00198     data = 0x20;
00199     send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG2);
00200 
00201     // write 0000 0001= 0x01 to XYZ_DATA_CFG register
00202     // [7]: reserved
00203     // [6]: reserved
00204     // [5]: reserved
00205     // [4]: hpf_out=0
00206     // [3]: reserved
00207     // [2]: reserved
00208     // [1-0]: fs=01 for accelerometer range of +/-4g range with 0.488mg/LSB
00209     data = 0x01;
00210     send_byte_to_reg(data,FXOS8700CQ_XYZ_DATA_CFG);
00211 
00212     // write 0000 1101 = 0x0D to accelerometer control register 1
00213     // [7-6]: aslp_rate=00
00214     // [5-3]: dr=001 for 200Hz data rate (when in hybrid mode)
00215     // [2]: lnoise=1 for low noise mode
00216     // [1]: f_read=0 for normal 16 bit reads
00217     // [0]: active=1 to take the part out of standby and enable sampling
00218     data = 0x0D;
00219     send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
00220 
00221     printf("Initialisation complete!\n");
00222 
00223 }