Sergii Doroshenko / MS5611_01BA03

Files at this revision

API Documentation at this revision

Comitter:
eseerge
Date:
Thu Jan 03 17:12:03 2013 +0000
Commit message:
Initial revision for ms5611_01ba03 baro

Changed in this revision

MS5611_01BA03.cpp Show annotated file Show diff for this revision Revisions of this file
MS5611_01BA03.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MS5611_01BA03.cpp	Thu Jan 03 17:12:03 2013 +0000
@@ -0,0 +1,256 @@
+/**
+ * @author Sergii Doroshenko
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2010 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * MS5611_01BA03 Barometric Pressure Sensor, Variometer.
+ *
+ * Datasheet:
+ *
+ * http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
+ */
+ 
+#include "MS5611_01BA03.h"
+
+extern Serial pc;
+
+uint8_t MS5611_01BA03::baro_read_reg(char reg)
+{
+    uint8_t byte;
+   
+    ENABLE_BARO;
+    spi_.write(reg);
+    byte = spi_.write(0x00);
+    DISABLE_BARO;
+
+    return byte;
+}
+
+void MS5611_01BA03::baro_write_reg(uint8_t reg, uint8_t val)
+{
+    ENABLE_BARO;
+    spi_.write(reg);
+    spi_.write(val);
+    DISABLE_BARO;
+}
+
+void MS5611_01BA03::ms5611_01ba_reset() {
+    ENABLE_BARO;
+    spi_.write(MS561101BA_RESET);
+    wait(0.03);
+    DISABLE_BARO;
+}
+
+static bool ms5611_01ba_crc(uint16_t* n_prom) {
+    uint8_t cnt;                            // simple counter  
+    uint16_t n_rem;                         // crc reminder 
+    uint8_t crc_read;                       // original value of the crc 
+    uint8_t  n_bit; 
+
+    n_rem = 0x00; 
+    crc_read = n_prom[7] & 0xF;             //save read CRC 
+    n_prom[7]=(0xFFF0 & (n_prom[7]));       //CRC byte is replaced by 0 - 0xFF00 // but 4 bit CRC!!!!!!
+    for (cnt = 0; cnt < 16; cnt++) {        // operation is performed on bytes 
+        // choose LSB or MSB 
+        if (cnt % 2 == 1) 
+            n_rem ^= (uint16_t)((n_prom[cnt>>1]) & 0x00FF); 
+        else 
+            n_rem ^= (uint16_t) (n_prom[cnt>>1]>>8); 
+            
+        for (n_bit = 8; n_bit > 0; n_bit--) { 
+            if (n_rem & (0x8000)) { 
+                n_rem = (n_rem << 1) ^ 0x3000; 
+            } 
+            else { 
+                n_rem = (n_rem << 1); 
+            } 
+        } 
+    } 
+
+    n_rem = (0x000F & (n_rem >> 12));   // final 4-bit reminder is CRC code 
+    n_prom[7] = crc_read;               // restore the crc_read to its original place 
+
+    return (crc_read == (n_rem ^ 0x00)) ;
+}
+
+static bool ms5611_01ba_crc2(uint16_t prom[]) {
+    int32_t i, j;
+    uint32_t res = 0;
+    uint8_t crc = prom[7] & 0xF;
+    prom[7] &= 0xFFF0;
+
+    for (i = 0; i < 16; i++) {
+        if (i & 1) 
+            res ^= ((prom[i>>1]) & 0x00FF);
+        else 
+            res ^= (prom[i>>1]>>8);
+
+        for (j = 8; j > 0; j--) {
+            if (res & 0x8000) res ^= 0x1800;
+            res <<= 1;
+        }
+    }
+    prom[7] |= crc;
+
+    return (crc == ((res >> 12) & 0xF)); 
+}
+
+void MS5611_01BA03::ms5611_01ba_readCalibration() {
+    union { uint16_t val; uint8_t raw[2]; } data;
+    uint8_t i;
+
+    //read first prom settings
+    for(i=0;i<8;i++) {
+        ENABLE_BARO;
+        spi_.write(0xA0+2*i);
+        data.raw[1] = spi_.write(0x0);  // read a 16 bit register
+        data.raw[0] = spi_.write(0x0);
+        ms5611_01ba_ctx.c[i] = data.val;
+        DISABLE_BARO;
+        wait(0.01);
+    }
+}
+
+bool MS5611_01BA03::init() {
+    ms5611_01ba_reset();
+    ms5611_01ba_readCalibration();
+    wait(0.5);
+    return true; //ms5611_01ba_crc(ms5611_01ba_ctx.c); 
+}
+ 
+// read uncompensated temperature value: send command first
+void MS5611_01BA03::ms5611_01ba_UT_Start() {
+    ENABLE_BARO;
+    spi_.write(MS561101BA_TEMPERATURE + OSR);
+    DISABLE_BARO;
+} 
+
+// read uncompensated pressure value: send command first
+void MS5611_01BA03::ms5611_01ba_UP_Start() {
+    ENABLE_BARO;
+    spi_.write(MS561101BA_PRESSURE + OSR);
+    DISABLE_BARO;
+}
+
+// read uncompensated pressure value: read result bytes
+void MS5611_01BA03::ms5611_01ba_UP_Read() {
+    ENABLE_BARO;
+    spi_.write(0x0);
+    ms5611_01ba_ctx.up.raw[2] = spi_.write(0x0);
+    ms5611_01ba_ctx.up.raw[1] = spi_.write(0x0);
+    ms5611_01ba_ctx.up.raw[0] = spi_.write(0x0);
+    DISABLE_BARO;
+}
+
+// read uncompensated temperature value: read result bytes
+void MS5611_01BA03::ms5611_01ba_UT_Read() {
+    ENABLE_BARO;
+    spi_.write(0x0);
+    ms5611_01ba_ctx.ut.raw[2] = spi_.write(0x0);
+    ms5611_01ba_ctx.ut.raw[1] = spi_.write(0x0);
+    ms5611_01ba_ctx.ut.raw[0] = spi_.write(0x0);
+    DISABLE_BARO;
+}
+
+void MS5611_01BA03::ms5611_01ba_Calculate() {
+    int32_t temperature, off2 = 0, sens2 = 0, delt;
+
+    int32_t dT   = ms5611_01ba_ctx.ut.val - ((uint32_t)ms5611_01ba_ctx.c[5] << 8);
+    int64_t off  = ((uint32_t)ms5611_01ba_ctx.c[2] << 16) + (((int64_t)dT * ms5611_01ba_ctx.c[4]) >> 7);
+    int64_t sens = ((uint32_t)ms5611_01ba_ctx.c[1] << 15) + (((int64_t)dT * ms5611_01ba_ctx.c[3]) >> 8);
+    temperature  = 2000 + (((int64_t)dT * ms5611_01ba_ctx.c[6]) >> 23);
+
+    if (temperature < 2000) { // temperature lower than 20st.C 
+        delt = temperature - 2000;
+        delt  = delt * delt;
+        off2  = (5 * delt) >> 1; 
+        sens2 = (5 * delt) >> 2; 
+        if (temperature < -1500) { // temperature lower than -15st.C
+            delt = temperature + 1500;
+            delt = delt * delt;
+            off2 += 7 * delt; 
+            sens2 += (11 * delt) >> 1; 
+        }
+    } 
+    off  -= off2; 
+    sens -= sens2;
+    pressure = (( (ms5611_01ba_ctx.up.val * sens ) >> 21) - off) >> 15;
+}
+
+MS5611_01BA03::MS5611_01BA03(PinName mosi, PinName miso, PinName sclk, PinName cs): spi_(mosi, miso, sclk) { 
+
+    cs_ = new DigitalOut(cs);
+
+    spi_.format(8,3);
+    spi_.frequency(1000000); // default 1000000
+    
+    timer.start();
+    
+    altitude = 0;
+}
+
+MS5611_01BA03::~MS5611_01BA03() {
+    timer.stop();
+    delete(cs_);
+    cs_ = NULL;
+}
+
+void MS5611_01BA03::ms5611_01ba_Update() {
+    if (timer.read_us() < ms5611_01ba_ctx.deadline) return; 
+    ms5611_01ba_ctx.deadline = timer.read_us();
+    switch (ms5611_01ba_ctx.state) {
+        case 0: 
+            ms5611_01ba_UT_Start(); 
+            ms5611_01ba_ctx.state++; 
+            ms5611_01ba_ctx.deadline += 10000; //according to the specs, the pause should be at least 8.22ms
+            break;
+        case 1: 
+            ms5611_01ba_UT_Read(); 
+            ms5611_01ba_ctx.state++;
+            break;
+        case 2: 
+            ms5611_01ba_UP_Start(); 
+            ms5611_01ba_ctx.state++; 
+            ms5611_01ba_ctx.deadline += 10000; //according to the specs, the pause should be at least 8.22ms
+            break;
+        case 3: 
+            ms5611_01ba_UP_Read();
+            ms5611_01ba_Calculate();
+            altitude = (1.0f - pow((float)pressure/101325.0f, 0.190295f)) * 4433000.0f; //centimeter
+     
+            ms5611_01ba_ctx.state = 0; 
+            ms5611_01ba_ctx.deadline += 4000;
+        break;
+    } 
+}
+
+int32_t MS5611_01BA03::getPressure() {
+    return pressure;
+}
+
+int32_t MS5611_01BA03::getAltitude() {
+    ms5611_01ba_Update();
+    return altitude;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MS5611_01BA03.h	Thu Jan 03 17:12:03 2013 +0000
@@ -0,0 +1,123 @@
+/**
+ * @author Sergii Doroshenko
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2010 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * MS5611_01BA03 Barometric Pressure Sensor, Variometer.
+ *
+ * Datasheet:
+ *
+ * http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
+ */
+ 
+#ifndef MS5611_01BA03_SPI_H
+#define MS5611_01BA03_SPI_H
+
+/**
+ * Includes
+ */
+#include "mbed.h"
+
+/**
+ * Defines
+ */
+#define ENABLE_BARO *cs_ = 0
+#define DISABLE_BARO *cs_ = 1
+
+/**
+ * Registers
+ */
+#define MS561101BA_PRESSURE     0x40
+#define MS561101BA_TEMPERATURE  0x50
+#define MS561101BA_RESET        0x1E
+
+/**
+ * OSR (Over Sampling Ratio) constants
+ */
+#define MS561101BA_OSR_256      0x00
+#define MS561101BA_OSR_512      0x02
+#define MS561101BA_OSR_1024     0x04
+#define MS561101BA_OSR_2048     0x06
+#define MS561101BA_OSR_4096     0x08
+
+#define OSR MS561101BA_OSR_4096 
+
+
+
+class MS5611_01BA03 {
+
+public:
+
+    /**
+     * Constructor.
+     *
+     * Send reset sequence at first
+     *
+     * @param mosi - mbed pin to use for the MOSI/SDI spi line.
+     * @param miso - mbed pin to use for the MISO/SDO spi line.
+     * @param sclk - mbed pin to use for the SCL/SCLK  spi line.
+     * @param cs - mbed pin to use for the CS spi line. (for sensor, not for mbed spi)
+     */
+    MS5611_01BA03(PinName mosi, PinName miso, PinName sclk, PinName cs);
+    ~MS5611_01BA03();
+    bool init();
+    int32_t getPressure();
+    int32_t getAltitude();
+    
+private:
+
+    // sensor registers from the MS561101BA datasheet
+    struct {
+        uint16_t c[8];
+        union {uint32_t val; uint8_t raw[4]; } ut; //uncompensated T
+        union {uint32_t val; uint8_t raw[4]; } up; //uncompensated P
+        uint8_t  state;
+        uint32_t deadline;
+    } ms5611_01ba_ctx;
+
+    uint8_t baro_read_reg(char reg);
+    void baro_write_reg(uint8_t reg, uint8_t val);
+    
+    void ms5611_01ba_reset();
+    void ms5611_01ba_readCalibration();
+    
+    
+    void ms5611_01ba_UT_Start();
+    void ms5611_01ba_UT_Read();
+    
+    void ms5611_01ba_UP_Start();
+    void ms5611_01ba_UP_Read();
+    
+    void ms5611_01ba_Calculate();
+    void ms5611_01ba_Update();
+    
+    SPI spi_;   
+    DigitalOut * cs_;
+    Timer timer;
+    int32_t  pressure;
+    int32_t  altitude;
+};
+    
+#endif // MS5611_01BA03_SPI_H
\ No newline at end of file