M5Unit-ENV 1.6.0 git rev:f6fd6b0
Loading...
Searching...
No Matches
unit_BMP280_data.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_ENV_UNIT_BMP280_DATA_HPP
11#define M5_UNIT_ENV_UNIT_BMP280_DATA_HPP
12
13#include <array>
14#include <cstdint>
15#include <limits> // NaN
16
17namespace m5 {
18namespace unit {
19namespace bmp280 {
20
25union Trimming {
26 uint8_t value[12 * 2]{};
27 struct {
28 //
29 uint16_t dig_T1;
30 int16_t dig_T2;
31 int16_t dig_T3;
32 //
33 uint16_t dig_P1;
34 int16_t dig_P2;
35 int16_t dig_P3;
36 int16_t dig_P4;
37 int16_t dig_P5;
38 int16_t dig_P6;
39 int16_t dig_P7;
40 int16_t dig_P8;
41 int16_t dig_P9;
42 // uint16_t reserved;
43 } __attribute__((packed));
44};
45
47// Raw ADC value when the measurement is skipped (osrs Skipped)
48constexpr uint32_t NOT_MEASURED{0x800000};
49
50// Bosch compensation formulas. t_fine couples pressure to temperature: pressure() runs the
51// temperature compensation first (on a fresh instance) to obtain t_fine.
52struct Calculator {
53 inline float temperature(const int32_t adc_P, const int32_t adc_T, const Trimming* t)
54 {
55 return t ? compensate_temperature_f(adc_T, *t) : std::numeric_limits<float>::quiet_NaN();
56 }
57 inline float pressure(const int32_t adc_P, const int32_t adc_T, const Trimming* t)
58 {
59 if (!t) {
60 return std::numeric_limits<float>::quiet_NaN();
61 }
62 if (t_fine == 0) {
63 (void)compensate_temperature_f(adc_T, *t); // For t_fine
64 }
65 return compensate_pressure_f(adc_P, *t);
66 }
67
68private:
69 float compensate_temperature(const int32_t adc_T, const Trimming& trim)
70 {
71 int32_t var1{}, var2{};
72 var1 = ((((adc_T >> 3) - ((int32_t)trim.dig_T1 << 1))) * ((int32_t)trim.dig_T2)) >> 11;
73 var2 = (((((adc_T >> 4) - ((int32_t)trim.dig_T1)) * ((adc_T >> 4) - ((int32_t)trim.dig_T1))) >> 12) *
74 ((int32_t)trim.dig_T3)) >>
75 14;
76 t_fine = var1 + var2; // [*1]
77 float T = static_cast<float>((t_fine * 5 + 128) >> 8);
78 return T * 0.01f;
79 }
80
81 float compensate_pressure(const int32_t adc_P, const Trimming& trim)
82 {
83 int64_t var1{}, var2{}, p{};
84 var1 = ((int64_t)t_fine) - 128000; // (*1) using it!
85 var2 = var1 * var1 * (int64_t)trim.dig_P6;
86 var2 = var2 + ((var1 * (int64_t)trim.dig_P5) << 17);
87 var2 = var2 + (((int64_t)trim.dig_P4) << 35);
88 var1 = ((var1 * var1 * (int64_t)trim.dig_P3) >> 8) + ((var1 * (int64_t)trim.dig_P2) << 12);
89 var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)trim.dig_P1) >> 33;
90 if (var1) {
91 p = 1048576 - adc_P;
92 p = (((p << 31) - var2) * 3125) / var1;
93 var1 = (((int64_t)trim.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
94 var2 = (((int64_t)trim.dig_P8) * p) >> 19;
95 p = ((p + var1 + var2) >> 8) + (((int64_t)trim.dig_P7) << 4);
96 return p / 256.f;
97 }
98 return 0.0f;
99 }
100
101 float compensate_temperature_f(const int32_t adc_T, const Trimming& trim)
102 {
103 float var1{}, var2{}, T{};
104 var1 = (((float)adc_T) / 16384.0f - ((float)trim.dig_T1) / 1024.0f) * ((float)trim.dig_T2);
105 var2 = ((((float)adc_T) / 131072.0f - ((float)trim.dig_T1) / 8192.0f) *
106 (((float)adc_T) / 131072.0f - ((float)trim.dig_T1) / 8192.0f)) *
107 ((float)trim.dig_T3);
108 t_fine = (int32_t)(var1 + var2); // [*2]
109 T = (var1 + var2) / 5120.0f;
110 return T;
111 }
112
113 float compensate_pressure_f(const int32_t adc_P, const Trimming& trim)
114 {
115 float var1{}, var2{}, P{};
116 var1 = ((float)t_fine / 2.0f) - 64000.0f; // (*2)
117 var2 = var1 * var1 * ((float)trim.dig_P6) / 32768.0f;
118 var2 = var2 + var1 * ((float)trim.dig_P5) * 2.0f;
119 var2 = (var2 / 4.0f) + (((float)trim.dig_P4) * 65536.0f);
120 var1 = (((float)trim.dig_P3) * var1 * var1 / 524288.0f + ((float)trim.dig_P2) * var1) / 524288.0f;
121 var1 = (1.0f + var1 / 32768.0f) * ((float)trim.dig_P1);
122 if (var1 == 0.0f) {
123 return 0;
124 }
125 P = 1048576.0f - (float)adc_P;
126 P = (P - (var2 / 4096.0f)) * 6250.0f / var1;
127 var1 = ((float)trim.dig_P9) * P * P / 2147483648.0f;
128 var2 = P * ((float)trim.dig_P8) / 32768.0f;
129 P = P + (var1 + var2 + ((float)trim.dig_P7)) / 16.0f;
130 return P;
131 }
132
134
135 int32_t t_fine{};
136};
138
143struct Data {
144 std::array<uint8_t, 6> raw{};
150
152 inline float temperature() const
153 {
154 return celsius();
155 }
157 inline float celsius() const
158 {
159 int32_t adc_P = (int32_t)(((uint32_t)raw[0] << 16) | ((uint32_t)raw[1] << 8) | ((uint32_t)raw[2]));
160 int32_t adc_T = (int32_t)(((uint32_t)raw[3] << 16) | ((uint32_t)raw[4] << 8) | ((uint32_t)raw[5]));
161 Calculator c{};
162
163 // adc_T is NOT_MEASURED if orsr Skipped (Not measured)
164 return (adc_T != NOT_MEASURED) ? c.temperature(adc_P >> 4, adc_T >> 4, trimming)
165 : std::numeric_limits<float>::quiet_NaN();
166 }
168 inline float fahrenheit() const
169 {
170 return celsius() * 9.0f / 5.0f + 32.f;
171 }
173 inline float pressure() const
174 {
175 int32_t adc_P = (int32_t)(((uint32_t)raw[0] << 16) | ((uint32_t)raw[1] << 8) | ((uint32_t)raw[2]));
176 int32_t adc_T = (int32_t)(((uint32_t)raw[3] << 16) | ((uint32_t)raw[4] << 8) | ((uint32_t)raw[5]));
177 Calculator c{};
178
179 // adc_T/P is NOT_MEASURED if orsr Skipped (Not measured)
180 return (adc_T != NOT_MEASURED && adc_P != NOT_MEASURED) ? c.pressure(adc_P >> 4, adc_T >> 4, trimming)
181 : std::numeric_limits<float>::quiet_NaN();
182 }
183};
184
185} // namespace bmp280
186} // namespace unit
187} // namespace m5
188#endif
For BMP280.
Top level namespace of M5Stack.
Unit-related namespace.
Measurement data group.
Definition unit_BMP280_data.hpp:143
const Trimming * trimming
Points to the owning unit's calibration for compensation.
Definition unit_BMP280_data.hpp:149
float temperature() const
temperature (Celsius)
Definition unit_BMP280_data.hpp:152
float pressure() const
pressure (Pa)
Definition unit_BMP280_data.hpp:173
float fahrenheit() const
temperature (Fahrenheit)
Definition unit_BMP280_data.hpp:168
std::array< uint8_t, 6 > raw
Definition unit_BMP280_data.hpp:144
float celsius() const
temperature (Celsius)
Definition unit_BMP280_data.hpp:157
Trimming parameter.
Definition unit_BMP280_data.hpp:25
float compensate_pressure(const int32_t psr_raw, const int32_t tmp_raw, const coeffs_t &c, const float kp, const float kt)
Compensated pressure (Pa) from raw PSR/TMP readings and scales kP/kT (datasheet 4....
Definition unit_SPA06_data.hpp:164
float compensate_temperature(const int32_t tmp_raw, const coeffs_t &c, const float kt)
Compensated temperature (degC) from a raw TMP reading and scale kT.
Definition unit_SPA06_data.hpp:157