Raspberry Pi Picoで6軸MPU6050モジュールの値を取得する方法

今回は、Raspberry Pi PicoMPU6050モジュールを使用し、加速度、角速度、温度を取得して計算する方法について解説します。
Raspberry Pi Picoは小型のマイクロコントローラボードであり、MPU6050はMEMSアクセラレータとジャイロスコープを備えたセンサーモジュールです。
他のセンサーの関係上、流行りのPythonではなく、C言語で解説していきます。

必要な材料と接続方法

出典:Raspberry Pi Pico(ピンヘッダ実装済) — スイッチサイエンス

まず、必要な材料と接続方法について説明します。

必要なもの
  • Raspberry Pi Pico
  • MPU6050モジュール
  • ジャンパーワイヤー
  • ブレッドボード

Raspberry Pi PicoとMPU6050の接続

Raspberry Pi PicoMPU6050ピンを接続します。
以下の接続を行ってください。

Raspberry Pi PicoMPU6050
GP4SDA
GP5SCL
3.3VVCC
GNDGND
Raspberry Pi PicoとMPU6050の接続

ソースコードの解説

それでは、実際にMPU6050から加速度角速度温度を取得するためのソースコードを解説します。
完成したソースコードがある参考サイトはこちらです。

MPU6050をリセットする関数

まず、mpu6050_reset関数は、MPU6050をリセットするための関数です。
MPU6050をリセットすることで、デバイスの初期状態に戻すことができます。
リセットのためには、I2C通信を使用して特定のレジスタにデータを書き込む必要があります。

以下はmpu6050_reset関数の詳細です。

static void mpu6050_reset() {
    uint8_t buf[] = {0x6B, 0x80};
    i2c_write_blocking(i2c_default, addr, buf, 2, false);
}

この関数では、bufという配列に2つの要素を持たせ、最初の要素にはリセットするレジスタのアドレス「0x6B」を、2番目の要素にはリセットデータ「0x80」を設定します。
著者の場合は、2番目の要素のリセットデータを「0x00」にしないと上手く取得できませんでした

そして、i2c_write_blocking関数を使用して、I2C通信を介してMPU6050にデータを送信します。
addrMPU6050I2Cアドレスを指定する変数です。

センサーからデータを取得する関数

次のmpu6050_read_raw関数は、MPU6050から生の加速度、角速度、温度データを読み取るための関数です。
以下はmpu6050_read_raw関数の詳細です。

static void mpu6050_read_raw(int16_t accel[3], int16_t gyro[3], int16_t *temp) {
    uint8_t buffer[6];
    uint8_t val = 0x3B;

    i2c_write_blocking(i2c_default, addr, &val, 1, true);
    i2c_read_blocking(i2c_default, addr, buffer, 6, false);

    for (int i = 0; i < 3; i++) {
        accel[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]);
    }

    val = 0x43;
    i2c_write_blocking(i2c_default, addr, &val, 1, true);
    i2c_read_blocking(i2c_default, addr, buffer, 6, false);

    for (int i = 0; i < 3; i++) {
        gyro[i] = (buffer[i * 2] << 8 | buffer[(i * 2) + 1]);
    }

    val = 0x41;
    i2c_write_blocking(i2c_default, addr, &val, 1, true);
    i2c_read_blocking(i2c_default, addr, buffer, 2, false);

    *temp = buffer[0] << 8 | buffer[1];
}

この関数では、まず6バイトのデータを読み取るためのバッファであるbuffer配列を定義します。
次に、val変数に読み取るデータの開始レジスタのアドレスを設定します。

i2c_write_blocking関数を使用し、i2c_defaultを介してMPU6050にアドレスを送信し、その後i2c_read_blocking関数を使用してデータを読み取ります。
accel配列とgyro配列には、バッファから読み取ったデータを適切な形式に変換して格納します。
また、temp変数には温度データが格納されます。

最後に、加速度角速度温度データを取得するためのレジスタのアドレスを変更し、同様の手順を繰り返します。
これらの関数を組み合わせることで、MPU6050から生のデータを読み取り、正確な物理単位に変換することができます。

メイン関数

それでは、これら上記の関数を使って取得した生のデータから、有用な値を求めるために計算していきます。
以下のソースコードをご覧ください。

(ソースコード省略)

int main() {
    stdio_init_all();
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
    #warning i2c/mpu6050_i2c example requires a board with I2C pins
    puts("Default I2C pins were not defined");
#else
    printf("Hello, MPU6050! Reading raw data from registers...\n");

    // This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
    i2c_init(i2c_default, 400 * 1000);
    gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
    gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
    // Make the I2C pins available to picotool
    bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));

    mpu6050_reset();

    int16_t acceleration[3], gyro[3], temp;

    while (1) {
        mpu6050_read_raw(acceleration, gyro, &temp);

        // These are the raw numbers from the chip, so

 will need tweaking to be really useful.
        // See the datasheet for more information
        printf("Acc. X = %d, Y = %d, Z = %d\n", acceleration[0], acceleration[1], acceleration[2]);
        printf("Gyro. X = %d, Y = %d, Z = %d\n", gyro[0], gyro[1], gyro[2]);
        // Temperature is simple so use the datasheet calculation to get deg C.
        // Note this is chip temperature.
        printf("Temp. = %f\n", (temp / 340.0) + 36.53);

        sleep_ms(100);
    }

#endif
    return 0;
}

このソースコードでは、I2Cを使用してMPU6050からデータを読み取ります。
まず、I2C初期化を行います。

i2c_init(i2c_default, 400 * 1000);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);

次に、先程の関数MPU6050をリセットします。

mpu6050_reset();

そして、無限ループ内でMPU6050からデータを読み取ります。

while (1) {
    mpu6050_read_raw(acceleration, gyro, &temp);

    printf("Acc. X = %d, Y = %d, Z = %d\n", acceleration[0], acceleration[1], acceleration[2]);
    printf("Gyro. X = %d, Y = %d, Z = %d\n", gyro[0], gyro[1], gyro[2]);
    printf("Temp. = %f\n", (temp / 340.0) + 36.53);

    sleep_ms(100);
}

上記のソースコードでは、mpu6050_read_raw関数を使用してMPU6050から生の加速度、角速度、温度データを読み取ります。
それぞれのデータは変数accelerationgyrotempに格納されます。

加速度と角速度の計算方法

取得した生の加速度角速度の値は、それ自体では直接的に有用な値ではありません。
したがって、これらの値を正確な物理単位に変換する必要があります。
具体的な変換方法は、MPU6050のデータシートに記載されています。
以下に変換方法の例を示します。

  • 加速度の単位は「G」(重力加速度)
  • 角速度の単位は「度/秒」

角速度±250deg/s加速度±2G想定です。

// 加速度(2G)用の変換係数(生値→[m/s2]) ※32767/2/9.8
#define ACCE_RANGE 1671.8
// 角速度(250[deg/s])用の変換係数(生値→[deg/s]) ※32767/250
#define GYRO_RANGE 131.1

なので、取得した生データから、上で設定した変換係数で割ると、実際の単位でデータを得られます。

printf("Acc. X = %d\n", acceleration[0] / ACCE_RANGE);
    printf("Acc. Y = %d\n", acceleration[1] / ACCE_RANGE);
    printf("Acc. Z = %d\n", acceleration[2] / ACCE_RANGE);
    printf("Gyro. X = %d\n", gyro[0] / GYRO_RANGE );
    printf("Gyro. Y = %d\n", gyro[1] / GYRO_RANGE );
    printf("Gyro. Z = %d\n", gyro[2] / GYRO_RANGE );

温度の計算方法

MPU6050から取得できる温度値は、データシートによると、デバイスの温度ではなく、チップ自体の温度です。
温度を摂氏に変換するには、データシートの計算式を使用します。(ここでは割愛します)

これらの計算方法を使用して、正確な加速度、角速度、温度を取得できます。

まとめ

この記事では、Raspberry Pi PicoMPU6050を使用して、加速度、角速度、温度を取得する方法について解説しました。
また、ソースコードを使用して、MPU6050から生のデータを読み取り、正確な物理単位に変換する方法を説明しました。

MPU6050は、制御系システムやロボットなどのプロジェクトで広く使用されるセンサーモジュールです。
この記事を参考に、Raspberry Pi PicoMPU6050を使ったプロジェクトを楽しんでください!

ソーテック社
¥2,618 (2023/06/27 09:49時点 | Amazon調べ)


Amazonベストセラー

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA