James Cummins / Mbed 2 deprecated el17jnc

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FXOS8700CQ.cpp Source File

FXOS8700CQ.cpp

00001 /* FXOS8700CQ Library
00002 
00003 Sample code from ELEC2645 - demonstrates how to create a library
00004 for the K64F on-board accelerometer and magnetometer
00005 
00006 (c) Craig A. Evans, University of Leeds, Jan 2017
00007 
00008 */
00009 
00010 #include "FXOS8700CQ.h"
00011 #include "mbed.h"
00012 
00013 
00014 // constructor is called when the object is created - use it to set pins and frequency
00015 FXOS8700CQ::FXOS8700CQ(PinName sda, PinName scl)
00016 {
00017     i2c = new I2C(sda,scl);        // create new I2C instance and initialise
00018 }
00019 
00020 // destructor is called when the object goes out of scope
00021 FXOS8700CQ::~FXOS8700CQ()
00022 {
00023     delete i2c;        // free memory
00024 }
00025 
00026 // based on 13.4 in datasheet - 200 Hz hybrid mode (both acc and mag)
00027 void FXOS8700CQ::init()
00028 {
00029     // i2c fast-mode - 10.1.1 data sheet
00030     i2c->frequency(400000);       // I2C Fast Mode - 400kHz
00031 
00032     // the device has an ID number so we check the value to ensure the correct
00033     // drive is on the i2c bus
00034     char data = read_byte_from_reg(FXOS8700CQ_WHO_AM_I);
00035     if (data != FXOS8700CQ_WHO_AM_I_VAL) { // if correct ID not found, hang and flash error message
00036         error("Incorrect ID!");
00037     }
00038 
00039     // write 0000 0000 = 0x00 to accelerometer control register 1 to place
00040     // FXOS8700CQ into standby
00041     // [7-1] = 0000 000
00042     // [0]: active=0
00043     data = 0x00;
00044     send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
00045 
00046     // write 0001 1111 = 0x1F to magnetometer control register 1
00047     // [7]: m_acal=0: auto calibration disabled
00048     // [6]: m_rst=0: no one-shot magnetic reset
00049     // [5]: m_ost=0: no one-shot magnetic measurement
00050     // [4-2]: m_os=111=7: 8x oversampling (for 200Hz) to reduce magnetometer noise
00051     // [1-0]: m_hms=11=3: select hybrid mode with accel and magnetometer active
00052     data = 0x1F;
00053     send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG1);
00054 
00055     // write 0010 0000 = 0x20 to magnetometer control register 2
00056     // [7]: reserved
00057     // [6]: reserved
00058     // [5]: hyb_autoinc_mode=1 to map the magnetometer registers to follow
00059     // the accelerometer registers
00060     // [4]: m_maxmin_dis=0 to retain default min/max latching even though not used
00061     // [3]: m_maxmin_dis_ths=0
00062     // [2]: m_maxmin_rst=0
00063     // [1-0]: m_rst_cnt=00 to enable magnetic reset each cycle
00064     data = 0x20;
00065     send_byte_to_reg(data,FXOS8700CQ_M_CTRL_REG2);
00066 
00067     // write 0000 0001= 0x01 to XYZ_DATA_CFG register
00068     // [7]: reserved
00069     // [6]: reserved
00070     // [5]: reserved
00071     // [4]: hpf_out=0
00072     // [3]: reserved
00073     // [2]: reserved
00074     // [1-0]: fs=01 for accelerometer range of +/-4g range with 0.488mg/LSB
00075     data = 0x01;
00076     send_byte_to_reg(data,FXOS8700CQ_XYZ_DATA_CFG);
00077 
00078     // write 0000 1101 = 0x0D to accelerometer control register 1
00079     // [7-6]: aslp_rate=00
00080     // [5-3]: dr=001 for 200Hz data rate (when in hybrid mode)
00081     // [2]: lnoise=1 for low noise mode
00082     // [1]: f_read=0 for normal 16 bit reads
00083     // [0]: active=1 to take the part out of standby and enable sampling
00084     data = 0x0D;
00085     send_byte_to_reg(data,FXOS8700CQ_CTRL_REG1);
00086 
00087 }
00088 
00089 Data FXOS8700CQ::get_values()
00090 {
00091     // 13 bytes - status plus 6 channels (2 bytes each)
00092     // x,y,z for accelerometer and magnetometer
00093     char data[FXOS8700CQ_READ_LEN];
00094     read_bytes_from_reg(FXOS8700CQ_STATUS,FXOS8700CQ_READ_LEN,data);
00095 
00096     // copy the 14 bit accelerometer byte data into 16 bit words
00097     int acc_x = (int16_t)(((data[1] << 8) | data[2]))>> 2;
00098     int acc_y = (int16_t)(((data[3] << 8) | data[4]))>> 2;
00099     int acc_z = (int16_t)(((data[5] << 8) | data[6]))>> 2;
00100 
00101     // copy the magnetometer byte data into 16 bit words
00102     int mag_x = (int16_t) (data[7] << 8) | data[8];
00103     int mag_y = (int16_t) (data[9] << 8) | data[10];
00104     int mag_z = (int16_t) (data[11] << 8) | data[12];
00105 
00106     Data values;  // struct to hold values
00107 
00108     // 0.488 mg/LSB in 4 g mode (8.1 data sheet)
00109     values.ax = 0.488e-3*acc_x;
00110     values.ay = 0.488e-3*acc_y;
00111     values.az = 0.488e-3*acc_z;
00112 
00113     // the magnetometer sensitivity is fixed at 0.1 μT/LSB
00114     values.mx = 0.1e-6*mag_x;
00115     values.my = 0.1e-6*mag_y;
00116     values.mz = 0.1e-6*mag_z;
00117 
00118     return values;
00119 }
00120 
00121 void FXOS8700CQ::send_byte_to_reg(char byte,char reg)
00122 {
00123     char data[2];
00124     data[0] = reg;
00125     data[1] = byte;
00126     // send the register address, followed by the data
00127     int nack = i2c->write(FXOS8700CQ_ADDR,data,2);
00128     if (nack)
00129         error("No acknowledgement received!");  // if we don't receive acknowledgement, send error message
00130 
00131 }
00132 
00133 float FXOS8700CQ::get_roll_angle()
00134 {
00135     Data values = get_values();
00136     double roll = atan2(values.ay, values.az);
00137     return roll*57.3;
00138 }
00139 
00140 float FXOS8700CQ::get_pitch_angle()
00141 {
00142     Data values = get_values();
00143 
00144     float ysquared = values.ay * values.ay;
00145     float zsquared = values.az * values.az;
00146     float mag = sqrt(ysquared+zsquared);
00147     double pitch = atan2(-1*values.ax,mag);
00148     return pitch*57.3;
00149 }
00150 
00151 // reads a byte from a specific register
00152 char FXOS8700CQ::read_byte_from_reg(char reg)
00153 {
00154     int nack = i2c->write(FXOS8700CQ_ADDR,&reg,1,true);  // send the register address to the slave
00155     // true as need to send repeated start condition (5.10.1 datasheet)
00156     // http://www.i2c-bus.org/repeated-start-condition/
00157     if (nack)
00158         error("No acknowledgement received!");  // if we don't receive acknowledgement, send error message
00159 
00160     char rx;
00161     nack = i2c->read(FXOS8700CQ_ADDR,&rx,1);  // read a byte from the register and store in buffer
00162     if (nack)
00163         error("No acknowledgement received!");  // if we don't receive acknowledgement, send error message
00164 
00165     return rx;
00166 }
00167 
00168 // reads a series of bytes, starting from a specific register
00169 void FXOS8700CQ::read_bytes_from_reg(char reg,int number_of_bytes,char bytes[])
00170 {
00171     int nack = i2c->write(FXOS8700CQ_ADDR,&reg,1,true);  // send the slave write address and the configuration register address
00172     // true as need to send repeated start condition (5.10.1 datasheet)
00173     // http://www.i2c-bus.org/repeated-start-condition/
00174 
00175     if (nack)
00176         error("No acknowledgement received!");  // if we don't receive acknowledgement, send error message
00177 
00178     nack = i2c->read(FXOS8700CQ_ADDR,bytes,number_of_bytes);  // read bytes
00179     if (nack)
00180         error("No acknowledgement received!");  // if we don't receive acknowledgement, send error message
00181 
00182 }