M5Unit-IMU 0.0.2 git rev:e5b00aa
Loading...
Searching...
No Matches
unit_bmm350_data.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
10#ifndef M5_UNIT_IMU_UNIT_UNIT_BMM350_DATA_HPP
11#define M5_UNIT_IMU_UNIT_UNIT_BMM350_DATA_HPP
12
13#include <array>
14#include <cstddef>
15#include <cstdint>
16
17namespace m5 {
18namespace unit {
19namespace bmm350 {
20
25enum class DataRate : uint8_t {
26 Rate400Hz = 0x02,
27 Rate200Hz = 0x03,
28 Rate100Hz = 0x04,
29 Rate50Hz = 0x05,
30 Rate25Hz = 0x06,
31 Rate12_5Hz = 0x07,
32 Rate6_25Hz = 0x08,
33 Rate3_125Hz = 0x09,
34 Rate1_5625Hz = 0x0A,
35};
36
41enum class Averaging : uint8_t {
42 None,
43 X2,
44 X4,
45 X8,
46};
47
51constexpr Averaging clamp_averaging(const DataRate rate, const Averaging avg)
52{
53 return (rate == DataRate::Rate400Hz) ? Averaging::None
54 : (rate == DataRate::Rate200Hz)
55 ? (static_cast<uint8_t>(avg) > static_cast<uint8_t>(Averaging::X2) ? Averaging::X2 : avg)
56 : (rate == DataRate::Rate100Hz)
57 ? (static_cast<uint8_t>(avg) > static_cast<uint8_t>(Averaging::X4) ? Averaging::X4 : avg)
58 : avg;
59}
60
62constexpr int32_t fix_sign24(const uint32_t raw)
63{
64 return (raw >= 0x800000u) ? static_cast<int32_t>(raw - 0x1000000u) : static_cast<int32_t>(raw);
65}
66
67// The following conversion coefficients are the values published in the
68// BMM350 datasheet (BST-BMM350-DS001), and match the ones the Bosch
69// BMM350_SensorAPI (BSD-3-Clause) derives at runtime from the sensor's
70// analog front-end gains in update_default_coefiecents(): e.g. for X/Y,
71// (1e6/2^20) / (14.55 * 19.46 * (1/1.5) * 0.714607238769531) = 0.0070700 uT/LSB.
72
74constexpr float lsb_to_ut_xy()
75{
76 return 0.00707f;
77}
79constexpr float lsb_to_ut_z()
80{
81 return 0.0071750f;
82}
84constexpr float temp_res_raw24()
85{
86 return 0.00098128f;
87}
89constexpr float TEMP_OFFSET{-25.49f};
90
103 float t_sens{};
104 float t_offs{};
105 float t0{23.0f};
106 float offset[3]{};
107 float sens[3]{};
108 float tco[3]{};
109 float tcs[3]{};
110 float cross[4]{};
111
113 inline float compensate_temp(const float t_raw) const
114 {
115 return (1.0f + t_sens) * t_raw + t_offs;
116 }
117
120 void compensate_mag(float (&m)[3], const float t_comp) const
121 {
122 for (size_t i = 0; i < 3; ++i) {
123 m[i] *= 1.0f + sens[i];
124 m[i] += offset[i];
125 m[i] += tco[i] * (t_comp - t0);
126 m[i] /= 1.0f + tcs[i] * (t_comp - t0);
127 }
128
129 const float cross_xy = cross[0];
130 const float cross_yx = cross[1];
131 const float cross_zx = cross[2];
132 const float cross_zy = cross[3];
133 const float denom = 1.0f - cross_yx * cross_xy;
134
135 const float x = (m[0] - cross_xy * m[1]) / denom;
136 const float y = (m[1] - cross_yx * m[0]) / denom;
137 const float z_delta = m[0] * (cross_yx * cross_zy - cross_zx) - m[1] * (cross_zy - cross_xy * cross_zx);
138 const float z = m[2] + z_delta / denom;
139
140 m[0] = x;
141 m[1] = y;
142 m[2] = z;
143 }
144};
145
152struct Data {
153 std::array<uint8_t, 12> raw{};
155
159 inline int32_t x_raw() const
160 {
161 return fix_sign24(assemble24(0));
162 }
164 inline int32_t y_raw() const
165 {
166 return fix_sign24(assemble24(3));
167 }
169 inline int32_t z_raw() const
170 {
171 return fix_sign24(assemble24(6));
172 }
174 inline int32_t temp_raw24() const
175 {
176 return fix_sign24(assemble24(9));
177 }
179 inline int16_t temp_adc() const
180 {
181 return static_cast<int16_t>(temp_raw24() >> 8);
182 }
184
188 inline float x_ut() const
189 {
190 return compensated_mag()[0];
191 }
193 inline float y_ut() const
194 {
195 return compensated_mag()[1];
196 }
198 inline float z_ut() const
199 {
200 return compensated_mag()[2];
201 }
203
204private:
205 // Assembles a little-endian 24bit unsigned value from raw[idx..idx+2]
206 inline uint32_t assemble24(const size_t idx) const
207 {
208 return static_cast<uint32_t>(raw[idx]) | (static_cast<uint32_t>(raw[idx + 1]) << 8) |
209 (static_cast<uint32_t>(raw[idx + 2]) << 16);
210 }
211 // Primary (pre-OTP) temperature conversion (degC)
212 inline float primary_temp() const
213 {
214 return static_cast<float>(temp_raw24()) * temp_res_raw24() + TEMP_OFFSET;
215 }
216 // Primary conversion (uT) followed by full OTP compensation for all 3 axes
217 inline std::array<float, 3> compensated_mag() const
218 {
219 std::array<float, 3> m{static_cast<float>(x_raw()) * lsb_to_ut_xy(),
220 static_cast<float>(y_raw()) * lsb_to_ut_xy(),
221 static_cast<float>(z_raw()) * lsb_to_ut_z()};
222 float raw_arr[3] = {m[0], m[1], m[2]};
223 comp.compensate_mag(raw_arr, comp.compensate_temp(primary_temp()));
224 m[0] = raw_arr[0];
225 m[1] = raw_arr[1];
226 m[2] = raw_arr[2];
227 return m;
228 }
229};
230
231} // namespace bmm350
232} // namespace unit
233} // namespace m5
234#endif
Top level namespace of M5Stack.
Definition ahrs_controller.cpp:26
Unit-related namespace.
One measurement (12 bytes burst from REG_MAG_X_XLSB, register 0x31): 9 bytes magnetometer (X,...
Definition unit_bmm350_data.hpp:152
int32_t z_raw() const
Raw magnetometer Z.
Definition unit_bmm350_data.hpp:169
float z_ut() const
Compensated magnetometer Z (uT)
Definition unit_bmm350_data.hpp:198
int32_t x_raw() const
Raw magnetometer X.
Definition unit_bmm350_data.hpp:159
int16_t temp_adc() const
Raw temperature ADC normalized to 16bit (temp_raw24() >> 8)
Definition unit_bmm350_data.hpp:179
std::array< uint8_t, 12 > raw
[0..2] X, [3..5] Y, [6..8] Z, [9..11] temperature
Definition unit_bmm350_data.hpp:153
int32_t y_raw() const
Raw magnetometer Y.
Definition unit_bmm350_data.hpp:164
float x_ut() const
Compensated magnetometer X (uT)
Definition unit_bmm350_data.hpp:188
int32_t temp_raw24() const
Raw temperature ADC (24bit, sign-extended)
Definition unit_bmm350_data.hpp:174
otp_compensation_t comp
OTP compensation coefficients used by x_ut()/y_ut()/z_ut()
Definition unit_bmm350_data.hpp:154
float y_ut() const
Compensated magnetometer Y (uT)
Definition unit_bmm350_data.hpp:193
Per-chip OTP compensation coefficients (read out at boot from the sensor's one-time-programmable memo...
Definition unit_bmm350_data.hpp:102
float tcs[3]
Per-axis (x,y,z) temperature coefficient of sensitivity.
Definition unit_bmm350_data.hpp:109
float compensate_temp(const float t_raw) const
Applies the OTP temperature compensation to a primary-converted temperature (degC)
Definition unit_bmm350_data.hpp:113
float t_sens
Temperature sensitivity coefficient.
Definition unit_bmm350_data.hpp:103
float sens[3]
Per-axis (x,y,z) sensitivity coefficient.
Definition unit_bmm350_data.hpp:107
float tco[3]
Per-axis (x,y,z) temperature coefficient of offset.
Definition unit_bmm350_data.hpp:108
float cross[4]
Cross-axis coefficients: [0]=x_y [1]=y_x [2]=z_x [3]=z_y.
Definition unit_bmm350_data.hpp:110
float t_offs
Temperature offset coefficient.
Definition unit_bmm350_data.hpp:104
float offset[3]
Per-axis (x,y,z) offset.
Definition unit_bmm350_data.hpp:106
void compensate_mag(float(&m)[3], const float t_comp) const
Applies per-axis offset/sensitivity/tco/tcs and cross-axis compensation (in-place) to primary-convert...
Definition unit_bmm350_data.hpp:120
float t0
Reference temperature (degC)
Definition unit_bmm350_data.hpp:105
constexpr float lsb_to_ut_z()
uT per LSB of the raw 24bit magnetometer value, Z axis
Definition unit_bmm350_data.hpp:79
constexpr float TEMP_OFFSET
Fixed offset (degC) applied to the primary temperature conversion.
Definition unit_bmm350_data.hpp:89
Averaging
Averaging factor (REG_PMU_CMD_AGGR_SET register 0x04, bits[5:4])
Definition unit_bmm350_data.hpp:41
@ X2
2 samples averaged (Regular, power-on default)
@ X4
4 samples averaged (LowNoise)
@ X8
8 samples averaged (UltraLowNoise)
constexpr float lsb_to_ut_xy()
uT per LSB of the raw 24bit magnetometer value, X/Y axes
Definition unit_bmm350_data.hpp:74
DataRate
Output data rate (REG_PMU_CMD_AGGR_SET register 0x04, bits[3:0])
Definition unit_bmm350_data.hpp:25
constexpr float temp_res_raw24()
degC per LSB of the raw 24bit temperature ADC value
Definition unit_bmm350_data.hpp:84
constexpr Averaging clamp_averaging(const DataRate rate, const Averaging avg)
Clamps avg to the combination the sensor accepts for the given rate (400Hz allows None only,...
Definition unit_bmm350_data.hpp:51
constexpr int32_t fix_sign24(const uint32_t raw)
Sign-extends a 24bit unsigned register value to a signed 32bit value.
Definition unit_bmm350_data.hpp:62