Lib for HP03SA atmospheric pressure sensor. Provides pressure, temperature and altitude data.

Dependents:   mbed_HP03SA_LM77

Revision:
0:61bbd81782de
diff -r 000000000000 -r 61bbd81782de HP03SA.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HP03SA.cpp	Sat Jan 10 19:10:17 2015 +0000
@@ -0,0 +1,321 @@
+/* mbed HP03SA Library, for an I2C Pressure and Temperature sensor which provides derived Altitude values
+ * Copyright (c) 2015, v01: WH, Initial version, ported in part from Elektor weatherstation (Sept 2011), Author: W. Waetzig
+ *                          See http://www.elektor-labs.com/project/usb-long-term-weather-logger-100888.12037.html
+ *                          Code also based on several other public sources:   
+ *                          See http://en.wikipedia.org/wiki/Atmospheric_pressure
+ *                          See https://learn.sparkfun.com/tutorials/bmp180-barometric-pressure-sensor-hookup-?_ga=1.94307604.888266135.1310146152
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "mbed.h"
+#include "HP03SA.h"
+
+/** Create an HP03SA interface for mbed pins
+  *
+  * @param i2c    I2C Bus 
+  * @param XCLR   Clock enable control line
+  */ 
+HP03SA::HP03SA(I2C *i2c, PinName XCLR) : _i2c(i2c), _xclr(XCLR) {
+
+  _init();
+}
+
+/**  Init the HP03SA
+  *  
+  */
+void HP03SA::_init() {
+  char buffer[18];
+
+  //HP03S initialization
+
+  _xclr=0;   //XCLR low for coefficients readout
+      
+  // Select C1 register
+  buffer[0] = 0x10;                                // Register address for _C1 MSB is 0x10
+  _i2c->write(HP03SA_EEPROM_SA, buffer, 1, true);  // Repeated Start
+  // Read calibration parameters
+  _i2c->read(HP03SA_EEPROM_SA, buffer, 18);   
+  
+  _C1 = (buffer[0] << 8)  | buffer[1];  // _C1 MSB, LSB
+  _C2 = (buffer[2] << 8)  | buffer[3];  // _C2 MSB, LSB
+  _C3 = (buffer[4] << 8)  | buffer[5];  // _C3 MSB, LSB
+  _C4 = (buffer[6] << 8)  | buffer[7];  // _C4 MSB, LSB
+  _C5 = (buffer[8] << 8)  | buffer[9];  // _C5 MSB, LSB
+  _C6 = (buffer[10] << 8) | buffer[11]; // _C6 MSB, LSB
+  _C7 = (buffer[12] << 8) | buffer[13]; // _C7 MSB, LSB
+  _A  =  buffer[14];                    // _A 
+  _B  =  buffer[15];                    // _B 
+  _C  =  buffer[16];                    // _C 
+  _D  =  buffer[17];                    // _D               
+
+  _pres_base_x10 = PBASE_X10;
+  _temp_base_x10 = TBASE_X10;
+
+  // Execute Dummy reads after init()
+  sample();
+  sample();   
+}  
+
+/** Read ADC value (either pressure or temperature depending on Control Register setting)
+  *
+  * @return int   pressure or temperature 
+  */ 
+int HP03SA::_readADC (void) {
+    char buffer[2];
+
+    // Select ADC register
+    buffer[0] = 0xFD;                              // Register address for ADC
+    _i2c->write(HP03SA_BARO_SA, buffer, 1, true);  // Repeated Start
+    // Read ADC
+    _i2c->read(HP03SA_BARO_SA, buffer, 2);   
+
+    return ((buffer[0] << 8) | buffer[1]);         // MSB, LSB
+}
+
+/** Read Pressure and Temperature
+  *
+  * @return none 
+  */ 
+void HP03SA::_readTempPres(void) {
+    char buffer[2];    
+    
+    _xclr=1;   // ADC-XCLR
+    
+    // Read ADC with pressure value
+    buffer[0] = 0xFF;             // Control Register address  
+    buffer[1] = 0xF0;             // function = select + start-conversion PRES
+    _i2c->write(HP03SA_BARO_SA, buffer, 2);
+    wait_ms(40);                  // delay for ADC-conversion
+    _D1  = _readADC();
+
+    // Read ADC with temperature value
+    buffer[0] = 0xFF;             // Control Register address
+    buffer[1] = 0xE8;             // function = select + start-conversion TEMP
+    _i2c->write(HP03SA_BARO_SA, buffer, 2);
+    wait_ms(40);                  // delay for ADC-conversion
+    _D2  = _readADC();
+
+    _xclr=0;   // ADC-XCLR                 
+}
+
+/** Calculate Pressure and Temperature
+  *
+  * @return none 
+  */ 
+void HP03SA::_calcTempPres(void) {
+    long int _D2_C5;
+    int _corr;    
+
+    // Temperature and Pressure calculations from HP03S datasheet version 1.3
+    // with 2nd-order corrections using the parameters _A, _B, _C, _D
+    // Measured values are: _D1(pressure) and _D2(temperature)
+    // Correct offset-calculation (_off)
+
+    _D2_C5 = _D2 - _C5;
+    if (_D2_C5 >= 0) 
+        _corr = _A;     // _A
+    else
+        _corr = _B;     // _B
+
+    _dUT = _D2_C5 - ((_D2_C5 >> 7) * (_D2_C5 >> 7) * (_corr >> _C)); // _C
+
+//  _off = (   (_C4 - 1024) * _dUT / 16384 + _C2 ) * 4;
+//  _off = ((( (_C4 - 1024) * _dUT ) >> 14 ) + _C2 ) << 2;
+    _off = ((( (_C4 - 1024) * _dUT ) >> 14 ) + _C2 ) << 2;
+
+//  _sens = _C3 * _dUT / 1024 + _C1 ;
+    _sens = (( _C3 * _dUT ) >> 10 ) + _C1 ;   
+
+//  _x = (_D1 - 7168) * _sens / 16384 - _off;
+    _x = (((_D1 - 7168) * _sens ) >> 14 ) - _off;    
+
+//  _pres = x * 10 / 32 + _C7;
+    _pres_x10 = (( _x * 10 ) >> 5 ) + _C7;  // Pressure in hPa x 10
+
+//  _temp = _dUT * _C6 / 65536 + 250;
+    _temp_x10 = (( _dUT * _C6 ) >> 16 ) - (_dUT >> _D) + 250; // _D, Temp in Celsius x 10
+}
+
+
+/** Calculate Altitude
+  *
+  * @return none 
+  */ 
+void HP03SA::_calcAlt(void) {
+// Calculation based on ISA model
+// http://en.wikipedia.org/wiki/Atmospheric_pressure
+//
+//  h = (1 - pow((P/Pref), RL/gM)) * Tref / L
+//
+//    h     altitude above Mean Sea Level in m
+//    P     atmospheric pressure at altitude h
+//    Pref  sea level standard atmospheric pressure 101325 Pa
+//    L     temperature lapse rate, = g/cp for dry air  0.0065 K/m
+//    Tref  sea level standard temperature  288.15 K (= 15.0 + 273.15)
+//    g     Earth-surface gravitational acceleration    9.80665 m/s2
+//    M     molar mass of dry air   0.0289644 kg/mol
+//    R     universal gas constant  8.31447 J/(mol•K)
+//    RL/gM 0.19026674
+//    gM/RL 5.25578009f
+
+//ISA calculation  
+//  _alt = 44330.76923f * (1.0f - pow( ((float) _pres_x10 / _pres_base_x10), RLGM));
+  _alt = (TBASE_X10 / LBASE_X10) * (1.0f - pow( ((float) _pres_x10 / _pres_base_x10), RLGM));
+      
+//Correction for temperature
+//  _temp_base_x10 = TBASE_X10 - ( (float) _alt * LBASE_X10 );
+//  _temp_base_x10 = TBASE_X10;
+  
+  _alt = (float) _alt * ((float)_temp_x10 + 2731.5f) / _temp_base_x10; 
+}
+
+/** Get Pressure and Temperature sample
+  *
+  * @return none 
+  */ 
+void HP03SA::sample(void) {
+  _readTempPres();
+  _calcTempPres();
+  _calcAlt();  
+}    
+
+/** Get Absolute Atmospheric Pressure in hPa x 10
+  * Note: sample() must be called before getAtmPressure()  
+  * Checked using http://luchtdruk.com/luchtdruk-in-nederland.html
+  *
+  * @return int Pressure in hPa x 10 
+  */ 
+int HP03SA::getAbsPressure(void) {
+  return _pres_x10;
+}
+
+/** Get Sealevel Atmospheric Pressure in hPa x 10
+  * This produces pressure readings that can be used for weather measurements.
+  * Note: sample() must be called before getSeaPressure()  
+  *  
+  * @param  int alt_meter Altitude above Mean Sea Level where measurement is taken
+  * @return int Pressure at sea level in hPa x 10 
+  */ 
+int HP03SA::getSeaPressure(int alt_meter) {
+//    return ( (float) _pres_x10 / pow (1.0f - ((float) alt_meter / 44330.0), 5.255) );    
+    return ( (float) _pres_x10 / pow (1.0f - ((float) alt_meter * LBASE_X10 / TBASE_X10), GMRL) );
+}
+
+/** Get Temperature as int in °Celsius x 10
+  * Note: sample() must be called before getTemperature()  
+  *
+  * @return int Temperature in °Celsius x 10
+  */ 
+int HP03SA::getTemperatureInt(void) {
+  return _temp_x10;
+}
+
+/** Get Temperature as float in °Celsius
+  * Note: sample() must be called before getTemperature()  
+  *
+  * @return float Temperature in °Celsius
+  */ 
+float HP03SA::getTemperature(void) {
+  return (float) _temp_x10 / 10.0f;  
+}
+
+
+/** Convert Temperature from °Celsius into °Fahrenheit
+  *
+  * @param  float celsius in °Celsius  
+  * @return float temperature in °Fahrenheit
+  */ 
+float HP03SA::celsiusToFahrenheit(float celsius) {
+  
+  return ((celsius * 9.0f) / 5.0f) + 32.0f; // Convert to Fahrenheit
+}
+
+
+/** Get Altitude in meters using ISA
+  * Note: sample() must be called before getAltitude()  
+  *
+  * @return int Altitude in meters above Mean Sea Level (MSL)
+  */ 
+int HP03SA::getAltitude(void) {
+  return _alt;
+}
+
+/** Get Altitude in feet using ISA
+  * Note: sample() must be called before getAltitudeFt()  
+  *
+  * @return int Altitude in feet above Mean Sea Level (MSL)
+  */ 
+int HP03SA::getAltitudeFt() {
+  return (float)_alt * 3.28084f;
+}
+    
+/** Get Status
+  *
+  * @return bool Sensor ready 
+  */ 
+bool HP03SA::getStatus(void) {
+  char buffer[2];      
+  int status;
+    
+  _xclr=1;   // ADC-XCLR
+
+  // Read ADC with pressure value (dummy operation to check status)
+  buffer[0] = 0xFF;             // Control Register address  
+  status=_i2c->write(HP03SA_BARO_SA, buffer, 1);
+
+  _xclr=0;   // ADC-XCLR  
+ 
+  return (status==0);           // True when device found   
+}
+
+/** Set QNH Pressure to calibrate sensor
+  *
+  * @param int pressure_x10 at Mean Sea Level in hPa x 10
+  *            The getAltitude() reading will be 0 m for the set pressure.
+  */  
+void HP03SA::setPressure(int pressure_x10) {
+  _pres_base_x10 = (float) pressure_x10;
+}
+
+/** Set QNH Altitude in meter to calibrate sensor
+  *
+  * @param int alt_meter Altitude in meters above Mean Sea Level (MSL) for current pressure  
+  *            The getAltitude() reading will be 'alt_meter' m for the current pressure.  
+  */ 
+void HP03SA::setAltitude(int alt_meter) {
+    
+// Compute _temp_base derived from the temp at set altitude and temp lapse
+//  _temp_base_x10 = ((float) _temp_x10 + 2731.5f) + ((float) alt * LBASE_X10);    
+ 
+// Compute pressure at Mean Sea Level from the pressure at the set altitude
+  _pres_base_x10 = (float) _pres_x10 * pow( TBASE_X10 / (TBASE_X10 - ((float) alt_meter * LBASE_X10)), GMRL);
+}
+
+/** Set QNH Altitude in feet to calibrate sensor
+  *
+  * @param int alt_feet Altitude in meters above Mean Sea Level (MSL) for current pressure
+  *            The getAltitudeFt() reading will be 'alt_feet' ft for the current pressure.   
+  */ 
+void HP03SA::setAltitudeFt(int alt_feet){
+  setAltitude(alt_feet / 3.28084f);
+}
+
+