Lib for HP03SA atmospheric pressure sensor. Provides pressure, temperature and altitude data.
HP03SA.cpp
- Committer:
- wim
- Date:
- 2015-01-10
- Revision:
- 0:61bbd81782de
File content as of revision 0:61bbd81782de:
/* 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); }