MicroPython的午睡(23) ラズパイPico、Passive Buzzer接続

Joseph Halfmoon

今回 Raspberry Pi Picoに接続する「定番の」部品はパッシブ・ブザーであります。片やONするだけで特定の周波数で鳴ってしまうアクティブ・ブザーに比べると、パッシブ・ブザーの場合、与える周波数を制御する必要はあるものの、音程を変えることができるので表現力が上回るっと。まあPWM波形を与えれば良いのでPWM出力に対応しているPicoにとっては何の問題もありませぬ。

※「MicroPython的午睡」投稿順 Indexはこちら

多くのマイコンでは、TIMERカウンタの中にPWM機能を含むことが多いです。しかし、ラズパイPicoではPWM専用のカウンタ群としてあり、TIMERとは別扱いです。RP2040 DataSheetを見ると、合計16チャンネルのPWMを使用することができることが分かります。データシートに書かれている制限をまとめると以下のようになります。

  • カウンタの実体は16ビット8本
  • カウンタ毎にちょっと高級なプリスケーラを設定(カウント周波数決定)できる
  • 1本のカウンタに対してコンペアレジスタが2本ある。2本がそれぞれ独立のPWM出力ピンを制御する(コンペアの内容で異なるデューティを指定できる)
  • すべてのGPIOピンにPWMチャネルをアサイン可能
  • 特定のGPIOピンは特定のPWMチャネルに1対1に紐づいている(合計30本のGPIOがあるので2つの端子が同一のPWMチャネルに紐づいているケースが多い。)

今回サンプルではGP22端子をPWM出力として使いました。このケースでは、PWMカウンタの3番目(0はじまり)のコンペアレジスタAチャネルを使っていることになります。そしてまったく同一のPWMチャネルをGP6端子に紐づけることが可能です。

MicroPythonからPWMはピン番号だけで制御できます。複数のPWM端子を併用するときには、上記の制限を確認の上、使用する必要があります。しかし、MicroPython上でPWMを1本使用するだけなら、PWMのチャネルのことはまったく忘れて端子番号のみでプログラムしても大丈夫だと思います。

今回はなるべく大きな音でブザーを鳴らしたかったので、ブザーの電源はUSBソケットから取り出されているVBUS端子から5V電源を取り出しました。以前に作ってあった小さなブザー基板を使った回路は以下のようです。保護のためダイオードD1、抵抗R1など挿入した上、MOSFET BSS138で駆動するようになっています。R2の33kはBSS138のゲートが浮かないためのプルダウンです。NMOSなのでラズパイPicoからHighを出力するとBSS138に電流が流れます。なお、PassiveとActiveブザーの扱いについてはここの投稿などご参照ください。

Pico_PassiveBuzzer_Schematicさて例によってPWMの制御用にMicroPythonからどのような関数が使用できるのか見てみると以下のようでした。

>>> import machine
>>> help(machine.PWM)
object <class 'PWM'> is of type type
deinit -- <function>
freq -- <function>
duty_u16 -- <function>
duty_ns -- <function>

freqで周波数をセットして、duty_u16か、duty_nsでデューティサイクルをセットできるようです。freq関数は、プリスケーラの設定値の計算など面倒なところは面倒見てくれているようで、そのまま周波数を渡せばOKみたいです。デューティの方は符号なし16ビットかns単位かで指定できるのだと思います。

どのくらいの周波数範囲にどの程度の周波数精度で設定できるのかまだ確かめていません(手抜きな。)今回は「ドレミファソラシド」的な1オクターブ分の音階を出力させてみました。とてもいい加減な設定ですが、一応それらしく聞こえています。また、デューティについては幾つかの設定の中で「力強く鳴る」感じの値を耳で聞いた印象でキメウチしてしまいました。後でオシロをつかって周波数やデューティの変化の様子を波形で確認したいと思います。本日は、要介護の親のため、片手間で例の「注射の予約」も試みている(当然ながら書いている現在つながらないです)ので、オシロでやるのはまた今度だな。。。

(追伸:昨晩遅くにネット予約完了。朝~昼、システムに負荷かけても申し訳ないので30分に1回ペースで試行してみるが、非常に込み合ってログインページにも行きつけない。昼前後に時々ログインページ表示されるが、入力コンプリートできず。午後になるとまた非常に込み合ってまったくつながらない。夜9時くらいからログインできる「確率」があがり、なんどかトライしているうちに入力コンプリートできた、という感じであります。)

MicroPython的午睡(22) ラズパイPico、AQM1602 LCDパネル接続 へ戻る

MicroPython的午睡(24) ラズパイPico、CDSセンサをADCに接続 へ進む

Passive Buzzerサンプルコード
import time
from machine import Pin, PWM

buzzer = PWM(Pin(22))
freqLis = [262, 294, 330, 349, 392, 440, 494, 523]

for _loop in range(5):
    for idx in range(0, len(freqLis)):
        buzzer.freq(freqLis[idx])
        buzzer.duty_u16(256*16)
        time.sleep(1.0)

buzzer.duty_u16(0)