MPL3115A2 - Altitude and temperature measuring

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

MPL3115A2 - Altitude and temperature measuring

MPL3115A2 - Altitude and temperature measuring

Hi Everyone,

 

I would like to share 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. I have used recently released Xtrinsic MEMS sensors board that features three types of Xtrinsic sensors including the MPL3115A2 and is fully compatible with the Freescale FRDM-KL25Z platform.

 

According to the User Manual, both interrupt pins of the MPL3115A2 are connected to the PTD3 pin of KL25Z MCU through a 4.7K pull-up resistor as well as both SCL and SDA lines that are connected to the I2C1 module (PTE1 and PTE0 pins) on the KL25Z. 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 PTD3 pin (connected to the INT2 of the MPL3115A2) for falling edge interrupt  

       SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;       // Turn on clock to Port D module

       PORTD_PCR3 |= (0|PORT_PCR_ISF_MASK|      // Clear the interrupt flag

       PORT_PCR_MUX(0x1)|                       // PTD3 is configured as GPIO

       PORT_PCR_IRQC(0xA));                     // PTD3 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);

}

 

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_PCR3 |= PORT_PCR_ISF_MASK;         // Clear the interrupt flag

       DataReady = 1;

}


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 INT2 pin that is configured to be an open-drain, active-low output. During the initialization of the MPL3115A2, the OSR ratio of 128 is selected and finally the part goes into Active Altimeter mode.

 

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, 0xB9);                        // Active altimeter mode, OSR = 128

}

 

In the main loop, the DataReady variable is periodically checked and if it is set, both altitude and temperature data are read and then calculated.

 

if (DataReady)          // Is a new set of data ready?

{           

       DataReady = 0;          


       OUT_P_MSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_MSB_REG);        // High byte of integer part of altitude,

       OUT_P_CSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_CSB_REG);        // Low byte of integer part of altitude

       OUT_P_LSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_P_LSB_REG);        // Decimal part of altitude in bits 7-4

       OUT_T_MSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_T_MSB_REG);        // Integer part of temperature

       OUT_T_LSB = I2C_ReadRegister(MPL3115A2_I2C_ADDRESS, OUT_T_LSB_REG);        // Decimal part of temperature in bits 7-4

             

            /* 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) ((OUT_P_MSB << 8) | OUT_P_CSB)) + (float) (OUT_P_LSB >> 4) * 0.0625;

      

             /* 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;                                                             

}

 

The calculated values can be watched in the "Variables" window on the top right of the Debug perspective or in the FreeMASTER application.


5599_5599.jpgMPL3115A2_Altitude&Temperature reading.JPG.jpg


5603_5603.jpgMPL3115A2_FreeMASTER_Altitude&Temperature.JPG.jpg


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, please feel free to ask below. Your feedback or suggestions are also welcome.

 

Regards,

Tomas

Original Attachment has been moved to: FreeMASTER---XTRINSIC-SENSORS-EVK_MPL3115A2_BasicReadUsingInterrupt.zip

Original Attachment has been moved to: XTRINSIC-SENSORS-EVK_MPL3115A2_BasicReadUsingInterrupt.zip

Labels (1)
Comments

Hi Tomas. I'm using KITSTBMPL3115A2 EVB to connect with KL25Z-FRDM. Connection Pins is: PTE0 <-> SDA, PTE1 <-> SCL, Pin 8 <-> VREFH, PTD3 <-> INT1 & INT2. VDD&VDDIO <-> P 3V3. GND <-> GND.

Should I have more 4.7 K Ohm pull registers for this?

Currently, I2C can not sent out.

Hi Thach,

First, sorry for not replying sooner, I did not have access to the internet during the weekend.

Yes, it is necessary to populate both 4.7k pull-up resistors for the I2C bus on the KITSTBMPL3115A2 sensor board. There are also no pull-ups on the interrupt outputs, so you can either populate them or set the interrupt pins to be push-pull outputs. To do this, just modify the following instruction in the MPL3115A2_Init routine:


I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG3, 0x11);          // Open drain, active low interrupts


replace by:


I2C_WriteRegister(MPL3115A2_I2C_ADDRESS, CTRL_REG3, 0x00);          // Push-pull, active low interrupts


I hope it helps.


Regards,

Tomas

Hi Tomas,

I had some strange readings from my mpl3115a2. First of all the sensor seems to work just fine, but now i'm getting 0xFF from P_MSB. So usly my altitude should be around 45meter but now im at -23meter.

is it shomthing that can be fixed or is the sensor broken. i read auto increment from 0x00 to 0x04 = P_msb to T_lsb, and the temperatur works just fine.

Hi Viggo,

If you are using a multiple-byte (burst) read, you should start from register OUT_P_MSB (0x01):

I2C_ReadMultiRegisters(MPL3115A2_I2C_ADDRESS, OUT_P_MSB_REG, 5, AltTempData); 

I hope this helps.

Regards,

Tomas

Hi,

yes. is 0x01 to 0x05, i wrote wrong numbers.

I2C_RegWrite(MPL3115A2_ADDRESS,OUT_P_MSB,5);

this is my i2c reg Write methode. and it looks almost the same ass yours.

so it's not that. i have gone thrue my code and i cant find anything wrong. so i wonder is this a bug ?

Hi Viggo,

OK, I just wanted to make sure that you read correct registers.

The fact is that the MPL3115A2 is designed more for the scenario of going between two floors, or from one point to another and measuring this delta, than to be giving absolute position.   

To adjust the most precise altitude, I recommend the following:

1. If you know your current position and the altitude using some external calibration point in meters, then adjust the OFF_H register (0x2D) to account for the discrepancy.

2. If you would like to adjust to weather changes, the BAR_IN_MSB (0x14) and BAR_IN_LSB (0x15) registers allow you to modify the pressure value that internally is used in the equation that converts pressure in Pascals to meters for altitude. So if there is a very stormy day and your local weather/airport gives the pressure normalized for sea level, this value should go into these registers. This should bring the height closer and additional will require the OFF_H adjustment.


Regards,

Tomas

Hi Tomas,

I am having trouble using One-Shot-Mode(OST).  I am trying to have the pressure sensor initiate a measurement, poll the status register to see if (PTDR|PDR|TDR) are set, and once they are, read OUT_T_MSB, OUT_T_LSB, OUT_P_MSB,OUT_P_CSB, OUT_P_LSB and repeat forever.  First  I set ControlReg1 to 0x01 to clear the OST bit and immediately after I set the ControlReg1 to 0x03 to start a new measurement.  But the Data ready bits in the Status Register never seem to get set.  I found thaf if I dont check the Status register and  always read the OUT Registers then I get bad measurement results.  If I set a break point at the measurement read then I get good results, which I think is because I've given enough time for the measurements to complete.  Any ideas or suggestions would be greatly appreciated.


Justin

Hi Justin,

It sounds to me like the data ready bits (PTDR, PDR and TDR) are not enabled using the corresponding bits in the PT_DATA_CFG (0x13) register. Please try to write 0x07 to the PT_DATA_CFG register to enable all data ready bits.

I hope it helps.

Regards,

Tomas

Hi Tomas,


Thanks for taking the time to help.  I initialize the MPL3115A2 with the following I2C writes:

   

    MPL3115A2_WriteReg(CTRL_REG1, 0);
    MPL3115A2_WriteReg(CTRL_REG2,2 );//ST_MASK
    MPL3115A2_WriteReg(CTRL_REG3, (PP_OD1_MASK | PP_OD2_MASK));
    MPL3115A2_WriteReg(CTRL_REG4, INT_EN_CLEAR);
    MPL3115A2_WriteReg(CTRL_REG5, INT_CFG_CLEAR);
    MPL3115A2_WriteReg(PT_DATA_CFG_REG, 7);//(DREM_MASK | PDEFE_MASK | TDEFE_MASK)
    MPL3115A2_WriteReg(F_SETUP_REG, 0);

Then I set to Active mode, and then Set the One-Shot:

    MPL3115A2_WriteReg(CTRL_REG1, ACTIVE_MASK);        //Set to Active
    MPL3115A2_WriteReg(CTRL_REG1, ACTIVE_SBYB_OST);        //Set OST Bit to Trigger Measurement


Then in the main loop I keep checking the Status Register:

            if(GetEventFlags() == 0x0E)

            {  

               //Pressure
              MPL3115A2_ReadReg(OUT_P_MSB_REG, &temp, 1);
              rawPressure->Byte.msbPressure = temp;
              MPL3115A2_ReadReg(OUT_P_CSB_REG, &temp, 1);
              rawPressure->Byte.csbPressure = temp;
              MPL3115A2_ReadReg(OUT_P_LSB_REG, &temp, 1);
              rawPressure->Byte.lsbPressure = temp;

               // Temp

             MPL3115A2_ReadReg(OUT_T_MSB_REG, &temp, 1);
             rawTemperature->hiTempByte = temp;
             MPL3115A2_ReadReg(OUT_T_LSB_REG, &temp, 1);
             rawTemperature->loTempByte = temp;

              MPL3115A2_WriteReg(CTRL_REG1, ACTIVE_MASK);        //Clear the previous One-Shot Bit
              MPL3115A2_WriteReg(CTRL_REG1, ACTIVE_SBYB_OST);        //Set OST Bit to Trigger another Measurement

            }

          From what I understand, reading the OUT_P_MSB and OUT_T_MSB should clear the PDR and TDR bits correct?

          Am I just missing something, I had trouble earlier because I was using the KL25Z and I didn't know about the I2C errata that causes repeated start to not work, but I fixed the code and now I see the repeated start.

Thanks again.

Hi Tomas,

You were right, I was not setting the PT_DATA_CFG register.  It turned out that I was not giving the sensor enough time between STOP and START conditions according to tBUF spec in the data sheet.  I put a delay in my I2C read and write functions and now the sensor works great.

Thanks for your help.

Justin

OK, glad to hear you got it working, Justin.


Regards,

Tomas

Hi Tomas,

I am seeing that the delay time required between stop and start is dependent upon the SCL clock frequency.  Specifically the lower the clock speed the greater the delay required.  If I'm running the SCL at 15KHz, it requires over 100uS delay but as I increase my clock speed I can decrease the delay and still get good communication with the sensor.  Can you confirm this or help me understand what is going on?


Thanks,

Justin

Hi Tomas,

We are looking at get the MPL3115A2 sensor with a number of different slave addresses for a medical device application.  We will have 3 MPL3115A2 sensors on a single clock and data line.  With other sensors, we have been able to re-program the slave address ourselves.  Can we do this with the MPL3115A2?  If not, how do we get different slave addresses from the factory?  Our application is large but we are still in the product validation stage.

Thanks,

Carl

Hi Carl,

Unfortunately the MPL3115A2 does not have address select pins and there is no way to re-program the slave address by user.

For small quantities, I would recommend using an I2C multiplexer such as the PCA9544A.

For big quantities, we might be able to change the slave address. Please send me a direct message with more information about your application, volumes, production data and what addresses you would like. I will forward the information to the product line and write you back once I get a response.

Regards,

Tomas

Hi Tomas,

Thank you for your reply.

We would be looking at a high volume of sensors (in the 100,000+ range).

Who should we speak with to discuss our application?

Thanks,

Carl

On Wed, Jan 13, 2016 at 2:01 AM, TomasVaverka <admin@community.freescale.com

Hi Carl,

I have informed both the product line manager and one of our local apps engineers who specializes in pressure sensors of your interest in the MPL3115A2. They will contact you soon via email.

Thanks again for your interest.

Regards,

Tomas

Thank you Tomas,

We look forward to hearing from someone regarding our application.

Also, what is the sample rate for the MPL3115A2 sensor? We are having

difficulty sampling at a rate faster than 1 sec. Ideally, we would like to

sample at 1/10 second.

Best regards,

Carl Geisz

On Mon, Jan 18, 2016 at 2:53 AM, TomasVaverka <admin@community.freescale.com

Carl,

You can increase the sample rate by utilizing One Shot Mode (OST). This is described in section 7.17.1 CTRL_REG1 on Table 58. OST mode gives you the ability to initiate a measurement immediately. The automated mode for the MPL3115A2 takes a measurement once a second. Let me know if you have any questions on OST mode.

I have passed your contact information to our sales team in St. Paul and someone should be contacting you shortly.

Regards,

Miguel

No ratings
Version history
Last update:
‎08-12-2013 01:56 AM
Updated by: