Sensors Knowledge Base

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Sensors Knowledge Base

Discussions

Sort by:
This posting summarizes known issues, not already in the errata) for Sensor Fusion Build 420: FRDM-KL25Z, KL26Z, KL46Z, K20D50M and K64F boards shipped to date do not include pull-up resistors on the NMI pin.  This has reportedly caused applications to not start properly because of inadvertent non-maskable interrupts.   There are several possible ways to resolve this: Add the missing pull-up resistor Disable the NMI during the first call to the NMI interrupt handler.  You can do that by replacing the existing default handler with:          // called on NMI          void Cpu_OnNMIINT(void)          {            // Disable NMI pin (some boards do not have pullups)            SIM_SCGC5 |= (uint32_t)SIM_SCGC5_PORTA_MASK; /* NMI and PORTA clock gate enable */            PORTA_PCR4 &= PORT_PCR_MUX_MASK;            /* enable input with pull up enable not NMI */            PORTA_PCR4 |= PORT_PCR_MUX(01) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;            // return with no action            return;          } Add two new PE components.  One of type BitIO_LDD and the other of type Init_GPIO.  Between them you can assign PTA4 as an input GPIO with pullup enabled.  This has the advantage of requiring no changes to the .c or .h files. KDS builds using optimization level O3 do not properly execute the command interpreter within Events.c function UART_OnBlockReceived().  Change the project settings optimization level to O1 and it should work fine. It is possible for the Sensor Fusion Toolbox (both Windows and Android versions) to "fall out of sync" with the development board firmware with regard to desired sensor fusion algorithm being executed.  Symptoms and root causes are reviewed in the PDF attached to this posting.
View full article
Hi Folks, If you are planning to design an application where a pressure sensor is needed but you are not sure about which kind of Pressure Measurement and Level of Integration is needed, or you even doesn’t know what does that means (like me before start working with pressure sensors), then this document can be useful. First, for a better understanding about what I’m talking about in this document and how pressure sensors and measurement works I’m adding below an image that shows a cross-section of a standard pressure sensor which basically shows the Physical Internal structure of a pressure sensor: What I’m trying to show in this image is the position of the Ports P1 and P2, you will see the importance of these ports and its position for the pressure measurement. Also in this image you can see that the die and the wire bonds are protected with a Silicone Gel, this gel can get damaged leaving the die and the wire bonds exposed to the media if it’s used with different media than dry clean air. Pressure Measurements can be divided into three different categories: Absolute pressure, Gage (Gauge) pressure and Differential pressure. Let’s learn something about these categories: + Absolute pressure refers to the absolute value of the force per-unit-area exerted on a surface. Therefore the absolute pressure is the difference between the pressure at a given point and the absolute zero of pressure or a perfect vacuum. In other words: Pressure is applied on Port P1 of the sensor while the Port P2 of the sensor is a vacuum sealed reference. + Gage (Gauge) pressure is the measurement of the difference between the absolute pressure and the Local atmospheric pressure. In other words: Port P2 of the sensor is exposed to the local atmosphere while Port P1 is where pressure is applied. *Local atmospheric pressure can vary depending on ambient temperature, altitude and local weather conditions. A gage pressure by convention is always positive. A 'negative' gage pressure is defined as vacuum. Vacuum is the measurement of the amount by which the local atmospheric pressure exceeds the absolute pressure. A perfect vacuum is zero absolute pressure. + Differential pressure is simply the measurement of one unknown pressure with reference to another unknown pressure. The pressure measured is the difference between the two unknown pressures. In other words: The difference in pressure between two points is measured where pressure is applied to both sides (Port P1 and Port P2) of sensor. Since a differential pressure is a measure of one pressure referenced to another, it is not necessary to specify a pressure reference. Figure below shows the relationship between Absolute, Gage pressure and Vacuum. Freescale Pressure Sensors can also be divided into three different categories according to the Level of Integration: Uncompensated, Temperature Compensated and Integrated, now let’s learn the difference between these categories: + Uncompensated Pressure Sensors are the most basic pressure sensors according to the level of integration; this type of sensor gives a differential output in the range of millivolts, this output will need to be temperature compensated and amplified with external circuitry before sending it to the MCU’s ADC.   + Compensated Pressure Sensors is the following step according to the level of integration; although this type of sensor also gives you a differential output in the range of millivolts, the given output it’s already internally temperature compensated, so externally you only need to add the amplification circuit before sending the sensor’s signal to the MCU’s ADC. + Integrated Pressure Sensor (IPS) gives you the complete solution embedded into the same package, the output signal of the integrated pressure sensors it’s already internally temperature compensated and amplified (the output range can be from 0 to ~3V or from 0 to ~5V depending on the part number), so you do not have to worry about adding external circuitry (just probably some decoupling capacitors), the sensor signal can be sent directly to the MCU’s ADC. Additional to the mentioned types of Pressure Sensors, we also have some Digital Output Pressure Sensors which can be communicated with the MCU via SPI (MPL115A1 Digital Pressure Sensor) or I2C (MPL115A2 and MPL3115A2 Digital Pressure Sensor). Now that you know about Pressure Measurement and Level of Integration, you can jump into my Community Guideline to select the best Freescale Pressure Sensor Part Number for your application. If there are any questions regarding this document, please feel free to ask below. Your feedback or suggestions are also welcome. Regards, Jose
View full article
Hi Folks, Due to a very high number of questions from our customers regarding how to select the proper Freescale Pressure Sensor for their applications I have decided to create this illustrated, step-by-step easy to follow guideline about how to do it by yourself. Step 1: Go to http://www.freescale.com/webapp/parametricSelector.sp Then click on “Pressure Sensors” Now you should see the following window: And at this point everything is intuitive and basically the rest for select the proper Freescale Pressure Sensor depends on the requirements of your application. However, in order to trying to give you a better explanation, I’m doing an example: For this example let assume that my application requirements are as follow: Pressure measurement range up to 100kPa (higher priority parametric search for my app) Absolute Pressure Sensor Analog Output Integrated Side Ported Mount surface Package: SOP 8 (*I added the “Package Type” Parametric Search) (lower priority) *You can add or remove search parameters clicking on the “Show/Hide Parameters” button.  Based on the mentioned requirements, I selected the check boxes on the Parametric Search Window starting from the parametric with higher priority and leaving the parametric with lower priority at the end, and as a result I will get something like the image below: * You can leave unselected check boxes if are not important for your application, for my example from the image above I leave the “Ambient Operating Temperature” option unselected. So, from the initial 37 pressure sensors options I have to select, now the list it’s reduced to only 1 option, so, for this particular example, the MPXV5100 is the best solution for my application. If there are any questions regarding this guideline, please feel free to ask below. Your feedback or suggestions are also welcome. Regards, Jose
View full article
         The FXTH87XXX is a sensor for use in applications that monitor tire pressure and temperature. It contains the pressure and temperature sensors, an X-axis and a Z-axis accelerometer, a microcontroller, an LF receiver and an RF transmitter all within a single package.          NCK2912 is a fully integrated single-chip receiver for use in an automotive environment. The device incorporated several commonly used building blocks including a crystal stabilized oscillator, a fractional-N based Phase Locked Loop(PLL) for a accurate frequency selection, Low Noise Amplifier(LNA), attenuator for Automatic Gain Control(AGC), I/Q down-mixer and two high resolution Analog to Digital Converters(ADC). By transforming signals in the digital domain in an early phase, one highly configurable RX channel is available including channel filter, ASK/FSK demodulator, clock-data recovery, bit processor and a micro-controller memory interface(DMA) allowing the micro-controller to complete the data handling and handshaking. NCK2912 has an embedded RISC micro-controller optimized for high performance and low power as well as an EROM for customer application.         
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,   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
This document provides answers for some of the common questions received by the Technical Support team about some inquiries with the usage of the CRTOUCH GUI.
View full article
The MMA690x, a SafeAssure solution, is a dual axis, Low g, XY, Sensorbased on Freescale’s HARMEMS technology, with an embedded DSP ASIC, allowing for additional processing of the digital signals. Here is a Render of the MMA690x Breakout Board downloaded from OSH park: 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 files.   If you're interested in more designs like this breakout board for other sensors, please go to Freescale Sensors Breakout Boards Designs – HOME
View full article
Hi Everyone, In one of my previous documents I presented a simple example code/demo that reads both the altitude and temperature data from the Xtrinsic MPL3115A2 pressure sensor and visualizes them using the FreeMASTER tool via USBDM interface. This time I would like to share another example with the MPL3115A2 programmed to measure pressure (barometer mode) and temperature. The Freescale FRDM-KL25Z board coupled with the Xtrinsic MEMS sensors board was used for this project. The initialization of the Kinetis KL25Z128 MCU remains the same, the only small change is in the initialization of the MPL3115A2, this time the barometer mode is selected with the OSR of 128. void MPL3115A2_Init (void) {      unsigned char reg_val = 0;                 I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0x04);               // Reset all registers to POR values          do            // Wait for the RST bit to clear      {        reg_val = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG1) & 0x04;      } while (reg_val);      I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, PT_DATA_CFG_REG, 0x07);         // Enable data flags      I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG3, 0x11);               // Open drain, active low interrupts      I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG4, 0x80);               // Enable DRDY interrupt      I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG5, 0x00);               // DRDY interrupt routed to INT2 - PTD3      I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0x39);               // Active barometer mode, OSR = 128           } In the main loop, both pressure and temperature data are read and then calculated as follows. if (DataReady)          // Is a new set of data ready? {                  DataReady = 0;           /* Read both the pressure and temperature data */                       OUT_P_MSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_MSB_REG);             OUT_P_CSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_CSB_REG);             OUT_P_LSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_LSB_REG);             OUT_T_MSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_T_MSB_REG);             OUT_T_LSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_T_LSB_REG);                                  /* Get pressure, the 20-bit measurement in Pascals is comprised of an unsigned integer component and a fractional component.      The unsigned 18-bit integer component is located in OUT_P_MSB, OUT_P_CSB and bits 7-6 of OUT_P_LSB.      The fractional component is located in bits 5-4 of OUT_P_LSB. Bits 3-0 of OUT_P_LSB are not used.*/                       Pressure = (float) (((OUT_P_MSB << 16) | (OUT_P_CSB << 😎 | (OUT_P_LSB & 0xC0)) >> 6) + (float) ((OUT_P_LSB & 0x30) >> 4) * 0.25;                          /* Get temperature, the 12-bit temperature measurement in °C is comprised of a signed integer component and a fractional component.      The signed 8-bit integer component is located in OUT_T_MSB. The fractional component is located in bits 7-4 of OUT_T_LSB.      Bits 3-0 of OUT_T_LSB are not used. */                          Temperature = (float) ((signed char) OUT_T_MSB) + (float) (OUT_T_LSB >> 4) * 0.0625;                                                        }         As usual, the calculated values can be watched in the "Variables" window on the top right of the Debug perspective or in the FreeMASTER application. The complete source code written in the CW 10.3 as well as the FreeMASTER project is attached to this document. If there are any questions regarding this simple application, please feel free to ask below. Your feedback or suggestions are also welcome. Regards, Tomas
View full article
Hi Everyone,   I would like to present another example code/demo that reads acceleration data from the Xtrinsic MMA8491Q digital accelerometer and visualizes them using the FreeMASTER tool via USBDM interface. I have used recently released Xtrinsic MEMS sensors board that features three types of Xtrinsic sensors including the MMA8491Q and is fully compatible with the Freescale FRDM-KL25Z platform.   In comparison with other Xtrinsic accelerometers, the MMA8491Q is turned on at the rising edge on the EN pin and acquires only one sample for each of the three axes. It does not have any interrupt pins, instead there are three push-pull logic outputs which provide tilt detection at 45 degrees as the original target application was tamper detection. However, it is possible to read the 14-bit output values through the I2C port as demonstrated in my example below.   According to the User Manual, both SCL and SDA lines are connected through the 4.7K pull-up resistors to the I2C1 module (PTE1 and PTE0 pins) on the KL25Z128 MCU and the EN pin is connected to the PTA13 pin. The EN input needs to be kept high until a new data is ready (max. 900us) and read. In my code I use the PIT module to wait 1ms before reading the output values. This timer is also used to read the output data periodically at a fixed rate. The timeout period of the PIT is set to 500us. 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_PORTE_MASK;       // Turn on clock to Port E module        PORTE_PCR1 = PORT_PCR_MUX(6);            // PTE1 pin is I2C1 SCL line        PORTE_PCR0 = PORT_PCR_MUX(6);            // PTE0 pin is I2C1 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 I2C1 module                //Configure the PTA13 pin as an output to drive the EN input of the MMA8491Q        SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;       // Turn on clock to Port A module        PORTA_PCR13 = PORT_PCR_MUX(1);           // PTA13 is configured as GPIO        GPIOA_PCOR |= 1<<13;                     // Set PTA13 pin low        GPIOA_PDDR |= 1<<13;                     // PTA13 pin is an output                //PIT initialization        SIM_SCGC6 |= SIM_SCGC6_PIT_MASK;         // Turn on clock to to the PIT module        PIT_LDVAL0 = 5240;                       // Timeout period = 500us        PIT_MCR = PIT_MCR_FRZ_MASK;              // Enable clock for PIT, freeze PIT in debug mode        PIT_TCTRL0 = PIT_TCTRL_TIE_MASK |        // Enable PIT interrupt                    PIT_TCTRL_TEN_MASK;          // and PIT                //Enable PIT interrupt on NVIC           NVIC_ICPR |= 1 << ((INT_PIT - 16) % 32);        NVIC_ISER |= 1 << ((INT_PIT - 16) % 32); }   In the PIT interrupt service routine (ISR), there is a variable Counter that is increased by one on every PIT interrupt (500us) and its value is then compared with two preset values. The first preset value EN_HIGH_TIME determines how long the EN pin will remain high to ensure a valid reading of a new set of output data. The second preset value DATA_UPDATE_PERIOD corresponds to the desired output data rate. At the end of the ISR, the PIT interrupt flag is cleared.   void PIT_IRQHandler() {        static int Counter = 0;        Counter++;                                   // Each increment represents 500us        switch (Counter)     {             case 1:             GPIOA_PSOR |= 1<<13;                 // Set EN pin high                      break;             caseEN_HIGH_TIME:                        // 1ms passed             DataReady = 1;                       // Data is ready                      break;             caseDATA_UPDATE_PERIOD:                  // 100ms passed             Counter = 0;                         // Clear Counter at the end of the sample period                      break;             default:                      break;     }        PIT_TFLG0 |= PIT_TFLG_TIF_MASK;              // Clear PIT interrupt flag }   In the main loop, the DataReady variable is periodically checked and if it is set, the accelerometer data registers 0x01 - 0x06 are read and then the acceleration in units of g is calculated. Finally the EN pin is set low to reduce the current consumption and the DataReady variable is cleared.   if (DataReady)                                                                  // Is a new set of data ready? {                  AccData[0] = I2C_ReadRegister(MMA8491Q_I2C_ADDRESS, OUT_X_MSB_REG);         // [7:0] are 8 MSBs of the 14-bit X-axis sample      AccData[1] = I2C_ReadRegister(MMA8491Q_I2C_ADDRESS, OUT_X_LSB_REG);         // [7:2] are the 6 LSB of 14-bit X-axis sample      AccData[2] = I2C_ReadRegister(MMA8491Q_I2C_ADDRESS, OUT_Y_MSB_REG);         // [7:0] are 8 MSBs of the 14-bit Y-axis sample      AccData[3] = I2C_ReadRegister(MMA8491Q_I2C_ADDRESS, OUT_Y_LSB_REG);         // [7:2] are the 6 LSB of 14-bit Y-axis sample      AccData[4] = I2C_ReadRegister(MMA8491Q_I2C_ADDRESS, OUT_Z_MSB_REG);         // [7:0] are 8 MSBs of the 14-bit Z-axis sample      AccData[5] = I2C_ReadRegister(MMA8491Q_I2C_ADDRESS, OUT_Z_LSB_REG);         // [7:2] are the 6 LSB of 14-bit Z-axis sample        Xout_14_bit = ((short) (AccData[0]<<8 | AccData[1])) >> 2;           // Compute 14-bit X-axis output value      Yout_14_bit = ((short) (AccData[2]<<8 | AccData[3])) >> 2;           // Compute 14-bit Y-axis output value      Zout_14_bit = ((short) (AccData[4]<<8 | AccData[5])) >> 2;           // Compute 14-bit Z-axis output value                         Xout_g = ((float) Xout_14_bit) / SENSITIVITY;          // Compute X-axis output value in g's      Yout_g = ((float) Yout_14_bit) / SENSITIVITY;          // Compute Y-axis output value in g's      Zout_g = ((float) Zout_14_bit) / SENSITIVITY;          // Compute Z-axis output value in g's                                              GPIOA_PCOR |= 1<<13;       // Set EN pin low      DataReady = 0;                                                                                                                                 }                       The calculated values can be watched in the "Variables" window on the top right of the Debug perspective or in the FreeMASTER application.       Attached you can find the complete source code written in the CW 10.3 as well as 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
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
All, Drop the attached into SDK_2.0_FRDM-KL25Z/boards/frdmkl25z_virtual_shield/issdk_examples/algorithms/sensorfusion/baremetal_sensor_fusion. Apologies for both the delay in posting and the fact that even though I thought I was linking to files elsewhere in the system, I ended up getting local copies built into this project.  Some of you may like that.  I don't particularly.  But as I've noted elsewhere, KDS and I have our differences... Regards, Mike
View full article
This is a standalone project generated via the Kinetis Project Generator tool for SF Version 7.1 operating on K64F/MULT2B shield with FreeRTOS.
View full article
Hi Everyone, In this document I would like to present a simple example code I created for the FRDMKL25-P3115 kit using the KDS 3.0.2 and KSDK 2.0. I will not cover the Sensor Toolbox – CE and Intelligent Sensing Framework (ISF) which primarily support this kit. The FreeMASTER tool is used to visualize both the pressure/altitude and temperature data that are read from the MPL3115A2 using an interrupt technique through the I 2 C interface. This example illustrates: 1. Initialization of the MKL25Z128 MCU (mainly PORT and I 2 C modules). 2. I 2 C data write and read operations. 3. Initialization of the MPL3115A2. 4. Output data reading using an interrupt technique. 5. Conversion of the output values from registers 0x01 – 0x05 to real values in Pascals/meters and °C 6. Visualization of the calculated values in the FreeMASTER tool. 1. As you can see in the FRDMSTBC-P3115 schematic and the image below, with jumpers J7 and J8 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 output is connected to the PTA5 pin and configured as push-pull active-low output, so the corresponding PTA5 pin configuration is GPIO with an interrupt on falling edge. The configuration is done in the BOARD_InitPins() function. void BOARD_InitPins(void) {     CLOCK_EnableClock(kCLOCK_PortC);                                            /* Port C Clock Gate Control: Clock enabled */     CLOCK_EnableClock(kCLOCK_I2c1);                                             /* I2C1 Clock Gate Control: Clock enabled */     PORT_SetPinMux(PORTC, PIN1_IDX, kPORT_MuxAlt2);                             /* PORTC1 (pin 56) is configured as I2C1_SCL */     PORT_SetPinMux(PORTC, PIN2_IDX, kPORT_MuxAlt2);                             /* PORTC2 (pin 57) is configured as I2C1_SDA */     CLOCK_EnableClock(kCLOCK_PortA);                                            /* Port A Clock Gate Control: Clock enabled */     PORT_SetPinMux(PORTA, PIN5_IDX, kPORT_MuxAsGpio);                           /* PORTA5 (pin 31) is configured as PTA5 */     PORT_SetPinInterruptConfig(PORTA, PIN5_IDX, kPORT_InterruptFallingEdge);    /* PTA5 is configured for falling edge interrupts */     NVIC_EnableIRQ(PORTA_IRQn);                                                 /* Enable PORTA interrupt on NVIC */ } 2. The 7-bit I 2 C address of the MPL3115A2 is a fixed value 0x60 (defined in the MPL3115A2.h file) which translates to 0xC0 for a write and 0xC1 for a read. As mentioned before, the SCL line is connected to the PTC1 pin and SDA line to the PTC2 pin. The I 2 C clock frequency is 100 kHz. The I2C_Init() function is used to enable and configure the I2C1 module. void I2C_Init(void) {     i2c_master_config_t config = {     .enableMaster = true,     .enableStopHold = false,     .enableHighDrive = false,     .baudRate_Bps = 100000,     .glitchFilterWidth = 0      };     I2C_MasterInit(I2C1, &config, 24000000U);     I2C_MasterTransferCreateHandle(I2C1, &p_handle, i2c_master_callback, NULL); } The screenshot below shows the write operation which writes the value 0x39 to the CTRL_REG1 register (0x26). Here is a burst read of 5 bytes from registers 0x01 to 0x05. It also shows how the INT1 pin is automatically deasserted by reading the output registers. 3. At the beginning of the initialization, all MPL3115A2 registers are reset to their default values by setting the RST bit of the CTRL_REG1 register. The DRDY interrupt is enabled and routed to the INT1 pin that is configured to be a push-pull, active-low output. Further, the OSR ratio of 128 is selected and finally the part goes into Active barometer (eventually altimeter) mode. void MPL3115A2_Init (void) {     I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0x04);               /* Reset all registers to POR values */     Pause(0xC62);          // ~1ms delay     I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, PT_DATA_CFG_REG, 0x07);         /* Enable data flags */     I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, CTRL_REG3, 0x00);               /* Push-pull, active low interrupt */     I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, CTRL_REG4, 0x80);               /* Enable DRDY interrupt */     I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, CTRL_REG5, 0x80);               /* DRDY interrupt routed to INT1 - PTA13 */     I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0x39);               /* Active barometer mode, OSR = 128 */     //I2C_WriteRegister(I2C1, MPL3115A2_I2C_ADDRESS, CTRL_REG1, 0xB9);             /* Active altimeter mode, OSR = 128 */ } 4. In the ISR, only the interrupt flag is cleared and the DataReady variable is set to indicate the arrival of new data. void PORTA_IRQHandler(void) {     PORT_ClearPinsInterruptFlags(PORTA, 1<<5);                /* Clear the interrupt flag */     DataReady = 1; } 5. In the main loop, the DataReady variable is periodically checked and if it is set, both pressure (eventually altitude) and temperature data are read and then calculated. if (DataReady)                  /* Is a new set of data ready? */ {     DataReady = 0;     I2C_ReadMultiRegisters(I2C1, MPL3115A2_I2C_ADDRESS, OUT_P_MSB_REG, RawData, 5);                      /* Read data output registers 0x01-0x05 */     /* Get pressure, the 20-bit measurement in Pascals is comprised of an unsigned integer component and a fractional component.     The unsigned 18-bit integer component is located in OUT_P_MSB, OUT_P_CSB and bits 7-6 of OUT_P_LSB.     The fractional component is located in bits 5-4 of OUT_P_LSB. Bits 3-0 of OUT_P_LSB are not used. */     Pressure = (float) (((RawData[0] << 16) | (RawData[1] << 8) | (RawData[2] & 0xC0)) >> 6) + (float) ((RawData[2] & 0x30) >> 4) * 0.25;     /* Get temperature, the 12-bit temperature measurement in °C is comprised of a signed integer component and a fractional component.     The signed 8-bit integer component is located in OUT_T_MSB. The fractional component is located in bits 7-4 of OUT_T_LSB.     Bits 3-0 of OUT_T_LSB are not used. */     Temperature = (float) ((short)((RawData[3] << 8) | (RawData[4] & 0xF0)) >> 4) * 0.0625;     /* Get altitude, the 20-bit measurement in meters is comprised of a signed integer component and a fractional component.     The signed 16-bit integer component is located in OUT_P_MSB and OUT_P_CSB.     The fraction component is located in bits 7-4 of OUT_P_LSB. Bits 3-0 of OUT_P_LSB are not used */     //Altitude = (float) ((short) ((RawData[0] << 8) | RawData[1])) + (float) (RawData[2] >> 4) * 0.0625; } 6.  The calculated values can be watched in the Debug perspective or in the FreeMASTER application. To open and run the FreeMASTER project, install the FreeMASTER 2.0 application and FreeMASTER Communication Driver. Attached you can find the complete source code written in the KDS 3.0.2 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. Best regards, Tomas
View full article
clicktaleID