mirror of
https://github.com/esphome/esphome.git
synced 2024-11-30 02:34:12 +01:00
[ms5611] Re-implement conversion from ADC readings to sensor values (#2665)
This commit is contained in:
parent
5ff7c8418c
commit
f310cacd41
1 changed files with 35 additions and 17 deletions
|
@ -75,30 +75,48 @@ void MS5611Component::read_pressure_(uint32_t raw_temperature) {
|
||||||
const uint32_t raw_pressure = (uint32_t(bytes[0]) << 16) | (uint32_t(bytes[1]) << 8) | (uint32_t(bytes[2]));
|
const uint32_t raw_pressure = (uint32_t(bytes[0]) << 16) | (uint32_t(bytes[1]) << 8) | (uint32_t(bytes[2]));
|
||||||
this->calculate_values_(raw_temperature, raw_pressure);
|
this->calculate_values_(raw_temperature, raw_pressure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculations are taken from the datasheet which can be found here:
|
||||||
|
// https://www.te.com/commerce/DocumentDelivery/DDEController?Action=showdoc&DocId=Data+Sheet%7FMS5611-01BA03%7FB3%7Fpdf%7FEnglish%7FENG_DS_MS5611-01BA03_B3.pdf%7FCAT-BLPS0036
|
||||||
|
// Sections PRESSURE AND TEMPERATURE CALCULATION and SECOND ORDER TEMPERATURE COMPENSATION
|
||||||
|
// Variable names below match variable names from the datasheet but lowercased
|
||||||
void MS5611Component::calculate_values_(uint32_t raw_temperature, uint32_t raw_pressure) {
|
void MS5611Component::calculate_values_(uint32_t raw_temperature, uint32_t raw_pressure) {
|
||||||
const int32_t d_t = int32_t(raw_temperature) - (uint32_t(this->prom_[4]) << 8);
|
const uint32_t c1 = uint32_t(this->prom_[0]);
|
||||||
float temperature = (2000 + (int64_t(d_t) * this->prom_[5]) / 8388608.0f) / 100.0f;
|
const uint32_t c2 = uint32_t(this->prom_[1]);
|
||||||
|
const uint16_t c3 = uint16_t(this->prom_[2]);
|
||||||
|
const uint16_t c4 = uint16_t(this->prom_[3]);
|
||||||
|
const int32_t c5 = int32_t(this->prom_[4]);
|
||||||
|
const uint16_t c6 = uint16_t(this->prom_[5]);
|
||||||
|
const uint32_t d1 = raw_pressure;
|
||||||
|
const int32_t d2 = raw_temperature;
|
||||||
|
|
||||||
float pressure_offset = (uint32_t(this->prom_[1]) << 16) + ((this->prom_[3] * d_t) >> 7);
|
// Promote dt to 64 bit here to make the math below cleaner
|
||||||
float pressure_sensitivity = (uint32_t(this->prom_[0]) << 15) + ((this->prom_[2] * d_t) >> 8);
|
const int64_t dt = d2 - (c5 << 8);
|
||||||
|
int32_t temp = (2000 + ((dt * c6) >> 23));
|
||||||
|
|
||||||
if (temperature < 20.0f) {
|
int64_t off = (c2 << 16) + ((dt * c4) >> 7);
|
||||||
const float t2 = (d_t * d_t) / 2147483648.0f;
|
int64_t sens = (c1 << 15) + ((dt * c3) >> 8);
|
||||||
const float temp20 = (temperature - 20.0f) * 100.0f;
|
|
||||||
float pressure_offset_2 = 2.5f * temp20 * temp20;
|
if (temp < 2000) {
|
||||||
float pressure_sensitivity_2 = 1.25f * temp20 * temp20;
|
const int32_t t2 = (dt * dt) >> 31;
|
||||||
if (temp20 < -15.0f) {
|
int32_t off2 = ((5 * (temp - 2000) * (temp - 2000)) >> 1);
|
||||||
const float temp15 = (temperature + 15.0f) * 100.0f;
|
int32_t sens2 = ((5 * (temp - 2000) * (temp - 2000)) >> 2);
|
||||||
pressure_offset_2 += 7.0f * temp15;
|
if (temp < -1500) {
|
||||||
pressure_sensitivity_2 += 5.5f * temp15;
|
off2 = (off2 + 7 * (temp + 1500) * (temp + 1500));
|
||||||
|
sens2 = sens2 + ((11 * (temp + 1500) * (temp + 1500)) >> 1);
|
||||||
}
|
}
|
||||||
temperature -= t2;
|
temp = temp - t2;
|
||||||
pressure_offset -= pressure_offset_2;
|
off = off - off2;
|
||||||
pressure_sensitivity -= pressure_sensitivity_2;
|
sens = sens - sens2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float pressure = ((raw_pressure * pressure_sensitivity) / 2097152.0f - pressure_offset) / 3276800.0f;
|
// Here we multiply unsigned 32-bit by signed 64-bit using signed 64-bit math.
|
||||||
|
// Possible ranges of D1 and SENS from the datasheet guarantee
|
||||||
|
// that this multiplication does not overflow
|
||||||
|
const int32_t p = ((((d1 * sens) >> 21) - off) >> 15);
|
||||||
|
|
||||||
|
const float temperature = temp / 100.0f;
|
||||||
|
const float pressure = p / 100.0f;
|
||||||
ESP_LOGD(TAG, "Got temperature=%0.02f°C pressure=%0.01fhPa", temperature, pressure);
|
ESP_LOGD(TAG, "Got temperature=%0.02f°C pressure=%0.01fhPa", temperature, pressure);
|
||||||
|
|
||||||
if (this->temperature_sensor_ != nullptr)
|
if (this->temperature_sensor_ != nullptr)
|
||||||
|
|
Loading…
Reference in a new issue