LED 大好きな皆さんこんにちは。私が好きなマイコン入り LED は WS2812B です。
さて、そんな WS2812B で構成されている、8x8x8、合計512個の LED を使った、3D 型 LED が L3D Cube です。この L3D 上で動くプログラムをネット上に公開し、リモート経由でファームウェアを書き込んで実行できる Cubetube.org や、そのプラットフォームとなっている Particle を使ったクラウドIDE上でのプログラミング&ファームウェア書き込みなど、先進的な試みがされています。
ただ、大きな問題としては、Particle の開発ボードの Photon が技適をとっていないため、日本では Photon を使うことが基本的にはできませんでした。ただ先日クラウドファンディング Makuake でこの L3D に Photon の技適をとった特別なモデルが販売されることとなりました。(なお、早期割引で4万ちょっとで買えるの、いろいろついてるしだいぶお得感ありましたね)
とまぁ L3D の紹介置いておいて、いざ買ってプログラミングしようとしたときに困るのは
- あんまりオフィシャルのライブラリがいけてない、もうほぼほぼ更新されてない
- Particle での開発になれてないとしんどい
- なら Arduino で開発だ!あれどこに Arduino での開発情報あるの…。
という問題に悩まされハコと化します。
というわけで、本エントリーでは Arduino で L3D を使う最低限の方法について解説します。
L3D の仕組み
L3D は冒頭で話したとおり、LED にマイコン入りの WS2812B を使っています。WS2812B は一本のデータ線と VDD(5V) / GND の3本のケーブルで接続でき、特定タイミングで信号を流すことによりRGB(255,255,255)で発光します。接続は直列なので、8x8x8 の L3D Cube でも内側では512個の WS2812B が(データ線は)直列につながるようになってます。
FastLED を使う
そのため、この WS2812B がつながるライブラリを使えばどれでも良くて、有名どころでは NeoPixel のライブラリがあります(オフィシャルライブラリでも利用)が、ここでは高速な汎用 LED ライブラリの FastLED を使います。
Arduino との接続
L3D の裏側にはずばり「ここに Arduino を置いてください」という場所があるのでそこに差せば OK です。ただ、オフィシャルサイトのどこにも Arduino との接続について書いてなかったので(あったら誰か教えてください…)、回路図を見ます。
- D2 が入力へ
- D4 にはボタンのスイッチが
- A1, A2, A3 が ADXL335 からの xyz 軸のアナログ入力値が
- AREF に 3.3 V が
- A0 には組み込みのマイク(オペアンプで増幅済み) が
がつながってます。この中で重要なのは D2 で、こいつが WS2812B のデータ線として接続されています。
なお、Arduino Uno で試してみましたが、基準電圧が 3.3V 系の Arduino シリーズでも、5V の出力ピンが 5V のモデルなら、ほかの入出力はすべて3.3V なので問題なく動くと思います。
FastLED を使って Arduino で動くコードを書く
FastLED は、確保したメモリアドレス(1LEDにつき3byte)から、タイミングを合わせデータ線に出力します。CRGB / CHSV という RGB と HSV を扱える構造体を、インライン/マクロ展開で便利扱うことができます。
オフィシャルのドキュメントと examples 以下のコードを見るのが手っ取り早いです。
8x8x8 の LED 上に、冒頭写真のような xyz 軸にそって R, G, B の色が濃くなっていくようなコードを書くとこんな感じです。
#include <FastLED.h>
#define NUM_LEDS 512
// D2 -> LEDs data pin
#define DATA_PIN 2
#define MAX_BRIGHTNESS 20
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(MAX_BRIGHTNESS); // global brightness
FastLED.showColor(CRGB::Black);
Serial.println("init");
}
// void fadeall(uint8_t n) { for(uint16_t i = 0; i < NUM_LEDS; i++) { leds[i].fadeToBlackBy(n); } }
// 引数の x, y, z にそった位置の LED ( CRGB ) を返す
CRGB& led(uint8_t x, uint8_t y, uint8_t z) {
return leds[y + x*8 + (7-z) * 64];
}
void loop() {
// static uint8_t hue;
static uint8_t n;
uint8_t x, y, z;
for (z = 0; z < 8; z++) {
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
// led(x, y, z) = CHSV(hue++, 255, 255);
led(x, y, z) = CRGB(x*32,y*32,z*32);
}
}
}
FastLED.show();
delay(5000);
// 全体的に明るくしたり暗くしたりする
for (n = MAX_BRIGHTNESS; n > 2; n--) {
FastLED.setBrightness(n);
FastLED.show();
delay(20);
}
delay(5000);
for (n = 2; n <= MAX_BRIGHTNESS; n++) {
FastLED.setBrightness(n);
FastLED.show();
delay(20);
}
delay(5000);
}
まんま素の FastLED ですが、led(x, y, z) という関数で、座標軸にあった led を返します。これでいわゆる1ドットづつ指定した開発はできるようになりました。
続いては、お好みに応じて Matrix 3D や Vector 3D といった 3D を扱う行列ベクトルを実装していけば、さらに手軽にプログラミングができるようになるでしょう。
消費電力
WS2812B は一つではそんなに食わなくとも、512個もあると馬鹿になりません。というか Arduino Uno の USB 経由での電源供給の場合、そこそこ光らせると Arduino 側のマイコンが落ちます。そのため、L3D の基盤に印刷されている High Power の入出力から、別途 5V を供給しないと、最高照度で光らせることは不可能です。
終わりに
L3D Cube の製品や Cubetube.org の試み自体は、大変面白いです。が、いざプログラミングをしようとすると、うまくいかずただのハコとなって眠っているひとが結構いる気がしています。
そんな方は、Arduino をつないで光らせてみてはいかがでしょうか。