LEDをPWM制御で明るさを変えてみよう

code

ラズパイピコ(Raspberry Pi Pico)で「Lチカ(LEDを点滅させる)」ができた人、次はもう一歩進んでLEDの明るさを自由にコントロールしてみましょう!

今回は「PWM(パルス幅変調)」という仕組みを使って、LEDの明るさを100%、50%、25%と段階的に変化させます。初心者でも大丈夫。コードをそのまま写して実行すれば、すぐに「光の変化」が体験できます。

しかも、PWMを理解しておくと、次に「モーターの回転数制御」や「LEDフェード効果」など応用にもつながります。この記事では、Raspberry Pi PicoとMicroPythonを使って、楽しく学べる実験を進めていきましょう!

完成イメージ

LEDの明るさが3段階で変化するよ。

この記事でできること(目的とゴール)

この記事では以下のことを学びます:

  • PWM(パルス幅変調)の基本的な考え方
  • Raspberry Pi PicoでLEDの明るさを制御する方法
  • 初心者向けコード → 中級者コード → リファクタリング済みコードへの流れ

PWMは「電気のON/OFFを高速で切り替えて、平均電力で明るさを調整する」技術なんだよ。電気を弱めてるわけじゃないの!

ピコさん
ピコさん
PWMは「電気のON/OFFを高速で切り替えて、平均電力で明るさを調整する」技術なんだよ!

準備:必要な道具と環境

パーツ一覧

品名役割代替案
Raspberry Pi Pico Wマイコン本体Pico(無印)でも可
Micro USBケーブルデータ通信・電源供給Type-A to Micro USB(データ通信対応)
ブレッドボード配線用の土台小型でもOK
ジャンパワイヤ(オス-オス)接続ケーブル色違いで用意すると便利
LED(赤・黄・緑など)点灯テスト用単色1つでも可
抵抗(220〜330Ω)電流制限470Ωでも可

動作環境(筆者の検証環境)

  • PC:MacBook Air (M1, macOS 15.5 arm64)
  • エディタ:Thonny 4.1.6(Python 3.10.11, Tk 8.6.13)
  • デバイス:Raspberry Pi Pico W(MicroPython)

もちろん、Windows や Linux 環境でも動作します。MicroPythonを導入していれば同じコードで実行可能です。

配線図

安全上の注意

  • LEDには極性(+と−)があります。長い脚が+側です。
  • 抵抗を必ず直列に入れましょう。入れ忘れるとLEDが焼ける危険があります。
  • 静電気が強い日や金属テーブル上では、手で基板を触る前に放電しておきましょう。

まずは動くだけのベタ打ちコード(初学者)

最初はPWMを使わず、LEDの点灯・消灯を高速に繰り返して明るさを「擬似的に」変える方法から始めます。

from machine import Pin
from time import sleep

# 定数定義
LED_PIN = 15
LED_ON = 1
LED_OFF = 0
PWM_STEP_TIME = 0.005

# 初期化
led = Pin(LED_PIN, Pin.OUT)

# メインループ
while True:
    # --- 通常点灯(100% duty) ---
    for i in range(20):
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)

    # --- 50% duty(擬似) ---
    for i in range(20):
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)
        led.value(LED_OFF)
        sleep(PWM_STEP_TIME)
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)
        led.value(LED_OFF)
        sleep(PWM_STEP_TIME)

    # --- 25% duty(擬似) ---
    for i in range(20):
        led.value(LED_ON)
        sleep(PWM_STEP_TIME)
        led.value(LED_OFF)
        sleep(PWM_STEP_TIME)
        led.value(LED_OFF)
        sleep(PWM_STEP_TIME)
        led.value(LED_OFF)
        sleep(PWM_STEP_TIME)

単純ですが、これでもLEDの明るさが少しずつ変わって見えます。 この方法は「PWMっぽい」挙動を再現していますが、実際のPWM機能を使ったほうがシンプルで滑らかです。

ピコさん
ピコさん
  PWM_STEP_TIME = 0.005 の数値を変えてみるとPWMの仕組みがわかるよ

リファクタリング①:PWMを使ってシンプルに

MicroPythonには、PWM制御を簡単に扱えるクラスがあります。これを使うとコードが一気にすっきりします。

from machine import Pin, PWM
from time import sleep

# 定数定義
LED_PIN = 15
PWM_FREQ_HZ = 1000  # 周波数(1kHz)
HOLD_SECONDS = 1.0  # 各デューティ比の表示時間(秒)

# 初期化
pwm = PWM(Pin(LED_PIN))
pwm.freq(PWM_FREQ_HZ)

# メインループ
while True:
    # --- 100% duty ---
    pwm.duty_u16(65535)  # 最大値(明るさMAX)
    sleep(HOLD_SECONDS)

    # --- 50% duty ---
    pwm.duty_u16(32768)  # 約半分
    sleep(HOLD_SECONDS)

    # --- 25% duty ---
    pwm.duty_u16(16384)  # 約1/4
    sleep(HOLD_SECONDS)

このように、pwm.duty_u16() に値(0〜65535)を渡すだけで、LEDの明るさを自由に制御できます。 数字が大きいほどLEDが明るくなります。

リファクタリング②:きれいで再利用しやすい形に

もう少しプログラムを整理して、見やすく・保守しやすくしてみましょう。 関数を定義してデューティ比をリスト化することで、追加や変更も簡単になります。

from machine import Pin, PWM
from time import sleep

# ==========================
# 定数定義
# ==========================
LED_PIN = 15          # LED接続ピン
PWM_FREQ_HZ = 1000    # PWM周波数(Hz)
HOLD_SECONDS = 1.0    # 各デューティ比の表示時間(秒)

# デューティ比リスト(比率で指定)
DUTY_RATIOS = [1.0, 0.5, 0.25]

# ==========================
# 関数定義
# ==========================
def set_brightness(pwm, ratio):
    """LEDの明るさをデューティ比で設定"""
    duty_value = int(65535 * ratio)
    pwm.duty_u16(duty_value)
    sleep(HOLD_SECONDS)

# ==========================
# メイン処理
# ==========================
def main():
    pwm = PWM(Pin(LED_PIN))
    pwm.freq(PWM_FREQ_HZ)

    while True:
        for ratio in DUTY_RATIOS:
            set_brightness(pwm, ratio)

# ==========================
# 実行部
# ==========================
if __name__ == "__main__":
    main()

関数化することで「明るさを設定する」という目的が明確になり、コード全体が読みやすくなりました。 また、デューティ比を増やすだけでステップ数を簡単に変更できます。

仕組みを理解する(技術解説)

PWMは「一定周期の中でON時間とOFF時間を切り替える」ことで平均電力を調整します。 LEDのような目に見えるものでは、ONの割合が増えるほど明るく見えるのです。

たとえば、周期が1msの場合:

  • ON 100% → 常に光る(明るい)
  • ON 50% → 半分だけ光る(中くらい)
  • ON 25% → ちらっと光る(暗い)

この制御は、LEDだけでなく「モーターの回転制御」「音量調整」「サーボ制御」にも応用される重要な基礎技術です。

ピコさん
ピコさん
PWMは「ON時間の割合」で明るさが決まるよ!

🔹なぜ周期を1msにしたのか <PWM_FREQ_HZ = 1000 # PWM周波数(Hz)>

人間の目は0.02秒(=20ms)より速い点滅を「点滅」として認識できません。
つまり、1ms周期(1kHz)なら目には「チラチラ」せず滑らかな光に見えるのです。

トラブルシューティング

もしうまく動かない場合は、以下を確認しましょう。

症状原因対処法
LEDが光らない極性ミスまたはピン番号間違いLEDの向き(長い脚が+)を確認
常に点灯しているGPIOが常にHIGHになっているプログラムを再実行、またはリセットボタンを押す
明るさが変わらないPWM周波数やデューティ設定ミスpwm.freq()とduty_u16()の値を見直す
LEDが焼けた抵抗未使用220〜330Ωの抵抗を必ず直列に挟む

まとめ/次回予告

今回は、PWM制御を使ってLEDの明るさを変化させる方法を学びました。

  • PWMはON/OFFの割合で明るさを制御する技術
  • MicroPythonではPWMクラスを使えば簡単に扱える
  • 関数化することで再利用性も向上

次回はこのPWMを応用して、LEDをなめらかにフェードイン・フェードアウトさせる方法に挑戦します。 ブックマークしておくと、次の記事もすぐに見つけられますよ!


コメント