LED_engine for WS2812B

半年ほど前に某メーカー向けの電飾装置のプロトタイプの製作依頼があったのですが、多忙な時期に短納期という条件であったため、先方に迷惑をかける可能性が高かったので請けませんでした。

そのときは、TLC5940で少しだけ実験してみたのですが、LED1個にRGB3本の制御線というのは、ちょっと大げさで、かつ実際の使用にはワイヤの数が多く、システムとしては難があるのではないかと、しばらく放って置いたのですが、ヒカリモノをほとんどいじったことがなかったこともあって、ちょっと手をつけておいたほうが良いかもと思っていたところ、シリアル制御できるフルカラーのLEDを見つけたので入手して実験してみました。

そのLEDは、秋月で売っていた「WS2812B」で、1個50円。なんとLEDにマイコンが内蔵されています。

通常のカラーLEDなら電圧を加えれば光りますが、これは電源につないだだけではだめで、シリアル(単線)で明るさの情報を送ってやらないと発光しません。そして最大の特徴は、数珠繋ぎに増やしていけること。最近、見かけることの多いテープ状になったLEDがありますが、あれに使われているようです。

仕様をみると、かなりきついことがわかりました。「0」の場合、およそ400n秒のHと800n秒のLの組み合わせ。
「1」の場合はその逆の時間のパルス列を生成する必要があります。RGBそれぞれに8個のデータを必要とするので、1個あたり24個のデータが必要です。例えば20個直列のときには、24x10=480パルスのデータを送ると、同一線上にありながら、20個のLEDをそれぞれ独立して制御することができます。

今回は開発中のリモートI/O用のデバッグボード(ATmega164P クロック16MHz)を使ってみたのですが、BASCOM-AVR(BASICコンパイラ)では、処理時間が追いつきません。そのため、次のようにしました。

・速度に関係ないメインルーチンはBASICで記述
・LEDへのシリアルの生成は全てアセンブラで記述

としたのですが、これでもかなりきつい。16MHZなので1クロックあたり62.5n秒ですが、シリアル信号の生成はRGB3つの配列に設定した8ビットの値を読み込み、0か1を判別しつつパルスを作っていかないとなりません。間に余計な命令を入れてしまうと、たちどころに、仕様を満足しなくなってしまいます。

プログラムとしてはあまり美しくなくなってしまいましたが、BASCOMのシミュレータとオシロを使って、何とか仕様通りのパルス列を作ることができました。

しかしながら、設定通りに光らない。1ビット(LSB)しか立てていないのに全点灯したりと、かなり悩みましたが、ネット検索していたらとんでもないものを見つけてしまいました。「仕様書が複数存在し、パルス幅も違う・・・・」。

なんだこりゃ。。。
もともと使っていたのは、秋月のWEBページに貼り付けてあったものですが(ちなみに秋月以外の販売店でも同じ仕様書でしたが。)、別のもの(350nと900nの組み合わせ)にタイミングを変えたところ(さらにきついタイミングでしたが)、正常点灯。
BASICでデータを設定しておいてアセンブラのルーチンを呼ぶだけなので、いろいろと応用できそうです。
固定パターンをスイッチで切り替えるといった使い方だけでなく、外部から(たとえば232で)設定を書き換えるといったことも容易にできるでしょう。

なお、今回のプログラムは業務で使う可能性もあるので公開できません。 悪しからず。

2015-09-22追記

ここを見に来られる方が多いようなので、すこし追加。
このLEDのようなタイミングをきちんと取らないと動かないものは、オシロスコープが必須です。実行速度は計算で出せますが、確認の為にもあったほうが良いです。
コード(プログラム)は公開しませんが、具体的に質問があれば個別にお答えすることは可能ですので、メールでお尋ねください。
(メールアドレスはメインサイトのどこかに書いてありますので。)
もう1年以上も前のことなので、よく覚えていないけど。