Skip to content

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

@senshu-hiro

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions