入手しやすいデバイスを使って作業効率アップ

M5StackやM5Paperなどを使って効率アップデバイスを作ります。

CoreS3とBMM150

先日、M5StackCoreS3を購入しました。
地磁気センサーのBMM150が標準搭載されており、今まで作った装置の置き換えに使えると考えたからです。
しかし、CoreS3のサンプルスケッチにはBMM150に関する物が見当たりません。
ライブラリをいくつか試したのですが、どれもBMM150を認識しません。

CoreS3の回路図を見ると、I2Cの配線がBMI270を経由しているようなので、
回路構成がこれに近い「M5Unit IMU Pro Mini」のサンプルスケッチを使うことにしました。

ライブラリをインストールして、サンプルスケッチの「getSensorData.ino」を開きます。
このままでは動かないので、一部を修正します。
それと、Grayとはチップの実装方向が違うみたいなので、読み出したデータにー1をかけます。
BMP280に関する部分は削除します。
以下、抜粋です。

    //#define BIM270_SENSOR_ADDR 0x68
    #define BIM270_SENSOR_ADDR 0x69

    //bmi270.init(I2C_NUM_0, BIM270_SENSOR_ADDR);
    bmi270.init(I2C_NUM_1, BIM270_SENSOR_ADDR);

    int16_t mx, my, mz = 0;
    bmi270.readMagneticField(mx, my, mz);
    mx=-mx;
    my=-my;
    mz=-mz;

BMM150のデータは補正が必要です。10秒くらいぐるぐる回して補正データを取得します。
補正部分のソースを掲載します。データはプリファレンス領域に保存します。
補正用データはsetup()で初期化しておきます。
以下、抜粋です。

Preferences prefs;
bmm150_mag_data mag_offset, mag_max, mag_min;

void bmm150_offset_save() {
    prefs.begin("bmm150", false);
    prefs.putBytes("offset", (uint8_t *)&mag_offset, sizeof(bmm150_mag_data));
    prefs.end();
}

void bmm150_offset_load() {
    if (prefs.begin("bmm150", true)) {
        prefs.getBytes("offset", (uint8_t *)&mag_offset, sizeof(bmm150_mag_data));
        prefs.end();
        Serial.println("bmm150 load offset finish....");
    } else {
        Serial.println("bmm150 load offset failed....");
    }
}

void bmm150_calibrate(uint32_t calibrate_time) {
    uint32_t calibrate_timeout = 0;

    M5.Lcd.println("FLIP AND ROTATE");
    M5.Lcd.printf("for %d mseconds\n", calibrate_time);
    
    calibrate_timeout = millis() + calibrate_time;
    while (calibrate_timeout > millis()) {
        if (bmi270.magneticFieldAvailable()) {
            int16_t mx, my, mz = 0;
            bmi270.readMagneticField(mx, my, mz);
            mx=-mx;
            my=-my;
            mz=-mz;
            if (mx) {
                mag_min.x = (mx < mag_min.x) ? mx : mag_min.x;
                mag_max.x = (mx > mag_max.x) ? mx : mag_max.x;
            }
            if (my) {
                mag_max.y = (my > mag_max.y) ? my : mag_max.y;
                mag_min.y = (my < mag_min.y) ? my : mag_min.y;
            }
            if (mz) {
                mag_min.z = (mz < mag_min.z) ? mz : mag_min.z;
                mag_max.z = (mz > mag_max.z) ? mz : mag_max.z;
            }
        }
        delay(100);
    }

    mag_offset.x = (mag_max.x + mag_min.x) / 2;
    mag_offset.y = (mag_max.y + mag_min.y) / 2;
    mag_offset.z = (mag_max.z + mag_min.z) / 2;
    
    M5.Lcd.println(mag_offset.x);
    M5.Lcd.println(mag_offset.y);
    M5.Lcd.println(mag_offset.z);
    
    bmm150_offset_save();
}

void setup() {
    auto cfg = M5.config();
    M5.begin(cfg);
    M5.Ex_I2C.begin();
    M5.Display.setTextSize(2);
    unifiedButton.begin(&M5.Display);

    //bmi270.init(I2C_NUM_0, BIM270_SENSOR_ADDR);
    bmi270.init(I2C_NUM_1, BIM270_SENSOR_ADDR);
    
    mag_max.x = -2000;
    mag_max.y = -2000;
    mag_max.z = -2000;
    mag_min.x =  2000;
    mag_min.y =  2000;
    mag_min.z =  2000;

CoreS3はボタンABCがありませんので、「 unifiedButton」ライブラリを使用しました。
これで移植が簡単になります。