🐣
【Raspberry Pi Pico W】PWMの使い方(micropython×Thonny)
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 オブジェクトを作成
詳しくは以下を参照ください
おおよその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を紹介しておきます
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