前回「ATOM LITE」本体内蔵のフルカラーLEDでイルミネーションを作りましたが1個だけでちょっと物足りない・・・今度はもうちょっとそれっぽくLEDを60個使いましょう♪
フルカラーLEDというと高価なイメージがありましたが最近ではイルミネーションで使用されるLEDの需要が高いせいか、テープ状に沢山のLEDが連なったLEDテープライトが安価で購入できます。
フルカラーLEDを1個づつ買うよりはるかに安く、配線もLEDにマイコンが内蔵されているので複数のLEDを通信線で接続するだけで簡単にそれぞれの色を制御できてお手軽です。
今回はこのLEDテープライト(NeoPixcel)を使用したイルミネーションの作り方を紹介します。
1.サンプルプログラムの動作紹介(ATOM LITE)
2.必要なもの
3.LEDテープライトとの接続(Groveコネクタ)
4.LED点灯制御ライブラリ(Adafruit NeoPixel)の準備
5.サンプルプログラム(コピペ)
6.プログラムの動作紹介
7.まとめ
1.サンプルプログラムの動作紹介(ATOM LITE)
電源を入れると60個のフルカラーLEDが連なったテープライト(1m)が全て白色に点灯します。
同時に2つの白い光が上から下に流れるように点灯していきます。
「ATOM LITE」本体のボタンを押す度に全てのLEDが「赤」「緑」「青」「白」の順に変わります。
この間も2つの白い光は上から下に流れ続けます。
色の変更も色の種類を増やすことも簡単にできるので、自分好みに点灯させてみましょう♪
2.必要なもの
必要なものはテープライトをプログラムで制御するためのマイコンボード「ATOM LITE」と、フルカラーLED(WS2812)がテープ状に連なったLEDテープライトです。
3.LEDテープライトとの接続(Groveコネクタ)
「ATOM LITE」と「LEDテープライト」の接続は付属の「Groveコネクタ」で下画像のように行います。
「LEDテープライト」には「Groveコネクタ」変換ケーブルが付属していますので直接「ATOM LITE」の「Groveコネクタ」に接続するだけです。
「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」の初期設定と合わせて紹介しています。
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:「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.show();
pixels.setPixelColor:LEDの色を指定するコマンドです。
LED番号:色を指定するLED番号です。手前が「0」で一番奥が「LED数-1」の数値になります。
pixels.Color(赤LED, 緑LED, 青LED):指定した番号のLEDの色を赤、緑、青のLEDの明るさでそれぞれ指定(メモリに設定)します。(0~255)
pixels.show:これを実行すると指定したLEDの明るさで全てのLEDを点灯します。
次にイルミネーションのサンプルプログラムについて紹介します。
サンプルプログラムでは17行目のように「配列」の中に「配列」がある「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]:全ての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間隔で色を変更していく
}
}
「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の点灯位置やタイミング、パターンが目で見てわかるため、プログラミング学習というより遊びながらいろいろ試しているうちにだんだん理解できるようになってくると思います。
コメント