High resolution barometer and altimeter using i2c mode
Dependents: upverter_fitbit_clone ReadingMag_HMC5883L_work
Revision 9:6104e8cdb3ec, committed 2015-07-14
- Comitter:
- loopsva
- Date:
- Tue Jul 14 16:19:59 2015 +0000
- Parent:
- 8:461f68bc94f2
- Commit message:
- Fixed minor bugs when using low-level I2C routines. Hi-level I2C routines ok. Also added hooks for the MS5805 (untested).
Changed in this revision
ms5611.cpp | Show annotated file Show diff for this revision Revisions of this file |
ms5611.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/ms5611.cpp Tue Apr 28 23:36:22 2015 +0000 +++ b/ms5611.cpp Tue Jul 14 16:19:59 2015 +0000 @@ -22,6 +22,7 @@ double S; // sea level barometer (mB) uint32_t C[8]; //coefficient storage +int MStype = 0; //--------------------------------------------------------------------------------------------------------------------------------------// // Constructor and destructor - default to be compatible with legacy m5611 driver @@ -39,7 +40,8 @@ _i2c.frequency(400000); _i2cWAddr = MS5611_ADDR_W; _i2cRAddr = MS5611_ADDR_R; - if(CSBpin == CSBpin_1) { + MStype = CSBpin; + if((CSBpin == CSBpin_1) || (CSBpin == MS5805)) { _i2cWAddr -= 2; _i2cRAddr -= 2; @@ -112,7 +114,7 @@ //! @return none //******************************************************** -void ms5611::m_i2c_send(char cmd) { +int ms5611::m_i2c_send(char cmd) { unsigned char ret; ret = m_i2c_start(false); if(!(ret)) { @@ -121,6 +123,7 @@ ret = m_i2c_write(cmd); m_i2c_stop(); } + return(ret); } //******************************************************** @@ -129,16 +132,29 @@ //! @return none //******************************************************** -void ms5611::cmd_reset() { +int ms5611::cmd_reset() { #if defined MS5611i2cLOWLEVEL - m_i2c_send(MS5611_CMD_RESET); + int ret = m_i2c_send(MS5611_CMD_RESET); + if(!(ret)) return(ret); #else char cobuf[1]; cobuf[0] = MS5611_CMD_RESET; - _i2c.write(_i2cWAddr, cobuf, 1, false); + int ret = _i2c.write(_i2cWAddr, cobuf, 1, false); + if((ret)) return(0); #endif + +#ifdef RTOS_H + Thread::wait(4); +#else wait_ms(4); +#endif + loadCoefs(); +#if defined MS5611i2cLOWLEVEL + return(ret); +#else + return(1); +#endif } //******************************************************** @@ -148,33 +164,47 @@ //******************************************************** unsigned long ms5611::cmd_adc(char cmd) { - char cobuf[3]; - cobuf[0] = 0; - cobuf[1] = 0; - cobuf[2] = 0; - unsigned int ret; + char cobuf[3] = {0, 0, 0}; unsigned long temp = 0; #if defined MS5611i2cLOWLEVEL - m_i2c_send(MS5611_CMD_ADC_CONV + cmd); + m_i2c_start(false); + m_i2c_write(MS5611_CMD_ADC_CONV + cmd); + m_i2c_stop(); #else cobuf[0] = MS5611_CMD_ADC_CONV + cmd; _i2c.write(_i2cWAddr, cobuf, 1, false); #endif switch (cmd & 0x0f) { +#ifdef RTOS_H + case MS5611_CMD_ADC_256 : Thread::wait(1); break; + case MS5611_CMD_ADC_512 : Thread::wait(3); break; + case MS5611_CMD_ADC_1024: Thread::wait(4); break; + case MS5611_CMD_ADC_2048: Thread::wait(6); break; + case MS5611_CMD_ADC_4096: Thread::wait(10); break; + case MS5805_CMD_ADC_8192: Thread::wait(19); break; +#else case MS5611_CMD_ADC_256 : wait_us(900); break; case MS5611_CMD_ADC_512 : wait_ms(3); break; case MS5611_CMD_ADC_1024: wait_ms(4); break; case MS5611_CMD_ADC_2048: wait_ms(6); break; case MS5611_CMD_ADC_4096: wait_ms(10); break; + case MS5805_CMD_ADC_8192: wait_ms(19); break; +#endif } #if defined MS5611i2cLOWLEVEL - m_i2c_send(MS5611_CMD_ADC_READ); + m_i2c_start(false); + m_i2c_write(MS5611_CMD_ADC_READ); + m_i2c_start(true); + cobuf[0] = m_i2c_readAck(); + cobuf[1] = m_i2c_readAck(); + cobuf[2] = m_i2c_readNak(); + m_i2c_stop(); #else cobuf[0] = MS5611_CMD_ADC_READ; _i2c.write(_i2cWAddr, cobuf, 1, true); cobuf[0] = 0; + _i2c.read(_i2cRAddr, cobuf, 3, false); #endif - ret = _i2c.read(_i2cRAddr, cobuf, 3, false); //if(ret) printf("\n*** ms5611 ADC Read Error "); temp = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2]; return temp; @@ -187,19 +217,21 @@ //******************************************************** unsigned int ms5611::cmd_prom(char coef_num) { - char cobuf[2]; - unsigned int ret; + char cobuf[2] = {0, 0}; unsigned int rC = 0; - cobuf[0] = 0; - cobuf[1] = 0; #if defined MS5611i2cLOWLEVEL - m_i2c_send(MS5611_CMD_PROM_RD + coef_num * 2); // send PROM READ command + m_i2c_start(false); + m_i2c_write(MS5611_CMD_PROM_RD + coef_num * 2);// send PROM READ command + m_i2c_start(true); + cobuf[0] = m_i2c_readAck(); + cobuf[1] = m_i2c_readNak(); + m_i2c_stop(); #else cobuf[0] = MS5611_CMD_PROM_RD + coef_num * 2; _i2c.write(_i2cWAddr, cobuf, 1, true); cobuf[0] = 0; + _i2c.read(_i2cRAddr, cobuf, 2, false); #endif - ret = _i2c.read(_i2cRAddr, cobuf, 2, false); //if(ret) printf("\n*** ms5611 PROM Read Error "); rC = cobuf[0] * 256 + cobuf[1]; return rC; @@ -212,12 +244,16 @@ //******************************************************** unsigned char ms5611::crc4(unsigned int n_prom[]) { - unsigned int n_rem; - unsigned int crc_read; - unsigned char n_bit; - n_rem = 0x00; - crc_read = n_prom[7]; - n_prom[7]=(0xFF00 & (n_prom[7])); + unsigned int n_rem = 0; + unsigned int crc_read = 0; + unsigned char n_bit = 0; + if(MStype == ms5611::MS5805) { + n_prom[0] = (n_prom[0] & 0x0FFF); + n_prom[7] = 0; + } else { + crc_read = n_prom[7]; + n_prom[7]=(0xFF00 & (n_prom[7])); + } for (int cnt = 0; cnt < 16; cnt++) { if (cnt%2 == 1) { n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF); @@ -232,8 +268,10 @@ } } } - n_rem= (0x000F & (n_rem >> 12)); - n_prom[7]=crc_read; + n_rem= ((n_rem >> 12) & 0x000F); + if(!(MStype == ms5611::MS5805)) { + n_prom[7]=crc_read; + } return (n_rem ^ 0x0); } @@ -295,8 +333,16 @@ //******************************************************** void ms5611::calcPT() { - int32_t D2 = cmd_adc(MS5611_CMD_ADC_D2 + MS5611_CMD_ADC_4096); // read D2 - int32_t D1 = cmd_adc(MS5611_CMD_ADC_D1 + MS5611_CMD_ADC_4096); // read D1 + int32_t D1 = 0; + int32_t D2 = 0; + if(MStype == ms5611::MS5805) { + D2 = cmd_adc(MS5611_CMD_ADC_D2 + MS5805_CMD_ADC_8192); // read D2 + D1 = cmd_adc(MS5611_CMD_ADC_D1 + MS5805_CMD_ADC_8192); // read D1 + } else { + D2 = cmd_adc(MS5611_CMD_ADC_D2 + MS5611_CMD_ADC_4096); // read D2 + D1 = cmd_adc(MS5611_CMD_ADC_D1 + MS5611_CMD_ADC_4096); // read D1 + } + int64_t dT = D2 - ((uint64_t)C[5] << 8); int64_t OFF = ((uint32_t)C[2] << 16) + ((dT * (C[4]) >> 7)); //was OFF = (C[2] << 17) + dT * C[4] / (1 << 6); int64_t SENS = ((uint32_t)C[1] << 15) + ((dT * (C[3]) >> 8)); //was SENS = (C[1] << 16) + dT * C[3] / (1 << 7); @@ -304,18 +350,26 @@ int32_t TEMP = 2000 + (int64_t)dT * (int64_t)C[6] / (int64_t)(1 << 23); if(TEMP < 2000) { // if temperature lower than 20 Celsius - float T1 = (TEMP - 2000) * (TEMP - 2000); - int64_t OFF1 = (5 * T1) / 2; - int64_t SENS1 = (5 * T1) / 4; - - if(TEMP < -1500) { // if temperature lower than -15 Celsius - T1 = (TEMP + 1500) * (TEMP + 1500); - OFF1 += 7 * T1; - SENS1 += 11 * T1 / 2; - } + float T1 = 0.0; + int64_t OFF1, SENS1 = 0; + if(MStype == ms5611::MS5805) { + T1 = 11 * ((dT * dT) >> 35); + OFF1 = 31 * ((TEMP - 2000) * (TEMP - 2000)) >> 3; + SENS1 = 63 * ((TEMP - 2000) * (TEMP - 2000)) >> 5; + } else { + T1 = (TEMP - 2000) * (TEMP - 2000); + OFF1 = (5 * T1) / 2; + SENS1 = (5 * T1) / 4; + + if(TEMP < -1500) { // if temperature lower than -15 Celsius + T1 = (TEMP + 1500) * (TEMP + 1500); + OFF1 += 7 * T1; + SENS1 += 11 * T1 / 2; + } + } OFF -= OFF1; SENS -= SENS1; - T = (float)TEMP / 100; + T = ((double)TEMP - T1)/ 100.0; } // int64_t P1 = ((((int64_t)D1 * SENS) >> 21) - OFF) >> 15; P = ((((int64_t)D1 * SENS ) >> 21) - OFF) / (double) (1 << 15) / 100.0; @@ -376,7 +430,7 @@ //******************************************************** float ms5611::getSeaLevelBaroFT(float known_alt) { - S = pow(pow((P * INHG), 0.190284) + 0.00001313 * known_alt , 5.2553026) * MB; + S = pow(pow((P * MB_INHG_DOUBLE), 0.190284) + 0.00001313 * known_alt , 5.2553026) * INHG_MB_DOUBLE; return((float)S); } @@ -389,6 +443,7 @@ //******************************************************** float ms5611::getSeaLevelBaroM(float known_alt) { - S = pow(pow((P * INHG), 0.190284) + 0.00001313 * known_alt * FTMETERS , 5.2553026) * MB; + S = pow(pow((P * MB_INHG_DOUBLE), 0.190284) + 0.00001313 * known_alt * FEET_METERS , 5.2553026) * INHG_MB_DOUBLE; return((float)S); } +
--- a/ms5611.h Tue Apr 28 23:36:22 2015 +0000 +++ b/ms5611.h Tue Jul 14 16:19:59 2015 +0000 @@ -3,18 +3,20 @@ #include "mbed.h" -#if(defined(TARGET_KL25Z) )//|| defined(TARGET_K64F)) +//IMPORTANT NOTE: First attempt at also using the MS5805. This code is untested!! + +// #define MS5611i2cLOWLEVEL 1 //if the use of low-level I2C routines is needed +// #warning "MS5611 using low level I2C routines" +// IMPORTANT NOTE: On the K64F, "ack/nack", returns from single byte i2c.write(int data) are opposite +// of i2c.write(int address, const char *data, int length, bool repeated=false) - #define MS5611i2cLOWLEVEL 1 //if the use of low-level I2C routines is needed - #warning "MS5611 using low level I2C routines" - -#endif - -#define SEA_PRESS 1013.25 //default sea level pressure level in mb -#define KNOWNALT 327.0 //default known altitude, 5200 Franklin Dr., 94588 -#define INHG 0.02952998751 //convert mb to in/Hg constant -#define MB 33.8638815 //convert in/Hg to mb constant -#define FTMETERS 0.3048 //convert feet to meters +#define SEA_PRESS 1013.25 //default sea level pressure level in mb +#define KNOWNALT 327.0 //default known altitude, 5200 Franklin Dr., 94588 +#define DEGC_DEGF_FLOAT 9.0 / 5.0 + 32.0//convert degrees C to degrees F +#define METERS_FEET 3.2808399 //convert meters to feet +#define FEET_METERS 0.3048006 //convert feet to meters +#define MB_INHG_DOUBLE 0.02952998751 //convert millibars to inches_of_mercury +#define INHG_MB_DOUBLE 33.8638815767 //convert inches_of_mercury to millibars /** Software routines to access the Measurement Specialties' MS5611-01BA03 @@ -46,34 +48,40 @@ * @code * #include "mbed.h" * #include "ms5611.h" - * - * //ms5611 ms(p9, p10); // i2c pins used - * ms5611 ms(p9, p10, ms5611::CSBpin_0); // NEW!! with rev 7. User can set polarity of CSB pin - * //ms5611 ms(p9, p10, ms5611::CSBpin_1); - * - * Serial pc(USBTX, USBRX); // local terminal interface - * - * + * + * #define SDA PTE25 + * #define SCL PTE24 + * + * //ms5611 ms(SDA, SCL); // i2c pins used, legacy default constructor + * ms5611 ms(SDA, SCL, ms5611::CSBpin_0); // NEW!! with rev 7. User can set polarity of CSB pin + * //ms5611 ms(SDA, SCL, ms5611::CSBpin_1); + * //ms5611 ms(SDA, SCL, ms5611::MS5805); // NEW!! with rev 8. Allow use of MS5805 as well + * + * Serial pc(USBTX, USBRX); // local terminal interface + * * int main (void) { - * pc.baud(921600); // set up USB serial speed - * + * pc.baud(230400); // set up USB serial speed + * * // set up the ms5611 - * pc.printf("\n\nInitializing the MS5611..\n"); - * ms.cmd_reset(); + * pc.printf("\n\nInitializing the MS5611..\r\n"); + * int msFlag = ms.cmd_reset(); + * if(!(msFlag)) { + * pc.printf("MS5611 I2C error!!\r\n"); + * return(-1); + * } * pc.printf("Ready\n"); - * + * * while(1) { * double Temp = ms.calcTemp(); //calculate press and temp, then returns current temperature in degC * double Press = ms.calcPressure(); //calculate press and temp, then returns current pressure in mb * double GetPress = ms.getPressure(); //returns current pressure in mb. Does no calculations. Ususally done after calcTemp() * double Altitude = ms.getAltitudeFT(1013.25); //enter pressure at sea level in mb, returns altitude in feet * double PressSeaLvlFT = ms.getSeaLevelBaroFT(327.2); //enter known altitude in feet, returns sea level pressure in mb - * double PressSeaLvlM = ms.getAltitudeFT(99.73); //enter known altitude in meters, returns seal level pressure in mb - * - * pc.printf("Temp: %.2f degC\n", Temp); - * pc.printf("Barometer: %.1f mB %.3f in/Hg\n", Press, Press * 0.0295301); - * pc.printf("Alt: %.1f ft\n", Altitude); - * pc.printf("Sea_Lvl: %.1f ft %.2f m\n", PressSeaLvlFT, PressSeaLvlM); + * + * pc.printf("Temp: %6.2f degC %6.2f degF\r\n", Temp, Temp * 9.0 / 5.0 + 32.0); + * pc.printf("Barometer: %7.2f mB %8.3f in/Hg\r\n", Press, Press * MB_INHG_DOUBLE); + * pc.printf("Sea_Lvl: %7.2f mB %8.3f in/Hg\r\n", PressSeaLvlFT, PressSeaLvlFT * MB_INHG_DOUBLE); + * pc.printf("Alt: %7.2f m %7.2f ft\r\n\r\n", Altitude, Altitude * FEET_METERS); * wait(2.0); * } * } @@ -83,19 +91,20 @@ //_____ M A C R O S -#define MS5611_ADDR_W 0xEE // Module address write mode (CSBpin = 0); -#define MS5611_ADDR_R 0xEF // Module address read mode -#define MS5611_CMD_RESET 0x1E // ADC reset command -#define MS5611_CMD_ADC_READ 0x00 // ADC read command -#define MS5611_CMD_ADC_CONV 0x40 // ADC conversion command -#define MS5611_CMD_ADC_D1 0x00 // ADC D1 conversion -#define MS5611_CMD_ADC_D2 0x10 // ADC D2 conversion -#define MS5611_CMD_ADC_256 0x00 // ADC OSR=256 -#define MS5611_CMD_ADC_512 0x02 // ADC OSR=512 -#define MS5611_CMD_ADC_1024 0x04 // ADC OSR=1024 -#define MS5611_CMD_ADC_2048 0x06 // ADC OSR=2048 -#define MS5611_CMD_ADC_4096 0x08 // ADC OSR=4096 -#define MS5611_CMD_PROM_RD 0xA0 // Prom read command +#define MS5611_ADDR_W 0xEE // Module address write mode (CSBpin = 0); +#define MS5611_ADDR_R 0xEF // Module address read mode +#define MS5611_CMD_RESET 0x1E // ADC reset command +#define MS5611_CMD_ADC_READ 0x00 // ADC read command +#define MS5611_CMD_ADC_CONV 0x40 // ADC conversion command +#define MS5611_CMD_ADC_D1 0x00 // ADC D1 conversion +#define MS5611_CMD_ADC_D2 0x10 // ADC D2 conversion +#define MS5611_CMD_ADC_256 0x00 // ADC OSR=256 +#define MS5611_CMD_ADC_512 0x02 // ADC OSR=512 +#define MS5611_CMD_ADC_1024 0x04 // ADC OSR=1024 +#define MS5611_CMD_ADC_2048 0x06 // ADC OSR=2048 +#define MS5611_CMD_ADC_4096 0x08 // ADC OSR=4096 +#define MS5805_CMD_ADC_8192 0x0A // ADC OSR=8192 +#define MS5611_CMD_PROM_RD 0xA0 // Prom read command /** Create ms5611 controller class * @@ -106,16 +115,20 @@ public: enum CSBpolarity { - CSBpin_0, //CSB pin is grounded, I2C address is 0xEE and 0xEF - CSBpin_1, //CSB pin is tied to Vdd, I2C address is 0xEC and 0xED + CSBpin_0, //CSB pin is grounded, I2C address is 0xEE and 0xEF + CSBpin_1, //CSB pin is tied to Vdd, I2C address is 0xEC and 0xED + MS5805, //MS5805 fixed at 0EC and 0xED }; + /** Create a MS5611 object using the specified I2C object * - User fixed I2C address 0xEE, CSB pin = 0 * - This is the default legacy constructor * @param sda - mbed I2C interface pin * @param scl - mbed I2C interface pin + * @return NONE */ ms5611(PinName sda, PinName scl); + /** Create a MS5611 object using the specified I2C object * - User defined use of the CSB pin * - CSB pin = 0, user set I2C address to 0xEE @@ -124,53 +137,56 @@ * @param scl - mbed I2C interface pin * @param ms5611::CSBpin_0 - CSB pin tied to ground * @param ms5611::CSBpin_1 - CSB pin tied to VDD + * @param ms5611::MS5805 - MS5805 has only one i2c address + * @return NONE */ ms5611(PinName sda, PinName scl, CSBpolarity CSBpin); + /** Initialize the MS5611 and set up the coefficients - * First - reset the MS5611 - * Second - load coefficient values from the MS5611 PROM - * Third - calculate coefficient checksum - * This routine only needs to be run once at boot up - * + * - First - reset the MS5611 + * - Second - load coefficient values from the MS5611 PROM + * - Third - calculate coefficient checksum + * - This routine only needs to be run once at boot up * @param NONE + * @return int I2C ack/nack status */ - void cmd_reset(); - /** Calculate and return compensated temperature - * Returns double temperature in degC - * + int cmd_reset(); + + /** Calculates compensated temperature * @param NONE + * @return double temperature in degC */ double calcTemp(); - /** Calculate and return compensated barometric pressure - * Returns double pressure in millibars - * + + /** Calculates compensated barometric pressure * @param NONE + * @return double pressure in millibars */ double calcPressure(); - /** Return compensated barometric pressure - * Returns double pressure in millibars - * DOES NOT RE-CALCULATE FIRST!!! - * Saves time if you calcTemp(); first - * + + /** Get compensated barometric pressure + * - DOES NOT RE-CALCULATE FIRST!!! + * - Result only valid if you calcTemp(); first * @param NONE + * @eturn double pressure in millibars */ double getPressure(); - /** Calculate and returns altitude in feet - * Returns float altitude in feet - * + + /** Calculates altitude in feet * @param float known pressure (mB) at sea level + * @return float altitude in feet */ float getAltitudeFT(float sea_pressure); - /** Calculate and returns sea level baro - * Returns float seal level barometer in feet - * + + /** Calculates sea level baro * @param float known altitude in feet + * @return float sea level barometer in feet */ float getSeaLevelBaroFT(float known_alt); - /** Calculate and returns sea level baro - * Returns float seal level barometer in meters - * + + /** Calculates sea level baro * @param float known altitude in meters + * @return float sea level barometer in meters */ float getSeaLevelBaroM(float known_alt); @@ -178,11 +194,12 @@ char _i2cWAddr; char _i2cRAddr; int m_i2c_start(bool readMode); + int MStype; void m_i2c_stop(void); unsigned char m_i2c_write(unsigned char data); unsigned char m_i2c_readAck(void); unsigned char m_i2c_readNak(void); - void m_i2c_send(char cmd); + int m_i2c_send(char cmd); void loadCoefs(); unsigned long cmd_adc(char cmd); unsigned int cmd_prom(char coef_num);