ソロでたのしむ

キャンプ、電子工作、DIY、乗り物などの趣味を紹介

LEDでレインボーカラー。シリアルLEDのWS2812BとArduinoで簡単に実現しましょう!

カラフルな照明って、見ているだけで楽しいですよね~

いろいろなものを、自分好みに光らせてみたい!と思いつつも、どうやって実現させようか?と考えてみると、けっこう大変そうだと思って、躊躇してしまいがちです。

でも、様々な基本プログラムが準備(公開)されているArduinoを使えば簡単にできる!ということがわかりました。

まずは手始めとして、64個のRGB-LEDをいくつかのパターンで光らせます。

f:id:solocamptouring:20180201054058j:plain

光り方のパターンは、ボリューム(可変抵抗)で変えられるようにします。

見た目だけなので利便性の効果はありませんが、車のオーバーヘッドコンソールに埋め込んで使っています。

ランダムな光り方に1980年代の映画に出てくるコンピュータ的な雰囲気が漂い、気分は007かナイトライダーです。

後日、ナイトライダーのボイスインジケータ風バージョンも作ってみたので、記事内に動画リンクをはっておきます。

 

原点回帰してLEDで遊ぶ

私は、マイコンを扱った経験は無いなかで、初めてArduinoを手にしてすぐに「Lチカ」をやってみました。儀式的にLEDを点滅させただけですが、スケッチ(プログラム)の数値を変更し、点滅間隔やパターンを変えてみたりして、Arduinoの基礎の基礎がなんとなく理解できた気がしました。

 それからしばらくの間はモーターを動かしたりGPSモジュールで遊んでいましたが、原点回帰でLEDを綺麗に光らせてみたいと考えました。

クリスマスの綺麗なイルミネーションのような、見ているだけで幸せになる点滅光やカラフルな光を目指します。

f:id:solocamptouring:20180916190042j:plain

 Arduinoを使ってLEDを光らせる

 Arduinoで遊びはじめる前から、ランダムな、もしくは有機的な光らせ方に興味があり、ホタル発光する回路とか、100均のロウソクLEDをランダムパターン発生器の代わりにした回路を作って遊んでいました。

せっかく Arduinoを使うのであれば、もっと多くのLEDを使って、いろんな光り方を試してみたいと思います。

LEDは WS2812Bを選択

 多数のLEDをモジュール化したものは、大きく分けると、一列に配置したテープ状のものと、マトリックスに配置されたボード状のものがあります。

 

今回は光らせて遊ぶだけでなく実際に何かに使いたいので、テープ状のものよりも使いやすそうなボード状のものを使ってみます。

次にLEDの選択ですが、これも実使用を考慮すると配線数を極力減らしたいと思います。調べてみるとWS2812Bモジュールというニーズに合致したLEDがある事がわかりました。

WS2812Bはマイコンチップを搭載したシリアルLEDで、直列に繋いだ多数のLEDを、数に限界はありますが信号線一本で制御できます。

マイコンチップごとにアドレシングできるので、制御信号としては個々のLEDの光り方情報が数珠繋ぎになっているデータを送ります。

一個目のLEDが自分の光り方情報だけ抜き取って、次のLEDに渡す。次のLEDがまた同じ動作をする。ということを繰り返していき、各LEDが個別に違った発光をするものです。

このWS2812Bを64個(8x8個)ならべたボードが市販されているので、入手しました。

f:id:solocamptouring:20180408114052j:plain

Arduinoとの配線

配線は、少なくていいので簡単です。

5~6V電源でArduinoとWS2812Bを駆動して、ボリュームにも電圧をかけたら、

  • WS2812BのデータピンとArduinoのデジタルピン(D4)
  • ボリュームで変えた電圧とArduinoのアナログピン(A5)

を配線して終了です。

カッコ内のピン番号は最後に紹介するスケッチ(プログラム)の場合です。

私のWS2812Bモジュールは、DINがデータのアウトプット(次のモジュールにデータをわたす)ピンで、DOUTがデータの入力ピンになっています。その場合の回路図をFritzingで作成しました。

f:id:solocamptouring:20180408112231j:plain

光らせ方パターン

多くの光り方パターンが定義されていて、簡単なスケッチ(プログラム)で思い通りの光らせ方ができるGitHubのFastLEDライブラリを使うことにします。

あまり多くのパターンを使うと、ボリュームでパターン変更する時にセンシティブになってしまうので、光らせ方は以下の7パターンだけにしておきます。

  1. onlycolorGlitter,;ストロボっぽくランダム発光
  2. sinelon, ;尾を引きながら横に流れる光
  3. onecolorconfetti, ;残像を残しながらランダム発光(一色)
  4. confetti,;残像を残しながらランダム発光(変色)
  5. sinelonWithGlitter ;上記組み合わせ
  6. rainbowWithGlitter; 64個全面で虹色発光(変色)しながら、白色Glitterを入れる
  7. allwhite,;全面で白色発光

7つの アルファベット名称はスケッチで定義したものです。

ArduinoでWS2812B(RGB-LED)を光らせる
ArduinoでWS2812B(RGB-LED)を光らせる
sinelonとallwhite

車のオーバーヘッドコンソールに装着 

せっかく作ったので、車の中で光らせます。

天井の自作コンソールに埋め込みました。

WS2812Bを64(8x8)個ならべたボードをオーバーヘッドコンソールに装着

今回のレインボーカラーからは進化させたサウンドレベルメーター風の光らせ方ですが、同じ車のコンソールに取り付けた作動状態は、動画で確認できます。

今回つかったsinelon(尾を引きながら横に流れる光)も、一部に取り込んでいます。


Arduino project #3 「サウンドレベルメーターをWS2812Bでつくる」Sound level meter with WS2812B

 Arduinoのスケッチ(プログラム)

GitHubのFastLEDで公開されているサンプルスケッチに手を加えて作成しました。

光り方に飽きてしまった場合に簡単に変えられるように、今回は使っていない光らせ方も定義だけは最後の部分にのせています。

#include "FastLED.h"

FASTLED_USING_NAMESPACE
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

#define DATA_PIN    4
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define HEIGHT 8
#define WIDTH 8
#define NUM_LEDS HEIGHT*WIDTH
CRGB leds[NUM_LEDS];
#define BRIGHTNESS          3
#define FRAMES_PER_SECOND  60
int analogPin = 5;
int val = 0;
void setup() { delay(3000); // 3 second delay for recovery // tell FastLED about the LED strip configuration FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); // set master brightness control FastLED.setBrightness(BRIGHTNESS); } // List of patterns to cycle through. Each is defined as a separate function below. typedef void (*SimplePatternList[])(); SimplePatternList gPatterns = { onlycolorGlitter, sinelon, onecolorconfetti, confetti, sinelonWithGlitter, rainbowWithGlitter, allwhite }; uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current uint8_t gHue = 96; // rotating "base color" used by many of the patterns void loop() { val = analogRead(analogPin); if (val < 150) { gCurrentPatternNumber = 0; } else if (val < 300){ gCurrentPatternNumber = 1; } else if (val < 450){ gCurrentPatternNumber = 2; } else if (val < 600){ gCurrentPatternNumber = 3; } else if (val < 750){ gCurrentPatternNumber = 4; } else if (val < 900){ gCurrentPatternNumber = 5; } else { gCurrentPatternNumber = 6; } // Call the current pattern function once, updating the 'leds' array gPatterns[gCurrentPatternNumber](); // send the 'leds' array out to the actual LED strip FastLED.show(); // insert a delay to keep the framerate modest FastLED.delay(1000/FRAMES_PER_SECOND); // do some periodic updates EVERY_N_MILLISECONDS( 800 ) { gHue++; } // slowly cycle the "base color" through the rainbow } void rainbow() { // FastLED's built-in rainbow generator fill_rainbow( leds, NUM_LEDS, gHue, 1); } void rainbowWithGlitter() { // built-in FastLED rainbow, plus some random sparkly glitter rainbow(); addGlitter(40); } void addGlitter( fract8 chanceOfGlitter) { if( random8() < chanceOfGlitter) { leds[ random16(NUM_LEDS) ] += CRGB::White; } } void addcolorGlitter( fract8 chanceOfGlitter) { if( random8() < chanceOfGlitter) { leds[ random16(NUM_LEDS) ] += CHSV( gHue, 255, 192); } } void sinelon() { // a colored dot sweeping back and forth, with fading trails fadeToBlackBy( leds, NUM_LEDS, 30); int pos = beatsin16(13,24,32); leds[pos] += CHSV( gHue, 255, 192); } void sinelonWithGlitter() { // built-in sinelon, plus some random sparkly glitter sinelon(); addGlitter(5); } void onlycolorGlitter() { // some random sparkly glitter FastLED.clear(); addcolorGlitter(5); } void confetti() { // random colored speckles that blink in and fade smoothly fadeToBlackBy( leds, NUM_LEDS, 20); int pos = random16(600); leds[pos] += CHSV( gHue, 255, 192); } void onecolorconfetti() { // random colored speckles that blink in and fade smoothly fadeToBlackBy( leds, NUM_LEDS, 20); int pos = random16(600); leds[pos] += CRGB::MidnightBlue; } void allwhite() { // all led white color fill_solid(leds, NUM_LEDS, CRGB::White); }