ソロでたのしむ

DIY、電子工作、キャンプ用品などの趣味を紹介します。

64個のLEDでレインボーカラー~シリアルLEDのWS2812Bと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); }