LEDテープライトでクリスマスイルミネーションを作ろう♪ATOM LITE

LEDテープライトでクリスマスイルミネーションATOM LITE
スポンサーリンク

前回「ATOM LITE」本体内蔵のフルカラーLEDでクリスマスイルミネーションを作りましたが1個だけでちょっと物足りない・・・今度はもうちょっとそれっぽくLEDを60個使いましょう♪

「ATOM LITE」って何?って方は → こちら
「開発環境の準備」がまだの方は → こちら
前回のLED1個のクリスマスイルミネーションを作ろう♪は → こちら

フルカラーLEDというと高価なイメージがありましたが最近ではイルミネーションで使用されるLEDの需要が高いせいか、テープ状に沢山のLEDが連なったLEDテープライトが安価で購入できます。

フルカラーLEDを1個づつ買うよりはるかに安いし、配線もLEDにマイコンが内蔵されているので複数のLEDを通信線で接続するだけで簡単にそれぞれの色を制御できてお手軽です。

今回はこのLEDテープライト(NeoPixcel)を使用してクリスマスイルミネーションの作り方を紹介します。


1.サンプルプログラムの動作紹介(ATOM LITE)

電源を入れると60個のフルカラーLEDが連なったテープライト(1m)が全て白色に点灯します。
同時に2つの白い光が上から下に流れるように点灯していきます。

「ATOM LITE」本体のボタンを押す度に全てのLEDが「赤」「緑」「青」「白」の順に変わります。
この間も2つの白い光は上から下に流れ続けます。

色の変更も色の種類を増やすことも簡単にできるので、自分好みにカスタマイズしてみましょう♪

流れるLEDテープライト
流れるLEDテープライト

2.必要なもの(部品リスト)

以下が今回使用した部品リストです。
使用したものはすべては「スイッチサイエンス」さんで購入できます。
送料はポスト投函のクロネコヤマトの「ネコポス」で200円。3000円以上の購入で送料無料になります。

品名型式等購入先価格
本体ATOM LITEスイッチサイエンス1287円
LEDテープライトSK6812搭載 防水RGB LEDテープ 100cm(60LEDs) スイッチサイエンス1056円

3.LEDテープライトとの接続(Groveコネクタ)

「ATOM LITE」と「LEDテープライト」の接続は付属の「Groveコネクタ」で下画像のように行います。

ATOM LITEとLEDテープライトとの接続

「LEDテープライト」には「Groveコネクタ」変換ケーブルが付属していますので直接「ATOM LITE」の「Groveコネクタ」に接続するだけです。

ATOM LITEとLEDテープライトとの接続

「LEDテープライト」の配線赤色が5V、黒色が0V(G)、黄色は通信線になります。
通信線は「ATOM LITE」の場合は端子「G26」を使用します。
「M5Stack GRAY」や「Arduino」シリーズを使用する場合はプログラム内でそれぞれ使用する端子番号を設定してください。


4.LED点灯制御ライブラリ(Adafruit NeoPixel)の準備

テープライトのフルカラーLEDには制御用ICとして「SK6812(WS2812B互換)」が使用されています。

この「SK6812」を制御するには「Adafruit_NeoPixel」ライブラリを使用します。
このライブラリを使用すると全てのLEDが簡単に制御できるのでプロジェクトに追加しておきましょう。

ライブラリの追加方法は以下のリンクで「FastLED」ライブラリの追加で「ATOM LITE」の初期設定と合わせて紹介しています。

「ATOM LITE」の初期設定と「ライブラリ」の追加方法は →こちら

5.サンプルプログラムの書込み(コピペ)

下のコードを「コピペ」して書き込んで動作確認してみましょう。
※コピーは下コード(黒枠)内の右上角にある小さなアイコンのクリックでもできます。

#include <M5Atom.h>
#include <Adafruit_NeoPixel.h>  //NeoPixel SK6812制御用ライブラリ

#define PIN        26  // LEDテープ信号端子
#define NUMPIXELS  60  // LEDの数

// NeoPixel初期設定
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int change = 0; //色指定用
int r = 0;      //LED色指定値格納用(赤)
int g = 0;      //LED色指定値格納用(緑)
int b = 0;      //LED色指定値格納用(青)
int cnt = 29;   //LED流れる光(2個)カウント用

// LEDベース色を指定。2次元配列(4色分のr,g,bの値を設定)
int rgb[4][3] = {{5 ,5 ,5}, {10 ,0 ,1}, {0, 10, 1}, {2, 0, 10}};

//----------------------------------------------------------------
// 初期設定
//----------------------------------------------------------------
void setup() {
  M5.begin(true, false, false);  //Serial,POWER,LED
  pixels.begin();     //NeoPixel初期化
  pixels.clear();     //LED色指定クリア

  //初期点灯色指定
  r = rgb[change][0]; //LEDベース色白用r(赤)の値格納。rgb[0][0]
  g = rgb[change][1]; //LEDベース色白用g(緑)の値格納。rgb[0][1]
  b = rgb[change][2]; //LEDベース色白用b(青)の値格納。rgb[0][2]
  for(int i = NUMPIXELS; i >= 0; i--) {     //LED番号59~0まで繰り返し
    pixels.setPixelColor(i, pixels.Color(r, g, b)); //全LED色指定(白)
    pixels.show();  //LED色出力
    delay(5);       //5ms間隔で色を変更していく
  }
}
//----------------------------------------------------------------
// メイン
//----------------------------------------------------------------
void loop() {
  M5.update();              //本体ボタン状態更新

  // ボタンが押されるごとに色変更
  if(M5.Btn.wasPressed()) { //本体ボタンが押されていれば
    change++;               //色指定用change+1
    if (change == 4) {      //changeが4なら
      change = 0;           //changeを0リセット
    }
  }
  // ボタンONでLED全色変更
  if (M5.Btn.wasPressed() == 1) { //本体ボタンが押されていれば
    r = rgb[change][0]; //LEDのベース色の値(changeによる)をr,g,bへそれぞれ格納
    g = rgb[change][1];
    b = rgb[change][2];
  for(int i = NUMPIXELS-1; i >= 0; i--) { //LED番号59~0まで繰り返し
      //全LED色指定
      pixels.setPixelColor(i, pixels.Color(r, g, b)); //LED色指定
      pixels.show();  //LED色出力
      delay(5);       //5ms間隔で色を変更していく
    }
  }

  // 流れる白い光x2(残光3、LED白とベース色を混ぜてだんだん暗く)
  pixels.setPixelColor(cnt-3, pixels.Color(30, 30, 30));  //LED白後半
  pixels.setPixelColor(cnt-2, pixels.Color((20+r)/2, (20+g)/2, (20+b)/2));  //残光1
  pixels.setPixelColor(cnt-1, pixels.Color((10+r)/2, (10+g)/2, (10+b)/2));  //残光2
  pixels.setPixelColor(cnt, pixels.Color((5+r)/2, (5+g)/2, (5+b)/2));       //残光3
  pixels.setPixelColor(cnt+1, pixels.Color(r, g, b));     //LEDベース色

  pixels.setPixelColor(cnt+27, pixels.Color(30, 30, 30)); //LED白前半
  pixels.setPixelColor(cnt+28, pixels.Color((20+r)/2, (20+g)/2, (20+b)/2)); //残光1
  pixels.setPixelColor(cnt+29, pixels.Color((10+r)/2, (10+g)/2, (10+b)/2)); //残光2
  pixels.setPixelColor(cnt+30, pixels.Color((5+r)/2, (5+g)/2, (5+b)/2));    //残光3
  pixels.setPixelColor(cnt+31, pixels.Color(r, g, b));    //LEDベース色
  pixels.show();

  if (cnt == 0) { //カウントが0なら
    pixels.setPixelColor(0 , pixels.Color(r, g, b));  //LED0番をベース色に
    cnt = 30;     //カウントリセット
  }
  cnt--;          //カウント-1

  delay(100);     //遅延時間(ms)
}

6.プログラムの動作紹介

「LEDテープライト」を制御する「Adafruit_NeoPixel」ライブラリの動作について、単純に全てのLEDを同じ色に点灯させる下コードのプログラムを例に紹介します。

#include <M5Atom.h>
#include <Adafruit_NeoPixel.h>  //NeoPixel SK6812制御用ライブラリ

#define PIN        26  // LEDテープ信号端子
#define NUMPIXELS  60  // LEDの数

// NeoPixel初期設定
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

// 初期設定
void setup() {
  M5.begin(true, false, false);  //Serial,POWER,LED
  pixels.begin();     //NeoPixel初期化
  pixels.clear();     //LED色指定クリア
}
// メイン
void loop() {
  for(int i = NUMPIXELS - 1; i >= 0; i--) {    //LED番号59~0まで繰り返し
    pixels.setPixelColor(i, pixels.Color(5, 5, 5)); //全LED色指定(r,g,b)
  }
  pixels.show();  //LED色出力
  delay(100);     //遅延時間(ms)
}

まずは上コードの2行目のようにヘッダーファイルを準備します。

#include <Adafruit_NeoPixel.h>  //NeoPixel SK6812制御用ライブラリ

次に8行目のように使用する「LEDテープライト(NeoPixel)」の初期設定を行います。

// NeoPixel初期設定
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

Adafruit_NeoPixel pixels:「LEDテープライト」の初期設定を行うコマンドです。
NUMPIXELS:使用する「LEDテープライト」に使われているLEDの数を設定します。
PIN:通信線として使用する端子番号を指定します。
NEO_GRB + NEO_KHZ800:通信速度の設定です。このまま記入します。


次に13~14行目のように「pixels.begin()」で初期化を「pixels.clear()」で全LED色指定をクリア(メモリクリア)します。

pixels.begin();     //NeoPixel初期化
pixels.clear();     //LED色指定クリア

次に18~21行目のように「for文」を使用してLEDの59番から0番目のLEDを同じ色に設定します。

for(int i = NUMPIXELS - 1; i >= 0; i--) {    //LED番号59~0まで繰り返し
  pixels.setPixelColor(i, pixels.Color(5, 5, 5)); //全LED色指定(r,g,b)
}
pixels.show();  //LED色出力
pixels.setPixelColor(LED番号, pixels.Color(赤LED, 緑LED, 青LED));
pixels.show();

pixels.setPixelColor:LEDの色を指定するコマンドです。
LED番号:色を指定するLED番号です。手前が「0」で一番奥が「LED数-1」の数値になります。
pixels.Color(赤LED, 緑LED, 青LED):指定した番号のLEDの色を赤、緑、青のLEDの明るさでそれぞれ指定(メモリに設定)します。(0~255
pixels.show:これを実行すると指定したLEDの明るさで全てのLEDを点灯します。

各LEDの明るさの指定値は最大20を目安に設定しましょう。
イルミネーションとしては10程度で十分と思います。明るくしすぎると電流が多くなってマイコンボードが発熱し最悪壊れます。
プログラム書込み直後はマイコンボードの発熱をしばらく確認し、熱くなるようならすぐに電源を切ってください。
今回の「ATOM LITE」で「LEDテープライト(LED60個)」の組み合わせの場合、全て30の設定でも発熱は無く使用できました。

次にイルミネーションのサンプルプログラムについて紹介します。

サンプルプログラムでは17行目のように「配列」の中に「配列」がある「2次元配列」を使用しています。

「配列」「2次元配列」についての詳細は → こちら

4色の情報を格納するために4つの「配列」を準備し、その中にLED赤、緑、青の明るさの値を指定する3つの「配列」を持った「2次元配列」を準備しています。

// LEDベース色を指定。2次元配列(4色分のr,g,bの値を設定)
int rgb[4][3] = {{5 ,5 ,5}, {10 ,0 ,1}, {0, 10, 1}, {2, 0, 10}};
int rgb[色番号][3色LED] = {1色目配列, 2色目配列, 3色目配列, 4色目配列};

int rgb[色番号][3色LED]:全てのLEDの点灯色をボタンを押す度に切り替えるための配列です。
 [色番号]には切り替えられる色の数(ここでは4色なので4)を指定します。
 [3色LED]の部分は赤、緑、青の3色なので[3]として、以下のように {, , } のLEDの明るさをそれぞれ設定しておきます。
1色目配列:白色を指定 {5, 5, 5}
2色目配列:赤っぽい色を指定 {10, 0, 1}
3色目配列:緑っぽい色を指定 {0, 10, 1}
4色目配列:青っぽい色を指定 {2, 0, 10}

赤、緑、青の指定は単色だと冷たいイメージになるので少しずつ違う色を混ぜています。
好みの赤、緑、青に調整してみましょう。

次に44~49行目のように[色番号]の指定に変数「change」を使用して、本体ボタンを押す度に「change」を+1して0~3まで変化させ、4になったら0リセットします。

// ボタンが押されるごとに色変更
if(M5.Btn.wasPressed()) { //本体ボタンが押されていれば
  change++;               //色指定用change+1
  if (change == 4) {      //changeが4なら
    change = 0;           //changeを0リセット
  }
}

M5.Btn.wasPressed()は本体ボタンの状態を確認するためのコマンドです。
本体ボタンの使い方については以下の記事で詳しく紹介しています。

本体ボタンの使い方は → こちら

次に51~61行目のように、本体ボタンが押された時に配列「rgb」に設定した[色番号]の各LED赤、緑、青の明るさを、変数「r」「g」「b」に取得します。

取得した「r」「g」「b」の値で「for文」を使用して、60個のLEDすべてに「pixels.setPixelColor」を実行することで色を指定しています。

// ボタンONでLED全色変更
if (M5.Btn.wasPressed() == 1) { //本体ボタンが押されていれば
  r = rgb[change][0]; //LEDのベース色の値(changeによる)をr,g,bへそれぞれ格納
  g = rgb[change][1];
  b = rgb[change][2];
  for(int i = NUMPIXELS-1; i >= 0; i--) { //LED番号59~0まで繰り返し
    //全LED色指定
    pixels.setPixelColor(i, pixels.Color(r, g, b)); //LED色指定
    pixels.show();  //LED色出力
    delay(5);       //5ms間隔で色を変更していく
  }
}
pixels.setPixelColor」の中で指定するLED番号「i」について、今回のようにLEDが60個の場合は0から始まるため手前が「0」で、一番奥を「59」で指定します。
今回は奥から手前、流れるように色を変えたかったため「59」~「0」の順で変更するように指定しています。

for文」の使い方については以下の記事で詳しく紹介しています。

for文」(繰り返し処理)の使い方は → こちら

次は流れる白い光(2個)のプログラムです。LED番号を半分に分けて0~29を64~68行目で指定し30~59を70~74行目で指定しています。LED番号はこの後のメイン処理内でカウントダウンする変数「cnt」の数値で指定しています。

光が流れていくのを表現するため、残光を残すようにLEDの明るさを指定しています。
白い光をLED番号「cnt – 3」に設定。「cnt ~ cnt -2」を残光に設定。
残光は白色を少しづつ暗くして、ベース色と混ぜて(加算して)1/2にして表現しています。

残光が終わったらLED番号「cnt + 1」をベース色に指定します。

// 流れる白い光x2(残光3、LED白とベース色を混ぜてだんだん暗く)
pixels.setPixelColor(cnt-3, pixels.Color(30, 30, 30));  //LED白後半
pixels.setPixelColor(cnt-2, pixels.Color((20+r)/2, (20+g)/2, (20+b)/2));  //残光1
pixels.setPixelColor(cnt-1, pixels.Color((10+r)/2, (10+g)/2, (10+b)/2));  //残光2
pixels.setPixelColor(cnt, pixels.Color((5+r)/2, (5+g)/2, (5+b)/2));       //残光3
pixels.setPixelColor(cnt+1, pixels.Color(r, g, b));     //LEDベース色

pixels.setPixelColor(cnt+27, pixels.Color(30, 30, 30)); //LED白前半
pixels.setPixelColor(cnt+28, pixels.Color((20+r)/2, (20+g)/2, (20+b)/2)); //残光1
pixels.setPixelColor(cnt+29, pixels.Color((10+r)/2, (10+g)/2, (10+b)/2)); //残光2
pixels.setPixelColor(cnt+30, pixels.Color((5+r)/2, (5+g)/2, (5+b)/2));    //残光3
pixels.setPixelColor(cnt+31, pixels.Color(r, g, b));    //LEDベース色
pixels.show();

77~81行目でLED番号を指定する変数「cnt」をカウントダウンしています。
白い光を2個にするため、「cnt」で29~0のカウントダウンをしてLED番号の指定に使用します。

if (cnt == 0) { //カウントが0なら
  pixels.setPixelColor(0 , pixels.Color(r, g, b));  //LED0番をベース色に
  cnt = 30;     //カウントリセット
}
cnt--;          //カウント-1

7.まとめ

今回使用した「LEDテープライト」に使用されているフルカラーLED「SK6812(WS2812B互換)」にはマイコンが内蔵されていて色の指定は信号線の通信で行うため、配線は電源線(5V、0V)の2本と信号線1本の合計3本線だけです。

点灯色やパターンも「ATOM LITE」や「Arduino」等のマイコンボードがあれば制御用ライブラリを使用することで簡単に制御できます。

価格は「ATOM LITE」と「LEDテープライト(1m)」で2500円程で購入できます。
市販で安いものもありますが、買って点灯させたら思ってた色と違ったり、好みの点灯パターンが無いなんてこともあると思います。

今回紹介した方法なら色の指定はLED赤、緑、青の明るさを設定するだけなので簡単です。
点灯パターンもLEDの点灯位置やタイミング、パターンが目で見てわかるため、プログラミング学習というより遊びながらいろいろ試しているうちにだんだん理解できるようになってくると思います。

今年のクリスマスは自分オリジナルのクリスマスイルミネーションで楽しく盛り上がりましょ~♪

コメント

タイトルとURLをコピーしました