M5Unit-IMU 0.0.2 git rev:e5b00aa
Loading...
Searching...
No Matches
unit_mpu6xxx.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_MPU6XXX_HPP
11#define M5_UNIT_IMU_UNIT_UNIT_MPU6XXX_HPP
12
13#include <M5UnitComponent.hpp>
14#include <m5_utility/container/circular_buffer.hpp>
15#include <memory>
16#include "unit_mpu6886_data.hpp"
18
19namespace m5 {
20namespace unit {
21
31class UnitMPU6xxx : public Component,
32 public PeriodicMeasurementAdapter<UnitMPU6xxx, mpu6886::Data>,
34 M5_UNIT_COMPONENT_HPP_BUILDER(UnitMPU6xxx, 0x68);
35
36public:
46 struct config_t {
48 bool start_periodic{true};
50 mpu6886::AccelRange accel_range{mpu6886::AccelRange::G8};
52 mpu6886::GyroRange gyro_range{mpu6886::GyroRange::DPS2000};
54 mpu6886::Dlpf dlpf{mpu6886::Dlpf::BW176};
56 uint8_t sample_rate_div{3};
57 };
58
59 virtual ~UnitMPU6xxx()
60 {
61 }
62
64 virtual bool begin() override;
67 virtual void update(const bool force = false) override;
68
74 {
75 return _cfg;
76 }
79 void config(const config_t& cfg)
80 {
81 _cfg = cfg;
82 }
84
91 bool writeAccelRange(const mpu6886::AccelRange range);
96 bool writeGyroRange(const mpu6886::GyroRange range);
106
109
116 bool writeSampleRateDiv(const uint8_t div);
120 bool readSampleRateDiv(uint8_t& div);
125 bool writeDlpf(const mpu6886::Dlpf dlpf);
129 bool readDlpf(mpu6886::Dlpf& dlpf);
131
139 bool softReset();
141
144
152 bool startPeriodicMeasurement(const mpu6886::AccelRange accel_range, const mpu6886::GyroRange gyro_range,
153 const mpu6886::Dlpf dlpf, const uint8_t sample_rate_div);
161
164
171 bool sleep() override;
179 bool wakeup() override;
181
186 virtual m5::imu::Capability imuSpec() const override
187 {
188 return m5::imu::Capability::Accel | m5::imu::Capability::Gyro | m5::imu::Capability::Temp;
189 }
196 virtual void imuConvertParam(m5::imu::imu_convert_param_t& out) const override;
198
199protected:
201 explicit UnitMPU6xxx(const uint8_t addr = DEFAULT_ADDRESS);
202
206 virtual bool accepts_whoami(const uint8_t id) const = 0;
208 virtual float temperature_res() const = 0;
210 virtual float temperature_offset() const = 0;
212
215 virtual bool start_periodic_measurement(const mpu6886::AccelRange accel_range, const mpu6886::GyroRange gyro_range,
216 const mpu6886::Dlpf dlpf, const uint8_t sample_rate_div);
218 bool stop_periodic_measurement();
219 bool read_measurement(mpu6886::Data& d);
220 bool write_register8_verified(const uint8_t reg, const uint8_t val);
221
222 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitMPU6xxx, mpu6886::Data);
223
224private:
225 // Settings for begin(); never written to after that. What is currently on the device lives in
226 // the live-state members below, so config() keeps meaning "what was configured"
227 config_t _cfg{};
228 // Mirrors of the registers this driver can change at runtime. imuConvertParam() needs the range
229 // actually in effect (a stale factor would silently misreport every sample), and the no-argument
230 // startPeriodicMeasurement() resumes from these rather than reverting to _cfg
231 mpu6886::AccelRange _accel_range{};
232 mpu6886::GyroRange _gyro_range{};
233 mpu6886::Dlpf _dlpf{};
234 uint8_t _sample_rate_div{};
235 uint32_t _pushed{}, _consumed{}; // readImuRaw pop counters (do not disturb latest()/oldest())
236 std::unique_ptr<m5::container::CircularBuffer<mpu6886::Data>> _data{};
237};
238
239namespace mpu6886 {
242constexpr uint32_t DEFAULT_STORED_SIZE{8};
243
244namespace command {
246// Register addresses (I2C addr 0x68/0x69 by AD0 pin)
247constexpr uint8_t REG_GYRO_OFFS_USR{0x13}; // 6 bytes
248constexpr uint8_t REG_SMPLRT_DIV{0x19};
249constexpr uint8_t REG_CONFIG{0x1A};
250constexpr uint8_t REG_GYRO_CONFIG{0x1B};
251constexpr uint8_t REG_ACCEL_CONFIG{0x1C};
252constexpr uint8_t REG_ACCEL_CONFIG2{0x1D};
253constexpr uint8_t REG_FIFO_EN{0x23};
254constexpr uint8_t REG_INT_PIN_CFG{0x37};
255constexpr uint8_t REG_INT_ENABLE{0x38};
256constexpr uint8_t REG_INT_STATUS{0x3A}; // bit0 = DATA_RDY (read clear)
257constexpr uint8_t REG_ACCEL_XOUT_H{0x3B}; // 14 bytes: accel6 + temp2 + gyro6 (big-endian)
258constexpr uint8_t REG_USER_CTRL{0x6A};
259constexpr uint8_t REG_PWR_MGMT_1{0x6B}; // bit7 RESET / bit6 SLEEP / CLKSEL[2:0]
260constexpr uint8_t REG_PWR_MGMT_2{0x6C};
261constexpr uint8_t REG_WHO_AM_I{0x75};
263} // namespace command
264} // namespace mpu6886
265
266} // namespace unit
267} // namespace m5
268#endif
Thin contract between measurement units and consumers (e.g. AHRS)
Definition imu_data_source.hpp:27
Shared base for the TDK InvenSense MPU 6-axis family (accel + gyro + temp)
Definition unit_mpu6xxx.hpp:33
virtual float temperature_offset() const =0
Temperature conversion: degC offset (imu_convert_param_t::temp_offset)
bool writeGyroRange(const mpu6886::GyroRange range)
Write the gyroscope range.
Definition unit_mpu6xxx.cpp:220
UnitMPU6xxx(const uint8_t addr=DEFAULT_ADDRESS)
Protected: UnitMPU6xxx is abstract, constructed only by concrete derived chips.
Definition unit_mpu6xxx.cpp:37
bool stopPeriodicMeasurement()
Stop periodic measurement.
Definition unit_mpu6xxx.cpp:177
bool sleep() override
Put the chip to sleep (REG_PWR_MGMT_1 SLEEP)
Definition unit_mpu6xxx.cpp:182
virtual void imuConvertParam(m5::imu::imu_convert_param_t &out) const override
Gets the conversion parameters for raw IMU data.
Definition unit_mpu6xxx.cpp:349
bool wakeup() override
Wake the chip from sleep()
Definition unit_mpu6xxx.cpp:197
bool readAccelRange(mpu6886::AccelRange &range)
Read the accelerometer range from the device (REG_ACCEL_CONFIG bits[4:3])
Definition unit_mpu6xxx.cpp:233
bool startPeriodicMeasurement()
Start periodic measurement in the current settings.
Definition unit_mpu6xxx.cpp:172
virtual bool accepts_whoami(const uint8_t id) const =0
Accepted WHO_AM_I id(s) for this chip; begin() rejects the device unless this returns true.
virtual m5::imu::Capability imuSpec() const override
Capability of this unit.
Definition unit_mpu6xxx.hpp:186
bool writeAccelRange(const mpu6886::AccelRange range)
Write the accelerometer range.
Definition unit_mpu6xxx.cpp:207
virtual void update(const bool force=false) override
Update the unit.
Definition unit_mpu6xxx.cpp:108
virtual bool start_periodic_measurement(const mpu6886::AccelRange accel_range, const mpu6886::GyroRange gyro_range, const mpu6886::Dlpf dlpf, const uint8_t sample_rate_div)
Virtual: UnitMPU9250 layers its aux-bypass re-open on top (the config write here includes INT_PIN_CFG...
Definition unit_mpu6xxx.cpp:125
bool writeSampleRateDiv(const uint8_t div)
Write the sample rate divider.
Definition unit_mpu6xxx.cpp:253
void config(const config_t &cfg)
Set the configuration.
Definition unit_mpu6xxx.hpp:79
virtual float temperature_res() const =0
Temperature conversion: degC per LSB (imu_convert_param_t::temp_res)
bool readGyroRange(mpu6886::GyroRange &range)
Read the gyroscope range from the device (REG_GYRO_CONFIG bits[4:3])
Definition unit_mpu6xxx.cpp:243
virtual bool begin() override
Begin the unit.
Definition unit_mpu6xxx.cpp:46
virtual m5::imu::Capability readImuRaw(m5::imu::imu_raw_data_t &out) override
Read the latest raw IMU data.
Definition unit_mpu6xxx.cpp:321
config_t config() const
Gets the configuration.
Definition unit_mpu6xxx.hpp:73
bool readDlpf(mpu6886::Dlpf &dlpf)
Read the digital low-pass filter bandwidth from the device (REG_CONFIG bits[2:0])
Definition unit_mpu6xxx.cpp:285
bool writeDlpf(const mpu6886::Dlpf dlpf)
Write the digital low-pass filter bandwidth.
Definition unit_mpu6xxx.cpp:272
bool readSampleRateDiv(uint8_t &div)
Read the sample rate divider from the device (REG_SMPLRT_DIV)
Definition unit_mpu6xxx.cpp:267
bool softReset()
Soft reset (REG_PWR_MGMT_1 DEVICE_RESET), leaving the chip initialized but unconfigured and stopped.
Definition unit_mpu6xxx.cpp:94
Public interface for IMU data providers.
Capability
Capability of the IMU data source (bitwise combinable)
Definition imu_types.hpp:22
Top level namespace of M5Stack.
Definition ahrs_controller.cpp:26
Unit-related namespace.
Raw to physical unit conversion coefficients.
Definition imu_types.hpp:69
Unified raw data (chip-native axes, no remap applied)
Definition imu_types.hpp:57
Settings for begin()
Definition unit_mpu6xxx.hpp:46
mpu6886::AccelRange accel_range
Accelerometer range.
Definition unit_mpu6xxx.hpp:50
uint8_t sample_rate_div
Sample rate divider (ODR = 1000/(1+div) Hz). 3 -> 250Hz.
Definition unit_mpu6xxx.hpp:56
mpu6886::GyroRange gyro_range
Gyroscope range.
Definition unit_mpu6xxx.hpp:52
mpu6886::Dlpf dlpf
Gyro/temp low pass filter.
Definition unit_mpu6xxx.hpp:54
bool start_periodic
Start periodic measurement on begin()?
Definition unit_mpu6xxx.hpp:48
One measurement (14 bytes burst from REG_ACCEL_XOUT_H, big-endian)
Definition unit_mpu6886_data.hpp:72
MPU6886 setting enums and measurement data (framework independent)
AccelRange
Accelerometer full scale range (register value = enum << 3)
Definition unit_mpu6886_data.hpp:24
GyroRange
Gyroscope full scale range (register value = enum << 3)
Definition unit_mpu6886_data.hpp:35
Dlpf
Gyro/temp digital low pass filter (REG_CONFIG reg DLPF_CFG, valid when FCHOICE_B=00)
Definition unit_mpu6886_data.hpp:46