はじめに:「サーボを動かす」その先へ
「サーボモータを動かす」のは電子工作の基本ですが、実はその内部で何が起きているかを知ることで、制御の精度は格段に上がります。
今回は、ホビー用サーボの定番 SG90 を例に、オシロスコープでPWM信号を可視化しながら、その仕組みを深掘りします。単にライブラリを使って動かすだけでなく、「なぜこの信号でこう動くのか」を理解することで、より高度な制御への扉が開きます。
📝 この記事で学べること:
- ホビー用サーボモータの内部構造とフィードバック制御の仕組み
- PWM信号とサーボ制御の関係を視覚的に理解
- オシロスコープを使った信号の可視化と解析方法
- Arduino UNO R4とServo.hライブラリによる正確な角度制御
- 個体差への対応と安定動作のためのハードウェア設計
💡 Arduinoが初めての方へ
Arduino IDEのインストールや基本的な使い方については、こちらの記事をご覧ください:
👉 【Arduino入門】開発環境の準備とLED点滅でHello World!
🎥 実際の動作をご覧ください
まずは、今回の実験の様子をご覧ください。画面左にサーボモータ、右上にシリアルモニタで送信した角度指令値、右下にオシロスコープでリアルタイム観測したPWM信号が表示されています。
シリアルモニタから角度値を送信すると、画面右下の波形の「山の幅(パルス幅)」が変化し、それに応じてサーボモータが指定の角度へ移動するのが確認できます。
🔧 必要な部品リスト
必須部品
| 部品名 | 数量 | 用途 | 参考価格 |
|---|---|---|---|
| Arduino UNO R4 Minima/WiFi | 1個 | メイン制御ボード | 約3,000〜4,000円 |
| SG90 サーボモータ | 1個 | 角度制御用アクチュエータ | 約300〜500円 |
| ジャンパー線(メス-オス/オス-オス) | 3本 | サーボとArduinoの接続 | - |
| 外部電源(5V) | 1個 | サーボモータ用電源 | 約1,000円〜 |
測定・固定用機材(推奨)
| 部品名 | 数量 | 用途 | 参考価格 |
|---|---|---|---|
| オシロスコープ | 1台 | PWM信号の可視化 | 約5,000円〜 |
| プロクソンバイス | 1個 | サーボモータの固定 | 約2,000円 |
| ブレッドボード | 1個 | 配線の整理 | 約300円 |
推奨製品のご紹介
これから始める方におすすめの製品をご紹介します。Arduino本体とサーボモータがあれば、すぐに実験を始められます。
💡 スターターキットがおすすめ
初めての方は、Arduino本体に加えて、ブレッドボード、ジャンパー線、抵抗などの基本部品がセットになったスターターキットが経済的です。
⚠️ 重要な注意点:電源分離の必要性
サーボモータは動作時に大きな電流(最大500mA〜1A)を消費します。Arduino の 5V ピンから直接電源を取ると、電圧降下によって Arduino 自体がリセットされる可能性があります。必ず外部電源を使用し、GND(マイナス側)のみを Arduino と共通接続してください。
🤖 ホビー用サーボの中身はどうなっている?
ブラックボックスになりがちなサーボモータですが、その中には小さな「ロボットシステム」が凝縮されています。
サーボモータの内部構造
SG90サーボモータの内部構造(分解図)
1. 小型DCモータ
動力源です。非常に高速で回転しますが、そのままでは力(トルク)が弱く、角度制御もできません。
2. 減速ギア
モータの高速回転をゆっくりな回転に変換し、代わりに強力な**トルク(回転力)**を生み出します。SG90では約1:200の減速比を持ち、数千回転/分の回転を数十回転/分まで減速します。
3. ポテンショメータ(可変抵抗)
出力軸の角度を検知するセンサーです。出力軸に機械的に連結されており、角度に応じて抵抗値(=電圧)が変化します。これが「現在角度」の情報源となります。
4. 制御基板(ドライバIC)
ここが心臓部です。Arduino からの「指示(PWM信号)」とポテンショメータからの「現在の角度」を常に比較し、一致するまでモータを回し続けます。
フィードバック制御の仕組み
これが フィードバック制御(閉ループ制御) と呼ばれるメカニズムです。
┌──────────────────────────────────────┐
│ Arduino からの指令(目標角度) │
│ ↓ │
│ 制御基板がPWM信号を解釈 │
│ ↓ │
│ モータを回転させる │
│ ↓ │
│ ポテンショメータが現在角度を測定 │
│ ↓ │
│ 目標角度と比較 → 一致? │
│ NO → さらに回転(ループ) │
│ YES → 停止 │
└──────────────────────────────────────┘
💡 重要なポイント
Arduino はモータを直接回しているのではなく、中の基板に対して**「何度の位置にいてください」と命令を送っているだけ**なのです。実際の位置制御は、サーボ内部の制御回路が自律的に行っています。
📡 制御の鍵「PWM信号」をオシロスコープで見る
サーボへの命令は、PWM(Pulse Width Modulation:パルス幅変調) という方式で行われます。
PWM信号の基本仕様
サーボが求める信号には、決まったルールがあります。
周期(Period)
約 20ms(50Hz)。20ミリ秒に1回、信号が立ち上がります。これは1秒間に50回パルスを送ることを意味します。
パルス幅(Pulse Width)
信号が「ON(HIGH)」になっている時間。この長さで角度が決まります。
サーボ制御用PWM信号の周期とパルス幅
一般的な仕様値(理論値)
標準的なサーボモータのPWM信号仕様は以下の通りです:
| パルス幅 | 角度 |
|---|---|
| 1.0 ms | 0度 |
| 1.5 ms | 90度(中立位置) |
| 2.0 ms | 180度 |
しかし、実際のSG90のような安価なサーボは、この仕様に個体差があります。
オシロスコープでの実測結果
今回の実験で確認した、実際のSG90の動作範囲は以下の通りでした:
オシロスコープで観測したSG90のPWM信号(実測値)
| パルス幅 | 角度 | 備考 |
|---|---|---|
| 0.5 ms (500μs) | 0度付近 | 実際に動作する最小値 |
| 1.45 ms (1450μs) | 90度(中立) | 個体により±0.05ms程度のズレあり |
| 2.4 ms (2400μs) | 180度付近 | 実際に動作する最大値 |
⚠️ 個体差への対応が重要
SG90のような安価なサーボは、このパルス幅の定義に個体差があるため、実機で波形を見ながら「どこまで回せるか」を確認するのが「思い通り」に動かす近道です。
なぜオシロスコープが必要なのか?
オシロスコープを使うことで、以下の情報が視覚的に確認できます:
- パルス幅の正確な測定:理論値と実測値の違いを確認
- 信号の周期確認:正しく50Hzで送信されているか
- ノイズの検出:電源ノイズなどの外乱を発見
- 個体差の把握:そのサーボの実際の動作範囲を特定
💻 Arduinoでの実践コード解説
Arduino標準の Servo.h ライブラリを使えば、複雑なタイマー処理を意識せずに制御できます。
基本的な制御プログラム
#include <Servo.h>
const int SERVO_PIN = 9; // サーボ信号線を接続するピン
Servo myServo;
void setup() {
Serial.begin(115200);
// 個体差に合わせてパルス幅の最小・最大を指定するのがコツ!
// attach(pin, min_pulse_width_us, max_pulse_width_us)
myServo.attach(SERVO_PIN, 500, 2400);
Serial.println("=== Arduino Servo Control ===");
Serial.println("Enter angle (0-180):");
}
void loop() {
if (Serial.available() > 0) {
int angle = Serial.parseInt();
// 入力値の範囲チェック
if (angle >= 0 && angle <= 180) {
myServo.write(angle); // 角度を指定
Serial.print("Command: ");
Serial.print(angle);
Serial.println(" degrees");
} else {
Serial.println("Error: Angle must be 0-180");
}
// シリアルバッファをクリア
while (Serial.available() > 0) {
Serial.read();
}
}
}
コードの重要ポイント解説
1. myServo.attach() の第2・第3引数
myServo.attach(SERVO_PIN, 500, 2400);
この2つの数値がキモです:
- 第2引数(500):0度の位置で出力するパルス幅(マイクロ秒)
- 第3引数(2400):180度の位置で出力するパルス幅(マイクロ秒)
デフォルト値は attach(SERVO_PIN) で 1000μs と 2000μs ですが、SG90の実際の動作範囲に合わせて調整することで、可動範囲を最大限に活用できます。
2. シリアル通信の設定
Serial.begin(115200);
Arduino UNO R4は高速なマイコンなので、115200 bps の高速通信が安定して使えます。オシロスコープでの観測と同時にシリアルモニタを使う場合、高速通信の方が画面更新がスムーズです。
3. 入力値の検証
if (angle >= 0 && angle <= 180) {
// 処理
}
不正な値をサーボに送らないよう、必ず範囲チェックを行います。範囲外の値を送ると、サーボが限界位置で無理に動こうとして消費電流が増え、故障の原因になります。
より高度な制御:スムーズな角度遷移
急激な角度変化を避け、滑らかに動かすコード例:
#include <Servo.h>
const int SERVO_PIN = 9;
Servo myServo;
int currentAngle = 90; // 現在の角度
int targetAngle = 90; // 目標角度
void setup() {
Serial.begin(115200);
myServo.attach(SERVO_PIN, 500, 2400);
myServo.write(currentAngle);
Serial.println("=== Smooth Servo Control ===");
Serial.println("Enter target angle (0-180):");
}
void loop() {
// シリアル入力の処理
if (Serial.available() > 0) {
int input = Serial.parseInt();
if (input >= 0 && input <= 180) {
targetAngle = input;
Serial.print("Target: ");
Serial.println(targetAngle);
}
while (Serial.available() > 0) Serial.read();
}
// スムーズに角度を変化させる
if (currentAngle < targetAngle) {
currentAngle++;
myServo.write(currentAngle);
delay(15); // 15msごとに1度ずつ変化
} else if (currentAngle > targetAngle) {
currentAngle--;
myServo.write(currentAngle);
delay(15);
}
}
このコードでは、目標角度に向かって1度ずつ、15msごとに変化させることで、機械的な衝撃を減らし、サーボの寿命を延ばすことができます。
⚠️ なぜ analogWrite() ではダメなのか?
Arduino初心者が陥りやすい落とし穴として、「PWMだから analogWrite() で制御できるはず」という誤解があります。
周波数の違いが致命的
Arduino の analogWrite() は、主にLEDの調光などに使われる関数で、以下のような高速PWMを出力します:
| Arduino ボード | 周波数 | 周期 |
|---|---|---|
| UNO(ピン5, 6を除く) | 約490 Hz | 約2.04 ms |
| UNO(ピン5, 6) | 約980 Hz | 約1.02 ms |
一方、サーボモータが求めるPWM信号は:
| 仕様 | 周波数 | 周期 |
|---|---|---|
| サーボ制御信号 | 50 Hz | 20 ms |
約10〜20倍も速い信号を送ることになります。
何が起きるのか?
サーボ内部の制御回路は「20msに1回、パルスが来る」ことを前提に設計されています。しかし analogWrite() では:
- 1秒間に490〜980回もパルスが来る
- 制御回路が「命令が速すぎる!」とパニック状態に
- サーボが震える、異音を発する、最悪の場合は発熱・破損
⚠️ 絶対に守るべきルール
サーボモータを制御する際は、必ず Servo.h ライブラリを使い、50Hzの適切な信号を送りましょう。
🔌 安定した動作のためのハードウェアの工夫
動画でも実践している通り、精密な制御には環境作りが欠かせません。
1. 電源の分離
なぜ電源分離が必要か?
サーボモータは、以下のような大電流を消費します:
| 動作状態 | 消費電流 |
|---|---|
| 無負荷(停止中) | 約10〜50 mA |
| 軽負荷動作時 | 約100〜300 mA |
| 最大負荷(ストール)時 | 500 mA〜1 A |
Arduino の 5V ピンから供給できる電流は最大 500mA 程度で、これを超えると:
- 電圧降下が発生
- Arduino の動作電圧が下がる
- マイコンがリセットされる(ブラウンアウト)
- プログラムが停止・誤動作
正しい接続方法
外部5V電源 ─┬─ サーボモータ(赤:VCC)
│
└─ Arduino 5V ピン(接続しない!)
GND共通 ────┬─ サーボモータ(茶:GND)
├─ Arduino GND
└─ 外部電源 GND
Arduino D9 ──── サーボモータ(橙:信号線)
💡 推奨電源
- USB電源アダプタ(5V 2A以上)
- 安定化電源
- 単3電池4本(約6V)+ レギュレータ
2. 物理的固定の重要性
サーボがガタつくと:
- 反動で正確な角度が出せない
- ポテンショメータの読み取り値がブレる
- オシロスコープでの測定結果が不安定になる
バイスなどでしっかりと土台を固定することで、安定した測定が可能になります。特にオシロスコープで波形を観測する場合、物理的な振動はノイズとして現れるため、固定は必須です。
3. 配線のノイズ対策
- 信号線はできるだけ短く:長い配線はアンテナとなり、ノイズを拾う
- 信号線とGNDをツイスト(ねじる):電磁ノイズをキャンセル
- 電源線と信号線を離す:電源のスイッチングノイズが混入しないように
📊 実験データと考察
個体差の実測データ
同じSG90を3個用意し、それぞれの実際の動作範囲を測定しました:
| サーボNo. | 0度時のパルス幅 | 90度時のパルス幅 | 180度時のパルス幅 |
|---|---|---|---|
| #1 | 500 μs | 1450 μs | 2400 μs |
| #2 | 520 μs | 1470 μs | 2380 μs |
| #3 | 480 μs | 1440 μs | 2420 μs |
最大で ±40μs の個体差があることが分かりました。この差は角度にすると約 ±3.6度 に相当します。
🎓 まとめ:仕組みを知ればもっと楽しくなる
シリアルモニタから値を送り、それが電気信号(PWM)に変わり、モータが物理的に動く。この一連の流れをオシロスコープで可視化すると、ブラックボックスだったサーボモータが、非常に論理的で愛着の持てるパーツに見えてきませんか?
この記事で学んだこと
✅ サーボモータの内部構造とフィードバック制御の原理
✅ PWM信号の仕様とオシロスコープでの可視化方法
✅ Servo.hライブラリの正しい使い方と個体差への対応
✅ 電源分離やノイズ対策などのハードウェア設計の重要性
✅ analogWrite() が使えない理由と周波数の違い
次のステップ
今回の知識を基に、以下のような応用に挑戦してみてください:
- 複数サーボの同時制御:ロボットアームの製作
- センサー連動:超音波センサーと組み合わせた自動追尾
- インピーダンス制御:電流監視で障害物検知(次回予告!)
🔍 専門用語解説
サーボモータ(Servo Motor)
指定した角度に正確に回転し、その位置を保持できるモーター。フィードバック制御により、目標角度と現在角度を常に比較して制御する。
PWM(Pulse Width Modulation:パルス幅変調)
デジタル信号のON時間(パルス幅)を変化させることで、アナログ的な制御を実現する技術。サーボ制御では、パルス幅で角度を指定する。
フィードバック制御(Feedback Control)
出力(現在の角度)を測定し、目標値との差を計算して制御量を調整する方式。閉ループ制御とも呼ばれる。
ポテンショメータ(Potentiometer:可変抵抗)
回転角度に応じて抵抗値が変化する素子。サーボモータでは角度センサーとして使用される。
デューティ比(Duty Cycle)
PWM信号の1周期において、ON時間が占める割合。サーボ制御では、周期20msに対するパルス幅の比率。
オシロスコープ(Oscilloscope)
電気信号の電圧変化を時間軸で表示する測定器。PWM信号の波形やパルス幅を正確に測定できる。
ストール(Stall)
モーターが負荷により回転できない状態。サーボがストールすると大電流が流れ、発熱や破損の原因となる。
ブラウンアウト(Brownout)
電圧降下により、マイコンが正常に動作できなくなる現象。サーボの大電流により発生しやすい。
📚 関連記事
- 【Arduino入門】開発環境の準備とLED点滅でHello World!
- 【Arduino電子ピアノ】圧電ブザーで音楽演奏!tone関数の使い方完全ガイド
- 【Arduinoで電子工作】AD変換の基礎:電圧値のリアルタイム可視化とPWM制御
💬 次回予告
次回は、この「サーボに流れる電流」を監視することで、障害物を検知するインピーダンス制御編に挑戦します!サーボが「何かにぶつかった」ことを電流値から判断し、自動停止する仕組みを実装します。お楽しみに!
質問や改善案があれば、コメント欄でお気軽にお知らせください。