Raspberry Pi 2 W で PWM送信
C/C++におけるPWM出力の実装を行いました。目指すところは赤外線リモコンの搬送波である38kHz、1/3DutyのPWM波です。MicroPythonと違って色々難解で理解に手間取りましたが、ようやく納得のいく形に収める事ができました。今回の立役者は、こちらの方です。本当にありがとうございました。
はじめに
まず、PWMモジュールの使用に当たり、次の変更を加えます。
# Add any user requested libraries
target_link_libraries(KeIR
hardware_spi
hardware_i2c
hardware_dma
hardware_pio
hardware_interp
hardware_timer
hardware_watchdog
hardware_clocks
hardware_pwm ←ココ
pico_cyw43_arch_lwip_threadsafe_background
)
これを加えると、#include "hardware/pwm.h"
が通るようになります。
実装
いきなり実装です。今回も、先ほどのサイト丸パクリとなっております。
// f=38kHz / Duty=1/3のPWM波形出力
gpio_set_function(PIN_PWM0, GPIO_FUNC_PWM); // PIN_PWM0 を PWM として使用
uint pwm_slice_num = pwm_gpio_to_slice_num(PIN_PWM0); // PIN_PWM0 をスライス(チャネル?)0に設定
int16_t wrap = 788;
pwm_set_clkdiv(pwm_slice_num, 5); // 周期 38kHz
pwm_set_wrap(pwm_slice_num, wrap); // 1/788
pwm_set_chan_level(pwm_slice_num, PWM_CHAN_A, wrap/3); // デューティ比 1/3
pwm_set_enabled(pwm_slice_num, true); // PWM 有効
となります。
メインクロックをsysclock、PWM分解能の設定値をwrap、分周比をclkdiv とすると、
PWM周波数 f = sysclock / ((wrap+1) ⋅ clkdiv)
ですので、そのように各パラメータを計算(筆者の場合はExcelに式入れて所望の値が出るまで当てずっぽうでやったわけですが)します。
罠
ここで注意したいのが、sysclkです。Raspberry Pico/ PicoW では sysclk=133MHz なのですが、Pico2/Pico2Wではsysclk=150MHzです。PWM周波数がsysclkに依存するので、ソースそのままでPico2に移行、は難しいかもしれません。クロックアップされている方等は慣れっこでしょうけど、乗換組さんたちは躓くかもしれません。
当然上のコードは Pico/PicoWでは調整をすることになります。裏で自動計算?しません~
波形確認
終わりに
頭悪いので他の方のやり方見ても全然理解できなくて、あのサイトを見つけるまで苦労しました。例外まで出しちゃって…
本当は赤外線送信まで含めるつもりだったんですが、面倒だったんでいずれ。
ソースの構造上受信から説明しないといけないので…
やりたいことは、TVチューナー(CATV)の音量ボタンで中華アンプの音量を変えることです。波形変換ですね。
MicroPythonの方ではほぼできているんですが、こちらはまだまだですね。
受信の方ですが、MicroPython版と違って受信波形データ化がめちゃ正確なんです。これがC/C++の醍醐味ですね。しばらくはC/C++に噛り付いてみようと思います。
いじょ