Sensors Knowledge Base

cancel
Showing results for 
Search instead for 
Did you mean: 

Sensors Knowledge Base

Discussions

Sort by:
Hi Everyone,   As I am often asked for a simple bare metal example code for the Xtrinsic FXOS8700CQ 6-axis sensor, I would like to share here one of my examples I have created for this part while working with the Freescale FRDM-KL25Z platform and FRDM-FXS-MULTI(-B) sensor expansion board that features many of the Xtrinsic sensors including the FXOS8700CQ. The FreeMASTER tool is used to visualize both the acceleration and magnetic data that are read from the FXOS8700CQ using an interrupt technique through the I 2 C interface.   This example illustrates:   1. Initialization of the MKL25Z128 MCU (mainly I2C and PORT modules). 2. I 2 C data write and read operations. 3. Initialization of the FXOS8700CQ. 4. Simple accelerometer offset calibration based on the AN4069. 5. Simple magnetic hard-iron offset calibration. 6. Output data reading using an interrupt technique. 7. Conversion of the output values from registers 0x01 – 0x06 and 0x33 – 0x38 to real values in g’s and µT and simple heading angle calculation. 8. Visualization of the calculated values in the FreeMASTER tool.   1. As you can see in the FRDM-FXS-MULTI(-B) / FRDM-KL25Z schematics and the image below, I2C signals are routed to the I2C1 module (PTC1 and PTC2 pins) of the KL25Z MCU and the INT1 output is connected to the PTD4 pin (make sure that pins 1-2 of J3 on the sensor expansion board are connected together using a jumper). The INT1 output of the FXOS8700CQ is configured as a push-pull active-low output, so the corresponding PTD4 pin configuration is GPIO with an interrupt on falling edge.   The MCU is, therefore, configured as follows.   void MCU_Init( void ) {      //I2C1 module initialization      SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;        // Turn on clock to I2C1 module      SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;       // Turn on clock to Port C module      PORTC_PCR1 |= PORT_PCR_MUX(0x2);         // PTC1 pin is I2C1 SCL line      PORTC_PCR2 |= PORT_PCR_MUX(0x2);         // PTC2 pin is I2C1 SDA line      I2C1_F  |= I2C_F_ICR(0x14);              // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us      I2C1_C1 |= I2C_C1_IICEN_MASK;            // Enable I2C0 module               //Configure the PTD4 pin (connected to the INT1 of the FXOS8700CQ) for falling edge interrupts      SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;       // Turn on clock to Port A module      PORTD_PCR4 |= (0|PORT_PCR_ISF_MASK|      // Clear the interrupt flag                      PORT_PCR_MUX(0x1)|       // PTD4 is configured as GPIO                      PORT_PCR_IRQC(0xA));     // PTD4 is configured for falling edge interrupts                   //Enable PORTD interrupt on NVIC      NVIC_ICPR |= 1 << (( INT_PORTD - 16)%32);      NVIC_ISER |= 1 << (( INT_PORTD - 16)%32); }   2. The 7-bit I2C address of the FXOS8700CQ is 0x1E since both SA0 and SA1 lines are shorted to GND using jumpers J21 and J23 on the sensor board. As shown above, the SCL line is connected to the PTC1 pin and SDA line to the PTC2 pin. The I2C clock frequency is 125 kHz.   The screenshot below shows the write operation which writes the value 0x35 to the CTRL_REG1 (0x2A).     And here is the single byte read from the WHO_AM_I register 0x0D. As you can see, it returns the correct value 0xC7.     Multiple bytes of data can be read from sequential registers after each FXOS8700CQ acknowledgment (AK) is received until a no acknowledge (NAK) occurs from the KL25Z followed by a stop condition (SP) signaling an end of transmission. A burst read of 6 bytes from registers 0x33 to 0x38, that is performed in the calibration routine “FXOS8700CQ_Mag_Calibration()”, is shown below. It also shows when the INT1 pin is automatically cleared.     3. At the beginning of the initialization, all registers are reset to their default values by setting the RST bit of the CTRL_REG2 register. Then the FXOS8700CQ is initialized as shown below.   void FXOS8700CQ_Init ( void ) {      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG2, 0x40);          // Reset all registers to POR values        Pause(0x631);        // ~1ms delay        I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, XYZ_DATA_CFG_REG, 0x00);   // +/-2g range with 0.244mg/LSB          I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG1, 0x1F);        // Hybrid mode (accelerometer + magnetometer), max OSR      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG2, 0x20);        // M_OUT_X_MSB register 0x33 follows the OUT_Z_LSB register 0x06 (used for burst read)                   I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG2, 0x02);          // High Resolution mode      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG3, 0x00);          // Push-pull, active low interrupt      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG4, 0x01);          // Enable DRDY interrupt      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG5, 0x01);          // DRDY interrupt routed to INT1 - PTD4      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x35);          // ODR = 3.125Hz, Reduced noise, Active mode   }   4. A simple accelerometer offset calibration method is implemented according to the AN4069.   void FXOS8700CQ_Accel_Calibration ( void ) {      char X_Accel_offset, Y_Accel_offset, Z_Accel_offset;        DataReady = 0;                while (!DataReady) { }       // Is a first set of data ready?      DataReady = 0;        I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x00);          // Standby mode             I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, OUT_X_MSB_REG, 6, AccelMagData);          // Read data output registers 0x01-0x06                 Xout_Accel_14_bit = (( short ) (AccelMagData[0]<<8 | AccelMagData[1])) >> 2;        // Compute 14-bit X-axis acceleration output value      Yout_Accel_14_bit = (( short ) (AccelMagData[2]<<8 | AccelMagData[3])) >> 2;        // Compute 14-bit Y-axis acceleration output value      Zout_Accel_14_bit = (( short ) (AccelMagData[4]<<8 | AccelMagData[5])) >> 2;        // Compute 14-bit Z-axis acceleration output value               X_Accel_offset = Xout_Accel_14_bit / 8 * (-1);         // Compute X-axis offset correction value      Y_Accel_offset = Yout_Accel_14_bit / 8 * (-1);         // Compute Y-axis offset correction value      Z_Accel_offset = (Zout_Accel_14_bit - SENSITIVITY_2G) / 8 * (-1);          // Compute Z-axis offset correction value               I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, OFF_X_REG, X_Accel_offset);                  I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, OFF_Y_REG, Y_Accel_offset);           I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, OFF_Z_REG, Z_Accel_offset);                    I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x35);          // Active mode again }   5. A simple software calibration of magnetic hard-iron offset consists of recording the minimum and maximum magnetometer readings while rotating the board horizontally and vertically and then computing the calibration values from their average. The calibration time is defined by the number of samples taken during calibration (local variable “i” in the while loop) and selected ODR. In my example I use 94 samples at 3.125Hz, so the calibration routine takes 30s.   void FXOS8700CQ_Mag_Calibration ( void ) {      short Xout_Mag_16_bit_avg, Yout_Mag_16_bit_avg, Zout_Mag_16_bit_avg;          short Xout_Mag_16_bit_max, Yout_Mag_16_bit_max, Zout_Mag_16_bit_max;          short Xout_Mag_16_bit_min, Yout_Mag_16_bit_min, Zout_Mag_16_bit_min;      char i = 0;        DataReady = 0;            while (i < 94)             // This takes ~30s (94 samples * 1/3.125)      {               if (DataReady)             // Is a new set of data ready?         {                          DataReady = 0;                                                                                                                                                                I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, MOUT_X_MSB_REG, 6, AccelMagData);         // Read data output registers 0x33 - 0x38                                   Xout_Mag_16_bit = ( short ) (AccelMagData[0]<<8 | AccelMagData[1]);        // Compute 16-bit X-axis magnetic output value              Yout_Mag_16_bit = ( short ) (AccelMagData[2]<<8 | AccelMagData[3]);        // Compute 16-bit Y-axis magnetic output value              Zout_Mag_16_bit = ( short ) (AccelMagData[4]<<8 | AccelMagData[5]);        // Compute 16-bit Z-axis magnetic output value                                            // Assign first sample to maximum and minimum values                        if (i == 0)              {                   Xout_Mag_16_bit_max = Xout_Mag_16_bit;                   Xout_Mag_16_bit_min = Xout_Mag_16_bit;                                                Yout_Mag_16_bit_max = Yout_Mag_16_bit;                   Yout_Mag_16_bit_min = Yout_Mag_16_bit;                                                Zout_Mag_16_bit_max = Zout_Mag_16_bit;                   Zout_Mag_16_bit_min = Zout_Mag_16_bit;              }                                       // Check to see if current sample is the maximum or minimum X-axis value                       if (Xout_Mag_16_bit > Xout_Mag_16_bit_max)    {Xout_Mag_16_bit_max = Xout_Mag_16_bit;}                       if (Xout_Mag_16_bit < Xout_Mag_16_bit_min)    {Xout_Mag_16_bit_min = Xout_Mag_16_bit;}                         // Check to see if current sample is the maximum or minimum Y-axis value                       if (Yout_Mag_16_bit > Yout_Mag_16_bit_max)    {Yout_Mag_16_bit_max = Yout_Mag_16_bit;}                       if (Yout_Mag_16_bit < Yout_Mag_16_bit_min)    {Yout_Mag_16_bit_min = Yout_Mag_16_bit;}                                       // Check to see if current sample is the maximum or minimum Z-axis value                       if (Zout_Mag_16_bit > Zout_Mag_16_bit_max)    {Zout_Mag_16_bit_max = Zout_Mag_16_bit;}                       if (Zout_Mag_16_bit < Zout_Mag_16_bit_min)    {Zout_Mag_16_bit_min = Zout_Mag_16_bit;}                              i++;          }           }        Xout_Mag_16_bit_avg = (Xout_Mag_16_bit_max + Xout_Mag_16_bit_min) / 2;            // X-axis hard-iron offset      Yout_Mag_16_bit_avg = (Yout_Mag_16_bit_max + Yout_Mag_16_bit_min) / 2;            // Y-axis hard-iron offset      Zout_Mag_16_bit_avg = (Zout_Mag_16_bit_max + Zout_Mag_16_bit_min) / 2;            // Z-axis hard-iron offset        // Left-shift by one as magnetometer offset registers are 15-bit only, left justified      Xout_Mag_16_bit_avg <<= 1;             Yout_Mag_16_bit_avg <<= 1;       Zout_Mag_16_bit_avg <<= 1;        I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x00);          // Standby mode to allow writing to the offset registers        I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, MOFF_X_LSB_REG, ( char ) (Xout_Mag_16_bit_avg & 0xFF));             I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, MOFF_X_MSB_REG, ( char ) ((Xout_Mag_16_bit_avg >> 😎 & 0xFF));            I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, MOFF_Y_LSB_REG, ( char ) (Yout_Mag_16_bit_avg & 0xFF));      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, MOFF_Y_MSB_REG, ( char ) ((Yout_Mag_16_bit_avg >> 😎 & 0xFF));                   I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, MOFF_Z_LSB_REG, ( char ) (Zout_Mag_16_bit_avg & 0xFF));      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, MOFF_Z_MSB_REG, ( char ) ((Zout_Mag_16_bit_avg >> 😎 & 0xFF));              I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x35);          // Active mode again       }   6. In the ISR, only the interrupt flag is cleared and the DataReady variable is set to indicate the arrival of new data.   void PORTD_IRQHandler() {      PORTD_PCR4 |= PORT_PCR_ISF_MASK;                // Clear the interrupt flag      DataReady = 1;       }   7. The output values from accelerometer registers 0x01 – 0x06 are first converted to signed 14-bit integer values and afterwards to real values in g’s. Similarly, the output values from magnetometer registers 0x33 – 0x38 are first converted to signed 16-bit integer values and afterwards to real values in microtesla (µT).   If the board remains flat, then the compass heading can be simply computed from the arctangent of the ratio of the two horizontal magnetic field components. I have used the atan2 function which returns the result in radians (-π and π), so I multiply it by 180/π to end up with degrees.   If you are interested in more complex algorithms for a tilt-compensated e-compass with soft-iron calibration, please refer to our eCompass software.   if (DataReady)             // Is a new set of data ready? {                  DataReady = 0;                                                                                                                      I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, OUT_X_MSB_REG, 12, AccelMagData);         // Read data output registers 0x01-0x06 and 0x33 - 0x38                 // 14-bit accelerometer data      Xout_Accel_14_bit = (( short ) (AccelMagData[0]<<8 | AccelMagData[1])) >> 2;        // Compute 14-bit X-axis acceleration output value      Yout_Accel_14_bit = (( short ) (AccelMagData[2]<<8 | AccelMagData[3])) >> 2;        // Compute 14-bit Y-axis acceleration output value      Zout_Accel_14_bit = (( short ) (AccelMagData[4]<<8 | AccelMagData[5])) >> 2;        // Compute 14-bit Z-axis acceleration output value                          // Accelerometer data converted to g's      Xout_g = (( float ) Xout_Accel_14_bit) / SENSITIVITY_2G;        // Compute X-axis output value in g's      Yout_g = (( float ) Yout_Accel_14_bit) / SENSITIVITY_2G;        // Compute Y-axis output value in g's      Zout_g = (( float ) Zout_Accel_14_bit) / SENSITIVITY_2G;        // Compute Z-axis output value in g's                           // 16-bit magnetometer data                   Xout_Mag_16_bit = ( short ) (AccelMagData[6]<<8 | AccelMagData[7]);          // Compute 16-bit X-axis magnetic output value      Yout_Mag_16_bit = ( short ) (AccelMagData[8]<<8 | AccelMagData[9]);          // Compute 16-bit Y-axis magnetic output value      Zout_Mag_16_bit = ( short ) (AccelMagData[10]<<8 | AccelMagData[11]);        // Compute 16-bit Z-axis magnetic output value                                                     // Magnetometer data converted to microteslas      Xout_uT = ( float ) (Xout_Mag_16_bit) / SENSITIVITY_MAG;        // Compute X-axis output magnetic value in uT      Yout_uT = ( float ) (Yout_Mag_16_bit) / SENSITIVITY_MAG;        // Compute Y-axis output magnetic value in uT      Zout_uT = ( float ) (Zout_Mag_16_bit) / SENSITIVITY_MAG;        // Compute Z-axis output magnetic value in uT                      Heading = atan2 (Yout_uT, Xout_uT) * 180 / PI;         // Compute Yaw angle }     8. The calculated values can be watched in the "Variables" window on the top right of the Debug perspective or in the FreeMASTER application. To open and run the FreeMASTER project, install the FreeMASTER 1.4 application and FreeMASTER Communication Driver.       Attached you can find the complete source code written in the CW for MCU's v10.5 including the FreeMASTER project.   If there are any questions regarding this simple application, please feel free to ask below. Your feedback or suggestions are also welcome.   Regards, Tomas Original Attachment has been moved to: FRDM-KL25Z-FXOS8700CQ-Basic-read-using-I2C-and-interrupt.zip Original Attachment has been moved to: FreeMASTER---FRDM-KL25Z-FXOS8700CQ-Basic-read-using-I2C-and-interrupt.zip
View full article
Hi Everyone,   If you are interested in a simple bare metal example code illustrating the use of the magnetic threshold detection function, please find below one of my examples I created for the FXOS8700CQ while working with the NXP FRDM-KL25Z platform and FRDM-FXS-MULT2-B sensor expansion board.   The FXOS8700CQ is set to detect magnetic field exceeding 12.8uT (128 counts) for a minimum period of 100ms on the X-axis. Once an event is triggered, an active low interrupt will be generated on the INT1 pin:   void FXOS8700CQ_Init (void) { I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_X_MSB_REG, 0x00); // Threshold value MSB I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_X_LSB_REG, 0x80); // Threshold value LSB I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_CFG_REG, 0xCB); // Event flag latch enabled, logic OR of enabled axes, only X-axis enabled, threshold interrupt enabled and routed to INT1 I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_COUNT_REG, 0x0A); // 100ms at 100Hz ODR and magnetometer mode only I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG1, 0x1D); // Max OSR, only magnetometer is active I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG3, 0x00); // Push-pull, active low interrupt I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x19); // ODR = 100Hz, Active mode }‍‍‍‍‍‍‍‍‍‍     In the ISR, only the interrupt flag is cleared and the M_THS_SRC (0x53) register is read in order to clear the SRC_M_THS flag in the M_INT_SRC register and deassert the INT1 pin, as shown on the screenshot below.   void PORTD_IRQHandler() { PORTD_PCR4 |= PORT_PCR_ISF_MASK; // Clear the interrupt flag M_Ths_src=I2C_ReadRegister(FXOS8700CQ_I2C_ADDRESS, M_THS_SRC_REG); // Read the M_THS_SRC register to clear the SRC_M_THS flag in the M_INT_SRC register and deassert the INT1 pin Event_Counter++; }‍‍‍‍‍‍       Attached you can find the complete source code. If there are any questions regarding this simple example code, please feel free to ask below.    Regards, Tomas
View full article
FRDM-STBC-AGM01: 9-Axis Inertial Measurement Sensor Board FRDM-KL25Z FRDM-STBC-AGM01 - Example project in KDS 3.0.0 using KSDK 1.2.0 and Processor Expert FRDM-STBC-AGM01 - Bare metal example project   FRDMSTBC-A8471: 3-Axis Accelerometer Sensor Toolbox Development Board FRDMSTBC-A8471 - Bare metal example project FRDMSTBC-A8471 - Example project in KDS 3.0.2 using KSDK 2.0 FXLS8471Q Auto-sleep with Transient threshold trigger    MPL3115A2: 20 to 110kPa, Absolute Digital (I 2 C) Pressure Sensor MPL3115A2 - Bare metal example project FRDMKL25-P3115 - Example project in KDS 3.0.2 using KSDK 2.0 https://community.nxp.com/docs/DOC-345632    MPL115A1: 50 to 115kPa, Absolute Digital (SPI) Pressure Sensor MPL115A1- Bare metal example project    FXOS8700CQ: Digital (I 2 C/SPI) Sensor - 3-Axis Accelerometer (±2g/±4g/±8g) + 3-Axis Magnetometer FXOS8700CQ - Bare metal example project FXOS8700CQ - Magnetic threshold detection function example code  FXOS8700CQ - Auto-sleep with Magnetic threshold trigger    FXLS8471Q: ±2g/±4g/±8g, 3-Axis, 14-Bit Digital (I 2 C/SPI) Accelerometer FXLS8471Q - Bare metal example project FXLS8471Q - FIFO Fill mode example code FXLS8471Q - Accelerometer vector-magnitude function example code FXLS8471Q - Accelerometer transient detection function example code FXLS8471Q - Accelerometer motion detection function example code  FXLS8471Q - Accelerometer orientation detection function example code    MMA8652FC: ±2g/±4g/±8g, 3-Axis, 12-Bit Digital (I 2 C) Accelerometer MMA8652FC - Bare metal example project MMA8652FC - Auto-WAKE/SLEEP mode   MMA8451Q: ±2g/±4g/±8g, 3-Axis, 14-bit Digital (I 2 C) Accelerometer MMA8451Q - Bare metal example project MMA8451Q - Single Tap Detection Bare metal example project FRDM-KL27Z MMA8451Q - How to build and run an ISSDK based example project    MMA8491Q: ±8g, 3-Axis , 14-bit Digital (I 2 C) Accelerometer/Tilt Sensor MMA8491Q - Acceleration data streaming using the PIT on the Kinetis KL25Z MCU   FXLN83xxQ: 3-Axis, Low-Power, Analog Accelerometer FXLN8371Q - Bare metal example project   FXAS21002C: 3-Axis Digital (I 2 C/SPI) Gyroscope FXAS21000 – Bare metal example project FXAS21002C - Angular rate threshold detection function example code   MAG3110FC: 3-Axis Digital (I 2 C) Magnetometer MAG3110FC – Bare metal example project   LM75A: Digital temperature sensor and thermal watchdog LM75A - Temperature data streaming using the PIT on the Kinetis KL25Z MCU
View full article
Hi Everyone, This tutorial is a guide on how to create a simple application in the Kinetis Design Studio that reads the data from both sensors on the FRDM-STBC-AGM01 board​ using an interrupt technique through the I 2 C interface. The Processor Expert is used to configure the I 2 C interface and GPIO on the MKL25Z128 MCU . I will not cover the Sensor Fusion library and the ISF​. Before you begin please make sure that both the Kinetis Design Studio (Eclipse based) and the Kinetis SDK are setup and you can already compile and debug code. If not, please refer to Erich's blog: Tutorial: Adafruit WS2812B NeoPixels with the Freescale FRDM-K64F Board – Part 2: Software Tools | MCU on Eclipse http://centaurian.co.uk/2015/05/22/toolchain-ksdk-1-2-0-with-eclipse-4-4-luna-and-gnu-arm-plugin/ 1. Create a new project in KDS Within KDS, click on "File" menu item and select "New" > "Kinetis Project" Name and set location of your project. I use the default location under the workspace area. Click Next. Select the development board used (in my case it is the FRDM-KL25Z) and click Next. Select “KSDK 1.2.0”. Set location to KSDK path, I use an absolute path. The location of my KSDK is in the default location where KSDK would install to. Ensure “Processor Expert” checkbox is checked. Press Next. Make sure that “GNU C Compiler” is selected. Click the "Finish" button. 2. Open Processor Expert Open the Processor Expert perspective, this should be a button on the top right hand side of Eclipse. If it is not there, try clicking on the “Open Perspective” button and then selecting “Processor Expert” in the form that appears. 3. Add I2C component Click on the “Components Library” tab, search for the component “fsl_i2c” and double click on it. Select the "i2cCom1:fsl_i2c" in the Components window. In the "Component Inspector" tab configure the I2C component. As you can see in the FRDM-STBC-AGM01 schematic , w ith jumpers J6 and J7 in their default position (2-3), the I 2 C signals are routed to the I2C1 module (PTC1 and PTC2 pins) of the KL25Z MCU. The 7-bit I 2 C slave address of the FXOS8700CQ is 0x1E (t o enter hex values, switch the format to the ‘H’ mode ) since both SA0 and SA1 pins are shorted to GND. The address of the FXAS21002C is 0x20 since SA0 pin is also shorted to GND. The I2C bus clock frequency is set to 400 kHz. 4. Add GPIO component Click on the “Components Library” tab, search for the component “fsl_gpio” and double click on it. Select the "gpio1:fsl_gpio" in the Components window. In the "Component Inspector" tab configure the GPIO component. The INT1_8700 output is connected to the PTD4 pin and the INT1_21002 pin to the PTA5 pin of the KL25Z MCU. These both interrupt pins are configured as push-pull active-low outputs, so the corresponding PTD4/PTA5 pin configuration is GPIO with an interrupt on falling edge. To enable both the PORTA and PORTD interrupts, select the “Events” tab and then select “generate code” next to PORTA IRQ and PORTD IRQ handlers. 5. Add Wait component​ Click on the “Components Library” tab, search for the component “Wait” and double click on it. At this point we have done all we can within Processor Expert. Make sure you save all on the project at this point then on the Components window, click on the "Generate code" button. 6. Add your code Here is the initialization of the FXOS8700CQ and FXAS21002C. /****************************************************************************** * FXOS8700CQ initialization function ******************************************************************************/ void FXOS8700CQ_Init (void) {   FXOS8700CQ_WriteRegister(CTRL_REG2, 0x40); // Reset all registers to POR values   WAIT1_Waitms(1);   FXOS8700CQ_WriteRegister(XYZ_DATA_CFG_REG, 0x00); // +/-2g range with 0.244mg/LSB   FXOS8700CQ_WriteRegister(M_CTRL_REG1, 0x1F); // Hybrid mode (accelerometer + magnetometer), max OSR   FXOS8700CQ_WriteRegister(M_CTRL_REG2, 0x20); // M_OUT_X_MSB register 0x33 follows the OUT_Z_LSB register 0x06 (used for burst read)   FXOS8700CQ_WriteRegister(CTRL_REG2, 0x02); // High Resolution mode   FXOS8700CQ_WriteRegister(CTRL_REG3, 0x00); // Push-pull, active low interrupt   FXOS8700CQ_WriteRegister(CTRL_REG4, 0x01); // Enable DRDY interrupt   FXOS8700CQ_WriteRegister(CTRL_REG5, 0x01); // DRDY interrupt routed to INT1 - PTD4   FXOS8700CQ_WriteRegister(CTRL_REG1, 0x25); // ODR = 25Hz, Reduced noise, Active mode } /****************************************************************************** * FXAS21002C initialization function ******************************************************************************/ void FXAS21002C_Init (void) {   FXAS21002C_WriteRegister(GYRO_CTRL_REG1, 0x40); // Reset all registers to POR values   WAIT1_Waitms(1);   FXAS21002C_WriteRegister(GYRO_CTRL_REG0, 0x03); // High-pass filter disabled, +/-250 dps range -> 7.8125 mdps/LSB = 128 LSB/dps   FXAS21002C_WriteRegister(GYRO_CTRL_REG2, 0x0C); // Enable DRDY interrupt, mapped to INT1 - PTA5, push-pull, active low interrupt   FXAS21002C_WriteRegister(GYRO_CTRL_REG1, 0x16); // ODR = 25Hz, Active mode } In the ISRs (look for the file Events.c), only the interrupt flags are cleared and the DataReady variables are set to indicate the arrival of new data. void PORTA_IRQHandler(void) {   /* Clear interrupt flag.*/   PORT_HAL_ClearPortIntFlag(PORTA_BASE_PTR);   /* Write your code here ... */   FXAS21002C_DataReady = 1; } void PORTD_IRQHandler(void) {   /* Clear interrupt flag.*/   PORT_HAL_ClearPortIntFlag(PORTD_BASE_PTR);   /* Write your code here ... */   FXOS8700CQ_DataReady = 1; } The output values from accelerometer registers 0x01 – 0x06 are first converted to signed 14-bit integer values and afterwards to real values in g’s. Similarly, the output values from magnetometer registers 0x33 – 0x38 are first converted to signed 16-bit integer values and afterwards to real values in microtesla (µT). if (FXOS8700CQ_DataReady)         // Is a new set of accel+mag data ready? {    FXOS8700CQ_DataReady = 0;       FXOS8700CQ_ReadRegisters(OUT_X_MSB_REG, 12, AccelMagData);         // Read FXOS8700CQ data output registers 0x01-0x06 and 0x33 - 0x38       // 14-bit accelerometer data    Xout_Accel_14_bit = ((int16_t) (AccelMagData[0]<<8 | AccelMagData[1])) >> 2;             // Compute 14-bit X-axis acceleration output value    Yout_Accel_14_bit = ((int16_t) (AccelMagData[2]<<8 | AccelMagData[3])) >> 2;             // Compute 14-bit Y-axis acceleration output value    Zout_Accel_14_bit = ((int16_t) (AccelMagData[4]<<8 | AccelMagData[5])) >> 2;             // Compute 14-bit Z-axis acceleration output value       // Accelerometer data converted to g's    Xout_g = ((float) Xout_Accel_14_bit) / SENSITIVITY_2G;         // Compute X-axis output value in g's    Yout_g = ((float) Yout_Accel_14_bit) / SENSITIVITY_2G;         // Compute Y-axis output value in g's    Zout_g = ((float) Zout_Accel_14_bit) / SENSITIVITY_2G;         // Compute Z-axis output value in g's    // 16-bit magnetometer data    Xout_Mag_16_bit = (int16_t) (AccelMagData[6]<<8 | AccelMagData[7]);        // Compute 16-bit X-axis magnetic output value    Yout_Mag_16_bit = (int16_t) (AccelMagData[8]<<8 | AccelMagData[9]);        // Compute 16-bit Y-axis magnetic output value    Zout_Mag_16_bit = (int16_t) (AccelMagData[10]<<8 | AccelMagData[11]);      // Compute 16-bit Z-axis magnetic output value    // Magnetometer data converted to microteslas    Xout_uT = (float) (Xout_Mag_16_bit) / SENSITIVITY_MAG;             // Compute X-axis output magnetic value in uT    Yout_uT = (float) (Yout_Mag_16_bit) / SENSITIVITY_MAG;             // Compute Y-axis output magnetic value in uT    Zout_uT = (float) (Zout_Mag_16_bit) / SENSITIVITY_MAG;             // Compute Z-axis output magnetic value in uT } Similarly, the output values from gyroscope registers 0x01 – 0x06 are first converted to signed 16-bit integer values and afterwards to real values in degrees per second. Temperature is also read out from the 0x12 register. if (FXAS21002C_DataReady)         // Is a new set of gyro data ready? {    FXAS21002C_DataReady = 0;    FXAS21002C_ReadRegisters(GYRO_OUT_X_MSB_REG, 6, GyroData);         // Read FXAS21002C data output registers 0x01-0x06    // 16-bit gyro data    Xout_Gyro_16_bit = (int16_t) (GyroData[0]<<8 | GyroData[1]);         // Compute 16-bit X-axis output value    Yout_Gyro_16_bit = (int16_t) (GyroData[2]<<8 | GyroData[3]);         // Compute 16-bit Y-axis output value    Zout_Gyro_16_bit = (int16_t) (GyroData[4]<<8 | GyroData[5]);         // Compute 16-bit Z-axis output value    // Gyro data converted to dps    Roll = (float) (Xout_Gyro_16_bit) / SENSITIVITY_250;               // Compute X-axis output value in dps    Pitch = (float) (Yout_Gyro_16_bit) / SENSITIVITY_250;              // Compute Y-axis output value in dps    Yaw = (float) (Zout_Gyro_16_bit) / SENSITIVITY_250;                // Compute Z-axis output value in dps    // Temperature data    FXAS21002C_ReadRegisters(GYRO_TEMP_REG, 1, GyroData);    Temp = (int8_t) (GyroData[0]); } The complete project including the I2C communication routines and sensor's header files is attached. 6. Build and debug the project To build the project, select the root folder of the project in the Project Explorer view and click the "Hammer" icon to build it. If everything goes well, no errors are shown in the "Problems" view: The .elf (binary) file has been created inside the "Debug" folder: Connect the SDA port on the FRDM-KL25Z board to a USB port on your computer. To debug the project for the first time, select the root folder of the project in the Project Explorer view and open the "Debug Configurations" window. Select the ""GDB PEMicro Interface Debugging" and click the "New launch configuration" icon. In the "Debugger" tab, select the "OpenSDA Embedded Debug - USB Port" interface and the KL25Z128M4 as a target device. Click the "Debug" button. Click the "Resume" button to run the project. You can pause the execution and look at the data using the "Suspend" button. Now you can edit, build and debug the project again. As we used a debug configuration, it is listed under the "Debug" icon, so you can start it from there. Well done if you managed to follow along and get it all working. As a bonus I have attached the FreeMASTER project that will allow you to visualize the gathered data. If there are any questions regarding this simple project, do not hesitate to ask below. Your feedback or suggestions are also welcome. Regards, Tomas
View full article
Hello community, This time, I would like to share a simple bare metal example code using the MAG3110 , the digital Magnetometer from NXP. I created this example code with the FRDM-KL25Z  platform and the FRDM-FXS-MULT2-B sensor expansion board. The complete source code is written in the Kinetis Design Studio V3.2.0  in collaboration with the FreeMASTER  tool in order to visualize the magnetic data. This document guides you through the initialization process and how to appreciate the demonstration. Section 1: Initialization of the MKL25Z128 MCU. Section 2: Initialization of the MAG3110. Section 3: Simple magnetic hard-iron offset calibration. Section 4: Output data reading using an interrupt technique. Section 5: Conversion of the output values. Section 6: FreeMASTER tool. 1. Initialization of the MKL25Z128 MCU Based on the figure below, the SCL and SDA signals, from the I2C Module, are connected to the PTC1 and PTC2 pins respectively. The INT1 output of the MAG3110 is connected to the PTD4 pin of the KL25Z. Please make sure the 2&3 pins of the J3 are connected together using a jumper at the FRDM-FXS-MULT2-B. The RGB LED from the FRDM-KL25Z is also set using the PTB18 and PTB19 pins as GPIOs. //I2C1 module initialization SIM_SCGC4 | = SIM_SCGC4_I2C1_MASK ;          // Turn on clock to I2C0 module SIM_SCGC5 | = SIM_SCGC5_PORTC_MASK ;         // Turn on clock to Port C module PORTC_PCR1 = PORT_PCR_MUX ( 2 ) ;              // PTC1 pin is I2C0 SCL line PORTC_PCR2 = PORT_PCR_MUX ( 2 ) ;              // PTC2 pin is I2C0 SDA line I2C1_F  = 0x14 ;                            // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us I2C1_C1 = I2C_C1_IICEN_MASK ;               // Enable I2C0 module //Configure the PTD4 pin (connected to the INT1 of the MAG3110) for rising edge interrupts SIM_SCGC5 | = SIM_SCGC5_PORTD_MASK ;         // Turn on clock to Port D module PORTD_PCR4  | = ( 0 | PORT_PCR_ISF_MASK |       // Clear the interrupt flag                   PORT_PCR_MUX ( 0x1 ) |       // PTD4 is configured as GPIO                   PORT_PCR_IRQC ( 0x09 ) ) ;    // PTD4 is configured for rising edge interrupts (MAG3110 generates low to high signal) //Configure RGB LED SIM_SCGC5 | = SIM_SCGC5_PORTB_MASK ;         // Turn on clock to Port B module PORTB_PCR19 = PORT_PCR_MUX ( 1 ) ;             // PTB19 is configured as GPIO GPIOB_PDDR | = ( 1 << 19 ) ;                   // Configure pin as output GPIOB_PSOR | = ( 1 << 19 ) ;                   // Turn OFF GREEN LED PORTB_PCR18 = PORT_PCR_MUX ( 1 ) ;             // PTB18 is configured as GPIO GPIOB_PDDR | = ( 1 << 18 ) ;                   // Configure pin as output GPIOB_PCOR | = ( 1 << 18 ) ;                   // Turn ON RED LED //Enable PORTD interrupt on NVIC NVIC_EnableIRQ ( PORTD_IRQn ) ;                // Enable interrupts NVIC_ClearPendingIRQ ( PORTD_IRQn ) ;          // Clear pending interrupts ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ 2. Initialization of the MAG3110 The MAG3110 is capable of measuring magnetic fields with an output data rate (ODR) up to 80 Hz. In this case, the ODR of the MAG3110 is set at 20Hz. The automatic resets are enabled. When new measurement data is available, the INT1 pin triggers a software interrupt. The WHO_AM_I register is read in order to verify the correct communication with the magnetometer. I2C_WriteRegister ( MAG3110_I2C_ADDRESS , CTRL_REG2 , 0x80 ) ;   // Enable automatic resets WhoAmI = I2C_ReadRegister ( MAG3110_I2C_ADDRESS , WHO_AM_I ) ; // Read WHO_AM_I Register I2C_WriteRegister ( MAG3110_I2C_ADDRESS , CTRL_REG1 , 0x11 ) ;   // ODR 20Hz (0.05s), Active mode ‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ 3. Simple magnetic hard-iron offset calibration. Please note that the magnetometer readings must be corrected for Hard-Iron and Soft-Iron effects. If you are interested in more complex algorithms you may refer to the NXP E-Compass Software. As an alternative, a method to calibrate the hard iron offset is rotating the MAG3110 in a figure of eight twisting motions for a few seconds, record the minimum and maximum magnetometer readings, compute the corresponding offset values by using the min/max averaging and then either subtract these offset values from the current magnetometer measurements or write them in the user offset registers with CTRL_REG2[RAW] = 0. The hard iron offset calibration is done as follow: short Xout_16_bit_avg , Yout_16_bit_avg , Zout_16_bit_avg ; short Xout_16_bit_max , Yout_16_bit_max , Zout_16_bit_max ; short Xout_16_bit_min , Yout_16_bit_min , Zout_16_bit_min ; short i = 0 ; while ( i < 200 ) // Calibration process ~10s (200 samples * 1/20Hz) {     if ( DataReady )         {             DataReady = 0 ;             I2C_ReadMultiRegisters ( MAG3110_I2C_ADDRESS , OUT_X_MSB , 6 , MagData ) ;         // Read data output registers 0x01-0x06             Xout_16_bit = ( ( short ) ( MagData [ 0 ] < < 8 | MagData [ 1 ] ) ) ;         // Compute 16-bit X-axis output value             Yout_16_bit = ( ( short ) ( MagData [ 2 ] < < 8 | MagData [ 3 ] ) ) ;         // Compute 16-bit Y-axis output value             Zout_16_bit = ( ( short ) ( MagData [ 4 ] < < 8 | MagData [ 5 ] ) ) ;         // Compute 16-bit Z-axis output value             if ( i == 0 )             {                 Xout_16_bit_max = Xout_16_bit ;                 Xout_16_bit_min = Xout_16_bit ;                 Yout_16_bit_max = Yout_16_bit ;                 Yout_16_bit_min = Yout_16_bit ;                 Zout_16_bit_max = Zout_16_bit ;                 Zout_16_bit_min = Zout_16_bit ;             }             // Check to see if current sample is the maximum or minimum X-axis value             if ( Xout_16_bit > Xout_16_bit_max ) { Xout_16_bit_max = Xout_16_bit ; }             if ( Xout_16_bit < Xout_16_bit_min ) { Xout_16_bit_min = Xout_16_bit ; }             // Check to see if current sample is the maximum or minimum X-axis value             if ( Yout_16_bit > Yout_16_bit_max ) { Yout_16_bit_max = Yout_16_bit ; }             if ( Yout_16_bit < Yout_16_bit_min ) { Yout_16_bit_min = Yout_16_bit ; }             // Check to see if current sample is the maximum or minimum X-axis value             if ( Zout_16_bit > Zout_16_bit_max ) { Zout_16_bit_max = Zout_16_bit ; }             if ( Zout_16_bit < Zout_16_bit_min ) { Zout_16_bit_min = Zout_16_bit ; }             i ++ ;         } } Xout_16_bit_avg = ( Xout_16_bit_max + Xout_16_bit_min ) / 2 ;     // X-axis hard-iron offset Yout_16_bit_avg = ( Yout_16_bit_max + Yout_16_bit_min ) / 2 ;     // Y-axis hard-iron offset Zout_16_bit_avg = ( Zout_16_bit_max + Zout_16_bit_min ) / 2 ;     // Z-axis hard-iron offset // Left-shift by one as magnetometer offset registers are 15-bit only, left justified Xout_16_bit_avg < <= 1 ; Yout_16_bit_avg < <= 1 ; Zout_16_bit_avg < <= 1 ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , CTRL_REG1 , 0x00 ) ;   // Standby mode // Set Offset I2C_WriteRegister ( MAG3110_I2C_ADDRESS , OFF_X_LSB , ( char ) ( Xout_16_bit_avg & 0xFF ) ) ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , OFF_X_MSB , ( char ) ( ( Xout_16_bit_avg > > 8 ) & 0xFF ) ) ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , OFF_Y_LSB , ( char ) ( Yout_16_bit_avg & 0xFF ) ) ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , OFF_Y_MSB , ( char ) ( ( Yout_16_bit_avg > > 8 ) & 0xFF ) ) ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , OFF_Z_LSB , ( char ) ( Zout_16_bit_avg & 0xFF ) ) ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , OFF_Z_MSB , ( char ) ( ( Zout_16_bit_avg > > 8 ) & 0xFF ) ) ; I2C_WriteRegister ( MAG3110_I2C_ADDRESS , CTRL_REG1 , 0x11 ) ;   //  Active mode again ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ 4. Output data reading using an interrupt technique. At the ISR, the interrupt flag is clear and the DataReady variable is set in order to know that a new magnetic measurement is ready. void PORTD_IRQHandler ( ) {     PORTD_PCR4 | = PORT_PCR_ISF_MASK ;             // Clear the interrupt flag     DataReady = 1 ; } ‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ 5. Conversion of the output values The output values from magnetometer are converted to signed 16-bit integer values and afterwards to real values in microtesla (µT). for ( ; ; ) {    if ( DataReady )     {             DataReady = 0 ;             I2C_ReadMultiRegisters ( MAG3110_I2C_ADDRESS , OUT_X_MSB , 6 , MagData ) ;         // Read data output registers 0x01-0x06            // 16-bit magnetometer data            Xout_16_bit = ( ( short ) ( MagData [ 0 ] < < 8 | MagData [ 1 ] ) ) ;         // Compute 16-bit X-axis output value            Yout_16_bit = ( ( short ) ( MagData [ 2 ] < < 8 | MagData [ 3 ] ) ) ;         // Compute 16-bit Y-axis output value            Zout_16_bit = ( ( short ) ( MagData [ 4 ] < < 8 | MagData [ 5 ] ) ) ;         // Compute 16-bit Z-axis output value            // Magnetometer data converted to microteslas           Xout_uT = ( float ) Xout_16_bit / SENSITIVITY ;      // Compute X-axis output magnetic value in uT            Yout_uT = ( float ) Yout_16_bit / SENSITIVITY ;      // Compute Y-axis output magnetic value in uT           Zout_uT = ( float ) Zout_16_bit / SENSITIVITY ;      // Compute Z-axis output magnetic value in uT    } } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ 6. FreeMASTER FreeMASTER is a user-friendly real-time debug monitor and data visualization tool that you can use for any application development and information management. In this case, it is used in order to visualize the magnetic data. In case you have problems with the communication port, please go to Project / Options… Select Plug-in Module and choose the FreeMASTER BDM Communication Plug-in option. Select configure and make sure the P&E Kinetis is selected. Select OK and Start the communication. Please find attached the complete source code, including the FreeMASTER project. You are invited to take part of the NXP community where you can post all your questions and you may find useful material for your projects. I hope you find useful and funny this sample project. Any suggestion will be appreciated. Best Regards, David
View full article
The following video shows how to run the FRDM 6DOF Bare Board eCompass using the FRDM-K22. This algorithm uses the FXOS8700 contained on the Freedom Board. In order to get more information about the Sensor Fusion Library for Kinetis MCU's 5.0, please refer to the following link: Sensor Fusion|Freescale I hope this material will be useful for you. David
View full article
This is a step-by-step guide document to set the FRDM-K64F-AGM01 on the Freescale Sensor Fusion Toolbox Software.
View full article
Hi Everyone, In this tutorial I intend to run through my simple bare metal example code I created for the Freescale FRDM-KL25Z platform and the FRDM-STBC-AGM01 board containing a three axis accelerometer + magnetometer (FXOS8700CQ) and a three axis gyroscope (FXAS21002C). I will not cover the Sensor Fusion library and the ISF which also support this board. The FreeMASTER tool is used to visualize all the data that are read from both sensors using an interrupt technique through the I 2 C interface. This example illustrates: 1. Initialization of the MKL25Z128 MCU (mainly I 2 C and PORT modules). 2. I 2 C data write and read operations. 3. Initialization of the FXOS8700CQ and FXAS21002C. 4. Simple accelerometer offset calibration based on the AN4069. 5. Output data reading using an interrupt technique. 6. Conversion of the output raw values to real values in g’s, µT, dps and °C. 7. Visualization of the calculated values in the FreeMASTER tool. 1. As you can see in the FRDM-STBC-AGM01 schematic, both sensors are controlled via I 2 C by default. With jumpers J6 and J7 in their default position (2-3), the I 2 C signals are routed to the I2C1 module (PTC1 and PTC2 pins) of the KL25Z MCU. The INT1_8700 output is connected to the PTD4 pin and the INT1_21002 pin to the PTA5 pin of the KL25Z MCU. These both interrupt pins are configured as push-pull active-low outputs, so the corresponding PTD4/PTA5 pin configuration is GPIO with an interrupt on falling edge. The MCU is, therefore, configured as follows. void MCU_Init( void ) {      //I2C1 module initialization      SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK;        // Turn on clock to I2C1 module      SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;       // Turn on clock to Port C module      PORTC_PCR1 |= PORT_PCR_MUX(0x2);         // PTC1 pin is I2C1 SCL line      PORTC_PCR2 |= PORT_PCR_MUX(0x2);         // PTC2 pin is I2C1 SDA line      I2C1_F  |= I2C_F_ICR(0x14);              // SDA hold time = 2.125us, SCL start hold time = 4.25us, SCL stop hold time = 5.125us      I2C1_C1 |= I2C_C1_IICEN_MASK;            // Enable I2C1 module                       //Configure the PTD4 pin (connected to the INT1 of the FXOS8700CQ) for falling edge interrupts      SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;       // Turn on clock to Port D module      PORTD_PCR4 |= (0|PORT_PCR_ISF_MASK|      // Clear the interrupt flag                       PORT_PCR_MUX(0x1)|      // PTD4 is configured as GPIO                       PORT_PCR_IRQC(0xA));    // PTD4 is configured for falling edge interrupts                   //Configure the PTA5 pin (connected to the INT1 of the FXAS21002) for falling edge interrupts      SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;       // Turn on clock to Port A module      PORTA_PCR5 |= (0|PORT_PCR_ISF_MASK|      // Clear the interrupt flag                       PORT_PCR_MUX(0x1)|      // PTA5 is configured as GPIO                       PORT_PCR_IRQC(0xA));    // PTA5 is configured for falling edge interrupts                          //Enable PORTD interrupt on NVIC      NVIC_ICPR |= 1 << (( INT_PORTD - 16)%32);      NVIC_ISER |= 1 << (( INT_PORTD - 16)%32);                //Enable PORTA interrupt on NVIC      NVIC_ICPR |= 1 << (( INT_PORTA - 16)%32);      NVIC_ISER |= 1 << (( INT_PORTA - 16)%32); } 2. The 7-bit I 2 C slave address of the FXOS8700CQ is 0x1E since both SA0 and SA1 pins are shorted to GND. The address of the FXAS21002C is 0x20 since SA0 pin is also shorted to GND. The two screenshots below show the write operation which writes the value 0x25 to the CTRL_REG1 (0x2A) of the FXOS8700CQ and 0x16 to the CTRL_REG1 (0x13) of the FXAS21002C. Here is the single byte read from the WHO_AM_I register. As you can see, it returns the correct value 0xC7 for the FXOS8700CQ and 0xD7 for the FXAS21002C. Finally, a burst read of 12 bytes from the FXOS8700CQ output data registers (0x01 – 0x06 and 0x33 – 0x38) and 6 bytes from the FXAS21002C output data registers (0x01 – 0x06) is shown below. 3. At the beginning of the initialization, all registers are reset to their default values by setting the RST bit of the CTRL_REG2 register. Then the FXOS8700CQ is initialized as shown below. void FXOS8700CQ_Init ( void ) {      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG2, 0x40);          // Reset all registers to POR values      Pause(0x631);          // ~1ms delay            I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, XYZ_DATA_CFG_REG, 0x00);   // +/-2g range with 0.244mg/LSB              I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG1, 0x1F);        // Hybrid mode (accelerometer + magnetometer), max OSR      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, M_CTRL_REG2, 0x20);        // M_OUT_X_MSB register 0x33 follows the OUT_Z_LSB register 0x06 (burst read)                       I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG2, 0x02);          // High Resolution mode      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG3, 0x00);          // Push-pull, active low interrupt      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG4, 0x01);          // Enable DRDY interrupt      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG5, 0x01);          // DRDY interrupt routed to INT1 - PTD4      I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x25);          // ODR = 25Hz, Reduced noise, Active mode   } And here is the initialization of the FXAS21002C. void FXAS21002C_Init ( void ) {      I2C_WriteRegister(FXAS21002C_I2C_ADDRESS, GYRO_CTRL_REG1, 0x40);     // Reset all registers to POR values      Pause(0x631);        // ~1ms delay            I2C_WriteRegister(FXAS21002C_I2C_ADDRESS, GYRO_CTRL_REG0, 0x03);     // High-pass filter disabled, +/-250 dps range -> 7.8125 mdps/LSB = 128 LSB/dps      I2C_WriteRegister(FXAS21002C_I2C_ADDRESS, GYRO_CTRL_REG2, 0x0C);     // Enable DRDY interrupt, routed to INT1 - PTA5, push-pull, active low interrupt      I2C_WriteRegister(FXAS21002C_I2C_ADDRESS, GYRO_CTRL_REG1, 0x16);     // ODR = 25Hz, Active mode        } 4. A simple accelerometer offset calibration method is implemented according to the AN4069 . void FXOS8700CQ_Accel_Calibration ( void ) {      char X_Accel_offset, Y_Accel_offset, Z_Accel_offset;            FXOS8700CQ_DataReady = 0;           while (!FXOS8700CQ_DataReady){}           // Is a first set of data ready?      FXOS8700CQ_DataReady = 0;            I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x00);          // Standby mode                 I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, OUT_X_MSB_REG, 6, AccelMagData);          // Read data output registers 0x01-0x06                     Xout_Accel_14_bit = (( short ) (AccelMagData[0]<<8 | AccelMagData[1])) >> 2;          // Compute 14-bit X-axis acceleration output value      Yout_Accel_14_bit = (( short ) (AccelMagData[2]<<8 | AccelMagData[3])) >> 2;          // Compute 14-bit Y-axis acceleration output value      Zout_Accel_14_bit = (( short ) (AccelMagData[4]<<8 | AccelMagData[5])) >> 2;          // Compute 14-bit Z-axis acceleration output value                   X_Accel_offset = Xout_Accel_14_bit / 8 * (-1);          // Compute X-axis offset correction value      Y_Accel_offset = Yout_Accel_14_bit / 8 * (-1);          // Compute Y-axis offset correction value      Z_Accel_offset = (Zout_Accel_14_bit - SENSITIVITY_2G) / 8 * (-1);          // Compute Z-axis offset correction value                   I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, OFF_X_REG, X_Accel_offset);                  I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, OFF_Y_REG, Y_Accel_offset);           I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, OFF_Z_REG, Z_Accel_offset);                        I2C_WriteRegister(FXOS8700CQ_I2C_ADDRESS, CTRL_REG1, 0x25);          // Active mode again } 5. In the ISRs, only the interrupt flags are cleared and the DataReady variables are set to indicate the arrival of new data. void PORTD_IRQHandler() {      PORTD_PCR4 |= PORT_PCR_ISF_MASK;          // Clear the interrupt flag      FXOS8700CQ_DataReady = 1;  } void PORTA_IRQHandler() {      PORTA_PCR5 |= PORT_PCR_ISF_MASK;          // Clear the interrupt flag      FXAS21002C_DataReady = 1;  } 6. The output values from accelerometer registers 0x01 – 0x06 are first converted to signed 14-bit integer values and afterwards to real values in g’s. Similarly, the output values from magnetometer registers 0x33 – 0x38 are first converted to signed 16-bit integer values and afterwards to real values in microtesla (µT). if (FXOS8700CQ_DataReady)          // Is a new set of accel + mag data ready? {                  FXOS8700CQ_DataReady = 0;                                                                                                                          I2C_ReadMultiRegisters(FXOS8700CQ_I2C_ADDRESS, OUT_X_MSB_REG, 12, AccelMagData);         // Read FXOS8700CQ data output registers 0x01-0x06 and 0x33 - 0x38                     // 14-bit accelerometer data      Xout_Accel_14_bit = (( short ) (AccelMagData[0]<<8 | AccelMagData[1])) >> 2;        // Compute 14-bit X-axis acceleration output value      Y out_Accel_14_bit = (( short ) (AccelMagData[2]<<8 | AccelMagData[3])) >> 2;        // Compute 14-bit Y-axis acceleration output value      Zout_Accel_14_bit = (( short ) (AccelMagData[4]<<8 | AccelMagData[5])) >> 2;        // Compute 14-bit Z-axis acceleration output value                              // Accelerometer data converted to g's      Xout_g = (( float ) Xout_Accel_14_bit) / SENSITIVITY_2G;        // Compute X-axis output value in g's      Yout_g = (( float ) Yout_Accel_14_bit) / SENSITIVITY_2G;        // Compute Y-axis output value in g's      Zout_g = (( float ) Zout_Accel_14_bit) / SENSITIVITY_2G;        // Compute Z-axis output value in g's                               // 16-bit magnetometer data                   Xout_Mag_16_bit = ( short ) (AccelMagData[6]<<8 | AccelMagData[7]);          // Compute 16-bit X-axis magnetic output value      Yout_Mag_16_bit = ( short ) (AccelMagData[8]<<8 | AccelMagData[9]);          // Compute 16-bit Y-axis magnetic output value      Zout_Mag_16_bit = ( short ) (AccelMagData[10]<<8 | AccelMagData[11]);        // Compute 16-bit Z-axis magnetic output value                                                         // Magnetometer data converted to microteslas      Xout_uT = ( float ) (Xout_Mag_16_bit) / SENSITIVITY_MAG;        // Compute X-axis output magnetic value in uT      Yout_uT = ( float ) (Yout_Mag_16_bit) / SENSITIVITY_MAG;        // Compute Y-axis output magnetic value in uT      Zout_uT = ( float ) (Zout_Mag_16_bit) / SENSITIVITY_MAG;        // Compute Z-axis output magnetic value in uT              } Similarly, the output values from gyroscope registers 0x01 – 0x06 are first converted to signed 16-bit integer values and afterwards to real values in degrees per second. Temperature is also read out from the 0x12 register. if (FXAS21002C_DataReady)         // Is a new set of gyro data ready? {                  FXAS21002C_DataReady = 0;                                                                                                                                       I2C_ReadMultiRegisters(FXAS21002C_I2C_ADDRESS, GYRO_OUT_X_MSB_REG, 6, GyroData);         // Read FXAS21002C data output registers 0x01-0x06                                   // 16-bit gyro data      Xout_Gyro_16_bit = ( short ) (GyroData[0]<<8 | GyroData[1]);           // Compute 16-bit X-axis output value      Yout_Gyro_16_bit = ( short ) (GyroData[2]<<8 | GyroData[3]);           // Compute 16-bit Y-axis output value      Zout_Gyro_16_bit = ( short ) (GyroData[4]<<8 | GyroData[5]);           // Compute 16-bit Z-axis output value                                           // Gyro data converted to dps      Roll = ( float ) (Xout_Gyro_16_bit) / SENSITIVITY_250;          // Compute X-axis output value in dps      Pitch = ( float ) (Yout_Gyro_16_bit) / SENSITIVITY_250;         // Compute Y-axis output value in dps      Yaw = ( float ) (Zout_Gyro_16_bit) / SENSITIVITY_250;           // Compute Z-axis output value in dps                               // Temperature data      Temp = I2C_ReadRegister(FXAS21002C_I2C_ADDRESS, GYRO_TEMP_REG);                   }   7. The calculated values can be watched in the "Variables" window on the top right of the Debug perspective or in the FreeMASTER application. To open and run the FreeMASTER project, install the FreeMASTER application​ and FreeMASTER Communication Driver . I guess this is enough to let you start experimenting with the FRDM-STBC-AGM01 board. Attached you can find the complete source code written in the CW for MCU's v10.6 including the FreeMASTER project. If there are any questions regarding this simple application, do not hesitate to ask below. Your feedback or suggestions are also welcome. Regards, Tomas
View full article
Freescale’s FXOS8700CQ 6-axis sensor combines industry leading accelerometer and magnetometer sensors in a small 3 x 3 x 1.2 mm QFN plastic package. The 14-bit accelerometer and 16-bit magnetometer are combined with a high-performance ASIC to enable an eCompass solution capable of a typical orientation resolution of 0.1 degrees and sub 5 degree compass heading accuracy for most applications. Applications include eCompass, enhanced user interface, augmented reality, and location based services (static geographic heading). Target products include smartphones, tablets, personal navigation devices, remote controls for smart TV’s, watches, gaming controllers, robotics, and unmanned air vehicles (UAVs). Here is a Render of the FXOS8700 Breakout- Board downloaded from OSH Park: And here is an image of the Layout Design for this board: In the Attachments section, you can find the Schematic Source File (.SCH), Schematic PDF File, Layout Source File (BRD), Gerber Files (GTL, GBL, GTS, GBS, GTO, GBO, GKO, XLN) and BOM for this Breakout-board. If you are interested in more designs like this breakout board for other sensors, please go to Freescale Sensors Breakout Boards Designs – HOME
View full article
Hello Freescale Community, Most of the new Freescale Sensors in our portfolio come in very small packages , s ome of them as small as 2x2x1mm, which is awesome! However, one of the problems that we detected last year is that many customers struggle in the evaluation stage of the project due to the small packages. They should either, buy an evaluation board or spend valuable time designing and manufacturing a PCB just for testing our devices. Our goal with this project is to share with our community the Freescale Sensors Breakout Boards we designed for this specific purpose, so you can easily manufacture your own sensor boards or modify our designs to fit  your specific application. This way you can easily evaluate Freescale sensors. The boards were designed to be used in a prototype board (DIP style pins) and they can communicate to any MCU thru IIC or SPI (depending on the sensor). These designs were made using Eagle Layout 6.5, if you want to modify the designs you can do it with the free version of Eagle CAD (for non-commercial purposes), or you can send the gerber files (included in the zip files) to your preferred PCB manufacturer. The following designs are available: + Altimeter: MPL3115A2 Breakout Board + Accelerometer: MMA845x Breakout Board MMA865x Breakout Board MMA8491 Breakout Board FXLN83xx Breakout Board FXLS8471 Breakout Board MMA690x Breakout Board + Accelerometer + Magnetometer (6-DOF): FXOS8700 Breakout Board + Gyroscope: FXAS2100x Breakout Board The above .ZIP files, contains the following design information: - Schematic Source File (.SCH) - Schematic (.PDF) - Layout Source File (.BRD) - Layout Images (.jpg) - Gerber Files (GTL, GBL, GTS, GBS, GTO, GBO, GKO, XLN). - PCB Render Image (.png created in OSH park) - BOM (.xls) Additional content: If you want to modify our designs, please download the attached library file "Freescale_Sensors_v2.lbr" and add it to your Eagle Library repository. We'll be more than glad to respond to your questions and please, let us know what you think. -Freescale Sensor's Support team.
View full article
Issue Using the STB GUI for eCompass kits RD4247MAG3110 and RD4247FXOS8700 only -- v6.1.0.1 on a machine that does not have the Adobe Flash Player ActiveX program installed may run into the following error after pressing the eCompass button: Solution Install the Adobe Flash Player + ActiveX from Adobe. Let us know if you are facing any other issues with the STB GUI v6.1.0.1. Regards, Tomas
View full article
My friend Matt Muddiman of Freescale gave this presentation as part of the MEMS Education Series (hosted by Arizona Technology Council and MEMS Industry Group) in Scottsdale Arizona earlier this week.
View full article
Video clip associated with "Android as a Platform for Sensor Fusion Education and Evaluation" presented at 2013 Sensors Expo & Conference by Michael Stanley.
View full article
"Android as a Platform for Sensor Fusion Education and Evaluation" presented at 2013 Sensors Expo & Conference by Michael Stanley.
View full article
clicktaleID