SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
sensor/accelerometer/bma/SensorBMA456H.hpp
Go to the documentation of this file.
1
31#pragma once
32
33#include "../../../SensorBuildOpt.h"
34#if !SENSORLIB_EXCLUDE_BMA456H
35
36#include "SensorBMA4XX.hpp"
37#include "../../../bosch/bma4xx/bma456h.h"
38
40{
41public:
42
50 std::function<void(TapType)> onTap = nullptr;
51 std::function<void()> onStepDetected = nullptr;
52 std::function<void(uint32_t)> onStepCount = nullptr;
53 std::function<void(ActivityType)> onActivity = nullptr;
54 std::function<void(void)> onAnyMotion = nullptr;
55 std::function<void(void)> onNoMotion = nullptr;
56 std::function<void(AccelerometerData &)> onDataReady = nullptr;
57 };
58
65 {
66 _remap_reg_offset = BMA456H_AXES_REMAP_OFFSET;
67 }
68
70
82
87 ~SensorBMA456H() = default;
88
94 void setOnTapCallback(std::function<void(TapType)> cb)
95 {
96 callbacks.onTap = std::move(cb);
97 }
98
103 void setOnStepDetectedCallback(std::function<void()> cb)
104 {
105 callbacks.onStepDetected = std::move(cb);
106 }
107
113 void setOnStepCountCallback(std::function<void(uint32_t)> cb)
114 {
115 callbacks.onStepCount = std::move(cb);
116 }
117
123 void setOnActivityCallback(std::function<void(ActivityType)> cb)
124 {
125 callbacks.onActivity = std::move(cb);
126 }
127
133 void setOnAnyMotionCallback(std::function<void(void)> cb)
134 {
135 callbacks.onAnyMotion = std::move(cb);
136 }
137
143 void setOnNoMotionCallback(std::function<void(void)> cb)
144 {
145 callbacks.onNoMotion = std::move(cb);
146 }
147
153 void setOnDataReadyCallback(std::function<void(AccelerometerData)> cb)
154 {
155 callbacks.onDataReady = std::move(cb);
156 }
157
164 {
165 callbacks = cbs;
166 }
167
174 {
175 return callbacks;
176 }
177
183 {
184 return callbacks;
185 }
186
195 bool enableFeature(uint16_t feature, bool enable)
196 {
197 if (feature & BMA456H_STEP_COUNTER_EN) {
198 if (bma456h_step_detector_enable(BMA4_ENABLE, dev.get()) != 0) {
199 SENSORLIB_LOG_E("bma456h_step_detector_enable failed");
200 return false;
201 }
202 }
203 if (bma456h_feature_enable(feature, enable, dev.get()) != 0) {
204 SENSORLIB_LOG_E("bma456h_feature_enable failed");
205 return false;
206 }
207 return true;
208 }
209
217 bool enableDataReady(bool enable = true, InterruptPinMap pin_map = InterruptPinMap::PIN1) override
218 {
219 return enableInterrupt(pin_map, BMA4_DATA_RDY_INT, enable);
220 }
221
233 bool enableStepCounter(bool enable, uint16_t step_counter_wm = 1, bool reset_counter = false) override
234 {
235
236 if (bma456h_step_counter_set_watermark(step_counter_wm, dev.get()) != 0) {
237 SENSORLIB_LOG_E("Failed to set step counter watermark");
238 return false;
239 }
240
241 if (reset_counter) {
242 if (bma456h_reset_step_counter(dev.get()) != 0) {
243 SENSORLIB_LOG_E("Failed to reset step counter");
244 return false;
245 }
246 }
247 return enableFeature(BMA456H_STEP_COUNTER_EN, enable);
248 }
249
256 bool getStepCounterWatermark(uint16_t &step_counter_wm) const
257 {
258 return bma456h_step_counter_get_watermark(&step_counter_wm, dev.get()) == 0;
259 }
260
270 bool enableStepDetector(bool enable, bool interrupt_enable = false,
271 InterruptPinMap pin_map = InterruptPinMap::PIN1) override
272 {
273 if (!enableInterrupt(pin_map, BMA456H_STEP_CNTR_INT, interrupt_enable)) {
274 return false;
275 }
276 return enableFeature(BMA456H_STEP_DETECTOR_EN, enable);
277 }
278
288 bool enableTapDetector(bool enable, bool interrupt_enable = false,
289 InterruptPinMap pin_map = InterruptPinMap::PIN1) override
290 {
291 if (!enableInterrupt(pin_map, BMA456H_TAP_OUT_INT, interrupt_enable)) {
292 return false;
293 }
294 return enableFeature(BMA456H_SINGLE_TAP_EN | BMA456H_DOUBLE_TAP_EN | BMA456H_TRIPLE_TAP_EN, enable);
295 }
296
305 bool enableActivityRecognition(bool enable, bool interrupt_enable = false,
306 InterruptPinMap pin_map = InterruptPinMap::PIN1) override
307 {
308 if (!enableInterrupt(pin_map, BMA456H_ACTIVITY_INT, interrupt_enable)) {
309 return false;
310 }
311 return enableFeature(BMA456H_STEP_ACTIVITY_EN, enable);
312 }
313
323 bool enableAnyMotionDetection(const MotionAxesConfig &cfg, bool enable,
324 bool interrupt_enable = false,
325 InterruptPinMap pin_map = InterruptPinMap::PIN1) override
326 {
327 uint16_t interrupt_sources = 0;
328 uint16_t feature = 0;
329 if (cfg.x_axis) feature |= BMA456H_ANY_MOTION_X_AXIS_EN;
330 if (cfg.y_axis) feature |= BMA456H_ANY_MOTION_Y_AXIS_EN;
331 if (cfg.z_axis) feature |= BMA456H_ANY_MOTION_Z_AXIS_EN;
332
333 if (cfg.x_axis || cfg.y_axis || cfg.z_axis) {
334 interrupt_sources |= BMA456H_ANY_MOT_INT;
335 }
336
337 if (!enableInterrupt(pin_map, BMA456H_ANY_MOT_INT, interrupt_enable)) {
338 return false;
339 }
340 return enableFeature(feature, enable);
341 }
342
343
353 bool enableNoMotionDetection(const MotionAxesConfig &cfg, bool enable,
354 bool interrupt_enable = false,
355 InterruptPinMap pin_map = InterruptPinMap::PIN1) override
356 {
357 uint16_t feature = 0;
358 if (cfg.x_axis) feature |= BMA456H_NO_MOTION_X_AXIS_EN;
359 if (cfg.y_axis) feature |= BMA456H_NO_MOTION_Y_AXIS_EN;
360 if (cfg.z_axis) feature |= BMA456H_NO_MOTION_Z_AXIS_EN;
361
362 if (!enableInterrupt(pin_map, BMA456H_NO_MOT_INT, interrupt_enable)) {
363 return false;
364 }
365 return enableFeature(feature, enable);
366 }
367
409 bool configNoMotion(uint16_t threshold, uint16_t duration) override
410 {
411 return configMotion(false, threshold, duration);
412 }
413
455 bool configAnyMotion(uint16_t threshold, uint16_t duration) override
456 {
457 return configMotion(true, threshold, duration);
458 }
459
503 bool configMotion(bool any_motion, uint16_t threshold, uint16_t duration) override
504 {
505 int8_t rslt = 0;
506
507 if (threshold > 16380) { // Max threshold based on 0.48mg resolution for 16g range
508 SENSORLIB_LOG_E("Threshold %u exceeds recommended maximum (16380)", threshold);
509 }
510
511 if (duration > 16383) { // Maximum 14-bit value
512 SENSORLIB_LOG_E("Duration %u exceeds recommended maximum (16383)", duration);
513 }
514
515 struct bma456h_any_no_mot_config any_mot_config = {0, 0, 0, 0};
516
517 if (any_motion) {
518 rslt = bma456h_get_any_mot_config(&any_mot_config, dev.get());
519 if (rslt != 0) {
520 SENSORLIB_LOG_E("bma456h_an_get_any_mot_config failed");
521 return false;
522 }
523 } else {
524 rslt = bma456h_get_no_mot_config(&any_mot_config, dev.get());
525 if (rslt != 0) {
526 SENSORLIB_LOG_E("bma456h_get_no_mot_config failed");
527 return false;
528 }
529 }
530
531 any_mot_config.threshold = threshold;
532 any_mot_config.duration = duration;
533
534 SENSORLIB_LOG_D("Configuring motion detection: threshold=%u LSB (%.2f mG), duration=%u LSB (%.2f ms at 50Hz)",
535 threshold, threshold * 0.48f,
536 duration, duration * 20.0f);
537
538 if (any_motion) {
539 if (bma456h_set_any_mot_config(&any_mot_config, dev.get()) != 0) {
540 SENSORLIB_LOG_E("Failed to configure any-motion detection");
541 return false;
542 }
543 } else {
544 if (bma456h_set_no_mot_config(&any_mot_config, dev.get()) != 0) {
545 SENSORLIB_LOG_E("Failed to configure no-motion detection");
546 return false;
547 }
548 }
549 return true;
550 }
551
552
563 bool configAnyMotionInPhysicalUnits(float threshold_mg, float duration_ms) override
564 {
565 uint16_t threshold_lsb = static_cast<uint16_t>(threshold_mg / 0.48f + 0.5f);
566 uint16_t duration_lsb = static_cast<uint16_t>(duration_ms / 20.0f + 0.5f);
567
568 SENSORLIB_LOG_D("Converting: %.2f mg -> %u LSB, %.2f ms -> %u LSB",
569 threshold_mg, threshold_lsb, duration_ms, duration_lsb);
570
571 return configAnyMotion(threshold_lsb, duration_lsb);
572 }
573
574
585 bool configNoMotionInPhysicalUnits(float threshold_mg, float duration_ms) override
586 {
587 uint16_t threshold_lsb = static_cast<uint16_t>(threshold_mg / 0.48f + 0.5f);
588 uint16_t duration_lsb = static_cast<uint16_t>(duration_ms / 20.0f + 0.5f);
589
590 SENSORLIB_LOG_D("Converting: %.2f mg -> %u LSB, %.2f ms -> %u LSB",
591 threshold_mg, threshold_lsb, duration_ms, duration_lsb);
592
593 return configNoMotion(threshold_lsb, duration_lsb);
594 }
595
604 bool getAnyMotionConfig(float &threshold_mg, float &duration_ms)
605 {
606 struct bma456h_any_no_mot_config any_mot_config;
607 if (bma456h_get_any_mot_config(&any_mot_config, dev.get()) != 0) {
608 SENSORLIB_LOG_E("Failed to read motion configuration");
609 return false;
610 }
611
612 threshold_mg = any_mot_config.threshold * 0.48f;
613 duration_ms = any_mot_config.duration * 20.0f;
614
615 SENSORLIB_LOG_D("Current config: threshold=%u LSB (%.2f mg), duration=%u LSB (%.2f ms)",
616 any_mot_config.threshold, threshold_mg,
617 any_mot_config.duration, duration_ms);
618
619 return true;
620 }
621
630 bool getNoMotionConfig(float &threshold_mg, float &duration_ms)
631 {
632 struct bma456h_any_no_mot_config no_mot_config;
633 if (bma456h_get_no_mot_config(&no_mot_config, dev.get()) != 0) {
634 SENSORLIB_LOG_E("Failed to read no-motion configuration");
635 return false;
636 }
637
638 threshold_mg = no_mot_config.threshold * 0.48f;
639 duration_ms = no_mot_config.duration * 20.0f;
640
641 SENSORLIB_LOG_D("Current no-motion config: threshold=%u LSB (%.2f mg), duration=%u LSB (%.2f ms)",
642 no_mot_config.threshold, threshold_mg,
643 no_mot_config.duration, duration_ms);
644
645 return true;
646 }
647
654 uint32_t getStepCount()
655 {
656 uint32_t step_count = 0;
657 if (bma456h_step_counter_output(&step_count, dev.get()) != 0) {
658 SENSORLIB_LOG_E("Failed to read step count");
659 return 0;
660 }
661 return step_count;
662 }
663
670 {
671 return bma456h_reset_step_counter(dev.get()) == 0;
672 }
673
681 {
682 bma456h_out_state activity_type = {0, 0, 0, 0};
683 if (bma456h_output_state(&activity_type, dev.get()) != 0) {
684 SENSORLIB_LOG_E("bma456h_get_activity_type failed");
686 }
687 return static_cast<ActivityType>(activity_type.activity_type);
688 }
689
697 {
698 bma456h_out_state tap_type = { 0, 0, 0, 0 };
699 if (bma456h_output_state(&tap_type, dev.get()) != 0) {
700 SENSORLIB_LOG_E("bma456h_get_tap_type failed");
701 return TapType::NO_TAP;
702 }
703 if (tap_type.triple_tap) {
704 return TapType::TRIPLE_TAP;
705 } else if (tap_type.double_tap) {
706 return TapType::DOUBLE_TAP;
707 } else if (tap_type.single_tap) {
708 return TapType::SINGLE_TAP;
709 }
710 return TapType::NO_TAP;
711 }
712
720 void update() override
721 {
722 if (bma4_read_int_status(&_status, dev.get()) != 0) {
723 return;
724 }
725
726 if (_status == 0) {
727 return;
728 }
729
730 if ((_status & BMA456H_TAP_OUT_INT) && callbacks.onTap) {
732 }
733
734 if ((_status & BMA456H_STEP_CNTR_INT) && callbacks.onStepDetected) {
737 uint32_t step_count = 0;
738 if (bma456h_step_counter_output(&step_count, dev.get()) == 0) {
739 callbacks.onStepCount(static_cast<uint32_t>(step_count));
740 }
741 }
742 }
743
744 if ((_status & BMA456H_ACTIVITY_INT) && callbacks.onActivity) {
746 }
747
748 if ((_status & BMA456H_ANY_MOT_INT) && callbacks.onAnyMotion) {
750 }
751
752 if ((_status & BMA456H_NO_MOT_INT) && callbacks.onNoMotion) {
754 }
755
756 if ((_status & BMA4_ACCEL_DATA_RDY_INT) && callbacks.onDataReady) {
758 if (readData(data)) {
760 }
761 }
762
763 _status = 0;
764 }
765
766private:
772 bool boschInitImpl() override
773 {
774 int8_t rslt = bma456h_init(dev.get());
775 if ( rslt != 0 ) {
776 SENSORLIB_LOG_E("bma456h_init failed with code %d", rslt);
777 return false;
778 }
779 rslt = bma456h_write_config_file(dev.get());
780 if (rslt != 0) {
781 SENSORLIB_LOG_E("bma456h_write_config_file failed with code %d", rslt);
782 return false;
783 }
784 return true;
785 }
786protected:
788 uint16_t _status;
789};
790
791#endif
InterruptPinMap
Enumeration of interrupt pin mapping options.
@ PIN1
Interrupt pin 1.
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
void setCallbacks(const EventCallbacks &cbs)
Set all callbacks at once.
void setOnTapCallback(std::function< void(TapType)> cb)
Set the callback for tap events.
void setOnStepDetectedCallback(std::function< void()> cb)
Set the callback for step detection events.
void setOnActivityCallback(std::function< void(ActivityType)> cb)
Set the callback for activity events.
BMA4XXCapability::Capability getCapabilities() const override
Get supported capabilities.
bool enableTapDetector(bool enable, bool interrupt_enable=false, InterruptPinMap pin_map=InterruptPinMap::PIN1) override
Enable or disable tap detection.
ActivityType getActivityType()
Get the current activity type.
bool getNoMotionConfig(float &threshold_mg, float &duration_ms)
Get current no-motion detection configuration.
bool configAnyMotion(uint16_t threshold, uint16_t duration) override
Configure any-motion detection parameters with detailed unit conversion.
bool configNoMotion(uint16_t threshold, uint16_t duration) override
Configure no-motion detection parameters with detailed unit conversion.
void update() override
Update sensor state and process interrupts.
bool getAnyMotionConfig(float &threshold_mg, float &duration_ms)
Get current motion detection configuration.
void setOnAnyMotionCallback(std::function< void(void)> cb)
Set the any-motion callback for motion events.
void setOnDataReadyCallback(std::function< void(AccelerometerData)> cb)
Set the callback for data ready events.
bool enableStepCounter(bool enable, uint16_t step_counter_wm=1, bool reset_counter=false) override
Enable or disable step counter.
EventCallbacks & getCallbacks()
Get the current callbacks.
bool enableDataReady(bool enable=true, InterruptPinMap pin_map=InterruptPinMap::PIN1) override
Enable data ready interrupt.
bool configAnyMotionInPhysicalUnits(float threshold_mg, float duration_ms) override
Configure any-motion detection using physical units.
void setOnStepCountCallback(std::function< void(uint32_t)> cb)
Set the callback for step count events.
TapType getTapType()
Get the detected tap type.
uint32_t getStepCount()
Get the current step count.
~SensorBMA456H()=default
Destructor for the SensorBMA456H class.
bool enableFeature(uint16_t feature, bool enable)
Enable or disable a specific feature.
bool resetStepCounter()
Reset the step counter.
bool enableStepDetector(bool enable, bool interrupt_enable=false, InterruptPinMap pin_map=InterruptPinMap::PIN1) override
Enable or disable step detector.
bool enableAnyMotionDetection(const MotionAxesConfig &cfg, bool enable, bool interrupt_enable=false, InterruptPinMap pin_map=InterruptPinMap::PIN1) override
Enable or disable any-motion detection.
bool getStepCounterWatermark(uint16_t &step_counter_wm) const
Get the current step counter watermark.
SensorBMA456H()
Constructor for the SensorBMA456H class.
bool enableNoMotionDetection(const MotionAxesConfig &cfg, bool enable, bool interrupt_enable=false, InterruptPinMap pin_map=InterruptPinMap::PIN1) override
Enable or disable no-motion detection.
const EventCallbacks & getCallbacks() const
Get the current callbacks (const version)
bool configMotion(bool any_motion, uint16_t threshold, uint16_t duration) override
Configure any-motion or no-motion detection parameters with detailed unit conversion.
bool configNoMotionInPhysicalUnits(float threshold_mg, float duration_ms) override
Configure no-motion detection using physical units.
bool enableActivityRecognition(bool enable, bool interrupt_enable=false, InterruptPinMap pin_map=InterruptPinMap::PIN1) override
Enable or disable activity recognition.
void setOnNoMotionCallback(std::function< void(void)> cb)
Set the callback for no-motion events.
bool enableInterrupt(InterruptPinMap pin_map, uint16_t interrupt_sources, bool enable)
Enable or disable specific interrupt sources on a pin.
bool readData(AccelerometerData &data) override
Get the accelerometer data.
std::unique_ptr< struct bma4_dev > dev
ActivityType
Activity detection type.
TapType
Tap detection type.
Structure representing accelerometer data.
std::function< void(uint32_t)> onStepCount
Callback for step count updates.
std::function< void(void)> onAnyMotion
Callback for any motion detection.
std::function< void(ActivityType)> onActivity
Callback for activity recognition events.
std::function< void(AccelerometerData &)> onDataReady
Callback for new accelerometer data.
std::function< void(void)> onNoMotion
Callback for no-motion detection.
std::function< void(TapType)> onTap
Callback for tap detection events.
std::function< void()> onStepDetected
Callback for step detection events.
uint8_t z_axis
Enable motion detection on Z-axis (1=enabled, 0=disabled)
uint8_t y_axis
Enable motion detection on Y-axis (1=enabled, 0=disabled)
uint8_t x_axis
Enable motion detection on X-axis (1=enabled, 0=disabled)