WS2811のATTiny13aでの色空間の使用

画像

そして再び、Habr!



私の新しいアイデアは、マイクロコントローラーで色空間を使用することです。

私のニュースがそのような誰かには見えないという事実は、まったく驚かないでしょう。

ただし、これまで見たことのない方法とその実装を提案します。



簡単な紹介、それがどのように始まったか。 ごく最近、年が終わり、私はそれから約300個のws2811 LEDを継承しました。 何らかの理由で、私の手は彼らに届きませんでしたが、新年のお祝いの後、私は叔母がガラスでできた小さなお土産のクリスマスツリーを持っていることを親relativeに気付きました。 しかし、今度は彼女はまったく輝きませんでした、そして非常にありふれた理由のために輝きませんでした...バッテリーは死んでいました。 彼の一連のLEDを思い出して、彼はこのクリスマスツリーのために小さなガーランドを作り、これらの欠点を完全に取り除き、私に近い他の人を少しでも幸せにすることを約束しました。



発達は頭の中で回転し、徐々に加速し、時には思考の旋風に変わりますが、これらの日まで、それは芽生えていません。 エフェクトプログラムとその切り替えに関連するすべてのアイデアが、RGBカラースペースに実装されたとき、頭の中では非常に面倒でひどく不便であるように見えました。さらに、このために使用するコントローラーを決定できませんでした。 しかし、デザイナーとしての小さな経験のおかげで、他のスペースの知識もあるため、HSLとHSVについて考えるようになりました。 新しいものを発明することには意味がありませんでした。検索するだけで実装する必要がありましたが、見つけられませんでした。 いいえ、もちろん、私は多くの興味深い解決策を見つけました、そして、それらの多くはあなたのもので、ここHabréですぐに提示されました、そして、私はあなたのすべてに無限に感謝しています、あなたは心に食べ物を与えました。



その結果、1つのS(彩度)コンポーネントを除外してHSLに専念し、一定のまま(これはCDM実装の追加パラメーターであるため)、コントローラーはATMega8Uの使用を決定しました。



コードをスケッチしてファームウェアをテストしたところ、何かが欠けていることに気付きました。 そして、私は本物と少し矛盾がありませんでした。

すべてのハンターは知りたいと思っています...そして再び私はこの質問に戻り、再び何もないことに気付きます...

自然界にはオレンジ色はありませんが、何と言っても、それは単なる日陰です。



これが私のアイデアの根幹であり、コードを完全に書き直し、色空間のコンパクトな記述を使用する方法を考案したおかげで、オレンジの範囲を拡張して別の空間セクターに移動したため、これはもはやHSLではなくHSVではなくRGBではありません。



本質的にのみ



スペースは、シリンダーが閉じている場合、シリンダーの表面として表すことができます。60°オフセットした角度で​​配置された基本色で、基本色から別の基本色へのグラデーション遷移で塗りつぶされます。



画像



ここで、円柱の高さは明るさであり、これはシェードのグラデーションのコンポーネントでもあります。

同じ空間は、辺が「A x B」の長方形で表されます。ここで、「A」はベースカラーとその色相を定義する角度、「B」は空間が閉じていないか円柱から外れている場合の明るさです。



このタスクでは、一辺が256 x 256の正方形を使用することを決定しました。これにより、バイトタイプ内で、角度は値が0..255(バイト)内で変化し、輝度は-127..127(符号付きバイト)でした。これにより、8つの基本色とそれぞれに32階調の陰影を使用する機会が得られました。



スペースは、RGBの配列として記述されます-基本色のコンポーネント、およびシェードのグラデーションがオンザフライで計算されます。

説明例:



{0,128,0}, {64,128,0}, {128,128,0}, {128,0,0}, {128,0,128}, {0,0,128}, {0,128,128}, {0,128,0}
      
      





基本的な色のシーケンスをここで説明します。それを単に虹と呼びましょう。コンポーネントの順序はws2811(GRB)データシートに従って変更され、最後の色は赤で、スペースを閉じます。次のようになります。



画像



ここで、たとえば183などのカラーインデックスを使用すると、次のようにRGB空間に表示できます。

ベースカラーインデックス= 183/32 = 5(青、または{0,0,128})

色相オフセット= 183%32 = 23

ここで、取得した基本色({0,0,128})と次の{0,128,128}の成分の差を計算して、増分を計算します(デルタと呼びましょう)。

 dG = 0 - 0 = 0, dR = 128 - 0 = 128, dB = 128 - 128 = 0;
      
      





色の間には32のグラデーションがあるため、成分の違いを分割する必要があります。

 dG= 0 / 32 = 0, dR= 128 / 32 = 4, dB= 0 / 32 = 0;
      
      





次に、結果のデルタに色相オフセットを乗算し、現在のベースカラー({0,0,128})のコンポーネントに追加する必要があります。

 G = 0 + 0 * 23 = 0, R = 0 + 4 * 23 = 92, B = 128 + 0 * 23 = 128;
      
      





{0.92,128}を取得しました。これに明るさを追加できます。たとえば、50:{50,142,178}-目的の色です。



例からわかるように、複雑なことは何もありません。 デルタが負の値をとる場合、乗算中の色相シフトは負の補数​​を与え、これは最終的なコンポーネントとの差をもたらします。これは、勾配コンポーネントが減少しているときに起こります。



そして、はい、明るさは比例ではなく線形に適用され、特定のエラーを与えますが、説明された問題の枠組み内ではこれは怖くないです。 また、負の輝度でオーバーフローが発生しないように、下限しきい値を監視する必要があります。



したがって、結果として生じるスペースにより、256 * 256 = 65536シェードを使用できます。



説明した方法全体が最適化され、すべての乗算と除算が排除され、簡略化された迅速な数学になりました。サイズを小さくするために最適化が必要な場合、アセンブラーに簡単に書き換えることができますコード。

結果として、ATMega8uを使用するという最初の決定は、tinkiを支持してキャンセルされました。これは、受信したファームウェアが0.5キロバイト未満しか使用しなかったためです。



いいえ、私は愚か者ではありません、私はただ怠け者です。



そのため、以下のコードは初期化を実行し、ws2811行にデータを出力する機能が含まれています。



画像



そして、これがメインループコードであり、使用例とともにスペースインデックスを色成分に変換する機能です。



画像



そして、ここに作品を示すビデオがあります(色は現実とはほど遠い):





テキスト内のコメントをより詳細に説明する意味はありません;メソッド自体はすでに上記で説明されています。 ご質問がある場合は、お問い合わせください。



まあ、実際、私が伝えたかったのはそれだけです。



...冗談ではありません!



画像



ここで、このメソッドの使用方法を少し想像してみましょう。 たとえば、この写真に示されているようなスペースです。



そう! 異なる色とそれらの間のグラデーションを記述することができます。 そして、説明の冒頭で、メソッドがグレーの濃淡の使用を許可しないと決めた人は間違っています。



結論として-最もおいしい



メモリ内のスペースを記述する配列は、32バイト(アラインメントのため)かかり、プログラムメモリに格納されます。 そのようなスペースの説明を複数作成し、移動中にそれらを切り替え、ポインターを配列に切り替えると、キュー内の新しいLEDごとに現在のスペースを選択できます。また、シェード間のグラデーションの数を拡張することもできます。 そして、コードをわずかに変更し、コンポーネントの説明のステップ数を8に増やすと、32 * 8で256(私のコード3ステップ)が得られ、7つの配列(0..255赤、黄、緑、青、青)が使用されます、紫、白)「画面上で同時に」16mの色合いを組み合わせてください。 ストレージに224バイトのファームウェアを使用する場合。 そして、もう少し汗をかいてコードを少し書き直せば、96バイト以内で同じ結果を得ることができます。



さらに、最適化と結果として得られる処理速度のおかげで、いわゆるディザリング方法を使用できます((英語版のディザレンからディザリング -震えるまで)さらに多くのシェードを実現できます(考えてみてください:512 * 512 * 512 = 134.217。 728)。また、相互にスペースのクロージャーを作成して、トランジション効果を排除または非表示にすることもできます。一般に、提案されたすべてを好みに合わせて好みや色に変更できますが、そのまま使用できます。保証します!



02/26/2015:無料で使用するためにソースコードをダウンロードすることを提案します。



02/27/2015: コードv1.2更新バージョンが利用可能です

変更点は次のとおりです。

1.基本色は1バイトのビットでエンコードされます:0bxxGGRRBB、配列は8バイトに削減されます。

2.パラグラフ1.に従って変換関数を変更しました。コードは少し大きくなりました(20〜30バイト)

将来的には、もっと興味のある人に変更を加える予定です。お見逃しなく



02/28/2015: バージョンv2.0へのコードの最終更新

変更点:

1.サブスペースでの作業を追加し、8x8スペースを導入しました(スイッチングのあるサブスペース用に65,536シェードを個別に選択)

画像



2.色のサブスペースを選択する例が追加されました(デモ例では、低輝度のしきい値に達したときに次のサブスペースに切り替えます)

画像

3.コードサイズが626バイトに増加しました(64バイト-スペース自体+ポインターへの16バイト、合計-80バイト、残りはサンプルコード:188バイト)。 したがって、エフェクトプログラムを整理するために、500バイトを超える追加コードを使用できます。

4.わずかに最適化されたコード。

5.プロファイリングは実行されませんでした。



結果:5本の無料の小さな脚。複数の個別のチャンネルを使用して、ws2811ラインに色効果を個別に表示し、ハードウェア入力または自動モードで制御を実装できます。 実装されたバッファー(14個のLED)を使用すると、この数の倍数であるLEDのラインを使用し、バッファー転送を繰り返してデータを次のセクションに転送できます。



この方向にはこれ以上更新はありません。アルゴリズムは完全であると考えますが、アイデアは尽きることがありません。 この方向で開発を独自に開発することをお勧めします。

たとえば、色の部分空間の滑らかな変更(テレポーテーション)を実装し、明るさ制御アルゴリズムを正しいものに変更し、色の彩度パラメーターを入力します。

今後の春に向けて、すべての喜びと成果に幸運を!



あなたのコメント、批判、質問、ヒントを楽しみにしています。

ご清聴ありがとうございました、すぐに会いましょう!



営利目的のプロジェクトでの使用、ソースコードの転売、営利目的およびmerc兵目的での使用は禁止されています。 ソースコードはそのまま無料で配布されます。他のサイトまたは他のソースで使用する場合は、著者の指示と配置の通知は必須です。



All Articles