ALEDクラスの使い方とグラデーション模様の描写

簡単にアドレサブルRGBデバイスのイルミネーションを自作できるように、代表的な模様(単色、グラデーション、1点発光)や、アニメーション(移動、回転、色変化、点滅)を作成できるALEDクラスを提供しています。本記事ではALEDクラスの基本的な使い方をまず説明します。そして、実際にスケッチを動かしながら、単色とグラデーション模様を描写する方法を解説しています。

本記事はArduino互換機「CG-CustomARGB」を使ったアドレサブルRGBプログラミングチュートリアルの一部です。

更新日 : 2020年5月19日

ALEDクラスを使うスケッチの構成

これまでのアドレサブルRGBチュートリアルで使っていたスケッチは、inoファイル1つのみの構成でした。今回は、以下のようにinoファイル + aled.hファイルの2つになっています。

ALEDクラスを使うスケッチの構成

全ての処理をinoファイルに記述しても良いのですが、コードが長くなってくると見通しが悪くなってきます。そこで、inoファイルはsetup、loop関数などのメインの処理を記述しておき、色を管理するクラスや、模様、アニメーション、LEDにデータ送信などをするALEDクラスはaled.hファイルに記述するようにします。inoファイルからaled.hファイルをinclude (参照)することで、aled.hファイルの機能を使うことが可能になる、という仕組みです。

なお、前項までのチュートリアルではinoファイルに以下の機能を記述していましたが、これらの機能もaled.hに移動されています。

  • アドレサブルRGB LEDにデータを送信するsendLedData関数とバッファーのsendBuf変数
  • 色を管理するRGB、HSVクラス

アドレサブルRGBデバイスの個別制御可能なLED数

前準備として、お使いのアドレサブルRGBデバイスの「個別制御可能なLED数」を把握しておく必要があります。まだの方は製品ページの「動作確認」を参考に数を確認して下さい。

なぜLED数の確認が必要なのでしょうか?理由は、LEDの数がデバイスによって異なるからです。ファンを例にとっても、中央部が発光するもの、外周部が発光するもの、片面か両面かなど、様々です。発光部に何個のLEDを搭載するかもメーカーによって異なります。デバイスのLED数より少ないデータを送信してしまうと、足りない分のLEDは発光しませんし、多く送信してしまうと余ったデータは反映されなくなってしまい、意図した模様にならない可能性が出てきます。

1つ注意しておかなければいけないのが、物理的なLED数と制御可能なLED数は異なる場合があるということです。Antec製 Prizm 140 ARGBを例に説明します。このファンは物理的には表面18個と裏面18個の合計36個のLEDを搭載しています。しかし、接続は以下のように表と裏のLEDが並列に繋がっているため、個別に制御できるのは18組となります。表と裏は必ず同じ色になるということです。

表と裏のLEDに18個のLEDを搭載するAntec製 Prizm 140 ARGB
Antec製 Prizm 140 ARGBのLED接続図

一方CORSAIR製QL140 RGBのように、表と裏別々に制御できるような接続になっているものもあります。どのような接続だったとしても、製品ページの「動作確認」にある手順で個別制御可能な数は分かりますので、安心して下さい。

単色模様を描写するスケッチ「SinglePattern」

では実際にスケッチを動かしてALEDクラスの使い方を説明していきます。シンプルな単色模様を描写するスケッチを用意しましたのでダウンロードして下さい。

書き込む前に、SinglePattern.inoの7行目の最後の引数「34」をお使いのデバイスの制御可能LED数に変更します。

// アドレサブルRGB制御用のALEDクラスを使う
//  デフォルトは全チャネルに同じデータを送信
//  チャネル1と3だけの場合は CH1|CH3 のようにする
//  LED数は使うデバイスに合わせる
ALED aled(CH1 | CH2 | CH3 | CH4 | CH5, 34);

変更できたらスケッチを書き込んで動作させてみましょう。以下のように動けば成功です。

  1. 赤に発光
  2. 3秒待機
  3. 水色に発光
  4. 3秒待機
  5. 白に発光
  6. 3秒待機して1.に戻る

SinglePatternスケッチ解説

1行目
#include "aled.h"  // Indoor Corgi アドレサブルRGB LED制御ライブラリを使用

同じディレクトリ内の「aled.h」ファイルの中身を参照しています。これにより、aled.h内に記述している機能をinoファイル内で使用できるようになります。

3-7行目
// アドレサブルRGB制御用のALEDクラスを使う
//  デフォルトは全チャネルに同じデータを送信
//  チャネル1と3だけの場合は CH1|CH3 のようにする
//  LED数は使うデバイスに合わせる
ALED aled(CH1 | CH2 | CH3 | CH4 | CH5, 34);

ALEDクラスのインスタンスを作成しています。ALEDクラスの機能を利用するための下準備と考えて下さい。

aled(出力チャネル, LED数);

という2つの引数(パラメーター)で初期化します。

1つめの引数である出力チャネルは、CH1からCH5のどこに接続されているデバイスにデータを送信するか決めます。複数選択する場合は「|」で区切ります。なお、CH1~CH5の値はaled.h内にマクロとして定義してあります。

2つめの引数のLED数は、「アドレサブルRGBデバイスの個別制御可能なLED数」で説明した通り、お使いのデバイスの個別制御可能なLEDの数を設定します。ALEDクラスは設定したLEDの数に合うように、送信データの長さやグラデーション模様の計算を最適化してくれます。

19行目
void loop() {

今回からsetup関数でなく、loop関数に処理を記述しています。loop関数は最後(58行目)まで実行した後、最初に戻って繰り返し実行されます。アニメーションなど、色を変化させる場合はloop関数を使用すると良いでしょう。

20-21行目
  // 1色の模様のデモ
  aled.pattern = ALED::patSingle;  // 1色の模様を選択

aled.patternメンバ変数に、模様の種類を指定します。aled.h内であらかじめ用意された以下の中から指定する必要があります。今回は最もシンプルな全LEDを同じ色にするpatSingleを指定しています。

  • patSinge : 全LEDを同じ色にする
  • patGrad : グラデーションにする
  • patSym : 対称になるようなグラデーションにする
  • patPoint1 : 1つのLEDだけ発光して、残りを消灯する
  • patPoint2 : 1つのLEDだけ変更して、残りは変更しない
22-26行目
  // 表示する模様の基準の色を指定する
  aled.color.hue = 0.0f;
  aled.color.sat = 100.0f;
  aled.color.val = 100.0f;

色を指定します。aled.colorメンバ変数はHSV型になっていて、hue, sat, valメンバ変数を持っているので、それを変更します。HSV型についての解説はチュートリアルの「HSV(HSB)モデルでRGB LEDの色を指定する」を参照して下さい。

28行目
  aled.draw();  // 模様を描写する

設定した模様と色にもとづいて、アドレサブルRGBデバイスを発光(最初は赤色)させます。aled.patternとaled.colorの値をもとにバッファーにRGB値を準備し、さらにsendLedData関数を実行してデータを送信する、という一連の流れを裏で一気に行っています。これは、これまでのチュートリアルで解説した手順ですが、ALEDクラスではdraw関数1行だけで実行できるようになっており、ユーザーは模様、色や後で解説するアニメーションの処理に集中できるメリットがあります。

30行目
  delay(3000);  // 3000ミリ秒(3秒)待機

delay関数はaled.hとは関係なく、Arduino IDE標準の機能です。ミリ秒で指定した時間だけ待機します。それぞれの命令は、実際には人の目では追えないくらい短い時間で行われるので、しばらく赤色で発光させておきたい場合は待機する必要があります。

32-57行目
  // 表示する模様の基準の色を指定する
  aled.color.hue = 180.0f;
  aled.color.sat = 80.0f;
  aled.color.val = 100.0f;

  aled.draw();  // 模様を描写する

  delay(3000);  // 3000ミリ秒(3秒)待機

  // 表示する模様の基準の色を指定する
  aled.color.hue = 0.0f;
  aled.color.sat = 0.0f;
  aled.color.val = 100.0f;

  aled.draw();  // 模様を描写する

  delay(3000);  // 3000ミリ秒(3秒)待機

  // 表示する模様の基準の色を指定する
  aled.color.hue = 0.0f;
  aled.color.sat = 0.0f;
  aled.color.val = 0.0f;

  aled.draw();  // 模様を描写する

  delay(3000);  // 3000ミリ秒(3秒)待機

色の値(aled.hue, aled.sat, aled.val)が変わっていますが、内容は23-30行目までの繰り返しです。まずはhue=180, sat=80なので水色、次はsat=0なので白、最後はval=0なので消灯となります。その後はloop関数の最初に戻って再度赤になる、という流れです。

グラデーション模様を表示するためのパラメーター

ALEDクラスの基本的な使い方は分かってもらえたのではないでしょうか。次はグラデーション模様を表示する方法について解説します。グラデーションというのは、場所に応じて色を徐々に変化させていく模様のことです。そのため、単色の場合よりも多くのパラメーター(ALEDクラスのメンバ変数)を指定する必要があります。ALEDクラスでグラデーション模様を決めるパラメータを表にまとめました。

パラメーター内容
pattern通常のグラデーションはALED::patGrad、対称なグラデーションはALED::patSymを指定。
colorHSV基準になる色を指定。HSVなので、hue, sat, valメンバ変数を指定する。
colorPatternHSV色の変化量を指定。HSVなので、hue, sat, valメンバ変数を指定する。
posfloat基準になる場所を指定。0から100の範囲で指定する。
ALEDクラスでグラデーション模様を決めるパラメーター

単色模様の時は色を決めていたcolorだけでしたが、colorPattern, posが増えていて、patternも2種類のグラデーションが指定できるようになっています。それぞれのパラメーターについては、実際にスケッチを動かしながら解説していきます。

グラデーション模様を表示するスケッチ「GradPattern」

まずは通常のグラデーション模様を描写するスケッチを用意しましたのでダウンロードして下さい。

書き込む前に、GradPattern.inoの7行目の最後の引数「34」をお使いのデバイスの制御可能LED数に変更します。変更できたらスケッチを書き込んで動作させてみましょう。以下のように動けば成功です。なお、各ステップを3秒間表示するようになっています。

  1. 赤~黄のグラデーション模様を描写
  2. 赤~紫の虹色のグラデーション模様を描写
  3. 赤が徐々に薄くなるグラデーション模様を描写
  4. 半周ごとに赤が徐々に薄く&暗くなるグラデーション模様を描写
  5. 4.の模様の位置が少し移動する
  6. 4.の模様の位置がさらに移動する

GradPatternスケッチ解説

20-27行目
  // グラデーション模様のデモ
  aled.pattern = ALED::patGrad;  // グラデーション模様を選択

  // 表示する模様の基準の色を指定する
  // 今回の例では基準の色は以下の値から変更しない
  aled.color.hue = 0.0f;
  aled.color.sat = 100.0f;
  aled.color.val = 100.0f;

今回はpatGradを指定して、通常のグラデーション模様を選択します。もう一つの対称グラデーション模様については後に別のスケッチを使って解説します。

また、基準になる色(colorメンバ変数)はグラデーションの解説にはさほど重要でないので、赤色に固定しています。そのため、この後に出てくる模様は全て赤色からスタートして色が変化していきます。もちろん、この値を変えることでも模様が変化しますので、一通りスケッチの動きが理解できたら変更してみるのも面白いと思います。

29-31行目
  // 基準の場所を0-100で指定する
  // 0だと1つめのLEDが基準になる
  aled.pos = 0.0f;

posはグラデーション模様を描き始める位置を0-100の範囲で指定します。0を指定すると1番目のLEDが基準になります。50を指定すると、全体の真ん中の位置からスタートします。一番最後のLEDの後は最初に戻ります(ループしている)ので、どこから始めたとしてもデバイス全体に模様が表示されます。

33-40行目
  // グラデーションの色の場所による変化量を指定する
  // hueを90変化させる例
  aled.colorPattern.hue = 90.0f;
  aled.colorPattern.sat = 0.0f;
  aled.colorPattern.val = 0.0f;

  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

colorPatternメンバ変数にグラデーションで変化させる色の量を指定します。ここではsatとvalが0なので、彩度と明るさは変化しません。一方hue=90なので色相を90変化させます。

上で説明した通り、colorが赤でpos=0なので、1番目のLEDは赤になります。そこから2番目、3番目と進むにつれてhueの値が変化していき、最後のLEDでhue=90の黄色になるイメージです。Antec製 Prizm 140 ARGBの場合だと、左下に1つめのLEDが配置されているので、そこが赤になり、反時計回りに色が変化していきます。

色相を90変化させる
42-49行目
  // グラデーションの色の場所による変化量を指定する
  // hueを360変化させる例
  aled.colorPattern.hue = 360.0f;
  aled.colorPattern.sat = 0.0f;
  aled.colorPattern.val = 0.0f;

  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

colorPattern.hue=360を指定しているので、ちょうど色相が1周して虹色の模様になります。

51-58行目
  // グラデーションの色の場所による変化量を指定する
  // satを-100変化させる例
  aled.colorPattern.hue = 0.0f;
  aled.colorPattern.sat = -100.0f;
  aled.colorPattern.val = 0.0f;

  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

colorPattern.hue=0なので色相は変化しなくなりました。代わりにcolorPattern.sat=-100なので徐々に彩度が減っていき、最後は0 (白色)になるような模様を描写します。この例から分かる通り、変化量にはマイナスの値を指定することもできます。

60-67行目
  // グラデーションの色の場所による変化量を指定する
  // satとvalを-200変化させる例 0を下回ったら100に戻る
  aled.colorPattern.hue = 0.0f;
  aled.colorPattern.sat = -200.0f;
  aled.colorPattern.val = -200.0f;

  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

colorPattern.satとcolorPattern.valに-200を指定しているので、彩度と明るさが変化します。この例から分かる通り、変化量は100を超えるような大きさであっても構いません。satとvalは100から徐々に減っていき、0になるとまた100に戻るようになっています。そのため、-200を指定すると100から0に変化する模様が2回現れることになるのです。

彩度、明度を-200変化させる
69-76行目
  // 場所を移動させる
  aled.pos = 10.0f;  // 先頭から10%の位置を基準にする
  aled.draw();       // 模様を描写する
  delay(3000);       // 3000ミリ秒(3秒)待機

  aled.pos = 20.0f;  // 先頭から20%の位置を基準にする
  aled.draw();       // 模様を描写する
  delay(3000);       // 3000ミリ秒(3秒)待機

模様の場所を変化させる例です。これまでは全てpos=0だったので1番目のLEDの位置からグラデーションを開始していました。posを10、20と変化させることで開始位置が変わります。Antec製 Prizm 140 ARGBのように円形にLEDが配置してある場合だと、反時計回りに少しずつ移動するように見えます。

対称グラデーション模様を表示するスケッチ「SymPattern」

次に、対称な模様を描写するするスケッチを用意しましたのでダウンロードして下さい。

書き込む前に、SymPattern.inoの7行目の最後の引数「34」をお使いのデバイスの制御可能LED数に変更します。変更できたらスケッチを書き込んで動作させてみましょう。以下のように動けば成功です。なお、各ステップを3秒間表示するようになっています。

  1. 赤~黄の通常のグラデーション模様を描写
  2. 赤~黄の対称なグラデーション模様を描写
  3. 赤が徐々に薄くなる通常のグラデーション模様を描写
  4. 赤が徐々に薄くなる対称なグラデーション模様を描写

SymPatternスケッチ解説

32-44行目
  // グラデーションの色の場所による変化量を指定する
  // hueを90変化させる例
  aled.colorPattern.hue = 90.0f;
  aled.colorPattern.sat = 0.0f;
  aled.colorPattern.val = 0.0f;

  aled.pattern = ALED::patGrad;  // 通常のグラデーション模様patGradの場合
  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

  aled.pattern = ALED::patSym;  // 対称のグラデーション模様patSymの場合
  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

対称なグラデーション模様も、指定するパラメーターは前項で解説した通常のグラデーションと同じです。異なるのはpatternにALED::patSymを指定する点です。このスケッチでは、通常のグラデーションとの比較のため、同じパラメーターで通常のグラデーションと対称なグラデーションをそれぞれ描写します。最初はhueを90変化させる場合です。

以下がAntec製 Prizm 140 ARGBでの比較です。通常のグラデーションでは、最初のLEDから最後のLEDにかけて色が変化します。そのため、最初のLED(赤)と最後のLED(黄緑)の間に境界が見られます。一方、対称なグラデーションでは最初のLEDから中間のLEDにかけて色が変化します。そのため、通常のグラデーションと違い、色の境界が無く常になめらかに変化しています。

通常のグラデーション
対称なグラデーション

なお、境界ができるかどうかはアドレサブルRGBデバイスのLEDの配置によっても変わります。

46-58行目
  // グラデーションの色の場所による変化量を指定する
  // satを-100変化させる例
  aled.colorPattern.hue = 0.0f;
  aled.colorPattern.sat = -100.0f;
  aled.colorPattern.val = 0.0f;

  aled.pattern = ALED::patGrad;  // 通常のグラデーション模様patGradの場合
  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

  aled.pattern = ALED::patSym;  // 対称のグラデーション模様patSymの場合
  aled.draw();  // 模様を描写する
  delay(3000);  // 3000ミリ秒(3秒)待機

次は、彩度を変化させる場合の比較です。こちらも対称なグラデーションだと最初と最後のLEDの間の境界が無くなめらかに描写できるていることが分かると思います。

通常のグラデーション
対称なグラデーション

まとめ

ALEDクラスの基本的な使い方は以上です。本クラスの機能を使うことで、シンプルなコードでグラデーション模様を描写することができました。ALEDクラスには今回解説した静止模様だけでなく、アニメーションを描写する機能も備わっています。次回はアニメーションをプログラミングする方法について解説します。

アドレサブルRGBのアニメーション(移動、回転、色変化、点滅)

本記事ではアニメーションの原理を説明した後、実際にスケッチを動かしながら移動、回転、色変化、点滅アニメーションのプログラミング方法を解説しています。ALEDクラスを利用することで、少ないコードでアニメーションを記述することができます。