🐣

【Raspberry Pi Pico W】PWMの使い方(micropython×Thonny)

2025/01/03に公開

1. はじめに

  • PWM制御でLEDを点滅させたり、メロディを鳴らしたりして遊んだので、記載しておきます

1.1 この記事について

  • Raspberry Pi Pico W(以下、Pico)のPWMを使ったサンプルプログラムを記載する
  • 細かい解説というより、備忘録とプログラム+回路図のサンプル重視
  • 入門・解説というより備忘録に近い

1.2 対象読者

  • Picoを使ったことがある
  • Thonnyを使ってPicoにプログラムを書き込み・実行ができる
  • プログラム言語(特にmicropython)が多少読める、書ける

1.3 動作環境

  • PC
    • OS:Windows 11 Home
    • プログラミング環境:Thonny(v4.1.4)
  • Raspberry Pi Pico W
    • ファームウェア:v1.24

2. PWMについて

  • Pulse Width Modulationの略称
  • HIGHとlowの電圧を切り替えることによって、電力量を調節したり、サーボモーターなどのデバイスを制御したりすることができる
  • 主なパラメータは以下の2つ
    • デューティー比(duty_rate) ・・・ 電圧がHIGHの状態の割合
    • 周波数(frequency)     ・・・ 1秒間に電圧のHIGH, lowを繰り返す回数

2.1 実際の信号について

上記説明だといまいち実感できないので、実際の信号を見てみましょう
一番上のグラフは、周波数=10Hz, duty比=0.5(=50%)に固定してあります

2.2 duty比を変更した場合

duty比を変更すると、HIGHの状態である長さが変わります

2.3 周波数を変更した場合

周波数を変更すると、HIGHとlowの矩形の数が変わります

2.4 micropythonでのパラメータ指定方法

pico(micropython)でPWMを使用する場合は、周波数はfreq(10以上の値でないとエラーとなる)で、duty比は割合ではなく16bit(unsigned intなので0以上65535以下)の整数値で指定します

pwm = PWM(pin, freq=50, duty_u16=8192)  # ピンの PWM オブジェクトを作成

詳しくは以下を参照ください
https://micropython-docs-ja.readthedocs.io/ja/latest/library/machine.PWM.html

おおよそのduty比とduty_u16の指定値の関係は、以下の表の通りです

duty比 duty_u16
0% 0
25% 16384
50% 32768
75% 49152
100% 65535

ちなみに電圧値HIGHは3.3V, lowは0V固定で、duty_u16=8192はduty比=12.5%ですね。

3. 実験

3.1 LEDを点滅/明るさを調節する

LEDの明滅(とついでにPWM信号をplotに可視化)をしてみます

  • freqを変えると1秒間の明滅回数が変わります
  • duty_u16を上げると明るさが増します

3.1.1 回路図+配線図(Fritzing)

3.1.2 実際の画像or動画

gitの設定により10枚/1秒のため、LEDの点滅がうまく表示されておりませんが、
実際は10Hzで明滅しております

3.1.3 プログラム例

ついでにprint文でGP0の値を読み取ってます

from machine import Pin, PWM
from time import sleep_ms

pwm = PWM(Pin(0), freq=10, duty_u16=32768)
gp1 = Pin(1, Pin.IN)

while True:
    status = gp1.value()  # PWMのHIGH(=1)/low(=0)を読みとる
    print(f"{status=}")
    sleep_ms(10)

3.2 パッシブブザーで音を聞く

  • freqを変えると音の高さが変わります
  • duty_u16を増減すると音色が変わります

3.2.1 回路図+配線図(Fritzing)

3.2.2 実際の画像or動画

git画像なので音は鳴りませんが、実際は聞いたことあるメロディが流れます

3.2.3 プログラム例

  • 途中で周波数を変えるには、PWM.freq(セットする周波数の値)とします
  • duty比を変更するには、PWM.duty_u16を使います(0にすることで実質的に無音にできます)
  • 本来無音(休符)である部分に10Hzにして音が鳴らないようにしてます
    (パッシブブザーからはわずかにカチカチと音が聞こえます)
from machine import Pin, PWM
from time import sleep_ms

pwm = PWM(Pin(0), freq=10, duty_u16=0)

melody = [1046, 1046, 1568, 1568, 1760, 1760, 1568, 10, 1397, 1397, 1318, 1318, 1174, 1174, 1046, 10]

for hz in melody:
    pwm.freq(hz)
    pwm.duty_u16(2**12)
    sleep_ms(300)
    pwm.duty_u16(0)
    sleep_ms(10)

3.3 サーボモータを指定角度に動かす

  • サーボモーターを任意の角度(-90~+90度)に動かせます
サーボモータの仕様について

参考までに、秋月電子さんのdatasheetを紹介しておきます
https://akizukidenshi.com/goodsaffix/SG90_a.pdf

3.3.1 回路図+配線図(Fritzing)

3.3.2 実際の画像or動画

3.3.3 プログラム例

Amazonなどで購入した場合、SG90そっくりの偽物の可能性がありますので
duty比は実際の動作を元に修正をしています(datasheet通りとなっておりません)

from machine import Pin, PWM
from time import sleep_ms

pwm = PWM(Pin(0), freq=50, duty_u16=0)
angle_duty = {0:1637, 45:3276, 90:4914, 135:6553, 180:8192}

while True:
    for angle, duty in angle_duty.items():
        pwm.duty_u16(duty)  # duty比を変更
        print(f"{angle=} {duty=}")
        sleep_ms(1000)

4.まとめ

  • PWM制御でLEDを点滅させたり、音を鳴らしたり、サーボモーターの制御などができる
  • PicoのPWMはmicropythonの場合はfreq=10より小さく指定はできない
  • サーボモーターは、機械要素と組み合わせるとロボットアームなど作れるので、今後チャレンジしてみたい

Discussion