diff --git a/library/MPL3115A2_Pressure/MPL3115A2.cpp b/library/MPL3115A2_Pressure/MPL3115A2.cpp index 642dbff..9f8879e 100644 --- a/library/MPL3115A2_Pressure/MPL3115A2.cpp +++ b/library/MPL3115A2_Pressure/MPL3115A2.cpp @@ -287,3 +287,57 @@ void MPL3115A2::IIC_Write(byte regAddr, byte value) Wire.endTransmission(true); } +// added by https://github.com/mariocannistra +// the following offset routines are from Michael Lange on mbed.org +// modified for some data types and to pre-calculate the offset in °C +// when reading the temperature offset + +//! Returns the altitude offset stored in the sensor. +int8_t MPL3115A2::offsetAltitude() { return (int8_t) IIC_Read(OFF_H); } +//! Sets the altitude offset stored in the sensor. The allowed offset range is from -128 to 127 meters. +void MPL3115A2::setOffsetAltitude(int8_t offset) { IIC_Write(OFF_H, offset); } +//! Returns the pressure offset stored in the sensor. +float MPL3115A2::offsetPressure() { return (float) IIC_Read(OFF_P); } +//! Sets the pressure offset stored in the sensor. The allowed offset range is from -128 to 127 where each LSB represents 2 Pa. +void MPL3115A2::setOffsetPressure(const char offset) { IIC_Write(OFF_P, offset); } +//! Returns the temperature offset stored in the sensor. +float MPL3115A2::offsetTemperature() { return (float) IIC_Read(OFF_T) * 0.0625 ; } +//! Sets the temperature offset stored in the sensor. The allowed offset range is from -128 to 127 where each LSB represents 0.0625ºC. +void MPL3115A2::setOffsetTemperature(const char offset) { IIC_Write(OFF_T, offset); } + +// the 2 following functions comes from http://www.henrylahr.com/?p=99 +// edited to merge them with the Sparkfun library + +// sets the "Barometric input for Altitude calculation" (see datasheet) +void MPL3115A2::setBarometricInput(float pressSeaLevel) +{ + IIC_Write(BAR_IN_MSB, (unsigned int)(pressSeaLevel / 2)>>8); + IIC_Write(BAR_IN_LSB, (unsigned int)(pressSeaLevel / 2)&0xFF); +} + +void MPL3115A2::runCalibration(float currentElevation) +{ + float pressureAccum = 0.0; + + setModeBarometer(); // Measure pressure in Pascals + setOversampleRate(7); // Set Oversample to the recommended 128 --> 512ms + enableEventFlags(); // Enable all three pressure and temp event flags + for (byte i=0;i<6;i++){ + delay(550); //wait for sensor to read pressure (512ms in datasheet) + pressureAccum = pressureAccum + readPressure(); + } + float currpress = pressureAccum / 6; //average pressure over (6/550) seconds + + //Serial.print("Current average pressure: "); + //Serial.print(currpress); + //Serial.println(" Pa"); + + //calculate pressure at mean sea level based on the known altitude + float powElement = pow(1.0-(currentElevation*0.0000225577), 5.255877); + calculated_sea_level_press = currpress / powElement; + //Serial.print("Calculated sea level pressure: "); + //Serial.print(calculated_sea_level_press); + //Serial.println(" Pa"); + + elevation_offset = 101325.0 - (101325.0 * powElement); +} diff --git a/library/MPL3115A2_Pressure/MPL3115A2.h b/library/MPL3115A2_Pressure/MPL3115A2.h index ce050d5..7242061 100644 --- a/library/MPL3115A2_Pressure/MPL3115A2.h +++ b/library/MPL3115A2_Pressure/MPL3115A2.h @@ -86,7 +86,22 @@ class MPL3115A2 { void setOversampleRate(byte); // Sets the # of samples from 1 to 128. See datasheet. void enableEventFlags(); // Sets the fundamental event flags. Required during setup. + // added by https://github.com/mariocannistra + // to declare the functions by Michael Lange on mbed.org + int8_t offsetAltitude(); + void setOffsetAltitude(int8_t offset); + float offsetPressure(); + void setOffsetPressure(const char offset); + float offsetTemperature(); + void setOffsetTemperature(const char offset); + // and the functions by http://www.henrylahr.com/?p=99 + void setBarometricInput(float pressSeaLevel); + void runCalibration(float currentElevation); + //Public Variables + float elevation_offset; + float calculated_sea_level_press; + private: //Private Functions diff --git a/library/MPL3115A2_Pressure/examples/barometer_calibration/barometer_calibration.ino b/library/MPL3115A2_Pressure/examples/barometer_calibration/barometer_calibration.ino new file mode 100644 index 0000000..3be7337 --- /dev/null +++ b/library/MPL3115A2_Pressure/examples/barometer_calibration/barometer_calibration.ino @@ -0,0 +1,153 @@ +/* + MPL3115A2 Barometric Pressure Sensor - Calibration Code + by https://github.com/mariocannistra + + i've put together this code to obtain more precise values + from the sensor --> when using it for altitude measurements <-- + and to get more precise barometer indications + + How I glued things together: + - slightly customize the code by http://www.henrylahr.com/?p=99 + - used the offset routines from Michael Lange on mbed.org + - completed with elevation_offset calculation by digitalmisery comment at https://www.sparkfun.com/products/11084 + - then packaged the calibration function within the original + library code by Nathan Seidle - SparkFun Electronics + + About the following line, hope to meet Nathan someday for the beer :-) If I will meet all of them.. then also food :-) + License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license). +*/ + +#include +#include "MPL3115A2.h" + +//Create an instance of the object +MPL3115A2 baro3115; + +#define ALTBASIS 332.0 // start altitude to calculate mean sea level pressure in meters + // got this averaging readouts from 3 different GPS + +void setup() +{ + // give me time to open serial monitor: + delay(3000); + + Wire.begin(); // Join i2c bus + Serial.begin(57600); // Start serial for output + + baro3115.begin(); // Get sensor online + + //Configure the sensor + // Set the # of samples from 1 to 128. See datasheet. + // Integer values between 0 < n < 7 give oversample ratios 2^n and + // sampling intervals of 0=6 ms , 1=10, 2=18, 3=34, 4=66, 5=130, 6=258, and 7=512 + baro3115.setOversampleRate(7); // Set Oversample to the recommended 128 --> 512ms + baro3115.enableEventFlags(); // Enable all three pressure and temp event flags + + Serial.println("BEFORE calibration..."); + // show sample data readouts before starting the calibration: + outData(); + + // set to zero all the sensor offsets and input values: + baro3115.setOffsetTemperature(0); + baro3115.setOffsetPressure(0); + baro3115.setOffsetAltitude(0); + baro3115.setBarometricInput(0.0); + + // let's have a look, just in case: + Serial.println("OFFSETS:"); + Serial.print(" pressure: "); + Serial.println(baro3115.offsetPressure() ,2); + Serial.print(" altitude: "); + Serial.println((float)baro3115.offsetAltitude() ,2); + Serial.print(" temperature(C): "); + Serial.println(baro3115.offsetTemperature() ,2); + + // now perform the calibration + + //calculate pressure for current ALTBASIS altitude by averaging a few readings + Serial.println("Pressure calibration..."); + + // this function calculates a new sea level pressure ref value + // it will NOT change the sensor registers + // see below setBarometricInput() where that value is actually set + // in the registers. the sensor will start using it just after. + baro3115.runCalibration(ALTBASIS); + + + Serial.print("calculated sea level pressure: "); + Serial.print(baro3115.calculated_sea_level_press ,2); + Serial.println(" Pa"); + + Serial.print("calculated elevation_offset: "); + Serial.print(baro3115.elevation_offset ,2); + Serial.println(" Pa"); + + // i originally had 35 hPa error in pressure readouts + // once i added the elevation_offset calculation, the error + // decreased and is now within 4 hPa (ie: 1015.18 instead of official 1011.5) + // (official = pro measurement at same elevation at 500 m from my laptop) + + // This configuration option calibrates the sensor according to + // the sea level pressure for the measurement location (2 Pa per LSB) + // The default value for "Barometric input for Altitude calculation" is 101,326 Pa + + baro3115.setBarometricInput( baro3115.calculated_sea_level_press ); + + // calibration performed + + // add temperature offset for my tested sensor + // seems the temperature probe is within the ADC and should not be used + // to measure the environment. Will try adding the offset i got by comparison + // with another thermometer + // you can enable this if you need it: + // baro3115.setOffsetTemperature((char) (0.65 / 0.0625) ); +} + +void outData() +{ + baro3115.setModeBarometer(); // Measure pressure in Pascals + delay(520); + // since we are using the calibration then we also have to add the + // calculated elevation related pressure offset: + float pressure = baro3115.readPressure() + baro3115.elevation_offset; + Serial.print("Pressure(Pa): "); + Serial.print(pressure, 2); + + // output is in Pa + // 1 kPa = 10 hPa = 1000 Pa + // 1 hPa = 100 Pascals = 1 mb + pressure = (pressure / 100) ; // ... / 1000 * 10 ; + Serial.print(" Pressure(hPa): "); + Serial.print(pressure, 2); + + float temperature = baro3115.readTemp(); + Serial.print(" Temperature(C): "); + Serial.print(temperature, 2); + + baro3115.setModeAltimeter(); // Measure altitude above sea level in meters + delay(520); + float altitude = baro3115.readAltitude(); + Serial.print(" Altitude above sea(m): "); + Serial.println(altitude, 2); +} + +void loop() +{ + outData(); +} + +// sample output: +//BEFORE calibration... +//Pressure(Pa): 1327.00 Pressure(hPa): 13.27 Temperature(C): 21.25 Altitude above sea(m): 332.25 +//OFFSETS: +// pressure: 0.00 +// altitude: 0.00 +// temperature(C): 0.00 +//Pressure calibration... +//calculated sea level pressure: 101552.34 Pa +//calculated elevation_offset: 3925.32 Pa +//Pressure(Pa): 101547.56 Pressure(hPa): 1015.48 Temperature(C): 21.25 Altitude above sea(m): 331.94 +//Pressure(Pa): 101543.31 Pressure(hPa): 1015.43 Temperature(C): 21.25 Altitude above sea(m): 331.62 +//Pressure(Pa): 101544.31 Pressure(hPa): 1015.44 Temperature(C): 21.25 Altitude above sea(m): 331.94 +//Pressure(Pa): 101546.06 Pressure(hPa): 1015.46 Temperature(C): 21.25 Altitude above sea(m): 331.75 +//Pressure(Pa): 101543.56 Pressure(hPa): 1015.44 Temperature(C): 21.25 Altitude above sea(m): 331.94