Arduino IDEを使って、M5Capsuleに実装されているIMUモジュール「BMI270」入力を行いました。ただし、Arduino IDEでM5Capsuleへのスケッチ書き込みが上手く実行できなくなりました。→ 2024/11/02 スケッチ書き込み手順が確認できました。
M5Capsuleの仕様を次に示します。「M5Capsule」を参照します。
M5Capsuleを次に示します。
開発環境の構築
M5Capsuleのプログラム開発はArduino IDEを使用します。詳細については、「M5AtomS3R Program Compilation & Upload」を参照します。
- メニュー「ファイル」 →「 環境設定」 を選択し、「追加のボードマネージャのURL 」次のURLを設定します。
- サイドバーで開発ボードマネージャを選択し、「M5Stack」を検索してインストールをクリックします。
- インストールが済むと、ボードリストから「M5Capsule」が選択できるようになります。
- メニューから「スケッチ」→「ライブラリをインクルード」→「ライブラリを管理」を開き、次のように「M5Capsule」 をインストールします。
https://static-cdn.m5stack.com/resource/arduino/package_m5stack_index.json
IMU入力プログラムの作成
次の手順でスケッチ例からIMUモジュール「BMI270」の入力プログラムを作成します。
スケッチ例では、出力が液晶パネルへのグラフィック表示となっており、シリアルモニターへのテキスト表示に変更しました。
作成したIMU入力プログラム「capsule_imu.ino」を次に示します。
capsule_imu.ino
// Include this to enable the M5 global instance. #include <M5Unified.h> const char* name = "00"; static constexpr const uint8_t calib_value = 64; static uint8_t calib_countdown = 0; static int prev_xpos[18]; char prnname[256]; void updateCalibration(uint32_t c, bool clear = false) { calib_countdown = c; if (c == 0) { clear = true; } if (clear) { memset(prev_xpos, 0, sizeof(prev_xpos)); //dsp.fillScreen(TFT_BLACK); if (c) { // Start calibration. M5.Imu.setCalibration(calib_value, calib_value, calib_value); // ※ The actual calibration operation is performed each time during M5.Imu.update. // // There are three arguments, which can be specified in the order of Accelerometer, gyro, and geomagnetic. // If you want to calibrate only the Accelerometer, do the following. // M5.Imu.setCalibration(100, 0, 0); // // If you want to calibrate only the gyro, do the following. // M5.Imu.setCalibration(0, 100, 0); // // If you want to calibrate only the geomagnetism, do the following. // M5.Imu.setCalibration(0, 0, 100); } else { // Stop calibration. (Continue calibration only for the geomagnetic sensor) M5.Imu.setCalibration(0, 0, calib_value); // If you want to stop all calibration, write this. // M5.Imu.setCalibration(0, 0, 0); // save calibration values. M5.Imu.saveOffsetToNVS(); } } auto backcolor = (c == 0) ? TFT_BLACK : TFT_BLUE; /* dsp.fillRect(rect_text_area.x, rect_text_area.y, rect_text_area.w, rect_text_area.h, backcolor); if (c) { dsp.setCursor(rect_text_area.x + 2, rect_text_area.y + 1); dsp.setTextColor(TFT_WHITE, TFT_BLUE); dsp.printf("Countdown:%d ", c); } */ } void startCalibration(void) { updateCalibration(10, true); } void setup() { Serial.begin(115200); // put your setup code here, to run once: auto cfg = M5.config(); M5.begin(cfg); switch (M5.Imu.getType()) { case m5::imu_none: name = "not found"; break; case m5::imu_sh200q: name = "sh200q"; break; case m5::imu_mpu6050: name = "mpu6050"; break; case m5::imu_mpu6886: name = "mpu6886"; break; case m5::imu_mpu9250: name = "mpu9250"; break; case m5::imu_bmi270: name = "bmi270"; break; default: name = "unknown"; break; }; M5_LOGI("imu:%s", name); } void loop() { sprintf(prnname, "imu:%s", name); //Serial.println(prnname); //delay(1000); static uint32_t frame_count = 0; static uint32_t prev_sec = 0; // To update the IMU value, use M5.Imu.update. // If a new value is obtained, the return value is non-zero. auto imu_update = M5.Imu.update(); if (imu_update) { // Obtain data on the current value of the IMU. auto data = M5.Imu.getImuData(); //drawGraph(rect_graph_area, data); /* // The data obtained by getImuData can be used as follows. data.accel.x; // accel x-axis value. data.accel.y; // accel y-axis value. data.accel.z; // accel z-axis value. data.accel.value; // accel 3values array [0]=x / [1]=y / [2]=z. data.gyro.x; // gyro x-axis value. data.gyro.y; // gyro y-axis value. data.gyro.z; // gyro z-axis value. data.gyro.value; // gyro 3values array [0]=x / [1]=y / [2]=z. data.mag.x; // mag x-axis value. data.mag.y; // mag y-axis value. data.mag.z; // mag z-axis value. data.mag.value; // mag 3values array [0]=x / [1]=y / [2]=z. data.value; // all sensor 9values array [0~2]=accel / [3~5]=gyro / [6~8]=mag M5_LOGV("ax:%f ay:%f az:%f", data.accel.x, data.accel.y, data.accel.z); M5_LOGV("gx:%f gy:%f gz:%f", data.gyro.x , data.gyro.y , data.gyro.z ); M5_LOGV("mx:%f my:%f mz:%f", data.mag.x , data.mag.y , data.mag.z ); //*/ M5_LOGV("ax:%f ay:%f az:%f", data.accel.x, data.accel.y, data.accel.z); sprintf(prnname, "ax:%f ay:%f az:%f", data.accel.x, data.accel.y, data.accel.z); Serial.println(prnname); M5_LOGV("gx:%f gy:%f gz:%f", data.gyro.x, data.gyro.y, data.gyro.z); sprintf(prnname, "gx:%f gy:%f gz:%f", data.gyro.x, data.gyro.y, data.gyro.z); Serial.println(prnname); M5_LOGV("mx:%f my:%f mz:%f", data.mag.x, data.mag.y, data.mag.z); sprintf(prnname, "mx:%f my:%f mz:%f", data.mag.x, data.mag.y, data.mag.z); Serial.println(prnname); ++frame_count; } else { M5.update(); // Calibration is initiated when a button or screen is clicked. if (M5.BtnA.wasClicked() || M5.BtnPWR.wasClicked() || M5.Touch.getDetail().wasClicked()) { startCalibration(); } } int32_t sec = millis() / 1000; if (prev_sec != sec) { prev_sec = sec; M5_LOGI("sec:%d frame:%d", sec, frame_count); frame_count = 0; if (calib_countdown) { updateCalibration(calib_countdown - 1); } if ((sec & 7) == 0) { // prevent WDT. vTaskDelay(1); } } }
プログラムの書き込み・実行(スケッチ書き込み失敗編)
次のように、エラーメッセージ「A fatal error occured: No serial data received.」が発生するようになりました。スケッチを変更していく過程で、最初はうまくいったArduino IDEでM5Capsuleへのスケッチ書き込みが、上手く実行できなくなりました。
EN,IO0ボタンを使ったような書き込み手順が必要なのかもしれません(参照:M5Stamp Pico MateでLチカ・ボタン入力)。
【 スケッチの書き込み 】
スケッチの書き込みは、書き込みモードで起動します。「BTN 0」と書かれたボタンを押下しながら電源を投入、または「GPIO0」とGNDをショートさせた状態で電源を投入します。この状態でArduino IDEから書き込みの指示を行います。
ダウンロードモードへの切り替え
スケッチ書き込みのためにダウンロードモードに入る必要があります。電源を入れる前に M5Capsule の G00(ステッカーのBTN0の位置) ボタンを押し続け、USB ケーブルを接続してダウンロードモードに入ります。
プログラムの書き込み・実行(スケッチ書き込み成功編)
作成したIMU入力プログラム「capsule_imu.ino」を実行すると、次のようにシリアルモニタにIMUモジュール「BMI270」からのセンサー情報が表示されます。