「ロボットアームって、なんか難しそう…逆運動学とか数学が必要なんでしょ?」

そう思って諦めかけているあなた、ちょっと待ってください。

実は、逆運動学(Inverse Kinematics)を一切使わなくても、Arduinoとサーボモーターがあれば動くロボットアームは作れるんですよね。数式ゼロ・行列計算ゼロで、可動する3軸ロボットアームをゼロから組み上げていきましょう!

この記事では、部品の選び方から回路配線、Arduinoのスケッチ(コード)まで一気通貫で解説します。途中でつまずかないよう、確認ステップも丁寧に挟んでいくので、ぜひ最後まで読んでみてください 🙌

この記事の対象読者と難易度

robot arm Arduino servo
robot arm Arduino servo / Photo by Tanha Tamanna Syed via Pexels
  • ✅ Arduino の基本操作(Lチカ・シリアル通信)は経験あり
  • ✅ サーボモーターを単体で動かしたことがある(または興味がある)
  • ✅ 逆運動学・線形代数の知識は不要!
  • 🔰 難易度:初〜中級者向け(Arduino 中級工作)

「サーボモーター複数制御って難しいんじゃないの?」というイメージがあるかもしれません。でも、コツさえ掴めばシンプルです。一緒にやっていきましょう 💪

必要な部品リスト

まず用意するものをまとめます。特別なものは少なく、電子工作ショップや通販で揃えられます。

部品名 数量 備考
Arduino UNO(またはMEGA) 1枚 UNOでも可・MEGAなら余裕あり
SG90 サーボモーター 3〜4個 180°回転タイプ
外部電源(5V・2A以上) 1個 USB電源ではNG!後述します
ブレッドボード 1枚 配線の確認用
ジャンパー線 適量 オス-オス・オス-メス
可変抵抗(10kΩ) 3〜4個 手動制御する場合
ロボットアームフレーム(3Dプリント or アクリル) 1式 市販キット or 自作

⚠️ 電源まわりは超重要です

サーボモーターを複数同時に動かすとき、Arduino本体のピンから電源を取るのは絶対にNGです。サーボ1個でも起動時に1A近い電流が流れることがあります。

必ず外部電源(5V・2A以上)を用意して、Arduinoとサーボの電源を分けてください。GNDだけは共通にします(これが地味に重要なポイント!)。

ロボットアームの構造を理解しよう

今回作るのは「3軸ロボットアーム」です。軸(ジョイント)が3つあるシンプルな構成で、イメージとしてはこんな感じです。

  • 🔄 ベース回転(軸1):左右に回る土台部分
  • 🦾 ショルダー(軸2):腕全体を前後に動かす
  • 💪 エルボー(軸3):先端部分を折り曲げる
  • グリッパー(オプション):物を掴む爪の開閉

「逆運動学なし」というのは、「目標座標(X, Y, Z)からサーボ角度を計算する処理を使わない」ということです。今回は可変抵抗(ポテンショメータ)で直接サーボ角度を指定する方式を採用します。つまり人が手でツマミを回して各軸を操作する、という直感的な仕組みです。

数学ゼロで動く、これが今回の最大のポイントですよね 😄

回路の配線

配線のざっくりとした流れはこんな感じです。

  1. 外部電源の5V → サーボの赤線(VCC)に接続
  2. 外部電源のGND → サーボの茶線(GND)Arduino GNDを共通接続
  3. サーボのオレンジ線(信号線)→ Arduino デジタルPWMピン(例:9, 10, 11番)
  4. 可変抵抗(3本足):両端を5VとGNDに、真ん中をArduinoアナログピンA0〜A2に接続

ピンアサイン早見表

役割 Arduinoピン 接続先
ベース回転サーボ(信号) D9(PWM) サーボ1 オレンジ線
ショルダーサーボ(信号) D10(PWM) サーボ2 オレンジ線
エルボーサーボ(信号) D11(PWM) サーボ3 オレンジ線
ベース可変抵抗(中点) A0 ポテンショメータ1
ショルダー可変抵抗(中点) A1 ポテンショメータ2
エルボー可変抵抗(中点) A2 ポテンショメータ3

配線が終わったら、一度サーボを外した状態で電圧と配線の確認をしておきましょう。テスターで5Vが出ているか確認してから接続するのが安全です。

Arduinoスケッチ①:基本の可変抵抗制御

まずは1番シンプルな実装です。可変抵抗を回すとサーボが追随する、一番ベーシックなコードです。

// ===================================
// ロボットアーム 基本制御スケッチ
// 可変抵抗3つでサーボ3軸を直接操作
// ===================================

#include <Servo.h>

// サーボオブジェクトを3つ作成
Servo baseServo;      // ベース回転軸
Servo shoulderServo;  // ショルダー軸
Servo elbowServo;     // エルボー軸

// アナログピン番号(可変抵抗の中点を接続)
const int BASE_POT     = A0;
const int SHOULDER_POT = A1;
const int ELBOW_POT    = A2;

void setup() {
  // サーボをPWMピンに紐付け
  baseServo.attach(9);
  shoulderServo.attach(10);
  elbowServo.attach(11);

  Serial.begin(9600);
  Serial.println("ロボットアーム 起動完了!");
}

void loop() {
  // アナログ値(0〜1023)を読み取り
  int baseVal     = analogRead(BASE_POT);
  int shoulderVal = analogRead(SHOULDER_POT);
  int elbowVal    = analogRead(ELBOW_POT);

  // 0〜1023 → 0〜180度に変換(map関数を使う)
  int baseAngle     = map(baseVal,     0, 1023, 0, 180);
  int shoulderAngle = map(shoulderVal, 0, 1023, 0, 180);
  int elbowAngle    = map(elbowVal,    0, 1023, 0, 180);

  // 各サーボに角度を送信
  baseServo.write(baseAngle);
  shoulderServo.write(shoulderAngle);
  elbowServo.write(elbowAngle);

  // シリアルモニタで確認用
  Serial.print("Base: ");     Serial.print(baseAngle);
  Serial.print(" | Shoulder: "); Serial.print(shoulderAngle);
  Serial.print(" | Elbow: ");   Serial.println(elbowAngle);

  delay(20);  // サーボの追随に余裕を持たせる
}

ポイントをまとめるとこんな感じです。

  • 🔑 Servo.h ライブラリで複数サーボを簡単に制御できます
  • 🔑 analogRead() で可変抵抗の値(0〜1023)を取得
  • 🔑 map() 関数で角度に変換するのが定番テクニックです
  • 🔑 delay(20) でサーボの動作が追いつく余裕を確保

Arduinoスケッチ②:スムーズな動きを実現する「徐々に動かす」実装


基本実装だとサーボがカクカクすることがありますよね。これを改善するのが「現在角度から目標角度に少しずつ近づける」スムージング処理です。

// ===================================
// ロボットアーム スムーズ制御スケッチ
// 急激な動きを抑えてなめらかに動作させる
// ===================================

#include <Servo.h>

Servo baseServo;
Servo shoulderServo;
Servo elbowServo;

const int BASE_POT     = A0;
const int SHOULDER_POT = A1;
const int ELBOW_POT    = A2;

// 現在の角度を記録する変数(初期値:中間位置の90度)
float currentBase     = 90.0;
float currentShoulder = 90.0;
float currentElbow    = 90.0;

// スムージング係数(0.05〜0.2くらいが自然)
// 小さいほどゆっくり・大きいほど即応性が上がる
const float SMOOTH = 0.1;

void setup() {
  baseServo.attach(9);
  shoulderServo.attach(10);
  elbowServo.attach(11);

  // 初期位置に移動
  baseServo.write(90);
  shoulderServo.write(90);
  elbowServo.write(90);

  Serial.begin(9600);
  delay(500);  // 初期移動の安定待ち
}

void loop() {
  // 目標角度を読み取り
  int targetBase     = map(analogRead(BASE_POT),     0, 1023, 0, 180);
  int targetShoulder = map(analogRead(SHOULDER_POT), 0, 1023, 0, 180);
  int targetElbow    = map(analogRead(ELBOW_POT),    0, 1023, 0, 180);

  // 現在値を目標値に向けて少しずつ近づける(線形補間)
  currentBase     += (targetBase     - currentBase)     * SMOOTH;
  currentShoulder += (targetShoulder - currentShoulder) * SMOOTH;
  currentElbow    += (targetElbow    - currentElbow)    * SMOOTH;

  // サーボへ書き込み(float → int に変換)
  baseServo.write((int)currentBase);
  shoulderServo.write((int)currentShoulder);
  elbowServo.write((int)currentElbow);

  delay(15);
}

ここが重要です!スムーズ制御の仕組みは「現在値と目標値の差の一定割合だけ毎回移動する」というシンプルな数式です。逆運動学のような複雑な計算は一切なし、これだけで見違えるほど動きが滑らかになりますよ 😊

Arduinoスケッチ③:ポーズの記録と再生

ロボットアームをもっと楽しく使うなら「ティーチング再生」機能がおすすめです。可変抵抗で動かした位置を記録して、あとで再生する仕組みです。

// ===================================
// ロボットアーム ティーチング再生スケッチ
// ボタンでポーズを記録→自動で繰り返し再生
// ===================================

#include <Servo.h>

Servo baseServo;
Servo shoulderServo;
Servo elbowServo;

const int BASE_POT     = A0;
const int SHOULDER_POT = A1;
const int ELBOW_POT    = A2;
const int RECORD_BTN   = 7;  // 記録ボタン(GNDとD7を接続)
const int PLAY_BTN     = 6;  // 再生ボタン(GNDとD6を接続)

// ポーズを最大20個まで記録
const int MAX_POSES = 20;
int poseBase[MAX_POSES];
int poseShoulder[MAX_POSES];
int poseElbow[MAX_POSES];
int poseCount = 0;

void setup() {
  baseServo.attach(9);
  shoulderServo.attach(10);
  elbowServo.attach(11);

  // ボタンはプルアップ入力(押すとLOW)
  pinMode(RECORD_BTN, INPUT_PULLUP);
  pinMode(PLAY_BTN,   INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("【記録モード】ポーズを決めてボタン(D7)を押してください");
}

void loop() {
  // 現在の可変抵抗値を読む
  int baseAngle     = map(analogRead(BASE_POT),     0, 1023, 0, 180);
  int shoulderAngle = map(analogRead(SHOULDER_POT), 0, 1023, 0, 180);
  int elbowAngle    = map(analogRead(ELBOW_POT),    0, 1023, 0, 180);

  // サーボをリアルタイムに追随させる
  baseServo.write(baseAngle);
  shoulderServo.write(shoulderAngle);
  elbowServo.write(elbowAngle);

  // 記録ボタンが押されたらポーズを保存
  if (digitalRead(RECORD_BTN) == LOW && poseCount < MAX_POSES) {
    poseBase[poseCount]     = baseAngle;
    poseShoulder[poseCount] = shoulderAngle;
    poseElbow[poseCount]    = elbowAngle;
    poseCount++;

    Serial.print("ポーズ記録! 合計: ");
    Serial.print(poseCount);
    Serial.println(" 個");
    delay(400);  // チャタリング防止
  }

  // 再生ボタンが押されたら記録済みポーズを順番に再生
  if (digitalRead(PLAY_BTN) == LOW && poseCount > 0) {
    Serial.println("===== 再生開始! =====");
    for (int i = 0; i < poseCount; i++) {
      baseServo.write(poseBase[i]);
      shoulderServo.write(poseShoulder[i]);
      elbowServo.write(poseElbow[i]);

      Serial.print("ポーズ "); Serial.print(i + 1);
      Serial.print(" / "); Serial.println(poseCount);
      delay(800);  // 各ポーズの保持時間(ms)
    }
    Serial.println("===== 再生終了! =====");
    delay(400);
  }
}

ティーチング再生のポイントはこちらです。

  • 🎬 記録ボタンを押した瞬間の角度を配列に保存していく
  • ▶️ 再生ボタンで保存した角度を順番にサーボへ送信
  • 🛡️ INPUT_PULLUP でボタンのチャタリングを防止
  • 💡 最大記録数 MAX_POSES はメモリに合わせて調整できます

よくあるトラブルと対処法


実際に組んでいると、こういったトラブルに遭遇することがあります。

サーボが震える・振動する

電源不足が最大の原因です。外部電源のアンペア数を確認してください。また電源ライン(5V・GND)に100µF前後の電解コンデンサを並列に入れると安定します。

サーボが一方向にしか動かない

map() 関数の最小・最大値の設定ミスが多いです。Serial.println() で実際のアナログ値を確認しましょう。

Arduino がリセットを繰り返す

→ サーボ起動時の突入電流でArduinoの電圧が落ちています。GNDを必ず共通にした上で、外部電源のアンペア数を上げてください。

サーボが設定角度まで動かない

→ SG90 の可動範囲は実際には 0〜180度に届かないことがあります。map() の範囲を 10〜170 に狭めると安全に動かせます。

発展編:シリアル通信でPCからコマンド制御

可変抵抗での操作に慣れたら、次はPCからシリアル通信でコマンドを送って動かす方法も試してみましょう。Arduino側のスケッチはこんな感じです。

// ===================================
// シリアル通信でコマンド受信して制御
// 送信例:「B90」→ベースを90度に移動
//         「S45」→ショルダーを45度
//         「E120」→エルボーを120度
// ===================================

#include <Servo.h>

Servo baseServo;
Servo shoulderServo;
Servo elbowServo;

void setup() {
  baseServo.attach(9);
  shoulderServo.attach(10);
  elbowServo.attach(11);

  baseServo.write(90);
  shoulderServo.write(90);
  elbowServo.write(90);

  Serial.begin(9600);
  Serial.println("コマンド待機中... 例: B90 / S45 / E120");
}

void loop() {
  if (Serial.available() > 0) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();

    if (cmd.length() < 2) return;

    char axis  = cmd.charAt(0);           // 先頭1文字が軸指定
    int  angle = cmd.substring(1).toInt(); // 残りが角度

    // 角度を0〜180の範囲に制限
    angle = constrain(angle, 0, 180);

    switch (axis) {
      case 'B': case 'b':
        baseServo.write(angle);
        Serial.print("ベース → "); Serial.println(angle);
        break;
      case 'S': case 's':
        shoulderServo.write(angle);
        Serial.print("ショルダー → "); Serial.println(angle);
        break;
      case 'E': case 'e':
        elbowServo.write(angle);
        Serial.print("エルボー → "); Serial.println(angle);
        break;
      default:
        Serial.println("不明なコマンド。B/S/E のいずれかを使ってください");
    }
  }
}

シリアルモニタから B90 と入力してエンターを押すと、ベースが90度に動きます。これができると、次はPythonから自動でコマンドを送る応用もできますよ 🐍

まとめ

今回の内容をざっくりまとめると、こんな感じです。

  • 逆運動学なしで、可変抵抗×Servo.h ライブラリだけでロボットアームが動かせる
  • 電源の分離(外部電源+GND共通)がサーボ複数制御の最重要ポイント
  • map() 関数で可変抵抗の値を角度に変換するのが基本パターン
  • ✅ スムージング処理を加えると動きが一気になめらかになる
  • ✅ ティーチング再生でロボットらしい繰り返し動作を実現できる
  • ✅ シリアル通信コマンドでPCからの外部制御にも発展できる

「ロボットアームは難しい」という先入観、少し変わりましたか?😊

最初は可変抵抗でサーボを1個動かすところから始めて、少しずつ軸を増やしていくのがおすすめです。段階的に組み上げていくと、途中でつまずきにくくなりますよ。

ぜひ自分だけのロボットアームを作ってみてください!動いた瞬間の感動、きっと病みつきになります 🤖✨

📡 Arduinoをもっと深く学ぼう!

Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。

Arduinoロボット入門のおすすめコース・部品を見る →

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る

Arduinoをはじめよう 第4版 (Make: PROJECTS)

もしも

Arduinoをはじめよう 第4版 (Make: PROJECTS)

Arduino公式推薦の定番入門書

Amazonで見る

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。