#ifndef __BMP280_H__ #define __BMP280_H__ #include #include #include #include "hal.h" class BMP280 { private: static const uint8_t ADDR0 = 0x76; // possible I2C addresses static const uint8_t ADDR1 = 0x77; static const uint8_t REG_CALIB = 0x88; // calibration register: static const uint8_t REG_ID = 0xD0; // ID register: always reads 0x58 static const uint8_t REG_RESET = 0xE0; // write 0xB6 to perform soft-reset static const uint8_t REG_STATUS = 0xF3; // status: ____C__I C=conversion in progress static const uint8_t REG_CTRL = 0xF4; // control: TTTPPPMM TTT=temp. oversampling, PPP=pressure oversampling, MM=power mode static const uint8_t REG_CONFIG = 0xF5; // config: TTTFFF_S TTT=? FFF=Filter S=3-wire SPI static const uint8_t REG_PRESS = 0xF7; // Pressure result: static const uint8_t REG_PRESS_MSB = 0xF7; // Pressure result: MSB static const uint8_t REG_PRESS_LSB = 0xF8; // Pressure result: LSB static const uint8_t REG_PRESS_XLSB = 0xF9; // Pressure result: more LSB static const uint8_t REG_TEMP_ = 0xFA; // Temperature result: static const uint8_t REG_TEMP_MSB = 0xFA; // Temperature result: MSB static const uint8_t REG_TEMP_LSB = 0xFB; // Temperature result: LSB static const uint8_t REG_TEMP_XLSB = 0xFC; // Temperature result: more LSB public: uint8_t Bus; // which I2C bus uint8_t ADDR; // detected I2C address uint8_t ID; // 0x58 for BMP280, 0x60 for BME280 private: union { int16_t Calib[13]; struct { uint16_t T1; // 13 temperature/pressure calibration values from EEPROM int16_t T2, T3; uint16_t P1; int16_t P2, P3, P4, P5, P6, P7, P8, P9; int16_t D; } ; } ; public: uint8_t Error; // error on the I2C bus (0=no error) int32_t RawTemp; // raw temperature - to be processed int32_t FineTemp; // for pressure calc. int16_t Temperature; // [0.1 degC] after processing int32_t RawPress; // raw pressure - to be processed uint32_t Pressure; // [0.25Pa ] after processing // uint16_t RawHum; // raw humidity - to be processed // int32_t Humidity; // [0.1 %] relative humidity after processing public: void DefaultCalib(void) // set default calibration constants { T1 = 27504; T2 = 26435; T3 = -1000; P1 = 36477; P2 = -10685; P3 = 3024; P4 = 2855; P5 = 140; P6 = -7; P7 = 15500; P8 = -14600; P9 = 6000; D = 0; } uint8_t CheckID(void) // check ID, to make sure the BMP280 is connected and works correctly // if it finds a BME280 it will use it without the humidity part { ADDR=0; Error=I2C_Read(Bus, ADDR0, REG_ID, ID); if( (!Error) && ( (ID==0x58) || (ID==0x60) ) ) { ADDR=ADDR0; return 0; } Error=I2C_Read(Bus, ADDR1, REG_ID, ID); if( (!Error) && ( (ID==0x58) || (ID==0x60) ) ) { ADDR=ADDR1; return 0; } return 1; } // 0 => no error and correct ID uint8_t hasHumidity(void) const { return ID==0x60; } // is this BME280 ? Can still be used as BMP280 uint8_t ReadCalib(void) // read the calibration constants from the EEPROM { Error=I2C_Read(Bus, ADDR, REG_CALIB, (uint8_t *)Calib, 2*13); return Error; } uint8_t ReadReady(void) // check if temperature and pressure conversion is done { uint8_t Status; Error=I2C_Read(Bus, ADDR, REG_STATUS, Status); if(Error) return Error; return (Status&0x09)==0; } // 1 = ready, 0 => busy uint8_t WaitReady(uint8_t Timeout=50, uint8_t Wait=30) // wait for the conversion to be ready { vTaskDelay(Wait); for(; Timeout; Timeout--) { uint8_t Err=ReadReady(); if(Err) return Err; // 1 is ready, >1 is an I2C bus error vTaskDelay(1); } return 0xFF; } // return "timeout" error uint8_t Trigger(void) // start a temperature+pressure measurement { uint8_t Data=0x00; Error=I2C_Write(Bus, ADDR, REG_CONFIG, Data); if(Error) return Error; Data=0x55; Error=I2C_Write(Bus, ADDR, REG_CTRL, Data); return Error; } // P.osp=16x, T.osp=2x uint8_t ReadRawPress(void) // read raw pressure ADC conversion result { RawPress=0; Error=I2C_Read(Bus, ADDR, REG_PRESS, (uint8_t *)(&RawPress), 3); if(Error) return Error; RawPress = ((RawPress<<16)&0xFF0000) | (RawPress&0x00FF00) | ((RawPress>>16)&0x0000FF); RawPress>>=4; return 0; } uint8_t ReadRawTemp(void) // read raw temperature ADC conversion result { RawTemp=0; Error=I2C_Read(Bus, ADDR, REG_TEMP_, (uint8_t *)(&RawTemp), 3); if(Error) return Error; RawTemp = ((RawTemp<<16)&0xFF0000) | (RawTemp&0x00FF00) | ((RawTemp>>16)&0x0000FF); RawTemp>>=4; return 0; } uint8_t Acquire(void) // trigger the readout and read raw results { if(Trigger()) return Error; if(WaitReady()!=1) return Error; if(ReadRawTemp()) return Error; return ReadRawPress(); } void Calculate(void) // calculate physical values from raw ADC readouts { calcTemperature(); // must be in this order: temperature first calcPressure(); } void calcTemperature(void) // calculate the temperature from raw readout and calibration values { int32_t var1 = ((((RawTemp>>3) - ((int32_t)T1<<1))) * ((int32_t)T2)) >> 11; int32_t var2 = ( ( (((RawTemp>>4) - (int32_t)T1) * ((RawTemp>>4) - (int32_t)T1) ) >> 12) * ((int32_t)T3) ) >> 14; FineTemp = var1 + var2; Temperature = ( (var1+var2) + 256) >> 9; // [0.1degC] // Temperature = ( (var1+var2) * 5 + 128) >> 8; // [0.01degC] } void calcPressure(void) // calculate the pressure - must calculate the temperature first ! { int64_t var1 = ((int64_t)FineTemp) - 128000; int64_t var2 = var1 * var1 * (int64_t)P6; var2 = var2 + ((var1*(int64_t)P5)<<17); var2 = var2 + (((int64_t)P4)<<35); var1 = ((var1 * var1 * (int64_t)P3)>>8) + ((var1 * (int64_t)P2)<<12); var1 = (((((int64_t)1)<<47)+var1))*((int64_t)P1)>>33; if (var1 == 0) { Pressure=0; return; } int64_t p = 1048576-RawPress; p = (((p<<31)-var2)*3125)/var1; var1 = (((int64_t)P9) * (p>>13) * (p>>13)) >> 25; var2 = (((int64_t)P8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)P7)<<4); Pressure = ((p+32)>>6); } } ; #endif // __BMP280_H__