今回は**ラジコンサーボ(RCサーボ)**を動かしてみます。
ロボットを作るときや、センサーと組み合わせて何かを動かしたいときなど、RCサーボはとてもよく使われる部品です。小さなモーターにギアや制御回路が内蔵されていて、指定した角度まで正確に動かせるのが特徴です。
そこで今回は、代表的なサーボモーター「SG90」を使って、サーボを動かす基本的な仕組みや制御方法を学んでいきましょう。
🌀 そもそも「PWM」ってなに?
**PWM(Pulse Width Modulation:パルス幅変調)**とは、
デジタル信号(ONかOFFだけ)を工夫して「出力の強さ」や「角度」を調整する方法です。
パルス幅(ON時間) |
おおよその角度 |
約0.5ms(ミリ秒) |
左端(0度) |
約1.5ms |
真ん中(90度) |
約2.5ms |
右端(180度) |
💡 PWMの周期は「20ms(=1秒 ÷ 50Hz)」で、
その中の 0.5〜2.5ms の間だけピンをONにします。
回路
SG90の線 |
接続先(Pico) |
説明 |
赤(VCC) |
5V(VSYSや外部5V) |
電源(強い電流) |
茶(GND) |
GND |
マイナス(共通) |
橙(PWM) |
GP16(ピン21) |
PWM信号(制御) |
✅ サーボ SG90 を動かす MicroPython コード
# ---------------------------------------------------------------
# Raspberry Pi Pico (W) で SG90 サーボを動かす簡易コンソールツール
#
# コマンド 動作
# ────────────── ────────────────────────────────────────────
# l … 左端まで回転(ステップ指定でゆっくり移動も可)
# r … 右端まで回転(ステップ指定でゆっくり移動も可)
# m … 真ん中(90°付近)へ移動
# t … センター → 右端 → 左端 → センター(デモ)
# q … 終了(PWM を停止してリセット)
#
# ▸ 配線例
# SG90 赤(VCC) : 5 V (Pico の VSYS か外部 5 V) ★電流に余裕のある電源推奨
# SG90 茶(GND) : GND
# SG90 橙(PWM) : GP16 ← 本スクリプトで制御するピン
#
# ▸ 制御のしくみ
# - サーボは 50 Hz (周期 20 ms) の PWM で動く
# - パルス幅 0.5 ms ≒ -90°、1.5 ms ≒ 0°、2.5 ms ≒ +90°
# - Pico の PWM は duty_ns() で“パルス幅(ナノ秒)”を直接指定できる
# ---------------------------------------------------------------
from machine import Pin, PWM
import time
import sys
# ─────────────────────────────────────────────
# 1. サーボ用 PWM 設定(GP16, 50 Hz)
# ─────────────────────────────────────────────
SERVO_PIN = 16
servo = PWM(Pin(SERVO_PIN))
servo.freq(50) # 50 Hz = 周期 20 ms
# パルス幅の最小・最大値(ナノ秒)
MIN_NS = 500_000 # 0.5 ms ≒ -90°
MID_NS = 1_500_000 # 1.5 ms ≒ 0°
MAX_NS = 2_500_000 # 2.5 ms ≒ +90°
def write_ns(pulse_ns):
"""指定したパルス幅(ns)でサーボを駆動"""
servo.duty_ns(int(pulse_ns))
def move_steps(start_ns, end_ns, steps=10, delay=0.5):
"""start → end へ分割ステップでゆっくり移動"""
step_ns = (end_ns - start_ns) / steps
for i in range(steps):
write_ns(start_ns + step_ns * (i + 1))
time.sleep(delay)
def menu():
print("\n==== SG90 Servo Control (Pico W) ====")
print("l = 左へ r = 右へ")
print("m = 中央へ t = デモ")
print("q = 終了")
print("───────────────────────────────────")
# 電源 ON 直後は中央へ
write_ns(MID_NS)
menu()
try:
while True:
cmd = input("Command > ").strip().lower()
# ------ デモ動作 ------
if cmd == "t":
print("センター → 右 → 左 → センター")
write_ns(MID_NS); time.sleep(1)
write_ns(MAX_NS); time.sleep(1)
write_ns(MIN_NS); time.sleep(1)
write_ns(MID_NS)
# ------ 右へ(+90°) ------
elif cmd == "r":
steps = int(input("ステップ数(1-10, Enter): ") or 10)
steps = max(1, min(steps, 10))
print(f"{steps} ステップで右端へ")
move_steps(MIN_NS, MAX_NS, steps)
# ------ 左へ(-90°) ------
elif cmd == "l":
steps = int(input("ステップ数(1-10, Enter): ") or 10)
steps = max(1, min(steps, 10))
print(f"{steps} ステップで左端へ")
move_steps(MAX_NS, MIN_NS, steps)
# ------ 中央へ ------
elif cmd == "m":
print("中央へ移動")
write_ns(MID_NS)
# ------ 終了 ------
elif cmd == "q":
print("プログラムを終了します")
break
# ------ 無効コマンド ------
else:
print("⚠ そのコマンドは無効です")
menu()
finally:
# 終了時に PWM を停止し出力を 0 に
servo.deinit()
print("PWM 停止、終了しました")
使いかた(Thonny 上で)
-
Pico W にこのファイルを保存して実行(▶ボタン)
-
Thonny のシェルに表示されるメニューに従い、l
/ r
/ m
/ t
/ q
を入力
-
サーボが指示通りに動くことを確認します
電源に注意
USB の 5 V でも動きますが、ピーク電流が足りないと位置が不安定になります。安定しない場合は VSYS(5 V) ピンや外部 5 V を使用してください。
"ステップ数(1-10, Enter): "
というプロンプトに書かれている
“1-10” は、ユーザーが入力できる数値の範囲(1 〜 10 の整数) を示しています。
なぜ 1〜10 なの?
-
細かく刻み過ぎない:ステップ数が大きすぎると動きが遅く、面倒になります。
-
粗すぎない:逆に 1〜2 しか選べないと動きがガクッと変わって雑になります。
-
直感的に扱いやすい:10 段階評価は人がイメージしやすいので、初心者にも分かりやすい設定です。
📌 なぜ PWM でサーボが動くの?
サーボモーターには中に制御回路が入っており、
PWM信号を「このパルス幅は何度だな」と判断して内部モーターをその角度に保ちます。
🧠 このプログラムの処理の流れ(わかりやすく)
1. 初期設定
servo = PWM(Pin(16)) # GP16ピンでPWMを開始
servo.freq(50) # 周波数はサーボ用に50Hz
2. 角度ごとのパルス幅(ナノ秒)を定義
MIN_NS = 500_000 # 0.5ms → 左端
MID_NS = 1_500_000 # 1.5ms → 真ん中
MAX_NS = 2_500_000 # 2.5ms → 右端
→ 数字は「ナノ秒」なので、1ms = 1,000,000ns
3. サーボを動かす関数
def write_ns(pulse_ns):
servo.duty_ns(int(pulse_ns))
→ この関数を使って、サーボを「どの角度にするか」を決めます。
🔁 move_steps()
関数
def move_steps(start_ns, end_ns, steps=10, delay=0.5):
・「いきなり動く」のではなく、ステップ(分割)してゆっくり動かす仕組みです。
・たとえば、0度 → 180度 を10ステップに分けて動かすことで、スムーズになります。
コメント
コメントを投稿