MPU6050 完全攻略:Arduino で加速度センサー&ジャイロを使いこなすチュートリアル
このチュートリアルでは、MPU6050 加速度センサーとジャイロスコープセンサーを Arduino で使用する方法を学びます。まず MPU6050 の仕組みとデータの読み取り方法を説明し、その後 2 つの実践例を作成します。 以下の動画をご覧いただくか、書面によるチュートリアルをお読みください。 最初の例では、Processing 開発環境を使用してセンサーの向きの 3D 可視化を行います。2 番目の例では、シンプルな自己安定化プラットフォーム、つまり DIY ジンバルを作成します。MPU6050 の向きと、加速度センサーとジャイロスコープの融合データに基づいて、プラットフォームを水平に保つ 3 つのサーボを制御します。 MPU6050 IMU には、3 軸加速度センサーと 3 軸ジャイロスコープが単一チップに統合されています。 ジャイロスコープは、X、Y、Z 軸に沿った回転速度、つまり時間に対する角位置の変化率を測定します。MEMS 技術とコリオリ効果を使用して測定しますが、詳細については私の「MEMS センサーの仕組み」チュートリアルをご覧ください。ジャイロスコープの出力は度/秒単位なので、角速度を積分するだけで角位置を取得できます。 一方、MPU6050 加速度センサーは、前回の ADXL345 加速度センサーの動画で説明したのと同じ方式で加速度を測定します。簡単に言うと、3 軸に沿った重力加速度を測定でき、三角関数の数学を使用してセンサーが配置されている角度を計算できます。加速度センサーとジャイロスコープのデータを融合、つまり組み合わせることで、センサーの向きに関する非常に正確な情報を得られます。 MPU6050 IMU は、6 つの出力、つまり 3 つの加速度センサー出力と 3 つのジャイロスコープ出力を持つため、6 軸モーショントラッキングデバイスまたは 6 DoF(6 自由度)デバイスとも呼ばれます。 Arduino を使用して MPU6050 センサーを接続し、データを読み取る方法を見てみましょう。Arduino との通信に I2C プロトコルを使用するため、電源用の 2 本に加えて、わずか 2 本のワイヤーで接続できます。 この Arduino チュートリアルに必要なコンポーネントは以下のリンクから入手できます: MPU6050 センサーからデータを読み取る Arduino コードです。コードの下に詳細な説明があります。 コードの説明: まず、I2C 通信に使用される Wire.h ライブラリをインクルードし、データ格納用の変数を定義します。 setup では、Wire ライブラリを初期化し、電源管理レジスタを通じてセンサーをリセットする必要があります。そのためには、センサーのデータシートを参照してレジスタアドレスを確認できます。 また、希望すれば加速度センサーとジャイロスコープのフルスケールレンジを設定レジスタで選択できます。この例では、加速度センサーのデフォルト ±2g レンジとジャイロスコープの 250 度/秒レンジを使用するため、この部分はコメントアウトしておきます。 loop ではまず加速度センサーデータの読み取りから始めます。各軸のデータは 2 バイトまたはレジスタに格納されており、これらのレジスタのアドレスはセンサーのデータシートから確認できます。 すべてを読み取るために、最初のレジスタから開始し、requestFrom() 関数を使用して X、Y、Z 軸のすべて 6 レジスタの読み取りを要求します。その後、各レジスタからデータを読み取り、出力が 2 の補数形式であるため、適切に組み合わせて正しい値を取得します。 角度計算に適した -1g から +1g の出力値を得るために、以前に選択した感度で出力を割ります。 最終的に、以下の 2 つの式を使用して加速度センサーデータからロールとピッチ角度を計算します。 次に、同じ方法でジャイロスコープデータを取得します。 6 つのジャイロスコープレジスタを読み取り、データを適切に組み合わせ、以前に選択した感度で割って度/秒単位の出力を取得します。 ここでは、計算された小さなエラー値で出力値を補正していることがわかります。これについては後で説明します。出力が度/秒なので、時間を掛けて度単位の角度を取得します。時間値は、millis() 関数を使用して各読み取りイテレーションの前に取得されます。 最後に、相補フィルターを使用して加速度センサーとジャイロスコープのデータを融合します。ここでは、外部の力の影響を受けず非常に正確なジャイロスコープデータの 96% を採用します。ジャイロスコープの欠点はドリフトすること、つまり時間の経過とともに出力に誤差が生じることです。したがって、長期的には加速度センサーのデータ、この場合は 4% を使用して、ジャイロスコープのドリフト誤差を除去します。 しかし、加速度センサーデータからヨーを計算できないため、ヨーには相補フィルターを実装できません。 結果を見る前に、エラー補正値の取得方法を簡単に説明します。これらのエラーを計算するには、センサーを平らで静止した状態にして calculate_IMU_error() カスタム関数を呼び出します。ここではすべての出力について 200 回読み取り、合計して 200 で割ります。センサーを平らで静止した状態で保持しているため、期待される出力値は 0 です。この計算でセンサーが生じる平均エラーを取得できます。 シリアルモニターに値を出力し、それらを知ったら、前述のようにロールとピッチの計算、および 3 つのジャイロスコープ出力の両方で実装できます。 最後に、Serial.print 関数を使用してロール、ピッチ、ヨーの値をシリアルモニターに表示し、センサーが正しく動作しているか確認できます。 次に、3D 可視化の例を作るために、Arduino がシリアルポートを通じて送信しているこのデータを Processing 開発環境で受け取るだけです。完全な Processing コードは以下の通り: ここでは Arduino からの着信データを読み取り、適切なロール、ピッチ、ヨー変数に格納します。メインの draw ループでは、これらの値を使用して 3D オブジェクトを回転させます。この場合、特定の色とテキストを持つシンプルな箱です。 スケッチを実行すると、MPU6050 センサーが向きをトラッキングする性能の良さがわかります。3D オブジェクトはセンサーの向きをかなり正確にトラッキングし、非常に反応が良いです。 前述の通り、ヨーには相補フィルターを使用できないため、時間の経過とともにヨーがドリフトするという欠点があります。これを改善するには追加のセンサーが必要です。通常は磁力計を使用し、ジャイロスコープのヨードリフトの長期補正として利用します。しかし、MPU6050 には実際、データのオンボード計算に使用される Digital Motion Processor(DMP)という機能があり、ヨードリフトを除去できます。 これは Digital Motion Processor を使用した同じ 3D 例です。ヨードリフトなしで向きトラッキングがどれだけ正確になったかがわかります。オンボードプロセッサは四元数も計算・出力でき、これは 3 次元での物体の向きと回転を表現するために使用されます。この例では、オイラー角を使用する際に発生するジンバルロックの問題もない四元数を使用して向きを表現しています。 しかし、センサーからこのデータを取得するのは、前述の方法より少し複雑です。まず、Arduino のデジタルピンに追加のワイヤーを接続する必要があります。これは MPU6050 からこのデータタイプを読み取るために使用される割り込みピンです。 コードも少し複雑になるため、Jeff Rowberg 氏の i2cdevlib ライブラリを使用します。このライブラリは GitHub からダウンロードでき、ウェブサイト記事にリンクを掲載します。 ライブラリをインストールしたら、ライブラリから MPU6050_DMP6 例を開きます。この例は各行にコメントが付いており、よく説明されています。 ここでは出力の種類を選択できます:四元数、オイラー角、ヨー・ピッチ・ロール、加速度値、または 3D 可視化用の四元数。このライブラリには 3D 可視化例の Processing スケッチも含まれています。前の例と同じ箱の形状にするために少し修正しました。選択した「OUTPUT_TEAPOT」出力で動作する MPU6050_DMP6 例用の 3D 可視化 Processing コードは以下の通り: ここでは serialEvent() 関数を使用して Arduino から送られてくる四元数を受信し、メインの draw ループでそれらを使用して 3D オブジェクトを回転させます。スケッチを実行すると、四元数が 3 次元でのオブジェクト回転にどれだけ適しているかがわかります。 このチュートリアルを過負荷にしないため、2 番目の例である DIY Arduino ジンバルまたは自己安定化プラットフォームは別の記事に掲載しました。 このチュートリアルに関する質問があれば、下のコメント欄で自由にお尋ねください。また、私の Arduino プロジェクトコレクションもお忘れなくチェックしてください。概要
仕組み

Arduino と MPU6050

MPU6050 Arduino コード
/* Arduino and MPU6050 Accelerometer and Gyroscope Sensor Tutorial by Dejan, https://howtomechatronics.com */
#include <Wire.h>
const int MPU = 0x68; // MPU6050 I2C アドレス
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
void setup() {
Serial.begin(19200);
Wire.begin(); // 通信を初期化
Wire.beginTransmission(MPU); // MPU6050 との通信開始
// MPU=0x68
Wire.write(0x6B); // レジスタ 6B と通信
Wire.write(0x00); // リセット - 6B レジスタに 0 を書き込み
Wire.endTransmission(true); // 送信終了
/*
// 加速度センサー感度設定 - フルスケールレンジ(デフォルト ±2g)
Wire.beginTransmission(MPU);
Wire.write(0x1C); // ACCEL_CONFIG レジスタと通信 (1C hex)
Wire.write(0x10); // レジスタビットを 00010000 に設定 (±8g フルスケールレンジ)
Wire.endTransmission(true);
// ジャイロスコープ感度設定 - フルスケールレンジ(デフォルト ±250deg/s)
Wire.beginTransmission(MPU);
Wire.write(0x1B); // GYRO_CONFIG レジスタと通信 (1B hex)
Wire.write(0x10); // レジスタビットを 00010000 に設定 (1000deg/s フルスケール)
Wire.endTransmission(true);
delay(20);
*/
// この関数を呼び出して、モジュールの IMU エラー値を取得する場合
calculate_IMU_error();
delay(20);
}
void loop() {
// === 加速度センサーデータの読み取り ===
Wire.beginTransmission(MPU);
Wire.write(0x3B); // レジスタ 0x3B (ACCEL_XOUT_H) から開始
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // 合計 6 レジスタ読み取り、各軸の値は 2 レジスタに格納
// ±2g レンジの場合、データシートによると生の値を 16384 で割る必要がある
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X 軸値
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y 軸値
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z 軸値
// 加速度センサーデータから Roll と Pitch を計算
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) 詳細は calculate_IMU_error() 関数参照
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
// === ジャイロスコープデータの読み取り ===
// previousTime = currentTime; // 実際の時刻読み取り前に前の時刻を保存
currentTime = millis(); // 現在の実際の時刻を読み取り
elapsedTime = (currentTime - previousTime) / 1000; // 1000 で割って秒に変換
Wire.beginTransmission(MPU);
Wire.write(0x43); // ジャイロデータ最初のレジスタアドレス 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // 合計 6 レジスタ読み取り、各軸の値は 2 レジスタに格納
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // 250deg/s レンジの場合、データシートによると生の値を 131.0 で割る
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// 計算されたエラー値で出力を補正
GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
GyroY = GyroY - 2; // GyroErrorY ~(2)
GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
// 現在生の値は度/秒 (deg/s) なので、秒 (s) を掛けて角度(度)を取得
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;
// 相補フィルター - 加速度センサーとジャイロの角度値を組み合わせ
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
// シリアルモニターに値を表示
Serial.print(roll);
Serial.print("/");
Serial.print(pitch);
Serial.print("/");
Serial.println(yaw);
}
void calculate_IMU_error() {
// この関数を setup で呼び出して、加速度センサーとジャイロデータのエラーを計算。
// ここから上記の式で使用されるエラー値がシリアルモニターに表示されます。
// IMU を平らな場所に置いて適切な値を取得し、その後正しい値を得られるようにすることに注意
// 加速度センサー値を 200 回読み取り
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;
// すべての読み取り値を合計
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;
}
// 合計を 200 で割ってエラー値を取得
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// ジャイロ値を 200 回読み取り
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
// すべての読み取り値を合計
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;
}
// 合計を 200 で割ってエラー値を取得
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// エラー値をシリアルモニターに表示
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}
// 加速度センサー感度設定 - フルスケールレンジ(デフォルト ±2g)
Wire.beginTransmission(MPU);
Wire.write(0x1C); // ACCEL_CONFIG レジスタと通信 (1C hex)
Wire.write(0x10); // レジスタビットを 00010000 に設定 (±8g フルスケールレンジ)
Wire.endTransmission(true);
// ジャイロスコープ感度設定 - フルスケールレンジ(デフォルト ±250deg/s)
Wire.beginTransmission(MPU);
Wire.write(0x1B); // GYRO_CONFIG レジスタと通信 (1B hex)
Wire.write(0x10); // レジスタビットを 00010000 に設定 (1000deg/s フルスケール)
Wire.endTransmission(true);
delay(20);
// */
// === 加速度センサーデータの読み取り ===
Wire.beginTransmission(MPU);
Wire.write(0x3B); // レジスタ 0x3B (ACCEL_XOUT_H) から開始
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // 合計 6 レジスタ読み取り、各軸の値は 2 レジスタに格納
// ±2g レンジの場合、データシートによると生の値を 16384 で割る必要がある
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X 軸値
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y 軸値
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z 軸値
// 加速度センサーデータから Roll と Pitch を計算
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) 詳細は calculate_IMU_error() 関数参照
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
// === ジャイロスコープデータの読み取り ===
// previousTime = currentTime; // 実際の時刻読み取り前に前の時刻を保存
currentTime = millis(); // 現在の実際の時刻を読み取り
elapsedTime = (currentTime - previousTime) / 1000; // 1000 で割って秒に変換
Wire.beginTransmission(MPU);
Wire.write(0x43); // ジャイロデータ最初のレジスタアドレス 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // 合計 6 レジスタ読み取り、各軸の値は 2 レジスタに格納
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // 250deg/s レンジの場合、データシートによると生の値を 131.0 で割る
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// 計算されたエラー値で出力を補正
GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
GyroY = GyroY - 2; // GyroErrorY ~(2)
GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
// 現在生の値は度/秒 (deg/s) なので、秒 (s) を掛けて角度(度)を取得
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;// 相補フィルター - 加速度センサーとジャイロの角度値を組み合わせ
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;void calculate_IMU_error() {
// この関数を setup で呼び出して、加速度センサーとジャイロデータのエラーを計算。
// ここから上記の式で使用されるエラー値がシリアルモニターに表示されます。
// IMU を平らな場所に置いて適切な値を取得し、その後正しい値を得られるようにすることに注意
// 加速度センサー値を 200 回読み取り
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;
// すべての読み取り値を合計
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;
}
// 合計を 200 で割ってエラー値を取得
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// ジャイロ値を 200 回読み取り
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
// すべての読み取り値を合計
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;
}
// 合計を 200 で割ってエラー値を取得
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// エラー値をシリアルモニターに表示
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}
MPU6050 向きトラッキング – 3D 可視化
/* Arduino and MPU6050 IMU - 3D Visualization Example by Dejan, https://howtomechatronics.com */
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch, yaw;
void setup() {
size(2560, 1440, P3D);
myPort = new Serial(this, "COM7", 19200); // シリアル通信開始
myPort.bufferUntil('\n');
}
void draw() {
translate(width/2, height/2, 0);
background(233);
textSize(22);
text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
// オブジェクトを回転
rotateX(radians(-pitch));
rotateZ(radians(roll));
rotateY(radians(yaw));
// 3D オブジェクト
textSize(30);
fill(0, 76, 153);
box(386, 40, 200); // 箱を描画
textSize(25);
fill(255, 255, 255);
text("www.HowToMechatronics.com", -183, 10, 101);
// delay(10);
// println("ypr:\t" + angleX + "\t" + angleY); // 適切な値が取得できているか確認
}
// シリアルポートからデータを読み取り
void serialEvent(Serial myPort) {
// シリアルポートから改行文字 '\n' までデータを読み取り、文字列変数 "data" に格納
data = myPort.readStringUntil('\n');
// 改行以外のバイトがあった場合:
if (data != null) {
data = trim(data);
// "/" で文字列を分割
String[] items = split(data, '/');
if (items.length > 1) {
//--- ロール、ピッチ(度)
roll = float(items[0]);
pitch = float(items[1]);
yaw = float(items[2]);
}
}
}




/* Arduino and MPU6050 IMU - 3D Visualization Example by Dejan, https://howtomechatronics.com */
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
Serial myPort;
String data="";
float roll, pitch, yaw;
void setup() {
size(2560, 1440, P3D);
myPort = new Serial(this, "COM7", 19200); // シリアル通信開始
myPort.bufferUntil('\n');
}
void draw() {
translate(width/2, height/2, 0);
background(233);
textSize(22);
text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
// オブジェクトを回転
rotateX(radians(-pitch));
rotateZ(radians(roll));
rotateY(radians(yaw));
// 3D オブジェクト
textSize(30);
fill(0, 76, 153);
box(386, 40, 200); // 箱を描画
textSize(25);
fill(255, 255, 255);
text("www.HowToMechatronics.com", -183, 10, 101);
// delay(10);
// println("ypr:\t" + angleX + "\t" + angleY); // 適切な値が取得できているか確認
}
// シリアルポートからデータを読み取り
void serialEvent(Serial myPort) {
// シリアルポートから改行文字 '\n' までデータを読み取り、文字列変数 "data" に格納
data = myPort.readStringUntil('\n');
// 改行以外のバイトがあった場合:
if (data != null) {
data = trim(data);
// "/" で文字列を分割
String[] items = split(data, '/');
if (items.length > 1) {
//--- ロール、ピッチ(度)
roll = float(items[0]);
pitch = float(items[1]);
yaw = float(items[2]);
}
}
}
製造プロセス
- Arduinoで作るセキュアなRFIDロック – ステップバイステップガイド
- Arduino UNOで作るLCDアニメーション&ゲーム入門
- Arduino & MPU6050:SG90 & MG996Rサーボの精密制御
- Python 3からArduino UNOを制御 – シリアル通信でLED点滅デモ
- Arduino NanoとRDA5807Mで作るコンパクトFMラジオ
- Arduino NanoとMPU6050で加速度から傾斜角を算出 - Visuino活用チュートリアル
- Arduino Nanoと指紋センサーで作るバイオメトリクス認証システム – 完全チュートリアル
- Arduino UNOで作るミニピアノ - ステップバイステップチュートリアル
- Raspberry Pi 3とArduinoで作る自作ノートPC:ステップバイステップガイド
- ESP32とArduino 101加速度計でジェスチャー認識 – 簡単DIYチュートリアル
- Arduino初心者チュートリアル01: 最初のプロジェクトを始めよう