FluxSand 1.0
FluxSand - Interactive Digital Hourglass
Loading...
Searching...
No Matches
bmp280.hpp
1#pragma once
2
3#include <cmath>
4#include <cstdint>
5#include <iostream>
6#include <stdexcept>
7#include <thread>
8
9#include "bsp_i2c.hpp" // Contains I2cDevice class implementation
10
15class Bmp280 {
16 public:
18 static constexpr uint8_t DEFAULT_I2C_ADDR = 0x77;
19
21 enum Register : uint8_t {
22 REG_ID = 0xD0, // Chip ID register
23 REG_RESET = 0xE0, // Reset register
24 REG_CTRL_MEAS = 0xF4, // Measurement control
25 REG_CONFIG = 0xF5, // Configuration
26 REG_PRESS_MSB = 0xF7, // Pressure MSB
27 REG_TEMP_MSB = 0xFA, // Temperature MSB
28 REG_CALIB = 0x88 // Calibration data start
29 };
30
35 Bmp280(I2cDevice& i2c) : i2c_(i2c) {
36 uint8_t id = i2c_.ReadRegister(REG_ID);
37 if (id != 0x58) { // Verify chip ID
38 std::perror("Invalid BMP280 ID");
39 }
40
42 Configure();
43
44 thread_ = std::thread(&Bmp280::ThreadFun, this);
45 }
46
47 void ThreadFun() {
48 while (true) {
51 std::this_thread::sleep_for(std::chrono::milliseconds(100));
52 }
53 }
54
55 void Display() {
56 std::cout << "Temperature: " << ReadTemperature() << " °C\n";
57 std::cout << "Pressure: " << ReadPressure() / 100.0f << " hPa\n";
58 }
59
65 int32_t adc_t = ReadRawTemperature();
66 return static_cast<float>(CompensateTemperature(adc_t)) / 100.0f;
67 }
68
73 float ReadPressure() {
74 int32_t adc_p = ReadRawPressure();
75 ReadRawTemperature(); // Required to update t_fine
76 CompensateTemperature(adc_t_); // Ensure t_fine is current
77 return static_cast<float>(CompensatePressure(adc_p)) / 256.0f;
78 }
79
80 private:
81 // NOLINTNEXTLINE
82 I2cDevice& i2c_;
83 int32_t t_fine_ = 0; // Shared temperature compensation value
84
85 // Calibration parameters
86 uint16_t dig_t1_;
87 int16_t dig_t2_, dig_t3_;
88 uint16_t dig_p1_;
89 int16_t dig_p2_, dig_p3_, dig_p4_, dig_p5_, dig_p6_, dig_p7_, dig_p8_,
90 dig_p9_;
91
92 int32_t adc_t_ = 0; // Cached raw temperature value
93
94 std::thread thread_;
95
97 void Configure() {
98 // Set oversampling: temp x1, pressure x1, normal mode
99 i2c_.WriteRegister(REG_CTRL_MEAS, 0b00100111);
100 // Set standby time 0.5ms, filter off
101 i2c_.WriteRegister(REG_CONFIG, 0b00000000);
102 }
103
106 uint8_t buf[24];
107 i2c_.ReadRegisters(REG_CALIB, buf, 24);
108
109 // Temperature calibration
110 dig_t1_ = static_cast<uint16_t>((buf[1] << 8) | buf[0]);
111 dig_t2_ = static_cast<int16_t>((buf[3] << 8) | buf[2]);
112 dig_t3_ = static_cast<int16_t>((buf[5] << 8) | buf[4]);
113
114 // Pressure calibration
115 dig_p1_ = (buf[7] << 8) | buf[6];
116 dig_p2_ = static_cast<int16_t>((buf[9] << 8) | buf[8]);
117 dig_p3_ = static_cast<int16_t>((buf[11] << 8) | buf[10]);
118 dig_p4_ = static_cast<int16_t>((buf[13] << 8) | buf[12]);
119 dig_p5_ = static_cast<int16_t>((buf[15] << 8) | buf[14]);
120 dig_p6_ = static_cast<int16_t>((buf[17] << 8) | buf[16]);
121 dig_p7_ = static_cast<int16_t>((buf[19] << 8) | buf[18]);
122 dig_p8_ = static_cast<int16_t>((buf[21] << 8) | buf[20]);
123 dig_p9_ = static_cast<int16_t>((buf[23] << 8) | buf[22]);
124 }
125
128 uint8_t data[3];
129 i2c_.ReadRegisters(REG_TEMP_MSB, data, 3);
130 adc_t_ = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
131 return adc_t_;
132 }
133
135 int32_t ReadRawPressure() {
136 uint8_t data[3];
137 i2c_.ReadRegisters(REG_PRESS_MSB, data, 3);
138 return (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
139 }
140
142 int32_t CompensateTemperature(int32_t adc_T) {
143 int32_t var1 = (((adc_T >> 3) - (static_cast<int32_t>(dig_t1_) << 1)) *
144 (static_cast<int32_t>(dig_t2_)) >>
145 11);
146
147 int32_t var2 = (((((adc_T >> 4) - static_cast<int32_t>(dig_t1_)) *
148 ((adc_T >> 4) - static_cast<int32_t>(dig_t1_))) >>
149 12) *
150 (static_cast<int32_t>(dig_t3_)) >>
151 14);
152
153 t_fine_ = var1 + var2;
154 return (t_fine_ * 5 + 128) >> 8;
155 }
156
158 uint32_t CompensatePressure(int32_t adc_P) {
159 int64_t var1 = static_cast<int64_t>(t_fine_) - 128000;
160 int64_t var2 = var1 * var1 * static_cast<int64_t>(dig_p6_);
161 var2 += (var1 * static_cast<int64_t>(dig_p5_)) << 17;
162 var2 += (static_cast<int64_t>(dig_p4_)) << 35;
163
164 var1 = ((var1 * var1 * static_cast<int64_t>(dig_p3_)) >> 8) +
165 ((var1 * static_cast<int64_t>(dig_p2_)) << 12);
166 var1 = (((static_cast<int64_t>(1) << 47) + var1) *
167 static_cast<int64_t>(dig_p1_)) >>
168 33;
169
170 if (var1 == 0) {
171 return 0; // Prevent division by zero
172 }
173
174 int64_t p = 1048576 - adc_P;
175 p = (((p << 31) - var2) * 3125) / var1;
176 var1 = (static_cast<int64_t>(dig_p9_) * (p >> 13) * (p >> 13)) >> 25;
177 var2 = (static_cast<int64_t>(dig_p8_) * p) >> 19;
178
179 return static_cast<uint32_t>((p + var1 + var2) >> 8) +
180 (static_cast<int64_t>(dig_p7_) << 4);
181 }
182};
float ReadPressure()
Definition bmp280.hpp:73
float ReadTemperature()
Definition bmp280.hpp:64
uint32_t CompensatePressure(int32_t adc_P)
Definition bmp280.hpp:158
static constexpr uint8_t DEFAULT_I2C_ADDR
Definition bmp280.hpp:18
void Configure()
Definition bmp280.hpp:97
void ReadCalibration()
Definition bmp280.hpp:105
int32_t ReadRawPressure()
Definition bmp280.hpp:135
int32_t CompensateTemperature(int32_t adc_T)
Definition bmp280.hpp:142
int32_t ReadRawTemperature()
Definition bmp280.hpp:127
Bmp280(I2cDevice &i2c)
Definition bmp280.hpp:35
uint8_t ReadRegister(uint8_t reg)
Definition bsp_i2c.hpp:53
void ReadRegisters(uint8_t reg, uint8_t *buffer, size_t length)
Definition bsp_i2c.hpp:86
void WriteRegister(uint8_t reg, uint8_t value)
Definition bsp_i2c.hpp:72