Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
HP03SA.cpp
00001 /* mbed HP03SA Library, for an I2C Pressure and Temperature sensor which provides derived Altitude values 00002 * Copyright (c) 2015, v01: WH, Initial version, ported in part from Elektor weatherstation (Sept 2011), Author: W. Waetzig 00003 * See http://www.elektor-labs.com/project/usb-long-term-weather-logger-100888.12037.html 00004 * Code also based on several other public sources: 00005 * See http://en.wikipedia.org/wiki/Atmospheric_pressure 00006 * See https://learn.sparkfun.com/tutorials/bmp180-barometric-pressure-sensor-hookup-?_ga=1.94307604.888266135.1310146152 00007 * 00008 * 00009 * Permission is hereby granted, free of charge, to any person obtaining a copy 00010 * of this software and associated documentation files (the "Software"), to deal 00011 * in the Software without restriction, including without limitation the rights 00012 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 * copies of the Software, and to permit persons to whom the Software is 00014 * furnished to do so, subject to the following conditions: 00015 * 00016 * The above copyright notice and this permission notice shall be included in 00017 * all copies or substantial portions of the Software. 00018 * 00019 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 * THE SOFTWARE. 00026 */ 00027 00028 #include "mbed.h" 00029 #include "HP03SA.h" 00030 00031 /** Create an HP03SA interface for mbed pins 00032 * 00033 * @param i2c I2C Bus 00034 * @param XCLR Clock enable control line 00035 */ 00036 HP03SA::HP03SA(I2C *i2c, PinName XCLR) : _i2c(i2c), _xclr(XCLR) { 00037 00038 _init(); 00039 } 00040 00041 /** Init the HP03SA 00042 * 00043 */ 00044 void HP03SA::_init() { 00045 char buffer[18]; 00046 00047 //HP03S initialization 00048 00049 _xclr=0; //XCLR low for coefficients readout 00050 00051 // Select C1 register 00052 buffer[0] = 0x10; // Register address for _C1 MSB is 0x10 00053 _i2c->write(HP03SA_EEPROM_SA, buffer, 1, true); // Repeated Start 00054 // Read calibration parameters 00055 _i2c->read(HP03SA_EEPROM_SA, buffer, 18); 00056 00057 _C1 = (buffer[0] << 8) | buffer[1]; // _C1 MSB, LSB 00058 _C2 = (buffer[2] << 8) | buffer[3]; // _C2 MSB, LSB 00059 _C3 = (buffer[4] << 8) | buffer[5]; // _C3 MSB, LSB 00060 _C4 = (buffer[6] << 8) | buffer[7]; // _C4 MSB, LSB 00061 _C5 = (buffer[8] << 8) | buffer[9]; // _C5 MSB, LSB 00062 _C6 = (buffer[10] << 8) | buffer[11]; // _C6 MSB, LSB 00063 _C7 = (buffer[12] << 8) | buffer[13]; // _C7 MSB, LSB 00064 _A = buffer[14]; // _A 00065 _B = buffer[15]; // _B 00066 _C = buffer[16]; // _C 00067 _D = buffer[17]; // _D 00068 00069 _pres_base_x10 = PBASE_X10; 00070 _temp_base_x10 = TBASE_X10; 00071 00072 // Execute Dummy reads after init() 00073 sample(); 00074 sample(); 00075 } 00076 00077 /** Read ADC value (either pressure or temperature depending on Control Register setting) 00078 * 00079 * @return int pressure or temperature 00080 */ 00081 int HP03SA::_readADC (void) { 00082 char buffer[2]; 00083 00084 // Select ADC register 00085 buffer[0] = 0xFD; // Register address for ADC 00086 _i2c->write(HP03SA_BARO_SA, buffer, 1, true); // Repeated Start 00087 // Read ADC 00088 _i2c->read(HP03SA_BARO_SA, buffer, 2); 00089 00090 return ((buffer[0] << 8) | buffer[1]); // MSB, LSB 00091 } 00092 00093 /** Read Pressure and Temperature 00094 * 00095 * @return none 00096 */ 00097 void HP03SA::_readTempPres(void) { 00098 char buffer[2]; 00099 00100 _xclr=1; // ADC-XCLR 00101 00102 // Read ADC with pressure value 00103 buffer[0] = 0xFF; // Control Register address 00104 buffer[1] = 0xF0; // function = select + start-conversion PRES 00105 _i2c->write(HP03SA_BARO_SA, buffer, 2); 00106 wait_ms(40); // delay for ADC-conversion 00107 _D1 = _readADC(); 00108 00109 // Read ADC with temperature value 00110 buffer[0] = 0xFF; // Control Register address 00111 buffer[1] = 0xE8; // function = select + start-conversion TEMP 00112 _i2c->write(HP03SA_BARO_SA, buffer, 2); 00113 wait_ms(40); // delay for ADC-conversion 00114 _D2 = _readADC(); 00115 00116 _xclr=0; // ADC-XCLR 00117 } 00118 00119 /** Calculate Pressure and Temperature 00120 * 00121 * @return none 00122 */ 00123 void HP03SA::_calcTempPres(void) { 00124 long int _D2_C5; 00125 int _corr; 00126 00127 // Temperature and Pressure calculations from HP03S datasheet version 1.3 00128 // with 2nd-order corrections using the parameters _A, _B, _C, _D 00129 // Measured values are: _D1(pressure) and _D2(temperature) 00130 // Correct offset-calculation (_off) 00131 00132 _D2_C5 = _D2 - _C5; 00133 if (_D2_C5 >= 0) 00134 _corr = _A; // _A 00135 else 00136 _corr = _B; // _B 00137 00138 _dUT = _D2_C5 - ((_D2_C5 >> 7) * (_D2_C5 >> 7) * (_corr >> _C)); // _C 00139 00140 // _off = ( (_C4 - 1024) * _dUT / 16384 + _C2 ) * 4; 00141 // _off = ((( (_C4 - 1024) * _dUT ) >> 14 ) + _C2 ) << 2; 00142 _off = ((( (_C4 - 1024) * _dUT ) >> 14 ) + _C2 ) << 2; 00143 00144 // _sens = _C3 * _dUT / 1024 + _C1 ; 00145 _sens = (( _C3 * _dUT ) >> 10 ) + _C1 ; 00146 00147 // _x = (_D1 - 7168) * _sens / 16384 - _off; 00148 _x = (((_D1 - 7168) * _sens ) >> 14 ) - _off; 00149 00150 // _pres = x * 10 / 32 + _C7; 00151 _pres_x10 = (( _x * 10 ) >> 5 ) + _C7; // Pressure in hPa x 10 00152 00153 // _temp = _dUT * _C6 / 65536 + 250; 00154 _temp_x10 = (( _dUT * _C6 ) >> 16 ) - (_dUT >> _D) + 250; // _D, Temp in Celsius x 10 00155 } 00156 00157 00158 /** Calculate Altitude 00159 * 00160 * @return none 00161 */ 00162 void HP03SA::_calcAlt(void) { 00163 // Calculation based on ISA model 00164 // http://en.wikipedia.org/wiki/Atmospheric_pressure 00165 // 00166 // h = (1 - pow((P/Pref), RL/gM)) * Tref / L 00167 // 00168 // h altitude above Mean Sea Level in m 00169 // P atmospheric pressure at altitude h 00170 // Pref sea level standard atmospheric pressure 101325 Pa 00171 // L temperature lapse rate, = g/cp for dry air 0.0065 K/m 00172 // Tref sea level standard temperature 288.15 K (= 15.0 + 273.15) 00173 // g Earth-surface gravitational acceleration 9.80665 m/s2 00174 // M molar mass of dry air 0.0289644 kg/mol 00175 // R universal gas constant 8.31447 J/(mol•K) 00176 // RL/gM 0.19026674 00177 // gM/RL 5.25578009f 00178 00179 //ISA calculation 00180 // _alt = 44330.76923f * (1.0f - pow( ((float) _pres_x10 / _pres_base_x10), RLGM)); 00181 _alt = (TBASE_X10 / LBASE_X10) * (1.0f - pow( ((float) _pres_x10 / _pres_base_x10), RLGM)); 00182 00183 //Correction for temperature 00184 // _temp_base_x10 = TBASE_X10 - ( (float) _alt * LBASE_X10 ); 00185 // _temp_base_x10 = TBASE_X10; 00186 00187 _alt = (float) _alt * ((float)_temp_x10 + 2731.5f) / _temp_base_x10; 00188 } 00189 00190 /** Get Pressure and Temperature sample 00191 * 00192 * @return none 00193 */ 00194 void HP03SA::sample(void) { 00195 _readTempPres(); 00196 _calcTempPres(); 00197 _calcAlt(); 00198 } 00199 00200 /** Get Absolute Atmospheric Pressure in hPa x 10 00201 * Note: sample() must be called before getAtmPressure() 00202 * Checked using http://luchtdruk.com/luchtdruk-in-nederland.html 00203 * 00204 * @return int Pressure in hPa x 10 00205 */ 00206 int HP03SA::getAbsPressure(void) { 00207 return _pres_x10; 00208 } 00209 00210 /** Get Sealevel Atmospheric Pressure in hPa x 10 00211 * This produces pressure readings that can be used for weather measurements. 00212 * Note: sample() must be called before getSeaPressure() 00213 * 00214 * @param int alt_meter Altitude above Mean Sea Level where measurement is taken 00215 * @return int Pressure at sea level in hPa x 10 00216 */ 00217 int HP03SA::getSeaPressure(int alt_meter) { 00218 // return ( (float) _pres_x10 / pow (1.0f - ((float) alt_meter / 44330.0), 5.255) ); 00219 return ( (float) _pres_x10 / pow (1.0f - ((float) alt_meter * LBASE_X10 / TBASE_X10), GMRL) ); 00220 } 00221 00222 /** Get Temperature as int in °Celsius x 10 00223 * Note: sample() must be called before getTemperature() 00224 * 00225 * @return int Temperature in °Celsius x 10 00226 */ 00227 int HP03SA::getTemperatureInt(void) { 00228 return _temp_x10; 00229 } 00230 00231 /** Get Temperature as float in °Celsius 00232 * Note: sample() must be called before getTemperature() 00233 * 00234 * @return float Temperature in °Celsius 00235 */ 00236 float HP03SA::getTemperature(void) { 00237 return (float) _temp_x10 / 10.0f; 00238 } 00239 00240 00241 /** Convert Temperature from °Celsius into °Fahrenheit 00242 * 00243 * @param float celsius in °Celsius 00244 * @return float temperature in °Fahrenheit 00245 */ 00246 float HP03SA::celsiusToFahrenheit(float celsius) { 00247 00248 return ((celsius * 9.0f) / 5.0f) + 32.0f; // Convert to Fahrenheit 00249 } 00250 00251 00252 /** Get Altitude in meters using ISA 00253 * Note: sample() must be called before getAltitude() 00254 * 00255 * @return int Altitude in meters above Mean Sea Level (MSL) 00256 */ 00257 int HP03SA::getAltitude(void) { 00258 return _alt; 00259 } 00260 00261 /** Get Altitude in feet using ISA 00262 * Note: sample() must be called before getAltitudeFt() 00263 * 00264 * @return int Altitude in feet above Mean Sea Level (MSL) 00265 */ 00266 int HP03SA::getAltitudeFt() { 00267 return (float)_alt * 3.28084f; 00268 } 00269 00270 /** Get Status 00271 * 00272 * @return bool Sensor ready 00273 */ 00274 bool HP03SA::getStatus(void) { 00275 char buffer[2]; 00276 int status; 00277 00278 _xclr=1; // ADC-XCLR 00279 00280 // Read ADC with pressure value (dummy operation to check status) 00281 buffer[0] = 0xFF; // Control Register address 00282 status=_i2c->write(HP03SA_BARO_SA, buffer, 1); 00283 00284 _xclr=0; // ADC-XCLR 00285 00286 return (status==0); // True when device found 00287 } 00288 00289 /** Set QNH Pressure to calibrate sensor 00290 * 00291 * @param int pressure_x10 at Mean Sea Level in hPa x 10 00292 * The getAltitude() reading will be 0 m for the set pressure. 00293 */ 00294 void HP03SA::setPressure(int pressure_x10) { 00295 _pres_base_x10 = (float) pressure_x10; 00296 } 00297 00298 /** Set QNH Altitude in meter to calibrate sensor 00299 * 00300 * @param int alt_meter Altitude in meters above Mean Sea Level (MSL) for current pressure 00301 * The getAltitude() reading will be 'alt_meter' m for the current pressure. 00302 */ 00303 void HP03SA::setAltitude(int alt_meter) { 00304 00305 // Compute _temp_base derived from the temp at set altitude and temp lapse 00306 // _temp_base_x10 = ((float) _temp_x10 + 2731.5f) + ((float) alt * LBASE_X10); 00307 00308 // Compute pressure at Mean Sea Level from the pressure at the set altitude 00309 _pres_base_x10 = (float) _pres_x10 * pow( TBASE_X10 / (TBASE_X10 - ((float) alt_meter * LBASE_X10)), GMRL); 00310 } 00311 00312 /** Set QNH Altitude in feet to calibrate sensor 00313 * 00314 * @param int alt_feet Altitude in meters above Mean Sea Level (MSL) for current pressure 00315 * The getAltitudeFt() reading will be 'alt_feet' ft for the current pressure. 00316 */ 00317 void HP03SA::setAltitudeFt(int alt_feet){ 00318 setAltitude(alt_feet / 3.28084f); 00319 } 00320 00321
Generated on Wed Jul 13 2022 10:14:21 by
1.7.2
HP03SA pressure sensor and altimeter