M5Unit-IMU 0.0.2 git rev:e5b00aa
Loading...
Searching...
No Matches
unit_sh200q.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_SH200Q_HPP
11#define M5_UNIT_IMU_UNIT_UNIT_SH200Q_HPP
12
13#include <M5UnitComponent.hpp>
14#include <m5_utility/container/circular_buffer.hpp>
15#include <memory>
16#include "unit_sh200q_data.hpp"
18
19namespace m5 {
20namespace unit {
21
32class UnitSH200Q : public Component,
33 public PeriodicMeasurementAdapter<UnitSH200Q, sh200q::Data>,
35 M5_UNIT_COMPONENT_HPP_BUILDER(UnitSH200Q, 0x6C);
36
37public:
46 struct config_t {
48 bool start_periodic{true};
50 sh200q::AccelRange accel_range{sh200q::AccelRange::G8};
52 sh200q::GyroRange gyro_range{sh200q::GyroRange::DPS2000};
54 sh200q::AccelOdr accel_odr{sh200q::AccelOdr::HZ256};
56 sh200q::GyroOdr gyro_odr{sh200q::GyroOdr::HZ500};
58 sh200q::GyroDlpf gyro_dlpf{sh200q::GyroDlpf::BW50};
59 };
60
63 explicit UnitSH200Q(const uint8_t addr = DEFAULT_ADDRESS);
65 virtual ~UnitSH200Q()
66 {
67 }
68
70 virtual bool begin() override;
73 virtual void update(const bool force = false) override;
74
79 {
80 return _cfg;
81 }
83 void config(const config_t& cfg)
84 {
85 _cfg = cfg;
86 }
88
95 bool writeAccelRange(const sh200q::AccelRange range);
100 bool writeGyroRange(const sh200q::GyroRange range);
108 bool readGyroRange(sh200q::GyroRange& range);
110
119 bool writeAccelOdr(const sh200q::AccelOdr odr);
127 bool writeGyroOdr(const sh200q::GyroOdr odr);
135 bool readGyroOdr(sh200q::GyroOdr& odr);
137
146 bool softReset();
148
151
160 bool startPeriodicMeasurement(const sh200q::AccelRange accel_range, const sh200q::GyroRange gyro_range,
161 const sh200q::AccelOdr accel_odr, const sh200q::GyroOdr gyro_odr,
162 const sh200q::GyroDlpf gyro_dlpf);
170
175 virtual m5::imu::Capability imuSpec() const override
176 {
177 return m5::imu::Capability::Accel | m5::imu::Capability::Gyro | m5::imu::Capability::Temp;
178 }
185 virtual void imuConvertParam(m5::imu::imu_convert_param_t& out) const override;
187
188protected:
189 bool start_periodic_measurement(const sh200q::AccelRange accel_range, const sh200q::GyroRange gyro_range,
190 const sh200q::AccelOdr accel_odr, const sh200q::GyroOdr gyro_odr,
191 const sh200q::GyroDlpf gyro_dlpf);
192 bool start_periodic_measurement();
193 bool stop_periodic_measurement();
194 bool read_measurement(sh200q::Data& d);
195 bool write_register8_verified(const uint8_t reg, const uint8_t val);
196 bool toggle_register_bits(const uint8_t reg, const uint8_t bits);
197
198 M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitSH200Q, sh200q::Data);
199
200private:
201 // Settings for begin(); never written to after that. What is currently on the device lives in
202 // the live-state members below, so config() keeps meaning "what was configured"
203 config_t _cfg{};
204 // Mirrors of the registers this driver can change at runtime. imuConvertParam() needs the range
205 // actually in effect (a stale factor would silently misreport every sample), and the no-argument
206 // startPeriodicMeasurement() resumes from these rather than reverting to _cfg
207 sh200q::AccelRange _accel_range{};
208 sh200q::GyroRange _gyro_range{};
209 sh200q::AccelOdr _accel_odr{};
210 sh200q::GyroOdr _gyro_odr{};
211 sh200q::GyroDlpf _gyro_dlpf{};
212 uint32_t _pushed{}, _consumed{}; // readImuRaw pop counters (do not disturb latest()/oldest())
213 std::unique_ptr<m5::container::CircularBuffer<sh200q::Data>> _data{};
214};
215
216namespace sh200q {
218constexpr uint32_t DEFAULT_STORED_SIZE{8};
219
220namespace command {
222constexpr uint8_t REG_OUTPUT{0x00}; // burst: accel6 + gyro6 + temp2 (little-endian) = 14 bytes
223constexpr uint8_t REG_ACC_CONFIG{0x0E}; // [7] HPF bypass / [4:3] ODR / [0] filter enable
224constexpr uint8_t REG_GYRO_CONFIG{0x0F}; // [4] HPF bypass / [3:1] ODR / [0] filter enable
225constexpr uint8_t REG_GYRO_DLPF{0x11}; // low bits: DLPF setting (ODR-relative bandwidth)
226constexpr uint8_t REG_FIFO_CONFIG{0x12}; // [7:6] buffer mode (00 = bypass)
227constexpr uint8_t REG_ACC_RANGE{0x16}; // [1:0] full scale
228constexpr uint8_t REG_GYRO_RANGE{0x2B}; // [2:0] full scale
229constexpr uint8_t REG_CHIP_ID{0x30}; // = 0x18
230// Undocumented registers: the datasheet register map ends at 0x30. The init sequence in begin()
231// mirrors the original M5StickC library (SH200Q.cpp) verbatim -- no public documentation exists
232// for these, and skipping them leaves the ADC in a bad state.
233constexpr uint8_t REG_ADC_RESET{0xC2}; // bit2 toggled 1 -> 0
234constexpr uint8_t REG_INIT_D8{0xD8}; // bit7 toggled 1 -> 0
235constexpr uint8_t REG_INIT_78{0x78}; // written 0x61 -> 0x00
236constexpr uint8_t REG_SET1{0xBA}; // written 0xC0
237constexpr uint8_t REG_SET2{0xCA}; // bit4 toggled 1 -> 0 ("ADC reset" in the original library)
239} // namespace command
240} // namespace sh200q
241
242} // namespace unit
243} // namespace m5
244#endif
Thin contract between measurement units and consumers (e.g. AHRS)
Definition imu_data_source.hpp:27
Senodia SH200Q 6-axis IMU (accel + gyro + temp). No standalone GROVE unit exists; it is the built-in ...
Definition unit_sh200q.hpp:34
virtual bool begin() override
Begin the unit.
Definition unit_sh200q.cpp:46
bool stopPeriodicMeasurement()
Mark periodic measurement as stopped (bookkeeping only; the chip stays running – call sleep() to powe...
Definition unit_sh200q.cpp:182
virtual m5::imu::Capability imuSpec() const override
Capability of this unit.
Definition unit_sh200q.hpp:175
virtual void imuConvertParam(m5::imu::imu_convert_param_t &out) const override
Gets the conversion parameters for raw IMU data.
Definition unit_sh200q.cpp:343
bool softReset()
Soft reset (the undocumented ADC/init reset dance inherited from the original library),...
Definition unit_sh200q.cpp:84
void config(const config_t &cfg)
Set the configuration.
Definition unit_sh200q.hpp:83
bool readAccelRange(sh200q::AccelRange &range)
Read the accelerometer range from the device (REG_ACC_RANGE bits[1:0])
Definition unit_sh200q.cpp:213
virtual m5::imu::Capability readImuRaw(m5::imu::imu_raw_data_t &out) override
Read the latest raw IMU data.
Definition unit_sh200q.cpp:315
config_t config() const
Gets the configuration.
Definition unit_sh200q.hpp:78
bool startPeriodicMeasurement()
Start periodic measurement in the current settings.
Definition unit_sh200q.cpp:177
bool writeGyroRange(const sh200q::GyroRange range)
Write the gyroscope range.
Definition unit_sh200q.cpp:200
UnitSH200Q(const uint8_t addr=DEFAULT_ADDRESS)
Construct with the I2C address the chip will answer on.
Definition unit_sh200q.cpp:37
virtual void update(const bool force=false) override
Update the unit.
Definition unit_sh200q.cpp:105
bool writeAccelRange(const sh200q::AccelRange range)
Write the accelerometer range.
Definition unit_sh200q.cpp:187
virtual ~UnitSH200Q()
Destructor.
Definition unit_sh200q.hpp:65
bool readGyroRange(sh200q::GyroRange &range)
Read the gyroscope range from the device (REG_GYRO_RANGE bits[2:0])
Definition unit_sh200q.cpp:223
bool readGyroOdr(sh200q::GyroOdr &odr)
Read the gyroscope output data rate from the device (REG_GYRO_CONFIG bits[3:1])
Definition unit_sh200q.cpp:271
bool writeAccelOdr(const sh200q::AccelOdr odr)
Write the accelerometer output data rate.
Definition unit_sh200q.cpp:233
bool readAccelOdr(sh200q::AccelOdr &odr)
Read the accelerometer output data rate from the device (REG_ACC_CONFIG bits[4:3])
Definition unit_sh200q.cpp:260
bool writeGyroOdr(const sh200q::GyroOdr odr)
Write the gyroscope output data rate.
Definition unit_sh200q.cpp:246
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_sh200q.hpp:46
bool start_periodic
Start periodic measurement on begin()?
Definition unit_sh200q.hpp:48
sh200q::AccelOdr accel_odr
Accelerometer output data rate.
Definition unit_sh200q.hpp:54
sh200q::AccelRange accel_range
Accelerometer range.
Definition unit_sh200q.hpp:50
sh200q::GyroRange gyro_range
Gyroscope range.
Definition unit_sh200q.hpp:52
sh200q::GyroOdr gyro_odr
Gyroscope output data rate (also paces the periodic measurement)
Definition unit_sh200q.hpp:56
sh200q::GyroDlpf gyro_dlpf
Gyro low pass filter.
Definition unit_sh200q.hpp:58
One measurement (14 bytes burst from REG_OUTPUT, little-endian – NOT the MPU byte order)
Definition unit_sh200q_data.hpp:101
SH200Q setting enums and measurement data (framework independent)
AccelOdr
Accelerometer output data rate (REG_ACC_CONFIG bits[4:3], normal mode)
Definition unit_sh200q_data.hpp:49
AccelRange
Accelerometer full scale range (REG_ACC_RANGE bits[1:0], register value = enum)
Definition unit_sh200q_data.hpp:25
GyroRange
Gyroscope full scale range (REG_GYRO_RANGE bits[2:0], register value = enum)
Definition unit_sh200q_data.hpp:37
GyroDlpf
Gyro digital low pass filter (REG_GYRO_DLPF). Bandwidths quoted at the default 500 Hz ODR; they scale...
Definition unit_sh200q_data.hpp:73
GyroOdr
Gyroscope output data rate (REG_GYRO_CONFIG bits[3:1])
Definition unit_sh200q_data.hpp:62