本記事ではRGBとHSVモデルの違い、HSVの利点、実際にHSVモデルを使ってアドレサブルRGBデバイスを光らせるスケッチについて解説しています。RGBの代わりにHSVモデルを使って色を表現することで、色を変化させて虹色の模様を描いたり、明るさを変化させて点滅させたりといったプログラミングが簡単にできます。
本記事はArduino互換機「CG-CustomARGB」を使ったアドレサブルRGBプログラミングチュートリアルの一部です。
HSV(HSB)モデルとは何か
HSVモデルとは色を表現する方法の1つです。赤、緑、青の組み合わせで色を表現するRGB方式と異なり、HSVでは色相(Hue)、彩度(Saturation)、明るさ(Value)の3つで表現します。明るさをBrightnessとしてHSBと呼ばれることもありますが、同じものです。詳細はwikipediaを参照して下さい。
HSVの利点
実際にアドレサブルRGBデバイス用にイルミネーションをプログラミングしようとした場合、RGBよりHSVの方が優れている点が多いです。
例えば、色を少しずつ変化させながら虹色の模様に発光させたいとします。RGBの場合はR, G, B全ての値を変化させなければならず、直感的にプログラムできません。一方HSVであれば、色相Hの値だけを徐々に変化させれば良いのです。
また、色の濃さを変化させたければS、明るさを変化させたり点滅させたければVの値だけ変えれば良いので、わかりやすいですね。
HSVを使ってLEDの色を指定する方法
HSVを使う利点は理解してもらえたと思います。しかし、最終的にアドレサブルRGBデバイスに送る際はRGB形式にする必要があります。これは、物理的にR, G, Bの3種類のLEDを組み合わせて色を表現しているためで、デバイス側としてはRGBのほうが都合が良いからです。
つまり、最初はHSVで色を計算しておき、それをRGBに変換してから送信すれば良いということになります。
- HSVでそれぞれのLEDの色を計算する。
- HSVからRGBに変換する
- RGBで色データを送信する
HSVからRGBに変換して送信するスケッチ「HSV」
では、HSVからRGBに変換して色データを送信するサンプルスケッチを用意しましたので、実際に動かしてみましょう。以下からダウンロードして書き込んで下さい。
なお、これ以降は以下の範囲を持つ円柱型HSVモデルを使用します。
- 色相 (Hue) : 0 ~ 360
- 彩度 (Saturation) : 0 ~ 100
- 明るさ (Value) : 0 ~ 100
お使いのアドレサブルRGBデバイスの一部が赤、黄、緑、水色、青、紫に発光していれば成功です。
スケッチ解説
1-83行目
RGBおよびHSV形式で色を管理するクラス(関連する機能をひとまとめにした型)を準備しました。内容を変更する必要はありません。実際に実行されるプログラムは88行目以降のsetup関数になります。
RGBクラスは、メンバ変数のred, green, blueに色の値を保持します。HSVクラスはメンバ変数のhue, sat, valに色の値を保持します。またメンバ関数のtoRGBを使うとRGBに変換することができます。
97-100行目
HSVColor hsv; // HSVモデルの色データを作成
hsv.hue = 0.0f; // 色相の値 0.0-360.0 単精度浮動小数点数なので末尾にfを付けている
hsv.sat = 100.0f; // 彩度の値 0.0-360.0
hsv.val = 100.0f; // 明るさの値 0.0-360.0
「hsv」という名前でHSVモデルの色を作成しています。その後、hue, sat, valのメンバ変数に値を設定しています。色相0なので赤色になります。HSVColorクラスでは値を小数で保持するようになっています。そこで、小数(厳密には単精度浮動小数点型)であることを明示するため、小数点以下1桁と「f」を末尾に追加しています。
102-104行目
// ループ
// iの値を0から5まで1ずつ増やしながら{}内を実行
for (uint16_t i = 0; i < 6; i++) {
6個のLED用の色をバッファーに準備するためにループを使用しています。変数iに0から5までの整数を順に代入しながら{}内(105-110行目)を繰り返し実行します。
105行目
RGBColor rgb = hsv.toRGB(); // HSVからRGBに変換
ここでHSVモデルの「hsv」変数からRGBモデルの「rgb」変数へ色のモデルを変換しています。色自体が変わるわけではありません。
106-108行目
sendBuf[i * 3] = rgb.green; // i+1番目のLEDの緑の値
sendBuf[i * 3 + 1] = rgb.red; // i+1番目のLEDの赤の値
sendBuf[i * 3 + 2] = rgb.blue; // i+1番目のLEDの青の値
RGBの色が取得できたので、バッファーに色の値を代入しています。ループを使用しているので、iの値からそれぞれのLED用のバッファーの位置を計算しています。
110行目
hsv.hue = hsv.hue + 60.0f; // 次のLEDの色相を60°変化させる
ここではhsvの色相を60°加算しています。i=0最初hueの値は0なので1つめのLEDは赤になります。一方2つめのLEDはhue=60なので黄、3つめはhue=120で緑・・・といった具合に色が変化します。
hsv.satの値を減らすと徐々に色が薄くなります。また、hsv.valの値を減らすと徐々に暗くなります。ぜひ試してみて下さい。
113行目
sendLedData(); // バッファーのデータをアドレサブルRGBデバイスに送信
ここでバッファーのデータをアドレサブルRGBデバイスに送信しており、LEDの色が変化します。
まとめ
本記事ではRGBとHSVモデルの違い、HSVの利点、実際にHSVモデルを使ってアドレサブルRGBデバイスを光らせるスケッチについて解説しました。RGBの代わりにHSVモデルを使って色を表現することで、色を変化させて虹色の模様を描いたり、明るさを変化させて点滅させたりといったプログラミングが簡単にできます。
あとは自由に実現したいイルミネーションをプログラミングして下さい!と言いたい所なのですが、実際にグラデーション模様を描いたり、点滅や回転などのアニメーションをさせようとすると、それなりの量のコードを書く必要があります。そこで、代表的な模様(単色、グラデーション、1点発光)や、アニメーション(移動、回転、点滅、色変化)を簡単に作成できるALEDクラスを提供しています。次回はこのALEDクラスを使い方を解説していきます。
ALEDクラスの使い方とグラデーション模様の描写
簡単にアドレサブルRGBデバイスのイルミネーションを自作できるように、代表的な模様(単色、グラデーション、1点発光)や、アニメーション(移動、回転、色変化、点滅)を作成できるALEDクラスを提供しています。本記事ではALEDクラスの基本的な使い方をまず説明します。そして、実際にスケッチを動かしながら、単色とグラデーション模様を描写する方法を解説しています。