リファレンスマニュアルでサンプルコードがありますが、それを使うのはムカつくので、自力で実装してみました。
なお既存のコードと見比べれば分かりますが、優位性は全くありません。
使用したものは MicroPython です。動作テストが楽ですからね。
動作
頑張りました。
ラスピコのPIO(MicoPythonで記述)とWS2812B、完全に理解した pic.twitter.com/cpfRBIaFkD
— しまじゃき (@obknt) February 10, 2021
...あ、これ過電流です。稼働中にラズピコちゃんから応答が一切なくなったので BOD とかが働いたのかな。
ソースコード
以下です。ぜんっぜんスマートじゃないですが。84行目の sm.active
以下で書いてある内容が実際の動作です。
上で述べた過電流に関しては最大輝度を下げることで対応できています。
注意点
勝手にハマったことを挙げます。
WS2812Bのパルス波形仕様
変態的なパルス波形で有名なこの LED モジュールですが、データシートの粗雑さが理解の妨げにもなりました。
以下の画像はデータシートのものですが、0 code と 1 code は必ず High から始まらなければならないと見えますよね。違うようです。
例えばこのサイトとかによると、1周期の間で High および Low の合計がデータシートの値の範囲内ならば良いというようです。ですからサンプルプロジェクトを動かすときはその理解が必要でした。
本記事に載せたコードは、律儀に High → Low と波形変化するものにしております。RET code も考慮するような構成にしなきゃいけなくて、地味に大変だった。
jmp命令の条件分岐
今回は x
レジスタの値によって分岐しようとしましたが、x
そのものの値を分岐条件としてジャンプすることは出来ません。まあこれは僕の不注意でハマったのですが、お察しの通り jmp(x, 'one')
と書いてしまったのでした。MicroPython の PIO では x
とかの実態がただの定数なので、エラーを起こすことなく誤ったコードを無事実行したと言う感じです。これは今後のアップデートで修正してほしいですねえ。例外投げるとか。
RP2040 のデータシートを御覧いただくと、x
レジスタに関する条件分岐では not_x
, x_dec
, x_not_y
しか使用不能です。よく考えて使いましょう()
やっぱりPythonは遅い
最大の懸案事項きましたこれ。実は RGB の値を 24bit の値に変換する関数を書いていたんですけど、これがあまりにも遅くて卒倒しそうになりました。
def rgb_data(r, g, b):
return (r << 8) | (g << 16) | (b)
実際にコードを実行している時にその遅さが目に見えたくらいです。論理演算をチョロっとするだけの関数なのにここまで遅いとは...やはり Python はク 癖が強いなと思いました。
現状、以下のようにラムダ式を利用することで、(よく分かりませんが)その問題は回避しています。
rgb_data = lambda r, g, b: (r << 8) | (g << 16) | (b)
でもこれ、何でこっちのほうが断然速いんですかね。