今回は、Raspberry Pi PicoとMPU6050モジュールを使用し、加速度、角速度、温度を取得して計算する方法について解説します。
Raspberry Pi Picoは小型のマイクロコントローラボードであり、MPU6050はMEMSアクセラレータとジャイロスコープを備えたセンサーモジュールです。
他のセンサーの関係上、流行りのPythonではなく、C言語で解説していきます。
必要な材料と接続方法
まず、必要な材料と接続方法について説明します。
- Raspberry Pi Pico
- MPU6050モジュール
- ジャンパーワイヤー
- ブレッドボード
Raspberry Pi PicoとMPU6050の接続
Raspberry Pi PicoとMPU6050のピンを接続します。
以下の接続を行ってください。
Raspberry Pi Pico | MPU6050 |
---|---|
GP4 | SDA |
GP5 | SCL |
3.3V | VCC |
GND | GND |
ソースコードの解説
それでは、実際にMPU6050から加速度、角速度、温度を取得するためのソースコードを解説します。
完成したソースコードがある参考サイトはこちらです。
MPU6050をリセットする関数
まず、mpu6050_reset
関数は、MPU6050をリセットするための関数です。
MPU6050をリセットすることで、デバイスの初期状態に戻すことができます。
リセットのためには、I2C通信を使用して特定のレジスタにデータを書き込む必要があります。
以下はmpu6050_reset
関数の詳細です。
1 2 3 4 |
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にデータを送信します。addr
はMPU6050のI2Cアドレスを指定する変数です。
センサーからデータを取得する関数
次のmpu6050_read_raw
関数は、MPU6050から生の加速度、角速度、温度データを読み取るための関数です。
以下はmpu6050_read_raw
関数の詳細です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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から生のデータを読み取り、正確な物理単位に変換することができます。
メイン関数
それでは、これら上記の関数を使って取得した生のデータから、有用な値を求めるために計算していきます。
以下のソースコードをご覧ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
(ソースコード省略) 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の初期化を行います。
1 2 3 4 5 |
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をリセットします。
1 |
mpu6050_reset(); |
そして、無限ループ内でMPU6050からデータを読み取ります。
1 2 3 4 5 6 7 8 9 |
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から生の加速度、角速度、温度データを読み取ります。
それぞれのデータは変数acceleration
、gyro
、temp
に格納されます。
加速度と角速度の計算方法
取得した生の加速度と角速度の値は、それ自体では直接的に有用な値ではありません。
したがって、これらの値を正確な物理単位に変換する必要があります。
具体的な変換方法は、MPU6050のデータシートに記載されています。
以下に変換方法の例を示します。
- 加速度の単位は「G」(重力加速度)
- 角速度の単位は「度/秒」
角速度は±250deg/s、加速度が±2G想定です。
1 2 3 4 |
// 加速度(2G)用の変換係数(生値→[m/s2]) ※32767/2/9.8 #define ACCE_RANGE 1671.8 // 角速度(250[deg/s])用の変換係数(生値→[deg/s]) ※32767/250 #define GYRO_RANGE 131.1 |
なので、取得した生データから、上で設定した変換係数で割ると、実際の単位でデータを得られます。
1 2 3 4 5 6 |
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 PicoとMPU6050を使用して、加速度、角速度、温度を取得する方法について解説しました。
また、ソースコードを使用して、MPU6050から生のデータを読み取り、正確な物理単位に変換する方法を説明しました。
MPU6050は、制御系システムやロボットなどのプロジェクトで広く使用されるセンサーモジュールです。
この記事を参考に、Raspberry Pi PicoとMPU6050を使ったプロジェクトを楽しんでください!
コメント