Skip to content

IMUの補正が機能しません #253

Description

@senshu-hiro

現象: Core2 において loadOffsetFromNVS() を実行すると、IMU の数値補正が
機能しません。

補正値は、M5Unifiedに含まれる imu.inoを実行して摘要しています。

// --- Check IMU  ---
if (M5.Imu.isEnabled()) {
    if (M5.Imu.loadOffsetFromNVS())
        Serial.println("loadOffsetFromNVS() Ok");
    else
        Serial.println("loadOffsetFromNVS() Ng");
} else {
    // stop
    Serial.println("Fatal: This device does not have an IMU.");
    while (true) { delay(100); }
}

証拠(ログ): 実際に M5_LOGD で出力された巨大な int32_t の数値。

[457][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ax:-3215561
[458][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ay:-1818034
[460][D][IMU_Class.cpp:362] loadOffsetFromNVS(): az:24262248
[466][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gx:2531496
[473][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gy:-2087627
[480][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gz:5125219
[486][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mx:0
[492][D][IMU_Class.cpp:362] loadOffsetFromNVS(): my:0
[498][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mz:0
[508][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ax:-3215561
[511][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ay:-1818034
[517][D][IMU_Class.cpp:362] loadOffsetFromNVS(): az:24262248
[524][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gx:2531496
[530][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gy:-2087627
[537][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gz:5125219
[543][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mx:0
[549][D][IMU_Class.cpp:362] loadOffsetFromNVS(): my:0
[555][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mz:0
loadOffsetFromNVS() Ok

指摘箇所:

IMU_Class::saveOffsetToNVS と loadOffsetFromNVS において、float 値が適切
な変換がなく、 nvs_set_i32 / nvs_get_i32 で扱われていないようです。

  1. ログから読み解ける異常事態

値のスケールがおかしい。

例えば az:24262248。
IMU の生データ(Raw)は通常 16bit (-32768 ~ 32767)です。
それに対して 2400 万 という補正値は明らかに桁が違います。

  1. 原因:

float のバイナリを int として解釈している NVS に保存されているのは、
float (浮動小数点数)のバイナリ と思われますが nvs_get_i32 (32bit
整数として取得)で読み出しているため、ビット列がそのまま整数として
解釈され、このような巨大な数値になっています。

例えば、float の $0.0$ 付近の微小な値は、整数として見ると非常に大き
な数字(IEEE 754 形式)になります。

これでは、M5.Imu.update() 内でこの数値をそのまま(あるいは整数とし
て)生データから引いたり足したりすると、計算結果が飽和(オーバーフ
ロー)するか、デタラメな値になります。

比較: 他の機種(Gray や StickC Plus2)では目立たないが、Core2 の座
標変換ロジックと組み合わさると致命的な誤差になる点。

(写真をご覧ください)

Image

【追記】
上手く機能しているPlus2でのログです。違いはどこにあるのでしょうか。

[ 398][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ax:-645899
[ 399][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ay:-683474
[ 401][D][IMU_Class.cpp:362] loadOffsetFromNVS(): az:6447865
[ 408][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gx:-2441146
[ 414][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gy:249571
[ 421][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gz:511871
[ 427][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mx:0
[ 433][D][IMU_Class.cpp:362] loadOffsetFromNVS(): my:0
[ 439][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mz:0
[ 447][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ax:-645899
[ 451][D][IMU_Class.cpp:362] loadOffsetFromNVS(): ay:-683474
[ 458][D][IMU_Class.cpp:362] loadOffsetFromNVS(): az:6447865
[ 464][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gx:-2441146
[ 471][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gy:249571
[ 478][D][IMU_Class.cpp:362] loadOffsetFromNVS(): gz:511871
[ 484][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mx:0
[ 490][D][IMU_Class.cpp:362] loadOffsetFromNVS(): my:0
[ 496][D][IMU_Class.cpp:362] loadOffsetFromNVS(): mz:0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions