High resolution barometer and altimeter using i2c mode
Dependents: upverter_fitbit_clone ReadingMag_HMC5883L_work
Diff: ms5611.cpp
- Revision:
- 2:05804ed70748
- Parent:
- 0:f97f410d4a21
- Child:
- 3:c2d1b0d432ad
--- a/ms5611.cpp Tue May 07 18:55:31 2013 +0000 +++ b/ms5611.cpp Thu May 09 16:34:52 2013 +0000 @@ -16,11 +16,15 @@ #include "mbed.h" #include "ms5611.h" +double P; // compensated pressure value +double T; // compensated temperature value + +uint32_t C[8]; //coefficient storage + //--------------------------------------------------------------------------------------------------------------------------------------// // Constructor and destructor ms5611::ms5611(PinName sda, PinName scl) : _i2c(sda, scl) { - } //******************************************************** @@ -91,10 +95,10 @@ void ms5611::m_i2c_send(char cmd) { unsigned char ret; - ret = m_i2c_start(false); // set device address and write mode - if(!(ret)) {//failed to issue start condition, possibly no device found */ + ret = m_i2c_start(false); + if(!(ret)) { m_i2c_stop(); - } else {// issuing start condition ok, device accessible + } else { ret = m_i2c_write(cmd); m_i2c_stop(); } @@ -107,8 +111,8 @@ //******************************************************** void ms5611::cmd_reset() { - m_i2c_send(MS5611_CMD_RESET); // send reset sequence - wait_ms(4); // wait for the reset sequence timing + m_i2c_send(MS5611_CMD_RESET); + wait_ms(4); loadCoefs(); } @@ -125,8 +129,8 @@ cobuf[2] = 0; unsigned int ret; unsigned long temp = 0; - m_i2c_send(MS5611_CMD_ADC_CONV + cmd); // send conversion command - switch (cmd & 0x0f) { // wait necessary conversion time + m_i2c_send(MS5611_CMD_ADC_CONV + cmd); + switch (cmd & 0x0f) { 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; @@ -167,14 +171,13 @@ //******************************************************** unsigned char ms5611::crc4(unsigned int n_prom[]) { - //int cnt; // simple counter - unsigned int n_rem; // crc reminder - unsigned int crc_read; // original value of the crc + unsigned int n_rem; + unsigned int crc_read; unsigned char n_bit; n_rem = 0x00; - crc_read = n_prom[7]; //save read CRC - n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0 - for (int cnt = 0; cnt < 16; cnt++) {// operation is performed on bytes // choose LSB or MSB + 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); } else { @@ -188,11 +191,11 @@ } } } - n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code -// printf("n_rem: %x crc_read: %x n_prom[7]: %x\n", n_rem, crc_read, n_prom[7]); - - n_prom[7]=crc_read; // restore the crc_read to its original place + n_rem= (0x000F & (n_rem >> 12)); + n_prom[7]=crc_read; return (n_rem ^ 0x0); +} + /* The CRC code is calculated and written in factory with the LSB byte in the prom n_prom[7] set to 0x00 (see Coefficient table below). It is thus important to clear those bytes from the calculation buffer before proceeding @@ -215,42 +218,32 @@ */ /* //Returns 0x0b as per AP520_004 - PTbuffer[0] = 0x3132; - PTbuffer[1] = 0x3334; - PTbuffer[2] = 0x3536; - PTbuffer[3] = 0x3738; - PTbuffer[4] = 0x3940; - PTbuffer[5] = 0x4142; - PTbuffer[6] = 0x4344; - PTbuffer[7] = 0x4546; + C[0] = 0x3132; + C[1] = 0x3334; + C[2] = 0x3536; + C[3] = 0x3738; + C[4] = 0x3940; + C[5] = 0x4142; + C[6] = 0x4344; + C[7] = 0x4546; n_crc = ms.crc4(C); // calculate the CRC pc.printf("testing CRC: 0x%x\n", n_crc); */ - -} + //******************************************************** //! @brief load all calibration coefficients //! //! @return none //******************************************************** -unsigned int PTbuffer[8]; // calibration coefficients - void ms5611::loadCoefs() { - // printf("Getting coefficients... "); for (int i = 0; i < 8; i++){ wait_ms(50); - PTbuffer[i] = cmd_prom(i); // read coefficients - // printf("0x%04x ", PTbuffer[i]); + C[i] = cmd_prom(i); } - // printf("\nCalculate CRC4: "); - unsigned char n_crc = crc4(PTbuffer); // calculate the CRC - // printf(" 0x%02x\n", n_crc); + unsigned char n_crc = crc4(C); } -double P; // compensated pressure value -double T; // compensated temperature value - //******************************************************** //! @brief calculate temperature and pressure //! @@ -258,23 +251,30 @@ //******************************************************** void ms5611::calcPT() { - unsigned long D2 = cmd_adc(MS5611_CMD_ADC_D2 + MS5611_CMD_ADC_4096); // read D2 - unsigned long D1 = cmd_adc(MS5611_CMD_ADC_D1 + MS5611_CMD_ADC_4096); // read D1 - // calculate 1st order pressure and temperature (MS5607 1st order algorithm) + 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 dT = D2 - ((uint32_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); + T = (2000 + (((uint64_t)dT * C[6]) / (float)(1 << 23))) / 100; + int32_t TEMP = 2000 + (int64_t)dT * (int64_t)C[6] / (int64_t)(1 << 23); - double dT = D2 - (PTbuffer[5] << 8); - //change OFF and SENS scaling factor for ms5611 - double OFF = (PTbuffer[2] << 16) + dT * PTbuffer[4] / (1 << 6); //was OFF = (PTbuffer[2] << 17) + dT * PTbuffer[4] / (1 << 6); - double SENS = (PTbuffer[1] << 15) + dT * PTbuffer[3] / (1 << 7); //was SENS = (PTbuffer[1] << 16) + dT * PTbuffer[3] / (1 << 7); - T = (2000 + (dT * PTbuffer[6]) / (1 << 23)) / 100; - P = (((D1*SENS) / (1 << 21) - OFF) / (1 << 15)) / 100; - -// dT = D2 - PTbuffer[5] * pow(2,8); -// OFF = PTbuffer[2] * pow(2,17) + dT * PTbuffer[4] / pow(2,6); -// SENS = PTbuffer[1] * pow(2,16) + dT * PTbuffer[3] / pow(2,7); -// T = (2000 + (dT * PTbuffer[6]) / pow(2,23)) / 100; -// P = (((D1*SENS) / pow(2,21) - OFF) / pow(2,15)) / 100; - // place to use P, T, put them on LCD, send them trough RS232 interface... + 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; + } + OFF -= OFF1; + SENS -= SENS1; + T = (float)TEMP / 100; + } +// int64_t P1 = ((((int64_t)D1 * SENS) >> 21) - OFF) >> 15; + P = ((((int64_t)D1 * SENS ) >> 21) - OFF) / (double) (1 << 15) / 100.0; } //******************************************************** @@ -297,4 +297,4 @@ double ms5611::calcPressure() { calcPT(); return(P); -} \ No newline at end of file +}