何度か使ってラズパイPicoのC/C++SDKの使い方も分かって来たぞ、という感触。今回はPWM出力をさらっと確かめるつもりで作業開始。しかし「さらっと」などと不埒なことを考えると「トホホ」が待っているのです。gpio.hは見つかるのにpwm.hが見つからない?なぜ、ビルドできないじゃん?解決して実機で走らせたら今度はLEDが光らない?トホホ。
※「トホホな疑問」投稿順Indexはこちら
(末尾に実験で使ったサンプルコード全文を掲げました。)
ラズパイPicoのC/C++のプロジェクト生成には、以前の投稿で書きました Raspberry Pi Pico Project Generator というツールを使わせていただいております。これ使えば CMakeLists.txt は自動でOKと安心しきっておったのですが。
gpio.h はインクルードできるのに pwm.h のインクルードができない
3チャネルのPWMを使って、RGB三色LEDを光らせるサンプルプログラムはほんの数分で書けました。ま、簡単だし。ビルドすれば即動くっしょ、という乗りでビルド。しかし、make中のエラーで落ちます。見れば、PWMを使うためのヘッダ pwm.hが見つからないと言っています。見つからなければコンパイルできないのは当然、でも何で?
SDKのパスの傘下にはちゃんとpwm.hが存在しています。ちょっと込み入った深いところにあるのだけれど。でも、同様な位置にあるgpio.hはインクルードできているみたい。この差は何?
振り返って見ると、ビルドする前にVS Codeのエディタ画面でも不穏な波線が出てました。こんな感じ。波線位置にカーソルあわせればファイルが見当たらない、と。
VS Codeは、何が見えて何が見えないのか、把握した上で補完してくれているのでしょう。こころみに以下のように
#include "hardware/"
の / を打った瞬間、補完機能が働いて以下のようにリストが現れます。その中に gpio.h は勿論、以前使った timer.h とか uart.h などがちゃんと登場します。こいつら別に何か指定した記憶が無いのに現れます。しかし、pwm.h は登場しません。
そのくせ、regsの下のレジスタ定義のヘッダの中には PWM関係のレジスタアクセス用のpwm.hが見えていたり(includeする pwm.h よりも下位のヘッダでより深い位置にある)します。なんで?
トホホなときは原典に立ち戻ると。原典は以下ですね(最新版は6月末の1.6でした。6月だけでも2回更新。私がダウンロードしてあったのは少し古かったです。こまめに更新した方がよさそうです。)
上記の文書の ”2.2. Every Library is an INTERFACE” から1か所引用させていただきます。
pico_stdlib provides all the basic functionality needed to get a simple application running and toggling GPIOs and printing to a UART,
ほえほえ、pico_stdlibを含めることで、gpioとか、uartとかも暗黙のうちに含まれてきていたのね。それで見えていたのか。逆に言えば、pico_stdlibには pwm は含まれていないので、明示的に入れてあげないとならないのね。
GUIで生成した CMakeLists.txt に手動で hardware_pwm を追加いたしました。こんな感じ。
そしたらビルド出来ましたです。VS Code上も波線消えました。トホホ。そんなことかい。ビルドできたので実機動作の確認へ。
実機動作の確認
実機動作の意図は簡単です。GPIOの以下の端子をRGB-LEDの3端子に割り当て、それぞれの端子をPWM駆動してやり、「いろいろな色」を光らせようという目論見です。
-
- R — GPIO4
- G — GPIO3
- B — GPIO2
アイキャッチ画像をご覧いただくとわかりますが、上記の3端子に加えてGPIO2のとなりのGND端子を使うと「ちょうどブレッドボード上でラズパイPico」に「直結」できるLEDモジュールが手持ちにあったのです。配線無、モジュール差し込むだけ。お手軽さに浮かれてデータシートも確認せずに差し込みました。ただ、よく考えるとこのモジュールはArduino用だったのです(5V IO電圧。)
走らせてみると、「ちゃんと」LEDが点灯し、色も変化します。OKと思ったら色が変です。赤と緑は見えているのに青がないです。なにかソフトの書き方間違えた?とも考えましたが、ハード側の理由っぽいです。PWM波形の確認を兼ねてオシロで当たれば、RGB3色ともPWM波形出ていました。ようやく使っているLEDのデータシート見たところ、青と緑のVfはミニマムでも3.3Vでした。モジュール上電流制限抵抗の1kΩが直列に入っています。3.3V IOのラズパイPico端子に直結したのでは青と緑はスペック割れているはず。それでも緑は元気に光るのですが、青はダメみたい。
しかたないので、この3色LEDモジュールをあきらめ、3.3V IOでも大丈夫そうなR, G, B3個のLEDで汚くジャンパ線でつないだものがこちら。
ちゃんとR, G, Bの3色光っております。しかし、Lチカで躓くとはトホホ。。。
トホホな疑問(38) PicoDAC、カラーコード、よく確かめたつもりだったんだけど へ戻る
トホホな疑問(40) ATSAMD51、Port Event制御1個しかうごかないんですけど へ進む
C/C++ SDKからPWM出力をするサンプルプログラム
#include <stdio.h> #include "pico/stdlib.h" #include "hardware/gpio.h" #include "hardware/pwm.h" // Color LED pins (analogOUT) #define LED_R (4) #define LED_G (3) #define LED_B (2) // PWM settings #define MAX_COUNT (255) uint pwm_slice1; uint pwm_slice2; void setLEDs(uint16_t R, uint16_t G, uint16_t B) { pwm_set_chan_level(pwm_slice1, PWM_CHAN_A, B); pwm_set_chan_level(pwm_slice1, PWM_CHAN_B, G); pwm_set_chan_level(pwm_slice2, PWM_CHAN_A, R); } int main() { stdio_init_all(); gpio_set_function(LED_R, GPIO_FUNC_PWM); gpio_set_function(LED_G, GPIO_FUNC_PWM); gpio_set_function(LED_B, GPIO_FUNC_PWM); pwm_slice1 = pwm_gpio_to_slice_num(LED_B); pwm_slice2 = pwm_gpio_to_slice_num(LED_R); pwm_set_wrap(pwm_slice1, MAX_COUNT); pwm_set_wrap(pwm_slice2, MAX_COUNT); setLEDs(0, 0, 0); pwm_set_enabled(pwm_slice1, true); pwm_set_enabled(pwm_slice2, true); setLEDs(255, 0, 0); sleep_ms(3000); setLEDs(0, 255, 0); sleep_ms(3000); setLEDs(0, 0, 255); sleep_ms(3000); for (uint16_t rIdx = 0; rIdx <= MAX_COUNT; rIdx++ ) { for (uint16_t gIdx = 0; gIdx <= MAX_COUNT; gIdx++ ) { for (uint16_t bIdx = 0; bIdx <= MAX_COUNT; bIdx++ ) { setLEDs(rIdx, gIdx, bIdx); sleep_ms(1); } } } setLEDs(0, 0, 0); puts("End of Execution."); return 0; }