An example on how to read temperature, pressure and altitude from HP206C barometer sensor.

Dependencies:   mbed

Revision:
0:0a071ea90726
diff -r 000000000000 -r 0a071ea90726 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Aug 02 12:18:49 2017 +0000
@@ -0,0 +1,219 @@
+#include "mbed.h"
+
+#define HP20X_SOFT_RST        0x06
+#define HP20X_WR_CONVERT_CMD  0x40
+#define HP20X_CONVERT_OSR4096 0 << 2
+#define HP20X_CONVERT_OSR2048 1 << 2
+#define HP20X_CONVERT_OSR1024 2 << 2
+#define HP20X_CONVERT_OSR512  3 << 2
+#define HP20X_CONVERT_OSR256  4 << 2
+#define HP20X_CONVERT_OSR128  5 << 2
+
+#define HP20X_READ_P          0x30 // read_p command
+#define HP20X_READ_A          0x31 // read_a command
+#define HP20X_READ_T          0x32 // read_t command
+#define HP20X_READ_PT         0x10 // read_pt command
+#define HP20X_READ_AT         0x11 // read_at command
+#define HP20X_READ_CAL        0X28 // RE-CAL ANALOG
+
+#define HP20X_WR_REG_MODE 0xC0
+#define HP20X_RD_REG_MODE 0x80
+
+#define HP20X_ANA_CAL  0x28 // recalibrate analog internal circuitries
+
+#define HP20X_OK_DEV   0X80 // successfully initialized
+#define HP20X_REG_PARA 0X0F // status register
+
+#define I2C_BAROMETER_ADDRESS 0x76 << 1 // 0xEC
+
+#define OSR_CFG HP20X_CONVERT_OSR2048
+
+Serial serial(SERIAL_TX, SERIAL_RX);
+I2C i2c(I2C_SDA, I2C_SCL); // PB_9, PB_8
+
+float temperature = 0.0f;
+float pressure = 0.0f;
+float altitude = 0.0f;
+bool baro_found = false;
+
+typedef enum {
+    HP20X_READ_TEMP,
+    HP20X_READ_PRES
+} barometerReadingType;
+
+// send a register reading command
+unsigned char readRegister(unsigned char reg) {
+    char i2cBuffer[1];
+    i2cBuffer[0] = (reg | HP20X_RD_REG_MODE);
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+
+    // read the data
+    i2c.read(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+
+    return i2cBuffer[0];
+}
+
+// send a register writing command
+void writeRegister(unsigned char reg, unsigned char data) {
+    char i2cBuffer[1];
+    i2cBuffer[0] = (reg | HP20X_WR_REG_MODE);
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+    i2cBuffer[0] = data;
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+}
+
+void enableCompensation() {
+    writeRegister(HP20X_REG_PARA, 0x01);
+}
+
+void disableCompensation() {
+    writeRegister(HP20X_REG_PARA, 0x00);
+}
+
+void softReset() {
+    char i2cBuffer[1];
+    i2cBuffer[0] = HP20X_SOFT_RST;
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+}
+
+void recalibrate() {
+    char i2cBuffer[1];
+    i2cBuffer[0] = HP20X_ANA_CAL;
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+}
+
+uint32_t readData3Bytes() {
+    uint32_t tmpData;
+    char tmpArray[3] = {0};
+
+    // request 3 bytes from device
+    i2c.read(I2C_BAROMETER_ADDRESS, tmpArray, 3);
+
+    // MSB
+    tmpData = tmpArray[0] << 16 | tmpArray[1] << 8 | tmpArray[2];
+
+    if(tmpData & 0x800000) {
+        tmpData |= 0xff000000;
+    }
+
+    return tmpData;
+}
+
+uint32_t *readData6Bytes() {
+    static uint32_t tmpData[2];
+    char tmpArray[6] = {0};
+
+    // request 6 bytes from device
+    i2c.read(I2C_BAROMETER_ADDRESS, tmpArray, 6);
+
+    // MSB
+    tmpData[0] = tmpArray[0] << 16 | tmpArray[1] << 8 | tmpArray[2]; // temperature
+    tmpData[1] = tmpArray[3] << 16 | tmpArray[4] << 8 | tmpArray[5]; // pressure
+
+    if(tmpData[0] & 0x800000) {
+        tmpData[0] |= 0xff000000;
+    }
+    if(tmpData[1] & 0x800000) {
+        tmpData[1] |= 0xff000000;
+    }
+
+    return tmpData;
+}
+
+void readTemperatureAndPressureStep1() {
+    char i2cBuffer[2];
+    i2cBuffer[0] = HP20X_WR_CONVERT_CMD | OSR_CFG;
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1); // ADC convert
+}
+
+void readTemperatureAndPressureStep2() {
+    char i2cBuffer[1];
+
+    i2cBuffer[0] = HP20X_READ_PT;
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+
+    uint32_t *p = readData6Bytes();
+    temperature = ((double)p[0] / 100.0f);
+    pressure = ((double)p[1] / 100.0f);
+}
+
+void readAltitude() {
+    char i2cBuffer[1];
+    i2cBuffer[0] = HP20X_READ_A;
+    i2c.write(I2C_BAROMETER_ADDRESS, i2cBuffer, 1);
+
+    altitude = ((double)readData3Bytes() / 100.0f);
+}
+
+// calculate the conversion time needed before reading back the sensor values
+uint8_t getConversionTime(barometerReadingType type) {
+    uint32_t OSR_ConvertTime;
+    if (OSR_CFG == HP20X_CONVERT_OSR128) {
+        switch (type) {
+            case HP20X_READ_TEMP: OSR_ConvertTime = 3; break; // 2.1 ms
+            case HP20X_READ_PRES: OSR_ConvertTime = 5; break; // 4.1 ms
+        }
+    } else if (OSR_CFG == HP20X_CONVERT_OSR256) {
+        switch (type) {
+            case HP20X_READ_TEMP: OSR_ConvertTime = 5; break; // 4.1 ms
+            case HP20X_READ_PRES: OSR_ConvertTime = 9; break; // 8.2 ms
+        }
+    } else if (OSR_CFG == HP20X_CONVERT_OSR512) {
+        switch (type) {
+            case HP20X_READ_TEMP: OSR_ConvertTime = 9; break; // 8.2 ms
+            case HP20X_READ_PRES: OSR_ConvertTime = 17; break; // 16.4 ms
+        }
+    } else if (OSR_CFG == HP20X_CONVERT_OSR1024) {
+        switch (type) {
+            case HP20X_READ_TEMP: OSR_ConvertTime = 17; break; // 16.4 ms
+            case HP20X_READ_PRES: OSR_ConvertTime = 34; break; // 32.8 ms
+        }
+    } else if (OSR_CFG == HP20X_CONVERT_OSR2048) {
+        switch (type) {
+            case HP20X_READ_TEMP: OSR_ConvertTime = 34; break; // 32.8 ms
+            case HP20X_READ_PRES: OSR_ConvertTime = 67; break; // 65.6 ms
+        }
+    } else if (OSR_CFG == HP20X_CONVERT_OSR4096) {
+        switch (type) {
+            case HP20X_READ_TEMP: OSR_ConvertTime = 67; break; // 65.6 ms
+            case HP20X_READ_PRES: OSR_ConvertTime = 132; break; // 131.1 ms
+        }
+    }
+
+    return OSR_ConvertTime;
+}
+
+int main()
+{
+    serial.baud(115200);
+    i2c.frequency((uint32_t)100e3);
+
+    serial.printf("HP206C barometer example...\n");
+
+    // detect the barometer
+    unsigned char result = readRegister(HP20X_REG_PARA);
+    if (result == HP20X_OK_DEV) {
+        baro_found = true;
+        softReset();
+        disableCompensation();
+        serial.printf("barometer found\n");
+    } else {
+        serial.printf("barometer NOT found \n");
+        while(1);
+    }
+
+    while(1)
+    {
+        if (baro_found) {
+            recalibrate();
+            wait_us(70); // this delay is a must if we read temperature, pressure or altitude right after the recalibration (in tests, 60 didn't worked) in microseconds
+            readTemperatureAndPressureStep1();
+            wait_ms(getConversionTime(HP20X_READ_PRES)); // get only the pressure, because its the longest interval
+            readTemperatureAndPressureStep2();
+            readAltitude();
+
+            serial.printf("temperature %f, pressure %f, altitude %f\n", temperature, pressure, altitude);
+            wait_ms(100); // don't hammer the serial console
+        }
+    }
+}