MPL115A1 reading consistantly low

One of the sensors I'm using in my tricorder/navigator/environmental monitor/dog tracker thingy is a MPL115A1 Sparkfun break out.

I'm using the example code, I've checked out the Freescale data sheet and I'm pretty sure the example code implements the hideously complicated calculation to read the temperature and barometric pressure.

But it is reading at least 10C low on temperature and about 100 KPa low on the pressure sensor.
Has anyone else used this sensor?

One thing I can think of is round off error, converting between fixed point math and floating point might explain this.
What do you guys think?

What do you guys think?

I'm thinking that after 16 posts, you should know the drill by now. Post links to the hardware you are having issues with, and post the code that illustrates the issue.

Hand-waving elicits condolences. Facts elicit help, more often than not.

Here is the link to the Sparkfun page.

And the revalent Freescale doc

Here is a link to the example code, it seems there is a limit to mow big a sketch we can post
http://www.sparkfun.com/datasheets/BreakoutBoards/MPL115A1-ATmega328Code-8-9-10.zip

I'm using the SPI version of this device on a Mega.

So again, has anyone else tried using this sensor on a Sparkfun breakout board.

And PaulS, please, if you don't know what I'm talking about, don't reply.
It was a fairly specific question about a specific sensor.
Anyone who has used it would recognise the the part number, even if you don't.
As to my 16 posts, the replies, besides yours have been really helpful.
Although I will give you credit for questioning why I was trying to use software serial on a Mega, my latest creation is using all 4 UARTS and they work very well indeed.

Ok, I've only just started using the Arduino platform, but seriously how many ways are there to hook up an SPI device?

Am I missing something?

MPL115A1 is a very specific part, the example code was to big to post here, the algorithm to extract the corrected pressure reading is also very specific.
Unless you have an MPL115A1 there is no way you would need to wade through the Freescale data sheet.

Here are the pin connections for a Mega, plus the register defs.
This come straight from the example sketch on the SparkFun sit, modified for the Arduino Mega.

MPL115A1 Breakout ------------- Arduino Mega
 -----------------               -------
         SDN ------------------- D49
         CSN ------------------- D53
         SDO ------------------- D50 *
         SDI ------------------- D51 *
         SCK ------------------- D52 *
         GND ------------------- GND
         VDD ------------------- VCC +
 
         * These pins physically connect to the SPI device so you can't change them
         + 5V board use 5V VDD, 3.3V board use 3.3V VDD
 
 License: CCAv3.0 Attribution-ShareAlike (http://creativecommons.org/licenses/by-sa/3.0/)
 You're free to use this code for any venture, but I'd love to hear about what you do with it,
 and any awesome changes you make to it. Attribution is greatly appreciated.
 */

// Includes
#include <SPI.h>

// Get your current altimiter setting from from the National
// Weather Service - http://www.weather.gov
// This value is often labeled "Barometer" or "Barometric Pressure" or just "Pressure"
#define NWS_BARO 30.04 

// Pin definitions
#define MPL115A1_ENABLE_PIN 49
#define MPL115A1_SELECT_PIN 53

// Masks for MPL115A1 SPI i/o
#define MPL115A1_READ_MASK  0x80
#define MPL115A1_WRITE_MASK 0x7F 

// MPL115A1 register address map
#define PRESH   0x00    // 80
#define PRESL   0x02    // 82
#define TEMPH   0x04    // 84
#define TEMPL   0x06    // 86

#define A0MSB   0x08    // 88
#define A0LSB   0x0A    // 8A
#define B1MSB   0x0C    // 8C
#define B1LSB   0x0E    // 8E
#define B2MSB   0x10    // 90
#define B2LSB   0x12    // 92
#define C12MSB  0x14    // 94
#define C12LSB  0x16    // 96
#define C11MSB  0x18    // 98
#define C11LSB  0x1A    // 9A
#define C22MSB  0x1C    // 9C
#define C22LSB  0x1E    // 9E

Here is the temperature calculation

float calculateTemperatureC() {
    
    unsigned int uiTadc;
    unsigned char uiTH, uiTL;
    
    unsigned int temperature_counts = 0;
    
    writeRegister(0x22, 0x00);  // Start temperature conversion
    delay(2);                   // Max wait time is 0.7ms, typ 0.6ms
    
    // Read pressure
    uiTH = readRegister(TEMPH);
    uiTL = readRegister(TEMPL);
    
    uiTadc = (unsigned int) uiTH << 8;
    uiTadc += (unsigned int) uiTL & 0x00FF;
    
    // Temperature is a 10bit value
    uiTadc = uiTadc >> 6;
    
    // -5.35 counts per °C, 472 counts is 25°C
    return 25 + (uiTadc - 472) / -5.35;
}

And the pressure calculation, this is the heavy bit!

float calculatePressurekPa() {
    
    // See Freescale document AN3785 for detailed explanation
    // of this implementation.
    
    signed char sia0MSB, sia0LSB;
    signed char sib1MSB, sib1LSB;
    signed char sib2MSB, sib2LSB;
    signed char sic12MSB, sic12LSB;
    signed char sic11MSB, sic11LSB;
    signed char sic22MSB, sic22LSB;
    signed int sia0, sib1, sib2, sic12, sic11, sic22, siPcomp;
    float decPcomp;
    signed long lt1, lt2, lt3, si_c11x1, si_a11, si_c12x2;
    signed long si_a1, si_c22x2, si_a2, si_a1x1, si_y1, si_a2x2;
    unsigned int uiPadc, uiTadc;
    unsigned char uiPH, uiPL, uiTH, uiTL;
    
    writeRegister(0x24, 0x00);      // Start Both Conversions
    //writeRegister(0x20, 0x00);    // Start Pressure Conversion
    //writeRegister(0x22, 0x00);    // Start temperature conversion
    delay(2);                       // Max wait time is 1ms, typ 0.8ms
    
    // Read pressure
    uiPH = readRegister(PRESH);
    uiPL = readRegister(PRESL);
    uiTH = readRegister(TEMPH);
    uiTL = readRegister(TEMPL);
    
    uiPadc = (unsigned int) uiPH << 8;
    uiPadc += (unsigned int) uiPL & 0x00FF;
    uiTadc = (unsigned int) uiTH << 8;
    uiTadc += (unsigned int) uiTL & 0x00FF;
    
    // Placing Coefficients into 16-bit Variables
    // a0
    sia0MSB = readRegister(A0MSB);
    sia0LSB = readRegister(A0LSB);
    sia0 = (signed int) sia0MSB << 8;
    sia0 += (signed int) sia0LSB & 0x00FF;
    
    // b1
    sib1MSB = readRegister(B1MSB);
    sib1LSB = readRegister(B1LSB);
    sib1 = (signed int) sib1MSB << 8;
    sib1 += (signed int) sib1LSB & 0x00FF;
    
    // b2
    sib2MSB = readRegister(B2MSB);
    sib2LSB = readRegister(B2LSB);
    sib2 = (signed int) sib2MSB << 8;
    sib2 += (signed int) sib2LSB & 0x00FF;
    
    // c12
    sic12MSB = readRegister(C12MSB);
    sic12LSB = readRegister(C12LSB);
    sic12 = (signed int) sic12MSB << 8;
    sic12 += (signed int) sic12LSB & 0x00FF;
    
    // c11
    sic11MSB = readRegister(C11MSB);
    sic11LSB = readRegister(C11LSB);
    sic11 = (signed int) sic11MSB << 8;
    sic11 += (signed int) sic11LSB & 0x00FF;
    
    // c22
    sic22MSB = readRegister(C22MSB);
    sic22LSB = readRegister(C22LSB);
    sic22 = (signed int) sic22MSB << 8;
    sic22 += (signed int) sic22LSB & 0x00FF;
    
    // Coefficient 9 equation compensation
    uiPadc = uiPadc >> 6;
    uiTadc = uiTadc >> 6;
    
    // Step 1 c11x1 = c11 * Padc
    lt1 = (signed long) sic11;
    lt2 = (signed long) uiPadc;
    lt3 = lt1*lt2;
    si_c11x1 = (signed long) lt3;
    
    // Step 2 a11 = b1 + c11x1
    lt1 = ((signed long)sib1)<<14;
    lt2 = (signed long) si_c11x1;
    lt3 = lt1 + lt2;
    si_a11 = (signed long)(lt3>>14);
    
    // Step 3 c12x2 = c12 * Tadc
    lt1 = (signed long) sic12;
    lt2 = (signed long) uiTadc;
    lt3 = lt1*lt2;
    si_c12x2 = (signed long)lt3;
    
    // Step 4 a1 = a11 + c12x2
    lt1 = ((signed long)si_a11<<11);
    lt2 = (signed long)si_c12x2;
    lt3 = lt1 + lt2;
    si_a1 = (signed long) lt3>>11;
    
    // Step 5 c22x2 = c22*Tadc
    lt1 = (signed long)sic22;
    lt2 = (signed long)uiTadc;
    lt3 = lt1 * lt2;
    si_c22x2 = (signed long)(lt3);
    
    // Step 6 a2 = b2 + c22x2
    lt1 = ((signed long)sib2<<15);
    lt2 = ((signed long)si_c22x2>1);
    lt3 = lt1+lt2;
    si_a2 = ((signed long)lt3>>16);
    
    // Step 7 a1x1 = a1 * Padc
    lt1 = (signed long)si_a1;
    lt2 = (signed long)uiPadc;
    lt3 = lt1*lt2;
    si_a1x1 = (signed long)(lt3);
    
    // Step 8 y1 = a0 + a1x1
    lt1 = ((signed long)sia0<<10);
    lt2 = (signed long)si_a1x1;
    lt3 = lt1+lt2;
    si_y1 = ((signed long)lt3>>10);
    
    // Step 9 a2x2 = a2 * Tadc
    lt1 = (signed long)si_a2;
    lt2 = (signed long)uiTadc;
    lt3 = lt1*lt2;
    si_a2x2 = (signed long)(lt3);
    
    // Step 10 pComp = y1 + a2x2
    lt1 = ((signed long)si_y1<<10);
    lt2 = (signed long)si_a2x2;
    lt3 = lt1+lt2;
    
    // Fixed point result with rounding
    //siPcomp = ((signed int)lt3>>13);
    siPcomp = lt3/8192;
    
    // decPcomp is defined as a floating point number
    // Conversion to decimal value from 1023 ADC count value
    // ADC counts are 0 to 1023, pressure is 50 to 115kPa respectively
    decPcomp = ((65.0/1023.0)*siPcomp)+50;
    
    return decPcomp;
}

I was NOT sniping, I was objecting to the tone.
This is not a syntax or basic electronics question, it IS very specific to this chip.
I was previously not aware there was a "drill" here.
I apologise for any offence

I've been experimenting with the same sensor, using similar code. I've found the pressure readings to be correct once I applied the necessary correction required because my location is 500 feet above sea level. However I too am having problems with the temperature reading - in my case the reading is about 5 degrees Celcius too low.

The code for calculating the temperature is very simple. It's entirely independent of the complicated routine for pressure calculation. And it conforms to the requirements of the sensor's technical datasheet. I added a line to the program to output the raw temperature data from the sensor which verifies that the code is working correctly.

I can only conclude that the algorithm published in the datasheet is actually incorrect. I'll investigate further and if I find anything useful I'll post it here.

Regards, Pete

There is an automated weather station about 15km from here that is about the same elevation as I am.
http://www.bom.gov.au/products/IDS60901/IDS60901.94683.shtml
When I've looked at the current barometer reading it seems to be very close to what my MPL115A1 is measuring.
Likewise the altitude is pretty close to what my EM-406 GPS module and the topographic map says my elevation is.
I recently bought a Sparkfun TMP-102 and SHT15 modules and I was going to try using the temperature reading from that to see if it made a difference to the barometric pressure reading.
I'm not sure if this is the right way to go, but more data can only be a good thing.

What is your experience of the temperature readings? This is where I'm encountering significant errors.

Regards, Pete

My temperature readings were consistantly 12C low.
This was why I was going to try readings from another temperature sensor.
As for the barometric pressure reading I'm still not sure.
I was going to try getting an aneroid barometer or 250ml of mercury and build "wet" barometer or manometer.