電子工作でよく見るws281x系(?!)LEDについて。
今年に入って、PICでなにかかしらをすることを覚えている最中で、最近はマイコン内蔵のLEDというものの制御を試してみていた。これ系LEDの仕組みは、LEDには電源・GNDとデータ線二本の計4本足がでていて、複数LEDをデータ線で直列につなぐことができる。見かけ上全LED分のRBGデータをストリームで流す感じで、つながれたLED達は自分の分のデータを取り込んだら、残りは次のLEDにそのまま流すっていうイメージ。
LEDの制御なんだけれども、デジタル信号の課題っぽくも感じられて、3種PIC/RaspberryPi/RaspberryPiPicoでそれぞれ試していた。Picoはたまたまで最近一つ手に入れてその使い方に慣れる過程でやってみた。
PIC
最初のトライで、まずはべたににGPIOピンにラッチデータを順に書き込むこと思い浮かんだけれども、よく知られる通りそれでは要求される信号波形や同期を維持するのが全然無理*1。これのPICでの使い方の定跡は、PWM+SPIで得られる信号群をCLCというロジック演算回路で所望の信号に合成するという方法、とのこと*2。これで動いたときは、マイコンやってる感に満ち溢れたです。
当初はまずこの砲弾型のやつからやってみた。MCC使ってサクサクいくはずが、一通り定番?にはまっていったのか人のはまらないところにも立ち寄ったのかしょうもないミスに気付くのが遅れるとかで、安定して任意の色を点灯させるのに時間を要した。その次に8連タイプのを試してみたが、こっちはLEDマイコンのパルス幅仕様がさらに短い。PL9823のときにはRBGデータの書き込みにMCCの生成関数SPI1_WriteBlock()使ったのだけど、関数呼び出しがスタックしているこれでは速度を満たせなかったようで関数を使わず展開してあげた。*3
Raspberry Pi
以前こんなLEDマトリクスをraspi-zero用に購入して、今もぼちぼち使っている*4。販売元が開放してくれているモジュールでプログラム書いている。このモジュールはws281xドライバに依存していて、要するにこのLEDマトリクスも上記のマイコン内蔵LEDを使っていたということ。ならばこのドライバモジュールで8連LEDとかを制御できるか?、できた。example/strandtest.pyを試してみて、NUM_COUNTの値は書き換えてあげる。これすなわち、やや割高になるけども8連のが4個あれば同等のモノが作れるということだった。
Readmeを読むと、PWMを使うが、オプション的にPiのPCM・SPIでドライブできるようにも実装されているとのこと。ちなみに多分PL9823はrpi-ws281x-pythonだとだめに思われた。コードで1.25usec固定になっている個所がある。試していないけど。
Raspberry Pi Pico
Picoを入手したのは、LEDをやりたいとかは関係なく、偶然秋葉原でRaspberry Pi Picoを店舗販売しているのを見つけたから。一つ購入して、それでgetting startedを眺めていたらmicropythonでのws2812bの例題が載っていた。最初VBUSとVSYSを間違えて配線して不安定な発光させたけども、例題のまますんなりできた。
microのつくpythonってのを使うのは初めて。ws2812bは色情報の1bitあたり1.25usec=800kHz、その800kHの10倍の速度周期でstatemachineというのを駆動してその1回の呼び出しのなかでビット情報に応じてHigh/Lowの制御をやってる。ws2812b()関数の中は細かい意味わかっていないけども何をしたいのか(ビットに応じた時間幅でHigh->Lowにする)かは明確に伝わってくる。
Picoの潜在力というか、マイコン的な性能に対して、分かりやすいプログラミング(このケースは高速周波数を生かして)で書けるということ、みたいなのを感じた*5。
後書き
- 信号処理という点ではPICのCLCについて興味深く思っている。
- WS281xというマイコンがやっている信号の読み取りの方法も学びたいと思ったけれどもそれはとりあえず後日。