4 #include "../M5Unified.hpp"
9 #if defined(ESP_PLATFORM)
11 #include <sdkconfig.h>
22 static constexpr
char LIBRARY_NAME[] =
"M5Unified";
26 static constexpr
const char* nvs_key_names[9] = {
"ax",
"ay",
"az",
"gx",
"gy",
"gz",
"mx",
"my",
"mz" };
30 #if !defined(M5UNIFIED_PC_BUILD)
41 auto res = mpu6886->begin(i2c);
42 if (!res) {
delete mpu6886; }
45 _imu_instance[0].reset(mpu6886);
46 switch (mpu6886->whoAmI())
62 if (board == m5::board_t::board_M5Atom)
64 _internal_axisorder_fixed[
sensor_index_accel] = (internal_axisorder_t)(axis_invert_x | axis_invert_z);
65 _internal_axisorder_fixed[
sensor_index_gyro ] = (internal_axisorder_t)(axis_invert_x | axis_invert_z);
73 if (!bmi2->begin(i2c)) {
delete bmi2; }
76 _imu_instance[0].reset(bmi2);
79 _internal_axisorder_fixed[
sensor_index_mag] = (internal_axisorder_t)(axis_invert_y | axis_invert_z);
86 if (!sh200q->begin(i2c)) {
delete sh200q; }
89 _imu_instance[0].reset(sh200q);
96 if (!bmm150->begin(i2c)) {
101 _imu_instance[1].reset(bmm150);
102 if (board == m5::board_t::board_M5Stack)
105 _internal_axisorder_fixed[
sensor_index_mag] = (internal_axisorder_t)(axis_invert_x | axis_invert_z);
112 if (!ak8963->begin(i2c)) {
117 _imu_instance[1].reset(ak8963);
120 _internal_axisorder_fixed[
sensor_index_mag ] = (internal_axisorder_t)(axis_order_yxz | axis_invert_z);
130 memset(&_offset_data, 0,
sizeof(imu_offset_data_t));
131 _update_convert_param();
132 _update_axis_order();
138 for (
int i = 0; i < 3; ++i)
140 for (
int j = 0; j < 3; ++j)
143 _offset_data.sensor[i].prev_value[j] = d;
144 _offset_data.sensor[i].avg_value[j] = d;
146 _offset_data.sensor[i].stillness = 255;
147 _offset_data.sensor[i].calibration();
159 void IMU_Class::_update_convert_param(
void)
161 if (_imu_instance[0]) { _imu_instance[0]->getConvertParam(&_convert_param); }
162 if (_imu_instance[1]) { _imu_instance[1]->getConvertParam(&_convert_param); }
165 _offset_data.accel.radius = 1.0f / _convert_param.
accel_res;
166 _offset_data.accel.tolerance = (1.0f / 2048.0f) / _convert_param.
accel_res;
167 _offset_data.accel.noise_level = 0.0625f / _convert_param.
accel_res;
168 _offset_data.accel.average_shifter = 1;
171 _offset_data.gyro.radius = 0;
172 _offset_data.gyro.tolerance = 0.0f / _convert_param.
gyro_res;
173 _offset_data.gyro.noise_level = 2.0f / _convert_param.
gyro_res;
174 _offset_data.gyro.average_shifter = 6;
177 _offset_data.mag.radius = 384.0f / _convert_param.
mag_res;
178 _offset_data.mag.tolerance = 64.0f / _convert_param.
mag_res;
179 _offset_data.mag.noise_level = 96.0f / _convert_param.
mag_res;
180 _offset_data.mag.average_shifter = 1;
185 _offset_data.accel.strength =
accel;
186 _offset_data.gyro.strength =
gyro;
187 _offset_data.mag.strength =
mag;
196 switch ((axis0 >> 1) + ((axis1 >> 1) << 2) + ((axis2 >> 1) << 4))
198 case 0 << 0 | 1 << 2 | 2 << 4: result = axis_order_xyz;
break;
199 case 0 << 0 | 2 << 2 | 1 << 4: result = axis_order_xzy;
break;
200 case 1 << 0 | 0 << 2 | 2 << 4: result = axis_order_yxz;
break;
201 case 1 << 0 | 2 << 2 | 0 << 4: result = axis_order_yzx;
break;
202 case 2 << 0 | 0 << 2 | 1 << 4: result = axis_order_zxy;
break;
203 case 2 << 0 | 1 << 2 | 0 << 4: result = axis_order_zyx;
break;
204 default:
return false;
206 result += (axis0 & 1) + ((axis1 & 1) << 1) + ((axis2 & 1) << 2);
207 _internal_axisorder_user = (internal_axisorder_t)result;
208 _update_axis_order();
212 void IMU_Class::_update_axis_order(
void)
214 static constexpr
const uint8_t internal_axisorder_table[6] =
216 0 << 0 | 1 << 2 | 2 << 4,
217 0 << 0 | 2 << 2 | 1 << 4,
218 1 << 0 | 0 << 2 | 2 << 4,
219 1 << 0 | 2 << 2 | 0 << 4,
220 2 << 0 | 0 << 2 | 1 << 4,
221 2 << 0 | 1 << 2 | 0 << 4,
224 std::uint32_t result = 0;
225 std::uint32_t bitshift = 0;
226 auto axis_order_user = _internal_axisorder_user;
227 auto order_user_tbl = internal_axisorder_table[axis_order_user >> axis_order_shift];
228 for (std::size_t sensor = 0; sensor < 3; ++sensor)
230 auto axis_order_fixed = _internal_axisorder_fixed[sensor];
231 auto order_fixed_tbl = internal_axisorder_table[axis_order_fixed >> axis_order_shift];
232 for (std::size_t j = 0; j < 3; ++j, bitshift += 3)
234 std::uint_fast8_t axis_user_index = (order_user_tbl >> (j << 1)) & 3;
235 bool invert_user = axis_order_user & (1 << j);
238 std::uint_fast8_t axis_fixed_index = (order_fixed_tbl >> (axis_user_index << 1)) & 3;
239 bool invert_fixed = axis_order_fixed & (1 << axis_user_index);
243 result |= ((axis_fixed_index << 1) + (invert_user != invert_fixed ? 1 : 0)) << bitshift;
247 _axis_order_3bit_x9 = result;
253 std::uint_fast8_t axis2 = (1 << (axis0 >> 1) | 1 << (axis1 >> 1)) ^ 0b111;
255 std::uint_fast8_t ax0 = axis2 ? (axis2 - 2) : 4;
256 axis2 += (bool)((axis0 & 0b110) == ax0) == (
bool)((axis0 & 1) == (axis1 & 1));
262 return setAxisOrder(axis0, axis1, getAxis2(axis0, axis1));
268 auto axis2 = getAxis2(axis0, axis1) ^ 1;
274 #if !defined(M5UNIFIED_PC_BUILD)
275 std::uint32_t nvs_handle = 0;
276 if (ESP_OK != nvs_open(LIBRARY_NAME, NVS_READWRITE, &nvs_handle))
281 for (
size_t i = 0; i < 3; ++i)
283 for (
size_t j = 0; j < 3; ++j, ++index)
285 int32_t val = _offset_data.sensor[i].value[j];
286 nvs_set_i32(nvs_handle, nvs_key_names[index], val);
287 M5_LOGV(
"%s:%d", nvs_key_names[index], val);
290 nvs_close(nvs_handle);
297 #if !defined(M5UNIFIED_PC_BUILD)
298 std::uint32_t nvs_handle = 0;
299 if (ESP_OK != nvs_open(LIBRARY_NAME, NVS_READONLY, &nvs_handle))
304 for (
size_t i = 0; i < 3; ++i)
306 for (
size_t j = 0; j < 3; ++j, ++index)
309 nvs_get_i32(nvs_handle, nvs_key_names[index], &val);
310 _offset_data.sensor[i].value[j] = val;
311 M5_LOGD(
"%s:%d", nvs_key_names[index], val);
314 nvs_close(nvs_handle);
322 for (
size_t i = 0; i < 3; ++i)
324 for (
size_t j = 0; j < 3; ++j, ++index)
326 _offset_data.sensor[i].value[j] = 0;
334 _offset_data.sensor[index / 3].value[index % 3] =
value;
340 return index < 9 ? _offset_data.sensor[index / 3].value[index % 3] : 0;
345 return index < 9 ? _raw_data.
value[index] : 0;
351 for (
size_t i = 0; i < 2; ++i)
353 if (_imu_instance[i].get())
355 uint_fast8_t t = _imu_instance[i]->getImuRawData(&_raw_data);
362 _latest_micros = m5gfx::micros();
368 std::uint_fast8_t mask_flg = _calibration_flg & res;
370 for (
size_t i = 0; mask_flg && i < 3; ++i, mask_flg >>= 1)
375 auto st = _offset_data.sensor[i].updateStillness(_raw_data.
sensor[i]);
378 _offset_data.sensor[i].calibration();
393 data->
usec = _latest_micros;
394 auto &raw = _raw_data;
396 auto &offset = _offset_data;
397 auto order = _axis_order_3bit_x9;
398 for (
int i = 0; i < 3; ++i)
400 float resolution = _convert_param.
value[i] * (1.0f / 65536.0f);
401 for (
int j = 0; j < 3; ++j)
403 auto axis_index = (order >> 1) & 3;
404 int32_t
value = (raw.sensor[i].value[axis_index] << 16) - offset.sensor[i].value[axis_index];
415 uint32_t us = m5gfx::micros();
416 if (us - _latest_micros > 256)
431 uint32_t us = m5gfx::micros();
432 if (us - _latest_micros > 256)
447 uint32_t us = m5gfx::micros();
448 if (us - _latest_micros > 256)
463 if (_imu_instance[0].get() && _imu_instance[0]->getTempAdc(&
temp))
474 return _imu_instance[0].get() && _imu_instance[0]->setINTPinActiveLogic(level);
483 for (
int i = 0; i < 3; ++i)
485 int32_t d = dst.
value[i] << 16;
487 int32_t diff = d - pv;
489 maxdiff = std::max(maxdiff, abs(diff));
493 maxdiff = std::max(maxdiff, abs(diff));
504 maxdiff = rt - (maxdiff + 1);
505 maxdiff = (maxdiff << 8) / rt;
511 res = std::min(res, maxdiff);
522 for (
int i = 0; i < 3; ++i)
528 float f = p -
value[i];
532 distance = sqrtf(distance * (1.0f / (65536.0f * 65536.0f)));
533 if (distance < 1.0f) {
return; }
536 float measure_error = distance -
radius;
539 float force = fabsf(measure_error);
543 if (measure_error < 0.0f) { force = -force; }
545 for (
int i = 0; i < 3; ++i)
547 value[i] += roundf(diffs[i] * fk);
std::uint_fast8_t updateStillness(const IMU_Base::point3d_i16_t &dst)
#define M5_LOGD(format,...)
Output Debug log with source info.
#define M5_LOGV(format,...)
Output Verbose log with source info.
bool begin(i2c_port_t port_num, int pin_sda, int pin_scl)
bool getMag(float *mx, float *my, float *mz)
bool begin(I2C_Class *i2c=nullptr, board_t board=board_t::board_unknown)
bool setAxisOrderRightHanded(axis_t axis0, axis_t axis1)
bool saveOffsetToNVS(void)
int16_t getRawData(size_t index)
sensor_mask_t update(void)
bool loadOffsetFromNVS(void)
bool setAxisOrderLeftHanded(axis_t axis0, axis_t axis1)
void clearOffsetData(void)
void setCalibration(uint8_t accel_strength, uint8_t gyro_strength, uint8_t mag_strength)
bool getGyro(float *gx, float *gy, float *gz)
bool setINTPinActiveLogic(bool level)
bool getAccel(float *ax, float *ay, float *az)
const imu_data_t & getImuData(void)
void setOffsetData(size_t index, int32_t value)
bool setAxisOrder(axis_t axis0, axis_t axis1, axis_t axis2)
int32_t getOffsetData(size_t index)
static constexpr const std::uint8_t DEV_ID_MPU9250
static constexpr const std::uint8_t DEV_ID_MPU6050
static constexpr const std::uint8_t DEV_ID_MPU6886