High resolution barometer and altimeter using i2c mode

Dependents:   Q2_Stabi

Fork of ms5611 by Kevin Braun

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
+}