はじめに
Arduinoで多数のLEDを同時に操作したいとなったときに、I/Oピンが足りない、ということがあります。
ひとつの入力ピンや出力ピンから多数の機器を制御する方法はたくさんありますが、LEDに関してはマイコン内蔵LEDを使うというのは最善の一手の1つです。
今回は個別制御可能なマイコン内蔵フルカラーLEDをArduinoから制御してみましょう。
マイコン内蔵LED
Adafruit NeoPixelのようなものをみるとわかります。
電圧をかけるとどのように光らせるかというDataそしてGNDの3つのラインだけで数珠つなぎになったLEDを光らすことができます。
Arduinoでよく使われるのは、入手がたやすく安価で5Vで駆動するWS2812Bです。その他12V駆動のWS2811やWS2812Bの後継WS2822などがあるそうで。
またRGBで制御できるWS2812B以外にも、RGBWで制御できるSK6812やSK6822などもあります。
WS2812BとSK6812を比べると、青の発色に違いがあり、鮮明な青が出るのはWS2812Bなので僕はWS2812Bを好んで使います。
WS2812Bは転送スピードが遅いので(約1Mbps)、場合によっては高速通信できるLPD8866 (20Mbps)なども使われたりします。
Adafruit公式や秋月電子をはじめ各種通販で購入することができますが、公式で購入するのは値が張ります。
AmazonのマーケットプレイスやAliexpressで「WS2812B」と検索すれば中華品が安価で手に入りますので、その辺りを狙ってみると良いかと思います。
マイコン内蔵LEDの消費電力は結構大きいので、同時に光らせる量や光量などの調整はきちんとしましょう。色々な人が計測していますので調べればいっぱい出てきます。
WS2812B + LPC810: http://aid.her.jp/uratan/led/index.html
ライブラリ
はじめに
このようなマイコン内蔵LEDを制御するためのArduinoのライブラリは複数ありますが、よく使われているのはAdafruit_NeoPixelライブラリかFastLEDライブラリのどちらかです。
Adafrit_NeoPixel GitHub : https://github.com/adafruit/Adafruit_NeoPixel
FastLED GitHub : https://github.com/FastLED/FastLED
どちらも一長一短あるそうですが、ArduinoのフォーラムによるとFastLEDの方が優位性があるそうなので、FastLEDを好んで使います。
ライブラリのインストール
ライブラリはArduino IDEから追加できます。
Arduino IDEの上部タブ「スケッチ」から「ライブラリをインクルード」「ライブラリを管理…」を押してライブラリマネージャーの画面を開きます。
検索窓から「FastLED」と入力するとFastLED by Daniel Garciaという項目が出てくるので、最新バージョンを選んでインストールします。
ライブラリをインストールしたらArduino IDEの「スケッチ」「ライブラリをインクルード」に「FastLED」の項目が増えているのでそれを選択すればFastLEDが組み込まれます。
FastLEDライブラリの使い方
基本的な使い方はFastLEDのGitHub内にあるwikiをみると書いてあります。
特にBasic Usageのページに基本的なことが書いてありますね。
#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN 6
はじめに FastLED.hのライブラリをインクルードします。NUM_LEDS
はLEDストリップ(LEDテープ)などにつながっている LEDの数、DATA_PIN
はLEDストリップのData InピンにつながっているI/Oピンの番号です。
CRGB leds[NUM_LEDS];
LEDストリップの変数宣言です。この場合、leds[]
という変数でこのLEDを指定しています。
LEDストリップが複数ある場合は、Multiple Controller Exampleのページを参照すればわかりますが、この変数を増やしてやればいいというわけですね。
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}
setup()
関数内で、FastLEDの初期化処理を行います。
void loop() {
leds[0] = CRGB::Red;
FastLED.show();
delay(30);
}
loop()内での記述ですが、leds[0] = CRGB::Red;
でledsテープの0番目のLEDの色を指定します。他の番号を指定したり色を変えてやることで様々に発光させることができます。
これらはFastLED.show();
が処理されるまで実際には発光しませんので、発光させたいタイミングでFastLED.show();
と書きます。
色の指定ですが、Pixel referenceのページに書いてある通り、様々な方法で指定することができます。
// Example 1:
leds[i].red = 50;
leds[i].green = 100;
leds[i].blue = 150;
// Example 2:
leds[i] = CRGB( 50, 100, 150);
// Example 3:
leds[i] = 0xFF007F;
// Example 4:
leds[i] = CRGB::HotPink;
// Example 5:
leds[i].setRGB( 50, 100, 150);
// Example 6:
leds[i] = leds[j];
特に、Example 3のカラーコードの指定と、Exapmle 2やExample 6のRGB指定は使いやすいのでこの方法をとることをお勧めします。
ArduinoでNeopixel操作
はじめに
今回はこんな感じでLEDストリップを光らせてみます。
このRGB発色はテストパターンとしておいておくことでLEDストリップがきちんと動作するかを確かめれるコードですね。
用意するもの
Arduino本体 (今回はArduino Uno互換機)
Akizuki : http://akizukidenshi.com/catalog/g/gM-07385/
LEDテープ (WS2812B)
Akizuki : http://akizukidenshi.com/catalog/g/gM-14307/
Arduinoボード
LEDストリップの5V端子、GND端子をArduinoの5V端子、GND端子にそれぞれつなぎます。
またLEDストリップのData In端子とArduinoの3番ピンをつなぎます。
Arduinoの5V端子はUSB供給で500mA、DCジャックの外部電力を用いて1Aまで供給できます。それ以上の電力を使う場合はArduinoの5V端子から電力を取らず、直接LEDストリップの5V端子と5V電源を繋げましょう。
Arduino IDE
テンプレートの読み込み
今回はFastLEDのテンプレートから使ってみましょう。
Arduino IDEの上部タブ「ファイル」「スケッチ例」から「FastLED」「Blink」を呼び出します。
#include <FastLED.h>
// How many leds in your strip?
#define NUM_LEDS 1
// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 3
#define CLOCK_PIN 13
// Define the array of leds
CRGB leds[NUM_LEDS];
void setup() {
// Uncomment/edit one of the following lines for your leds arrangement.
// FastLED.addLeds<TM1803, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<TM1804, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<TM1809, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2811, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
// FastLED.addLeds<APA104, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<UCS1903, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<UCS1903B, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<GW6205, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<GW6205_400, DATA_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<SM16716, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<LPD8806, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<P9813, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<APA102, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<DOTSTAR, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<SM16716, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<LPD8806, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<P9813, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
// FastLED.addLeds<DOTSTAR, DATA_PIN, CLOCK_PIN, RGB>(leds, NUM_LEDS);
}
void loop() {
// Turn the LED on, then pause
leds[0] = CRGB::Red;
FastLED.show();
delay(500);
// Now turn the LED off, then pause
leds[0] = CRGB::Black;
FastLED.show();
delay(500);
}
長々と書いてあるコードですが、そのほとんどはコメントアウトです。
必要な項目を残して設定していきましょう。#define NUM_LEDS
はLEDの数、今回は16個並べてやるので、1を16に変更します。#define DATA_PIN
はData Inに繋げるI/Oピン番号。今回は3番ピンに繋いだので、そのまま3にしておきます。#define CLOCK_PIN
ですが、WS2812Bにはクロックピンはないので、削除して大丈夫です。
setup()関数にある多くのコメントアウトですが、自分の使うLEDチップの型番以外はコメントアウトしています。初期ではNeoPixelが有効になっていて他のものはコメントアウトされています。
WS2812Bを使っているので、WS2812Bのところのコメントアウトを外して有効にしてやっても大丈夫ですが、NeoPixelのままでも問題なく動きます。
必要のない項目は全部消して大丈夫ですのでコメントアウトされているものは削除しましょう。
loop()関数内はleds[0]に対して、赤色に光らせたり消したりを500ms間隔で行うというコードになっていますね。せっかく16個も繋げたのにはじめの1個だけというのも切ないので、増やします。
for(int i = 0; i<NUM_LEDS; i++){
leds[i] = CRGB( 255, 0, 0);
FastLED.show();
delay(100);
leds[i] = CRGB( 0, 0, 0);
FastLED.show();
}
loop()内をこのように変更してやれば、for()
文によって16個が順番に点灯するようになります。CRGB::RED;
とする代わりに、RGBを個別に設定できるようにCRGB (255, 0,0)
と書いてやります。
例えばこのCRGB (255, 0,0)
を変えてやることで、色々な色にすることができるので、for()
文を増やして緑や青に設定し直してみましょう。
コードの全体
#include <FastLED.h>
#define NUM_LEDS 16
#define DATA_PIN 3
CRGB leds[NUM_LEDS];
void setup() {
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}
void loop() {
for(int i = 0; i<NUM_LEDS; i++){
leds[i] = CRGB( 255, 0, 0);
FastLED.show();
delay(100);
leds[i] = CRGB( 0, 0, 0);
FastLED.show();
}
for(int i = 0; i<NUM_LEDS; i++){
leds[i] = CRGB( 0, 255, 0);
FastLED.show();
delay(100);
leds[i] = CRGB( 0, 0, 0);
FastLED.show();
}
for(int i = 0; i<NUM_LEDS; i++){
leds[i] = CRGB( 0 , 0, 255);
FastLED.show();
delay(100);
leds[i] = CRGB( 0, 0, 0);
FastLED.show();
}
}
というわけで最終的にこんな感じです。
こいつをコンパイル、書き込みしてやれば、LEDが流れるように光るはずですね。
まとめ
LEDを大量に使う場合、こういったマイコン内蔵LEDを使うことで、Arduinoで使用するI/Oピンを劇的に減らすことができます。
また、DMX(照明用の通信規格)を入れ込んでやればLEDをさらに個別に制御してやることもできるので、照明を作りたい時も便利ですね。