M5Stack(Basicを除く)で作る電子コンパス

注意:手持ち M5Stack Fire(MPU9250)でしか試していない


 けっこうドリフト(値が変動)するので、そこら辺が気になる人は移動平均処理を追加するとよい。
 10回くらいで平均を取ると、それなりに値が安定して見えるようになる。


 3つのボタンを下にして置いた状態のとき

magCount[0] Y軸
magCount[1] X軸
magCount[2] Z軸

という風に、X軸とY軸とが入れ替わるので要注意


 三角形を描画するにあたり、Z軸を無視して描くだけで、もれなくそれっぽくなるという w

// define must ahead #include <M5Stack.h>
// #define M5STACK_MPU6886 
#define M5STACK_MPU9250 
// #define M5STACK_MPU6050
// #define M5STACK_200Q

#include <LovyanGFX.hpp>
#define _M5DISPLAY_H_
class M5Display {};

#include <M5Stack.h>

static LGFX lcd;
static LGFX_Sprite sprite(&lcd);

#include "utility/MPU9250.h"
MPU9250 IMU;

// the setup routine runs once when M5Stack starts up
void setup(){

  // Initialize the M5Stack object
  M5.begin();
  M5.Power.begin();
  M5.IMU.Init();
  IMU.initMPU9250();
  delay(100);
  IMU.initAK8963(IMU.magCalibration);

  IMU.magbias[0] = -120;
  IMU.magbias[1] = -1475;
  IMU.magbias[2] = -120;

  lcd.init();
  lcd.setColorDepth(16);
  sprite.setColorDepth(8);
  sprite.createSprite(320, 240);  
  lcd.fillScreen(TFT_BLACK);
  sprite.setTextColor(TFT_WHITE);
}

// the loop routine runs over and over again forever
void loop() {
  if (IMU.readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01) {
    IMU.readMagData(IMU.magCount);
    IMU.getMres();

    float mg_0 = (float)IMU.magCount[0] * IMU.mRes * IMU.magCalibration[0] - IMU.magbias[0];
    float mg_1 = (float)IMU.magCount[1] * IMU.mRes * IMU.magCalibration[1] - IMU.magbias[1];
    float mg_2 = (float)IMU.magCount[2] * IMU.mRes * IMU.magCalibration[2] - IMU.magbias[2];

    float at = atan(mg_0 / mg_1);
    float x = cos(PI / 2 - at) * 20;
    float y = sin(PI / 2 - at) * 20;

    sprite.clear();
    sprite.fillTriangle(160 - x, 120 - y, 160 + x, 120 + y, 160 + mg_1 / 3, 120 - mg_0 / 3, TFT_RED);

    sprite.setTextSize(1);
    sprite.setCursor(0, 0);
    sprite.printf("Bias:%f %f %f", IMU.magbias[0], IMU.magbias[1], IMU.magbias[2]);
    sprite.setCursor(0, 10);
    sprite.printf("Calb:%f %f %f", IMU.magCalibration[0], IMU.magCalibration[1], IMU.magCalibration[2]);
    sprite.setCursor(0, 20);
    sprite.printf("mres:%f", IMU.mRes);
    sprite.setCursor(0, 40);
    sprite.printf("coun:%6d %6d %6d", (int16_t)IMU.magCount[0], (int16_t)IMU.magCount[1], (int16_t)IMU.magCount[2]);

    sprite.setTextSize(2);
    sprite.setCursor(0, 190);
    sprite.printf(" %6.1f %6.1f %6.1f", mg_0, mg_1, mg_2);

    sprite.pushSprite(0, 0);
  }

  delay(100);
}