Merge branch 'master' into change-to-sending-expresslrs_RFrates_e-in-sync-packet
[ExpressLRS.git] / src / lib / Baro / baro_bmp280.cpp
blob6bf9bd0dd1aa3d21800ed1031ad2bd1599a7c4a0
1 #include "baro_bmp280.h"
2 #include <Arduino.h>
3 #include "logging.h"
5 void BMP280::initialize()
7 if (m_initialized)
8 return;
10 // All the calibration registers are in order of our struct and are 2 bytes long too,
11 // so just read them directly into our calib data
12 readRegister(BMP280_REG_CALIB_COEFFS_START, (uint8_t *)&m_calib, sizeof(m_calib));
14 // configure IIR filter, 0.5ms standby time (freerunning)
15 constexpr uint8_t BMP280_FILTER = FILTER_COEFF << 2;
16 writeRegister(BMP280_REG_CONFIG, (uint8_t *)&BMP280_FILTER, sizeof(BMP280_FILTER));
18 m_initialized = true;
21 uint8_t BMP280::getTemperatureDuration()
23 // Calculate in microseconds, then divide by 1000 for ms, rounding up
24 constexpr uint32_t duration = 1250U +
25 (2300U * ((1U << OVERSAMPLING_TEMPERATURE) >> 1)) +
26 (2300U * ((1U << OVERSAMPLING_PRESSURE) >> 1) + 575U);
27 return (FREERUNNING_NUM_SAMPLES * duration + 999U) / 1000U;
30 void BMP280::startTemperature()
32 // Measure both Pressure and Temperature, freerunning to allow internal IIR to smooth extra samples for us
33 constexpr uint8_t SAMPLING_MODE = (FREERUNNING_NUM_SAMPLES != 0) ? BMP280_MODE_NORMAL : BMP280_MODE_FORCED;
34 constexpr uint8_t BMP280_MODE = (OVERSAMPLING_PRESSURE << 2 | OVERSAMPLING_TEMPERATURE << 5 | SAMPLING_MODE);
35 writeRegister(BMP280_REG_CTRL_MEAS, (uint8_t *)&BMP280_MODE, sizeof(BMP280_MODE));
38 uint32_t BMP280::getPressure()
40 return m_pressureLast;
43 int32_t BMP280::getTemperature()
45 // uint8_t status = 0xff;
46 // readRegister(BMP280_REG_STATUS, &status, sizeof(status));
47 // if (status & bit(3))
48 // {
49 // DBGLN("not ready");
50 // }
52 uint8_t buf[BMP280_LEN_TEMP_PRESS_DATA] = {0};
53 readRegister(BMP280_REG_PRESSURE_MSB, buf, sizeof(buf));
55 int32_t adc_P = ((uint32_t)buf[0] << 12) | ((uint32_t)buf[1] << 4) | ((uint32_t)buf[2] >> 4);
56 int32_t adc_T = ((uint32_t)buf[3] << 12) | ((uint32_t)buf[4] << 4) | ((uint32_t)buf[5] >> 4);
58 // BME280_compensate_T_int32()
59 int32_t var01, var02;
60 var01 = ((((adc_T >> 3) - ((int32_t)m_calib.dig_T1 << 1))) * ((int32_t)m_calib.dig_T2)) >> 11;
61 var02 = (((((adc_T >> 4) - ((int32_t)m_calib.dig_T1)) * ((adc_T >> 4) - ((int32_t)m_calib.dig_T1))) >> 12) * ((int32_t)m_calib.dig_T3)) >> 14;
62 int32_t t_fine = var01 + var02;
64 // BME280_compensate_P_int64()
65 int64_t var1, var2, p;
66 var1 = ((int64_t)t_fine) - 128000;
67 var2 = var1 * var1 * (int64_t)m_calib.dig_P6;
68 var2 = var2 + ((var1*(int64_t)m_calib.dig_P5) << 17);
69 var2 = var2 + (((int64_t)m_calib.dig_P4) << 35);
70 var1 = ((var1 * var1 * (int64_t)m_calib.dig_P3) >> 8) + ((var1 * (int64_t)m_calib.dig_P2) << 12);
71 var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)m_calib.dig_P1) >> 33;
72 if (var1 == 0)
73 return BaroBase::PRESSURE_INVALID;
75 p = 1048576 - adc_P;
76 p = (((p << 31) - var2) * 3125) / var1;
77 var1 = (((int64_t)m_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
78 var2 = (((int64_t)m_calib.dig_P8) * p) >> 19;
79 p = ((p + var1 + var2) >> 8) + (((int64_t)m_calib.dig_P7) << 4);
80 // p is pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
81 // Output value of "24674867" represents 24674867/256 = 96386.2 Pa = 963.862 hPa
82 m_pressureLast = ((uint32_t)p) >> 8;
84 int32_t temperature = (t_fine * 5 + 128) >> 8;
85 //DBGLN("%u t=%d p=%u", millis(), temperature, m_pressureLast);
87 return temperature;
90 bool BMP280::detect()
92 // Assumes Wire.begin() has already been called
93 uint8_t chipid = 0;
95 // BMP280 can have two addresses based on the SDO pin.
96 // Adafruit breakout has it tied high, Aliexpress boards have it tied low
97 for (uint8_t addr : { BMP280_I2C_ADDR, BMP280_I2C_ADDR_ALT })
99 m_address = addr;
100 readRegister(BMP280_REG_CHIPID, &chipid, sizeof(chipid));
101 if (chipid == BMP280_CHIPID || chipid == BME280_CHIPID)
102 return true;
105 return false;