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

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

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

更新日 : 2020年5月19日

アニメーションの原理

まずはアニメーションの原理について説明します。これまでのチュートリアルで模様を描写する方法は理解してもらえたと思います。時間の経過とともに模様を少しずつ変化させながら、何度も描写すればアニメーションして(動いて)見えるようになるのです。動画がたくさんの静止画でできているのと同じ原理です。

Embed from Getty Images

以下が移動アニメーションの原理です。時間とともにLED#1、LED#2、LED#3・・・と順に点灯させていけば、光が移動しているように見えます。ファンのような円形のデバイスであれば回転しているように見えます。

移動アニメーションの原理

前回の記事で説明した通り、ALEDクラスには模様の「場所」を指定するposパラメーター(メンバ変数)があります。つまり、posを少しずつ変化させながらdrawで描写すれば、移動アニメーションが作成できます。

なお、ALEDクラスには、posを手動で変化させなくても自動で変化させつつアニメーションの表示間隔も調整してくれる機能があります。これについては後ほど解説します。

移動アニメーション実験スケッチ「ManualMove」

実際にスケッチを動かして試してみましょう。移動アニメーションするスケッチを用意しました。以下からダウンロードして下さい。

書き込む前に、ManualMove.inoの7行目の最後の引数をお使いのデバイスの制御可能LED数に変更します。変更できたらスケッチを書き込んで動作させてみましょう。以下のように動けば成功です。

  1. 赤い光が移動しながら2周する
  2. 虹色の模様に変わり、移動しながら2周する

ManualMoveスケッチ解説

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

  // グラデーション模様の色の変化量を指定する
  // 今回の例では以下の虹色模様から変更しない
  aled.colorPattern.hue = 360.0f;

今回の例で使用する色を指定しています。特に変更しないのでsetup関数に記述しています。

31行目
  aled.pattern = ALED::patPoint1;  // posに最も近いLEDが1個だけ点灯する模様を選択

今回初めて登場するALED::patPoint1を指定しています。この模様は、posに最も近い位置のLEDを基準の色に点灯し、それ以外のLEDを全て消灯します。この模様はアニメーションと組み合わせて効果を発揮するので、前回の記事では解説していませんでした。

なお、ALED::patPoint2というものも用意しており、こちらはposに最も近い位置のLEDを基準の色に点灯し、それ以外のLEDは変更しません。

33-39行目
  // 以下のループを200回実行する
  for (uint16_t i = 0; i < 200; i++) {
    aled.draw();                              // 模様を描写する
    delay(30);                                // 30ミリ秒待機
    aled.pos = aled.pos + 1.0f;               // 場所を少しだけ移動させる
    if (aled.pos >= 100.0f) aled.pos = 0.0f;  // 100に達したら0に戻る
  }

ここでは模様を描写した後、posメンバ変数を加算することで、場所を少し移動させています。場所は0-100の範囲でなければならない決まりなので、100に達したら0に戻る処理が入っています。forループにより、この処理が200回実行されます。1回あたりposが1ずつ動くので、合計で2周することになります。

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

  // 以下のループを200回実行する
  for (uint16_t i = 0; i < 200; i++) {
    aled.draw();                              // 模様を描写する
    delay(30);                                // 30ミリ秒待機
    aled.pos = aled.pos + 1.0f;               // 場所を少しだけ移動させる
    if (aled.pos >= 100.0f) aled.pos = 0.0f;  // 100に達したら0に戻る
  }

グラデーション模様に変わっているだけで、内容は31-39行目と同じです。グラデーション模様が2回転します。




ALEDクラスのアニメーション機能

ManualMoveスケッチ例で、アニメーションさせる方法は理解してもらえたのではないでしょうか?実は、ManualMoveスケッチのような処理を自分で記述しなくとも、ALEDクラスには簡単にアニメーションさせるための機能が備わっており、いくつか利点もあります。

ALEDクラスのアニメーション機能の利点の1つめが、手動でposなどの値を変えてdraw関数を呼び出す必要がないことです。posChangeメンバ変数に値をセットしておいてanimation関数を呼び出すことで、自動的にposを変更してdrawを呼び出す処理を行ってくれます。

パラメーター内容
posChangefloatアニメーション1ステップあたりのposの変動量
colorChangeHSVアニメーション1ステップあたりのcolorの変動量
valChangefloatアニメーション1ステップあたりのvalの変動量
アニメーション用のパラメーター

ALEDクラスのアニメーション機能の利点の2つめが、アニメーションの間隔を一定に調整してくれることです。ManualMoveスケッチでは30ミリ秒の固定の待ち時間を設定していました。しかし、実際にはdrawを実行する際にLEDの色を計算する時間がかかっています。この計算時間は、グラデーションのような複雑な模様や、LEDの合計が多いとより長い時間がかかります。結果として、アニメーションの間隔が不安定になってしまいます。ALEDクラスのアニメーション機能では、待ち時間を調整して1ステップのアニメーションが33ミリ秒(30Hz, 1秒当たり30回のアニメーション)にしてくれるため、安定した速度でアニメーションさせることができます。(なおLEDが非常に多いと33ミリ秒で収まらない場合もあります。そういう場合はperiodメンバ変数で周期を変更できます)

移動アニメーションスケッチ「MoveAnimation」

ALEDのアニメーション機能を使って、ManualMoveと同じ動作をするスケッチを用意しました。以下からダウンロードして下さい。

書き込む前に、MoveAnimation.inoの7行目の最後の引数をお使いのデバイスの制御可能LED数に変更します。変更できたらスケッチを書き込んで動作させてみましょう。以下のように動けば成功です。ManualMoveとほぼ同じですので、動画はManualMoveの説明を参照して下さい。

  1. 赤い光が移動しながら2周する
  2. 虹色の模様に変わり、移動しながら2周する

MoveAnimationスケッチ解説

30-37行目
  // 移動するアニメーション
  aled.pattern = ALED::patPoint1;  // posに最も近いLEDが1個だけ点灯する模様を選択

  aled.posChange = 1.0f;  // 1ステップのアニメーションあたりposを1増やす
  aled.animation(200);    // アニメーションを200ステップ実行

  aled.pattern = ALED::patGrad;  // グラデーション模様を選択
  aled.animation(200);           // アニメーションを200ステップ実行

ManualMoveで必要だったforループ、posの変更、draw、待機が必要なくなって簡潔に記述できていることが分かると思います。あらかじめposChangeを指定しておけば、あとはanimationを呼び出すだけでアニメーションが実行できます。引数はステップ数を整数で指定します。

色変化アニメーションスケッチ「ColorAnimation」

次は色を変化させるアニメーションを試してみましょう。スケッチを以下からダウンロードして下さい。

書き込む前に、ColorAnimation.inoの7行目の最後の引数をお使いのデバイスの制御可能LED数に変更します。変更できたらスケッチを書き込んで動作させてみましょう。以下のように、単色模様の色が時間とともに変化すれば成功です。




ColorAnimationスケッチ解説

26-30行目
  // 色変化するアニメーション
  aled.pattern = ALED::patSingle;  // 単色模様を選択

  aled.colorChange.hue = 1.0f;  // 1ステップのアニメーションあたり変化させる値
  aled.animation(360);          // アニメーションを360ステップ実行

単色模様を選択しています。アニメーションで色相を変化させるため、colorChange.hueの値を設定しています。colorChange.satやcolorChange.valを設定することも可能です。

明るさパラメーターvalの種類と用途

移動、色のアニメーションと試したので、最後は明るさを変化させて点滅するアニメーションです。スケッチを試す前に、明るさパラメーターの種類が多く混乱を招く可能性があるので、先に解説しておきます。

明るさ関連のパラメーター(メンバ変数)を以下の表にまとめました。

パラメーター用途
color.val模様の基準の色の明るさ。ある場所の明るさを指定するために使用。
colorChange.valアニメーション1ステップあたりのcolor.valの変化量
colorPattern.valグラデーション模様の明るさの変化量
val全体の明るさを調整。点滅アニメーションおよびLEDデバイス自体が明るすぎる場合の調整に使用。
valChangeアニメーション1ステップあたりのvalの変化量
明るさパラメーターvalの種類と用途

color.valとcolorPattern.valはグラデーション模様を描写する際に使用しましたね。このパラメータを変更してグラデーション模様の点滅アニメーションをさせようとするとうまくいきません。というのも、ある場所の明るさを計算するためのパラメーターなので、これを0にしても全体が消灯するわけではないからです。

そこで使用するのがvalパラメーターです。これはチュートリアルでははじめて登場するものですが、デバイス全体の明るさを調整するものです。具体的には、val=50にすると全体の明るさが半分になり、0にすると全て消灯します。アニメーションの際はvalChangeにステップごとの変化量を指定することになります。

また、LEDが露出しているデバイスなどは、100%の明るさだと眩しすぎるというケースがあります。そういった場合はvalを50などにすることで全体の明るさを抑えることができます。

点滅アニメーションスケッチ「BlinkAnimation」

では明るさを変化させて点滅させるアニメーションを試してみましょう。スケッチを以下からダウンロードして下さい。

書き込む前に、BlinkAnimation.inoの7行目の最後の引数をお使いのデバイスの制御可能LED数に変更します。変更できたらスケッチを書き込んで動作させてみましょう。以下のように、動いている虹色のグラデーション模様が時間とともに点滅すれば成功です。

BlinkAnimationスケッチ解説

25行目
  aled.val = 0.0f;        // 消灯からスタートする

特に何も指定しないとvalの値は100になっています。今回は消灯状態からスタートするため、valに0をセットしています。

26行目
  aled.posChange = 1.0f;  // 移動アニメーションも併用

点滅とは直接関係ありませんが、移動や色変化のアニメーションも併用できます。posChangeを指定することで、虹色の模様が動きつつ、点滅するようにしています。

31-32行目
  aled.valChange = 2.0f;  // 1ステップのアニメーションで明るさを2増やす
  aled.animation(50);  // アニメーションを50ステップ実行(明るさ100になるまで)

消灯状態から明るさを増やしていく部分です。1ステップあたり2ずつ増えるように指定し、50ステップのアニメーションを実行するので、明るさが100まで変化します。

34-35行目
  aled.valChange = 0.0f;  // アニメーションで明るさを変更しない
  aled.animation(100);    // アニメーションを100ステップ実行(移動のみ)

明るさ100のまま変更せず100ステップアニメーションします。点灯状態で少し時間を置いたほうが綺麗に見えます。posChangeは設定されているので移動のみのアニメーションになります。

なお、valは100を超えても0に戻ることはないので、valChangeを2のままにしておいても同じ動作になります。

37-38行目
  aled.valChange = -2.0f;  // 1ステップのアニメーションで明るさを2減らす
  aled.animation(50);  // アニメーションを50ステップ実行(明るさ0になるまで)

明るさ100から明るさを減らしていく部分です。1ステップあたり2ずつ減るように指定し、50ステップのアニメーションを実行するので、明るさが0まで変化します。




まとめ

移動、回転、色変化、点滅アニメーションのプログラミング方法は以上です。ALEDクラスを利用することで、少ないコードでアニメーションを記述することができたと思います。これまでは、全てのチャネルに同じイルミネーションを描写していました。次回はチャネルごとに異なるイルミネーションを描写する方法について説明します。

複数のアドレサブルRGBデバイスをアニメーションする

ALEDクラスには、複数のアドレサブルRGBデバイスに異なる模様やアニメーションを描写する機能が装備されています。本記事では、ParallelAnimationクラスを使う方法と、複数のチャネルをグループ化したALEDクラスを作成する方法について、スケッチを動かしながら解説しました。この機能を使えば、少ないコードで複数のチャネルに異なるイルミネーションをさせることが可能になります。