スキップしてメイン コンテンツに移動

サーボモーターを動かしてみよう(SG90制御入門)

 今回は**ラジコンサーボ(RCサーボ)**を動かしてみます。

ロボットを作るときや、センサーと組み合わせて何かを動かしたいときなど、RCサーボはとてもよく使われる部品です。小さなモーターにギアや制御回路が内蔵されていて、指定した角度まで正確に動かせるのが特徴です。

そこで今回は、代表的なサーボモーター「SG90」を使って、サーボを動かす基本的な仕組みや制御方法を学んでいきましょう。

🌀 そもそも「PWM」ってなに?

**PWM(Pulse Width Modulation:パルス幅変調)**とは、
デジタル信号(ONかOFFだけ)を工夫して「出力の強さ」や「角度」を調整する方法です。

  • サーボモーターは 50Hz の PWM信号(1秒間に50回)で角度を決めます。

  • 「ONにしている時間(パルス幅)」を変えると、サーボの角度が変わります。

パルス幅(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 上で)

  1. Pico W にこのファイルを保存して実行(▶ボタン)

  2. Thonny のシェルに表示されるメニューに従い、l / r / m / t / q を入力

  3. サーボが指示通りに動くことを確認します

電源に注意
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ステップに分けて動かすことで、スムーズになります。


コメント

このブログの人気の投稿

Raspberry Pi Pico Wを使ってみよう

   Raspberry Pi Pico W(ラズベリーパイ ピコ ダブリュー) は、英国 Raspberry Pi 財団が 2022 年に発売した Wi-Fi 搭載マイコンボードです。従来の「Raspberry Pi」と聞くと Linux が動くシングルボードコンピュータ(SBC)を思い浮かべがちですが、Pico W は マイクロコントローラ (MCU)に分類され、いわゆる “組み込み開発” を手軽に始められるデバイスです。搭載 MCU はデュアルコア Arm Cortex-M0+(133 MHz 動作)の RP2040 。ここに Infineon 製 CYW43439 チップが追加され、 2.4 GHz IEEE 802.11 b/g/n Wi-Fi(BLE 対応 FW も提供中) が使えるのが最大の特徴です。  開発言語は MicroPython や CircuitPython が真っ先に紹介されることが多いのですが、 公式 Pico SDK を使えば C/C++ でも本格的に開発 できます。SDK は CMake ベースで Windows/macOS/Linux いずれでも利用可能。さらに、Arduino Core RP2040 が整備されたことで Arduino IDE 2.x からも “スケッチ感覚” で書き込みが可能 になりました。したがって、 「まずは Python でサッと試す」 「より高速化や省メモリ化が必要になったら C/C++ へ移行」 といった二段構えの学習ルートが取れるのが魅力です。 メニュー(基礎編) 01. Raspberry Pi Pico Wの開発環境を整える。 02. スイッチで 発光ダイオード(LED) を点灯・消灯させる 03. タイマーで発光ダイオード(LED)を1秒ごとに点滅させる 04. シリアル通信(オウム返し ) 05. シリアル通信(発光ダイオードの点灯・消灯) 06. サーボモーターを動かしてみよう(SG90制御入門) 07. DCモータを動かす(PWM) 08. IRリモートでRGBLED点灯 09. アナログ電圧を測定する(ADCの基本) 10. GPIO割り込み処理 11. リレーを駆動してLEDを制御する 12. DFPlayer で MP3 再生 13. 7 セグ 4 ...

スイッチで発光ダイオード(LED)を点灯・消灯させる

 スイッチを使って発光ダイオード(LED)を制御してみましょう。今回は、スイッチをオンにすると LED が点灯し、オフにすると消灯するように動作させます。もちろん、スイッチと LED を直接接続するのではなく、適切な回路を介して制御します。 1.回路 GPIO16 はデジタル入力として使用し、内部プルアップを有効にします。GPIO15 は出力として設定します。なお、接続には 1kΩ(1キロオーム)の抵抗を使用します。 【ソースコード】 # スイッチで LED を ON / OFF する簡単な例 #   GPIO15 : LED(出力)— LOW で消灯、HIGH で点灯 #   GPIO16 : スイッチ(入力)— 内部プルアップ抵抗を使用 # # ※ 配線例 #   LED のアノード → 1 kΩ 抵抗 → GPIO15 #   LED のカソード → GND #   スイッチ片側   → GPIO16 #   スイッチ反対側 → GND # # ★ 動作 #   スイッチを押す(GPIO16 が LOW)   → LED 点灯 #   スイッチを離す(GPIO16 が HIGH) → LED 消灯 from machine import Pin    # GPIO 制御ライブラリ import utime               # 時間関連(今回は使用しないが拡張用に読み込み) led = Pin ( 15 , Pin.OUT)                 # GPIO15 を出力モードに設定(LED 用) sw   = Pin ( 16 , Pin.IN, Pin.PULL_UP)     # GPIO16 を入力モード+内部プルアップ有効 while True:     if sw. value () == 1 :      # プルアップなので押していないときは 1   ...

シリアル通信(オウム返し)

 Raspberry Pi Pico Wは単体で使うのも便利ですが、パソコンや他のマイコンなど、さまざまな機器と通信できるとさらに活用の幅が広がります。 そこで今回は「シリアル通信」について紹介します。 まずは、パソコンから送られてきたデータをPico Wが受け取り、同じデータをそのままパソコンに送り返す、いわゆる「オウム返し(エコー)」を実装してみましょう。 シリアル通信とは? シリアル通信は、マイコンとパソコンや他の機器がデータを1ビットずつ順番に送受信する通信方式です。Raspberry Pi Pico WではUART(Universal Asynchronous Receiver/Transmitter)というハードウェアを使って実現します。 接続回路  id      TX       RX        baudrate     parity    stopbit  0  GPIO0 GPIO1   9600  なし  1  1  GPIO4 GPIO5   9600  なし  1 今回はUART1(GPIO4:TX、GPIO5:RX)を使用します。 ソースコード例 from machine import UART, Pin # UART1ポートを9600bpsで初期化(ボーレートを指定) sirial = UART ( 1 , 9600 ) # UARTの詳細設定: 9600bps 、データビット8、パリティ無し、ストップビット1で初期化 sirial. init ( 9600 , bits = 8 , parity = None, stop = 1 ) # UARTで文字列を送信する(※MicroPythonではバイト列で送るのが正しいため b '' にしたほうが安全) sirial. write (b 'Hello World \n\r ' )  # 起動時に「Hello World」を送信 # メインループ while True:     # 受信バッファにデータが存在するかチェック     if sirial. any () > 0 : ...