SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
SensorBMM150.cpp
Go to the documentation of this file.
1
31#include "../../../SensorBuildOpt.h"
32#if !SENSORLIB_EXCLUDE_BMM150
33
34#include "SensorBMM150.hpp"
35#include <cstring>
36
37SensorBMM150::SensorBMM150() : _error_code(BMM150_OK)
38{
39}
40
42{
43 if (!_dev) {
44 return false;
45 }
46
47 struct bmm150_mag_data mag_data = {0, 0, 0};
48 if (bmm150_read_mag_data(&mag_data, _dev.get()) != BMM150_OK) {
49 return false;
50 }
51
52 const float x_gauss = MagnetometerUtils::microTeslaToGauss(mag_data.x);
53 const float y_gauss = MagnetometerUtils::microTeslaToGauss(mag_data.y);
54 const float z_gauss = MagnetometerUtils::microTeslaToGauss(mag_data.z);
55
56 data.raw.x = static_cast<int16_t>(x_gauss) - _x_offset;
57 data.raw.y = static_cast<int16_t>(y_gauss) - _y_offset;
58 data.raw.z = static_cast<int16_t>(z_gauss) - _z_offset;
59
60 data.magnetic_field.x = x_gauss * _sensitivity;
61 data.magnetic_field.y = y_gauss * _sensitivity;
62 data.magnetic_field.z = z_gauss * _sensitivity;
64 data.heading_degrees = data.heading * (180.0f / M_PI);
65 data.skip_data = false;
66
67 updateInterruptStatus();
68 data.overflow = (_dev->int_status & BMM150_INT_DATA_OVERFLOW) != 0;
69
70 return true;
71}
72
74{
75 if (!updateInterruptStatus()) {
76 return false;
77 }
78 return (_dev->int_status & BMM150_INT_ASSERTED_DRDY) != 0;
79}
80
82{
83 if (!_dev) {
84 return false;
85 }
86
87 _error_code = bmm150_soft_reset(_dev.get());
88 if (_error_code != BMM150_OK) {
89 return false;
90 }
91
92 hal->delay(5);
93 _error_code = bmm150_get_sensor_settings(&_settings, _dev.get());
94 return _error_code == BMM150_OK;
95}
96
98{
99 if (!_dev) {
100 return false;
101 }
102 return bmm150_perform_self_test(BMM150_SELF_TEST_NORMAL, _dev.get()) == BMM150_OK;
103}
104
106{
107 switch (range) {
109 _config.range = 16.0f;
110 return true;
111 default:
112 SENSORLIB_LOG_E("BMM150 does not support configurable full-scale range");
113 return false;
114 }
115}
116
118{
119 if (!_dev) {
120 return false;
121 }
122
123 const int odr_x100 = static_cast<int>(odr * 100.0f + 0.5f);
124 uint8_t data_rate = 0;
125 switch (odr_x100) {
126 case 200:
127 data_rate = BMM150_DATA_RATE_02HZ;
128 break;
129 case 600:
130 data_rate = BMM150_DATA_RATE_06HZ;
131 break;
132 case 800:
133 data_rate = BMM150_DATA_RATE_08HZ;
134 break;
135 case 1000:
136 data_rate = BMM150_DATA_RATE_10HZ;
137 break;
138 case 1500:
139 data_rate = BMM150_DATA_RATE_15HZ;
140 break;
141 case 2000:
142 data_rate = BMM150_DATA_RATE_20HZ;
143 break;
144 case 2500:
145 data_rate = BMM150_DATA_RATE_25HZ;
146 break;
147 case 3000:
148 data_rate = BMM150_DATA_RATE_30HZ;
149 break;
150 default:
151 SENSORLIB_LOG_E("Invalid BMM150 output data rate: %.2f", odr);
152 return false;
153 }
154
155 _settings.data_rate = data_rate;
156 _error_code = bmm150_set_sensor_settings(BMM150_SEL_DATA_RATE, &_settings, _dev.get());
157 if (_error_code != BMM150_OK) {
158 return false;
159 }
160
161 _config.sample_rate = odr;
162 return true;
163}
164
166{
167 if (!_dev) {
168 return false;
169 }
170
171 switch (mode) {
174 _settings.pwr_mode = BMM150_POWERMODE_NORMAL;
175 break;
177 _settings.pwr_mode = BMM150_POWERMODE_FORCED;
178 break;
180 _settings.pwr_mode = BMM150_POWERMODE_SLEEP;
181 break;
182 default:
183 return false;
184 }
185
186 _error_code = bmm150_set_op_mode(&_settings, _dev.get());
187 if (_error_code != BMM150_OK) {
188 return false;
189 }
190
191 _config.mode = mode;
192 return true;
193}
194
196{
197 if (!_dev) {
198 return false;
199 }
200
201 uint8_t xy_rep = BMM150_REPXY_REGULAR;
202 uint8_t z_rep = BMM150_REPZ_REGULAR;
203 switch (osr) {
205 xy_rep = BMM150_REPXY_HIGHACCURACY;
206 z_rep = BMM150_REPZ_HIGHACCURACY;
208 break;
210 xy_rep = BMM150_REPXY_ENHANCED;
211 z_rep = BMM150_REPZ_ENHANCED;
213 break;
215 xy_rep = BMM150_REPXY_REGULAR;
216 z_rep = BMM150_REPZ_REGULAR;
218 break;
220 xy_rep = BMM150_REPXY_LOWPOWER;
221 z_rep = BMM150_REPZ_LOWPOWER;
223 break;
224 default:
225 return false;
226 }
227
228 _settings.xy_rep = xy_rep;
229 _settings.z_rep = z_rep;
230 _error_code = bmm150_set_sensor_settings(BMM150_SEL_XY_REP | BMM150_SEL_Z_REP, &_settings, _dev.get());
231 return _error_code == BMM150_OK;
232}
233
235{
236 (void)dsr;
237 SENSORLIB_LOG_E("BMM150 does not support downsampling rate setting");
238 return false;
239}
240
243{
244 (void)dsr;
245 if (!setOperationMode(mode)) {
246 return false;
247 }
248 if (!setFullScaleRange(range)) {
249 return false;
250 }
251 if (!setOutputDataRate(odr)) {
252 return false;
253 }
254 if (!setOversamplingRate(osr)) {
255 return false;
256 }
257 return true;
258}
259
260bool SensorBMM150::initImpl(uint8_t param)
261{
262 (void)param;
263
264 if (!ensureValid()) {
265 return false;
266 }
267
268 std::memset(&_settings, 0, sizeof(_settings));
269
270 _dev = std::make_unique<struct bmm150_dev>();
271 if (!_dev) {
272 SENSORLIB_LOG_E("Device handler alloc failed");
273 return false;
274 }
275 std::memset(_dev.get(), 0, sizeof(struct bmm150_dev));
276
277 switch (_iface) {
278 case COMM_I2C:
279 _dev->intf = BMM150_I2C_INTF;
280 break;
281 case COMM_SPI:
282 _dev->intf = BMM150_SPI_INTF;
283 break;
284 default:
285 return false;
286 }
287
291 _dev->intf_ptr = staticComm.get();
292
293 _error_code = bmm150_init(_dev.get());
294 if (_error_code != BMM150_OK) {
295 return false;
296 }
297
298 _error_code = bmm150_get_sensor_settings(&_settings, _dev.get());
299 if (_error_code != BMM150_OK) {
300 return false;
301 }
302
303 _info.uid = _dev->chip_id;
304 _info.manufacturer = "Bosch";
305 _info.model = "BMM150";
308 _info.version = 1;
309
310 _x_offset = 0;
311 _y_offset = 0;
312 _z_offset = 0;
313 _sensitivity = 0.01f;
314
317 _config.range = 16.0f;
318 _config.sample_rate = 10.0f;
319 _config.latency = 0;
320
323 10.0f,
326}
327
328bool SensorBMM150::updateInterruptStatus()
329{
330 if (!_dev) {
331 return false;
332 }
333 return bmm150_get_interrupt_status(_dev.get()) == BMM150_OK;
334}
335
336#endif
@license MIT License
@ MAGNETOMETER
Magnetometer sensor.
OperationMode
Enumeration of sensor operation modes.
MagFullScaleRange
Enumeration defining full-scale range settings for the sensor.
MagDownSampleRatio
Enumeration defining down-sample ratios for the sensor.
@ DSR_1
1x down-sample ratio
#define M_PI
MagOverSampleRatio
Enumeration defining over-sample ratios for the sensor.
@ OSR_8
8x over-sample ratio
@ OSR_4
4x over-sample ratio
@ OSR_2
2x over-sample ratio
@ OSR_1
1x over-sample ratio
#define SENSORLIB_LOG_E(...)
@ COMM_SPI
@ COMM_I2C
bool ensureValid() const override
Ensure the communication interface is valid.
std::unique_ptr< SensorCommStatic > staticComm
std::unique_ptr< SensorHal > hal
bool setOutputDataRate(float odr) override
Set output data rate.
bool readData(MagnetometerData &data) override
Read one magnetometer sample.
bool isDataReady() override
Check if fresh data is ready.
bool setOperationMode(OperationMode mode) override
Set operation mode.
bool setDownsamplingRate(MagDownSampleRatio dsr) override
Set downsampling rate.
bool selfTest() override
Execute BMM150 normal self-test.
bool reset() override
Reset the sensor using external pin and software reset.
bool configMagnetometer(OperationMode mode, MagFullScaleRange range, float odr, MagOverSampleRatio osr, MagDownSampleRatio dsr=MagDownSampleRatio::DSR_1) override
Apply combined magnetometer configuration.
bool setFullScaleRange(MagFullScaleRange range) override
Set full-scale range.
bool setOversamplingRate(MagOverSampleRatio osr) override
Set oversampling level by mapping to BMM150 XY/Z repetition values.
SensorBMM150()
Construct a BMM150 driver instance.
SensorConfig _config
Current configuration.
SensorInfo _info
Sensor information.
static int8_t sensor_static_read_data(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr)
static int8_t sensor_static_write_data(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr)
static void sensor_static_delay_us(uint32_t us, void *private_data)
float microTeslaToGauss(float ut)
Converts microTesla to Gauss.
float calculateHeading(const MagnetometerData &data, float declination=0.0f)
Calculate heading (yaw) angle from magnetometer data in radians.
Structure representing magnetometer data.
RawVector raw
raw data
float heading_degrees
heading angle (degrees)
float heading
heading angle (radians)
bool skip_data
skip data flag
SensorVector magnetic_field
magnetic field strength (Gauss)
bool overflow
data overflow flag
int16_t x
X-axis raw value.
int16_t y
Y-axis raw value.
int16_t z
Z-axis raw value.
uint32_t latency
Reporting latency in milliseconds.
float sample_rate
Sample rate in Hz.
float range
Measurement range.
SensorType type
Type of the sensor.
OperationMode mode
Operation mode.
uint8_t version
Hardware/firmware version.
uint8_t i2c_address
Default I2C address.
uint32_t uid
Unique identifier.
SensorType type
Sensor type.
const char * manufacturer
Manufacturer name.
const char * model
Model name/identifier.
float x
X-axis component.
float y
Y-axis component.
float z
Z-axis component.