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.
Fork of MS5637 by
ms5637.cpp
00001 //! 00002 //! @file an520_I2C.c,v 00003 //! 00004 //! Copyright (c) 2009 MEAS Switzerland 00005 //! 00006 //! 00007 //! 00008 //! @brief This C code is for starter reference only. It is written for the 00009 //! MEAS Switzerland MS56xx pressure sensor modules and Atmel Atmega644p 00010 //! microcontroller. 00011 //! 00012 //! @version 1.0 $Id: an520_I2C.c,v 1.0 00013 //! 00014 //! @todo 00015 00016 #include "mbed.h" 00017 #include "ms5637.h" 00018 //Serial pc2(USBTX, USBRX); 00019 00020 double P; // compensated pressure value (mB) 00021 double T; // compensated temperature value (degC) 00022 double A; // altitude (ft) 00023 double S; // sea level barometer (mB) 00024 00025 uint32_t C[8]; //coefficient storage 00026 00027 //--------------------------------------------------------------------------------------------------------------------------------------// 00028 // Constructor and destructor 00029 00030 ms5637::ms5637(PinName sda, PinName scl) : _i2c(sda, scl) { 00031 _i2c.frequency(400000); 00032 } 00033 00034 //******************************************************** 00035 //! @brief send I2C start condition and the address byte 00036 //! 00037 //! @return 0 00038 //******************************************************** 00039 00040 int ms5637::m_i2c_start(bool readMode) { 00041 int twst; 00042 _i2c.start(); 00043 if(readMode == true) { 00044 twst = m_i2c_write(MS5637_ADDR_R); 00045 } else { 00046 twst = m_i2c_write(MS5637_ADDR_W); 00047 } 00048 return(twst); 00049 } 00050 00051 //******************************************************** 00052 //! @brief send I2C stop condition 00053 //! 00054 //! @return none 00055 //******************************************************** 00056 00057 void ms5637::m_i2c_stop(void) { 00058 _i2c.stop(); 00059 } 00060 00061 //******************************************************** 00062 //! @brief send I2C stop condition 00063 //! 00064 //! @return remote ack status 00065 //******************************************************** 00066 00067 unsigned char ms5637::m_i2c_write(unsigned char data) { 00068 int twst = _i2c.write(data); 00069 return(twst); 00070 } 00071 00072 //******************************************************** 00073 //! @brief read I2C byte with acknowledgment 00074 //! 00075 //! @return read byte 00076 //******************************************************** 00077 00078 unsigned char ms5637::m_i2c_readAck(void) { 00079 int twst = _i2c.read(1); 00080 return(twst); 00081 } 00082 00083 //******************************************************** 00084 //! @brief read I2C byte without acknowledgment 00085 //! 00086 //! @return read byte 00087 //******************************************************** 00088 00089 unsigned char ms5637::m_i2c_readNak(void) { 00090 int twst = _i2c.read(0); 00091 return(twst); 00092 } 00093 00094 //******************************************************** 00095 //! @brief send command using I2C hardware interface 00096 //! 00097 //! @return none 00098 //******************************************************** 00099 00100 void ms5637::m_i2c_send(char cmd) { 00101 unsigned char ret; 00102 ret = m_i2c_start(false); 00103 if(!(ret)) { 00104 m_i2c_stop(); 00105 } else { 00106 ret = m_i2c_write(cmd); 00107 m_i2c_stop(); 00108 } 00109 } 00110 00111 //******************************************************** 00112 //! @brief send reset sequence 00113 //! 00114 //! @return none 00115 //******************************************************** 00116 00117 void ms5637::cmd_reset() { 00118 m_i2c_send(MS5637_CMD_RESET); 00119 wait_ms(4); 00120 loadCoefs(); 00121 } 00122 00123 //******************************************************** 00124 //! @brief preform adc conversion 00125 //! 00126 //! @return 24bit result 00127 //******************************************************** 00128 00129 unsigned long ms5637::cmd_adc(char cmd) { 00130 char cobuf[3]; 00131 cobuf[0] = 0; 00132 cobuf[1] = 0; 00133 cobuf[2] = 0; 00134 unsigned int ret; 00135 unsigned long temp = 0; 00136 m_i2c_send(MS5637_CMD_ADC_CONV + cmd); 00137 switch (cmd & 0x0f) { 00138 case MS5637_CMD_ADC_256 : wait_us(900); break; 00139 case MS5637_CMD_ADC_512 : wait_ms(3); break; 00140 case MS5637_CMD_ADC_1024: wait_ms(4); break; 00141 case MS5637_CMD_ADC_2048: wait_ms(6); break; 00142 case MS5637_CMD_ADC_4096: wait_ms(10); break; 00143 } 00144 m_i2c_send(MS5637_CMD_ADC_READ); 00145 00146 ret = _i2c.read(MS5637_ADDR_R, cobuf, 3, false); 00147 if(ret) printf("\n*** ms5637 ADC Read Error "); 00148 temp = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2]; 00149 return temp; 00150 } 00151 00152 //******************************************************** 00153 //! @brief Read calibration coefficients 00154 //! 00155 //! @return coefficient 00156 //******************************************************** 00157 00158 unsigned int ms5637::cmd_prom(char coef_num) { 00159 char cobuf[2]; 00160 unsigned int ret; 00161 unsigned int rC = 0; 00162 cobuf[0] = 0; 00163 cobuf[1] = 0; 00164 m_i2c_send(MS5637_CMD_PROM_RD + coef_num * 2); // send PROM READ command 00165 ret = _i2c.read(MS5637_ADDR_R, cobuf, 2, false); 00166 if(ret) printf("\n*** ms5637 PROM Read Error "); 00167 rC = cobuf[0] * 256 + cobuf[1]; 00168 return rC; 00169 } 00170 00171 //******************************************************** 00172 //! @brief calculate the CRC code 00173 //! 00174 //! @return crc code 00175 //******************************************************** 00176 00177 unsigned char ms5637::crc4(unsigned int n_prom[]) { 00178 unsigned int n_rem; 00179 unsigned int crc_read; 00180 unsigned char n_bit; 00181 n_rem = 0x00; 00182 crc_read = n_prom[7]; 00183 n_prom[7]=(0xFF00 & (n_prom[7])); 00184 for (int cnt = 0; cnt < 16; cnt++) { 00185 if (cnt%2 == 1) { 00186 n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF); 00187 } else { 00188 n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8); 00189 } 00190 for (n_bit = 8; n_bit > 0; n_bit--) { 00191 if (n_rem & (0x8000)) { 00192 n_rem = (n_rem << 1) ^ 0x3000; 00193 } else { 00194 n_rem = (n_rem << 1); 00195 } 00196 } 00197 } 00198 n_rem= (0x000F & (n_rem >> 12)); 00199 n_prom[7]=crc_read; 00200 return (n_rem ^ 0x0); 00201 } 00202 00203 /* 00204 The CRC code is calculated and written in factory with the LSB byte in the prom n_prom[7] set to 0x00 (see 00205 Coefficient table below). It is thus important to clear those bytes from the calculation buffer before proceeding 00206 with the CRC calculation itself: 00207 n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0 00208 As a simple test of the CRC code, the following coefficient table could be used: 00209 unsigned int nprom[] = {0x3132,0x3334,0x3536,0x3738,0x3940,0x4142,0x4344,0x4500}; 00210 the resulting calculated CRC should be 0xB. 00211 00212 DB 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 00213 Addr 00214 0 16 bit reserved for manufacturer 00215 1 Coefficient 1 (16 bit unsigned) 00216 2 Coefficient 2 (16 bit unsigned) 00217 3 Coefficient 3 (16 bit unsigned) 00218 4 Coefficient 4 (16 bit unsigned) 00219 5 Coefficient 5 (16 bit unsigned) 00220 6 Coefficient 6 (16 bit unsigned) 00221 7 0 0 0 0 CRC(0x0) 00222 */ 00223 /* 00224 //Returns 0x0b as per AP520_004 00225 C[0] = 0x3132; 00226 C[1] = 0x3334; 00227 C[2] = 0x3536; 00228 C[3] = 0x3738; 00229 C[4] = 0x3940; 00230 C[5] = 0x4142; 00231 C[6] = 0x4344; 00232 C[7] = 0x4546; 00233 n_crc = ms.crc4(C); // calculate the CRC 00234 pc.printf("testing CRC: 0x%x\n", n_crc); 00235 */ 00236 00237 //******************************************************** 00238 //! @brief load all calibration coefficients 00239 //! 00240 //! @return none 00241 //******************************************************** 00242 00243 void ms5637::loadCoefs() { 00244 for (int i = 0; i < 8; i++){ 00245 wait_ms(50); 00246 C[i] = cmd_prom(i); 00247 } 00248 unsigned char n_crc = crc4(C); 00249 } 00250 00251 //******************************************************** 00252 //! @brief calculate temperature and pressure 00253 //! 00254 //! @return none 00255 //******************************************************** 00256 00257 void ms5637::calcPT() { 00258 int32_t D2 = cmd_adc(MS5637_CMD_ADC_D2 + MS5637_CMD_ADC_4096); // read D2 00259 int32_t D1 = cmd_adc(MS5637_CMD_ADC_D1 + MS5637_CMD_ADC_4096); // read D1 00260 00261 float dT = (float)D2 - ((float)C[5] * 256.0); 00262 float TEMP = 2000.0 + (dT*(float)C[6])/8388608.0; 00263 00264 float OFF = ((float)C[2] * 131072.0 + (dT * (float)C[4])/64.0); 00265 float SENS = ((float)C[1] * 65536.0)+ ((dT * ((float)C[3]) /128.0)); 00266 00267 // Commented out serial pc2 at start of code so you can check raw values 00268 //pc2.printf("D1: %d\r\nD2: %d\r\nC1: %d\r\nC2: %d\r\nC3: %d\r\nC4: %d\r\nC5: %d\r\nC6: %d\r\n", D1, D2, C[1], C[2], C[3], C[4], C[5], C[6]); 00269 //pc2.printf("OFF: %f\r\nSENS: %f\r\n",OFF, SENS); 00270 00271 if(TEMP < 2000) { // if temperature lower than 20 Celsius 00272 float T1 = (TEMP - 2000.0) * (TEMP - 2000.0); 00273 float OFF1 = (61.0 * T1) / 16.0; 00274 float SENS1 = (29.0 * T1) / 16.0; 00275 00276 if(TEMP < -1500) { // if temperature lower than -15 Celsius 00277 T1 = (TEMP + 1500.0) * (TEMP + 1500.0); 00278 OFF1 += 17.0 * T1; 00279 SENS1 += 9.0 * T1 ; 00280 } 00281 OFF -= OFF1; 00282 SENS -= SENS1; 00283 } 00284 T = TEMP / 100.0; 00285 P = ((D1*(SENS / 2097152.0)-OFF)/32768.0)/100.0; 00286 } 00287 00288 //******************************************************** 00289 //! @brief calculate temperature 00290 //! 00291 //! @return double temperature degC 00292 //******************************************************** 00293 00294 double ms5637::calcTemp() { 00295 calcPT(); 00296 return(T); 00297 } 00298 00299 //******************************************************** 00300 //! @brief calculate pressure 00301 //! 00302 //! @return double barometric pressure millibar 00303 //******************************************************** 00304 00305 double ms5637::calcPressure() { 00306 calcPT(); 00307 return(P); 00308 } 00309 00310 //******************************************************** 00311 //! @brief get pressure, no calculation 00312 //! 00313 //! @return double barometric pressure millibar 00314 //******************************************************** 00315 00316 double ms5637::getPressure() { 00317 calcPT(); 00318 return(P); 00319 } 00320 00321 //******************************************************** 00322 //! @brief get altitude from known sea level barometer, 00323 //! @ no pre-pressure calculation 00324 //! 00325 //! @enter float sea level barometer 00326 //! @return float altitude in feet 00327 //******************************************************** 00328 00329 float ms5637::getAltitudeFT(float sea_pressure) { 00330 A = (1 - (pow((P / (double)sea_pressure), 0.190284))) * 145366.45; 00331 return((float)A); 00332 } 00333 00334 //******************************************************** 00335 //! @brief get sea level pressure from known altitude(ft), 00336 //! @ no pre-pressure calculation 00337 //! 00338 //! @enter float known altitude in feet 00339 //! @return float seal level barometer in mb 00340 //******************************************************** 00341 00342 float ms5637::getSeaLevelBaroFT(float known_alt) { 00343 S = pow(pow((P * INHG), 0.190284) + 0.00001313 * known_alt , 5.2553026) * MB; 00344 return((float)S); 00345 } 00346 00347 //******************************************************** 00348 //! @brief get sea level pressure from known altitude(m), 00349 //! @ no pre-pressure calculation 00350 //! 00351 //! @enter float known altitude in meters 00352 //! @return float seal level barometer in mb 00353 //******************************************************** 00354 00355 float ms5637::getSeaLevelBaroM(float known_alt) { 00356 S = pow(pow((P * INHG), 0.190284) + 0.00001313 * known_alt * FTMETERS , 5.2553026) * MB; 00357 return((float)S); 00358 }
Generated on Tue Jul 12 2022 21:47:37 by
1.7.2
