altb_pmic / Mbed 2 deprecated Grove-Barometric_Pressure_Sensor_Example

Dependencies:   HP206C mbed

main.cpp

Committer:
pmic
Date:
2019-06-25
Revision:
1:a6eded1f5043
Parent:
0:5119eeafd9ce
Child:
2:ecd5c6118888

File content as of revision 1:a6eded1f5043:

#include "mbed.h"

#define I2C_BAROMETER_ADDRESS 0x76 << 1 // 0xEC, device adress

#define HP20X_SOFT_RST        0x06 // for initializing, takes longer than next
#define HP20X_ANA_CAL         0x28 // recalibrate analog internal circuitries, for unstable environment

#define HP20X_WR_CONVERT_CMD  0x40

#define HP20X_READ_PT         0x10 // read pressure and altitude command
#define HP20X_READ_A          0x31 // read altitude command

#define HP20X_WR_REG_MODE     0xC0
#define HP20X_RD_REG_MODE     0x80

#define HP20X_OK_DEV          0X80 // successfully initialized
#define HP20X_REG_PARA        0X0F // status register

#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 OSR_CFG HP20X_CONVERT_OSR1024

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();
        // recalibrate();
        disableCompensation();
        // enableCompensation();
        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\r\n", temperature, pressure, altitude);
            serial.printf("altitude %f\r\n", altitude);
            // wait_ms(1); // don't hammer the serial console
        }
    }
}