ガイド · 読了まで12分

ArduinoでクリスマスツリーのLEDライト:WS2812Bで雪と虹のエフェクト

ArduinoでクリスマスツリーのLEDライトを作ります。WS2812BのLEDテープ、雪、虹、きらめきのエフェクト、ボタンでのモード切り替え、5 V電源の計算とコードを紹介します。

クリスマスツリーのLEDプロジェクトにArduinoとWS2812BのLEDテープを使うと、市販のツリーライトにある決まった数種類のモードを超えて、いちばん楽しく遊べます。LEDを1個ずつ色と明るさを制御できるので、てっぺんから舞い降りる雪、枝のまわりを回る虹、ランダムにきらめく赤・緑・金色の星などを加えられます。しかも必要なのは、データ線1本、ボタン1個、そして正しく選んだ5 V電源だけです。

このガイドでは、部品リストから始めて、テープの長さに合わせた電源の計算、電源・ボード・テープの正しい配線、ボタンでエフェクトを切り替える完全なArduino Unoのプログラム(FastLED)、そして同じプロジェクトのESP32版(Adafruit NeoPixel)とRaspberry Pi Pico版(MicroPython)を、ステップごとに組み立てていきます。最後に、テープをツリーに巻く方法、安全面で気をつけること、よくある問題の解決方法も紹介します。

WS2812B NeoPixelアドレサブルRGB LED
WS2812B NeoPixelアドレサブルRGB LED

クリスマスツリーにWS2812BのLEDテープを使う理由

昔ながらのクリスマスライトでは、すべての電球が同時に点灯するか、いくつかのグループに分かれて順番に点灯します。一方WS2812Bは、LEDの1個1個に小さなドライバチップが入っています。Arduinoはデータ線で色の情報を次々に送り、最初のLEDが自分の分の24ビットを受け取って、残りを次のLEDに渡します。そのため100個や300個のLEDテープを1本のピンで制御でき、LEDごとに別々の色を設定できます。この仕組みのおかげで、雪のように動くエフェクトに、固定のライトでは出せない生き生きとした表情が生まれます。アドレサブルLEDの仕組みをもっと詳しく知りたい場合は、WS2812B NeoPixelの記事をご覧ください。

項目値
パッケージ5050 SMD、ドライバチップはLEDに内蔵
電源5 V(おおよそ3.5〜5.3 V)
電流1色あたり約20 mA、白の最大輝度で約60 mA
データ1本の信号線、800 kHz、LED1個あたり24ビット(G-R-Bの順)
データの送信時間LED1個あたり30 µs、100個で約3 ms
データ入力のしきい値論理1には少なくとも0.7 × VDD(5 Vで3.5 V)
色1チャンネルあたり256段階、合計1,670万色
テープの密度30、60、144 LED/m
カットLEDの間にある銅パッドの中央で切断できる

部品リスト

  • WS2812BのLEDテープ:高さ1.5〜1.8 mのツリーなら、60 LED/mのテープ2.5 mか、30 LED/mのテープ5 mから始めるのがおすすめです。シリコン被覆のIP65タイプは、枝に引っかけたりほこりがついたりしても丈夫です。
  • 制御用ボード:Arduino Uno、Nano、ESP32、またはRaspberry Pi Pico。
  • 5 V電源:電流値は下の表を見て選んでください。LED 100個なら5 V 4 Aが余裕のある選択です。
  • DCジャック(メス、ネジ端子付き):電源のプラグを、はんだ付けなしで配線につなぐためのものです。
  • 1000 µF / 10 Vの電解コンデンサ:テープの入口で急な電流の変動をなだらかにします。
  • 330 Ωの抵抗:データ線に直列に入れます。信号の反射をおさえ、最初のLEDの入力電流を制限します。
  • 押しボタン:エフェクトを切り替えるためのものです。
  • 太い電線:5VとGNDのラインには、断面積が少なくとも0.75〜1.5 mm²の電線を使います。
  • 必要に応じて74AHCT125または74HCT245:ESP32やPicoの3.3 Vのデータ信号を5 Vに引き上げるためのものです。

電源の計算:何アンペアの電源が必要?

WS2812Bの中にある赤・緑・青のチップは、それぞれ最大輝度で約20 mAを消費します。つまりLED1個は、白の最大輝度で約60 mAを使います。最悪の場合の電流はI = LEDの数 × 60 mAの式で求められます。LED 100個のテープは、すべてのLEDが真っ白で最大輝度のとき6 Aを消費し、P = 5 V × 6 A = 30 Wになります。虹、雪、星のエフェクトでは、ほとんどのLEDが単色か暗めなので、実際の電流は最悪の場合の3分の1程度にとどまります。安全に選ぶには、この標準的な電流を2倍してから一番近い電源の定格に切り上げ、ソフトウェアの電流制限を電源の約80%に設定してください。電流・電圧・電力の関係は、オームの法則計算ツールで簡単に確認できます。

LEDの数最悪の場合(白の最大輝度)エフェクトの標準的な電流おすすめの電源ソフトウェアの制限(MAX_MA)
301.8 A約0.6 A5 V 2 A1600 mA
603.6 A約1.2 A5 V 3 A2400 mA
1006 A約2 A5 V 4 A3200 mA
1509 A約3 A5 V 6 A4800 mA
300(5 m、60 LED/m)18 A約6 A5 V 12 A9600 mA

長いテープでは、2つ目の問題として電圧降下が起こります。テープ上の細い銅のパターンには抵抗があるため、5 mのテープの終端では電圧が4 Vを下回ることがあります。すると青と緑のチップが弱くなり、白が黄色っぽくくすんで見えます。対策は、5VとGNDをテープの始まりだけでなく、1〜1.5 mごと(またはLED 100〜150個ごと)に、電源から引いた別の電線でもう一度給電することです。これを電源インジェクション(給電の追加)といいます。この電線には、5 Aなら少なくとも0.75 mm²、10 Aなら1.5 mm²の太さを使ってください。データ線はテープの始まりにだけつなぎます。

テープをArduinoの5Vピンから給電しようとするのは絶対にやめてください。USB給電のUnoの5Vピンが出せるのは最大400〜500 mAで、LEDを数個暗めに点灯させるのがやっとです。それ以上になるとボードがリセットしたり、USBの保護ヒューズが働いたり、ボード上の細いパターンが発熱したりします。テープは必ず電源から直接給電してください。

配線図:5 V電源、テープ、ボード

接続Arduino UnoESP32Raspberry Pi Pico
テープのDIN(データ)D6(330 Ω経由)GPIO 13(330 Ω経由)GP0(330 Ω経由)
テープの5V電源の+5 V電源の+5 V電源の+5 V
テープのGND電源のGND + UnoのGND電源のGND + ESP32のGND電源のGND + PicoのGND
ボタンD2とGNDGPIO 4とGNDGP15とGND
1000 µFのコンデンサテープの入口で5V–GND間テープの入口で5V–GND間テープの入口で5V–GND間
ボードの電源(完成時)5VピンまたはUSB5V(VIN)ピンまたはUSBVSYS(ショットキーダイオード経由)またはUSB
  1. テープ上の矢印を探し、矢印が始まる側の端(DIN)に電線をはんだ付けします。反対側のDOUT側からデータを送っても、LEDは1個も点灯しません。
  2. 電源の+5 V出力をテープの5V端子(テープによっては+5VやVCCと表記)に、電源のGNDをテープのGND端子につなぎます。
  3. 1000 µFのコンデンサを、テープの入口で5VとGNDの間につなぎます。長い足(プラス)を5Vに、本体に帯の印がある側の足(マイナス)をGNDにつなぎます。
  4. ボードのGNDピンを電源のGNDにつなぎます。共通のGNDがないと、データ信号の基準がなくなります。
  5. ボードのデータピン(UnoではD6)を、330 Ωの抵抗を通してテープのDIN端子につなぎます。抵抗はテープに近い側に置くと、より安定します。
  6. ボタンの片方の足をD2に、もう片方をGNDにつなぎます。内部プルアップはコードで有効にします。
  7. LEDを150個より多く使う場合は、テープの中央と終端にも、電源から別の5VとGNDの電線を引いてください。
  8. 開発中はボードをUSBから、テープを電源から給電します。完成したら電源の5 VをUnoの5Vピンに入れてもかまいませんが、その場合はUSBケーブルを同時に挿さないでください。
いちばん多いミスは、ボードのGNDと電源のGNDをつなぎ忘れることです。この場合、LEDがランダムな色でちらついたり、まったく反応しなかったりします。詳しくは共通GNDの記事をご覧ください。2つ目によくある問題は、ESP32やPicoの3.3 Vのデータ信号です。WS2812Bは5 V給電のとき、論理1を確実に判定するのに少なくとも3.5 Vを必要とします。多くのテープは3.3 Vでも動きますが、最初のほうのLEDがちらつく場合は、間にレベル変換モジュール(74AHCT125)を入れてください。

Arduino Unoのコード(FastLED):3つのエフェクトとボタンでのモード切り替え

Arduino IDEでライブラリマネージャを開き、FastLEDを検索してライブラリをインストールします。詳しい手順はArduinoにライブラリを追加する方法をご覧ください。下のプログラムには、虹、雪、星のようにきらめくエフェクトが入っていて、ボタンを押すたびに次のエフェクトに切り替わります。コードはdelay()ではなくmillis()を使っているので、エフェクトの動作中もいつでもボタンを検出できます。この方法の考え方はmillis()とdelay()の違いの記事で紹介しています。

C++ (Arduino IDE)
1#include <FastLED.h>
2
3#define LED_PIN     6      // şeridin DIN girişi (330 ohm üzerinden) / strip DIN input (via 330 ohm)
4#define BUTTON_PIN  2      // buton, diğer bacak GND / button, other leg to GND
5#define NUM_LEDS    100    // şeritteki LED sayısı / number of LEDs on the strip
6#define BRIGHTNESS  120    // genel parlaklık 0-255 / global brightness 0-255
7#define MAX_MA      3200   // 4 A adaptörün %80'i / 80% of a 4 A supply
8
9CRGB leds[NUM_LEDS];
10
11const uint8_t MODE_COUNT = 3;                          // 0 gökkuşağı, 1 kar, 2 yıldız / 0 rainbow, 1 snow, 2 twinkle
12const uint16_t FRAME_MS[MODE_COUNT] = {20, 60, 30};    // kare süreleri (ms) / frame times (ms)
13const CRGB XMAS[4] = {CRGB::Red, CRGB::Green, CRGB::Gold, CRGB::White};
14
15uint8_t mode = 0;
16uint8_t hue = 0;
17
18void setup() {
19  pinMode(BUTTON_PIN, INPUT_PULLUP);
20  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
21  FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_MA);  // akım sınırı / current limit
22  FastLED.setBrightness(BRIGHTNESS);
23  FastLED.clear(true);                                // açılışta hepsini söndür / all off at start
24}
25
26void checkButton() {
27  static bool lastState = HIGH;
28  static unsigned long lastChange = 0;
29  bool state = digitalRead(BUTTON_PIN);
30  if (state != lastState && millis() - lastChange > 50) {  // 50 ms zıplama filtresi / 50 ms debounce
31    lastChange = millis();
32    lastState = state;
33    if (state == LOW) {                                     // basıldı / pressed
34      mode = (mode + 1) % MODE_COUNT;
35      FastLED.clear();
36    }
37  }
38}
39
40void rainbow() {
41  fill_rainbow(leds, NUM_LEDS, hue, 3);   // her LED'de ton 3 artar / hue +3 per LED
42  hue += 2;                               // renkler döner / colours rotate
43}
44
45void snowfall() {
46  for (int i = 0; i < NUM_LEDS - 1; i++) {
47    leds[i] = leds[i + 1];                // bir LED aşağı kaydır / shift one LED down
48  }
49  if (random8() < 38) {
50    leds[NUM_LEDS - 1] = CRGB::White;     // tepede yeni kar tanesi / new flake at the top
51  } else {
52    leds[NUM_LEDS - 1] = CRGB(0, 0, 24);  // koyu mavi gece / dark blue night
53  }
54}
55
56void twinkle() {
57  fadeToBlackBy(leds, NUM_LEDS, 20);      // hepsini biraz kıs / dim everything a little
58  if (random8() < 80) {
59    leds[random16(NUM_LEDS)] = XMAS[random8(4)];  // rastgele yıldız / random star
60  }
61}
62
63void loop() {
64  checkButton();
65  static unsigned long lastFrame = 0;
66  if (millis() - lastFrame >= FRAME_MS[mode]) {
67    lastFrame = millis();
68    if (mode == 0) rainbow();
69    else if (mode == 1) snowfall();
70    else twinkle();
71    FastLED.show();                       // renkleri şeride gönder / push colours to the strip
72  }
73}
行・設定役割
NUM_LEDSテープのLEDの数です。間違えると、テープの一部が点灯しなかったり、エフェクトがずれたりします。
BRIGHTNESS全体の明るさ(0〜255)です。120くらいでツリーには十分明るく、電流と発熱の面でも安全です。
setMaxPowerInVoltsAndMilliamps(5, MAX_MA)(電流制限)FastLEDがフレームごとの消費電流を予測し、制限を超えそうなら自動で明るさを下げます。
addLeds<WS2812B, LED_PIN, GRB>(テープの設定)テープの種類、データピン、色の順番を設定します。WS2812Bの順番はGRBです。
FRAME_MS各エフェクトのフレーム時間(ms)です。値が小さいほどアニメーションが速くなります。
checkButton()(ボタンの読み取り)50 msのチャタリング対策をしてボタンを読み取り、押すたびにモードを1つ進めます。
FastLED.show()(テープへの送信)メモリ上の色をテープに送ります。呼び出さないと、変化は何も表示されません。

エフェクトの仕組み

虹:fill_rainbow関数は、最初のLEDに指定した色相(hue)から始めて、LEDごとに色相を3ステップずつ増やします。FastLEDの色相は0〜255の範囲なので、LED 100個では色相が合計300ステップ進み、テープ全体で色の輪が1周より少し多く表示されます。フレームごとに変数hueを2ずつ増やしているので、色がツリーのまわりをゆっくり回ります。色の帯をもっと広くしたい場合は、3の代わりに1か2を使ってください。

雪:テープをツリーに下から上へ巻くと、最初のLEDがいちばん下、最後のLEDがてっぺんになります。フレームごとにすべての色をLED1個分下にずらし、てっぺんに白い雪の粒か濃い青の夜空のピクセルを追加します。random8()は0〜255の数を返すので、38より小さくなる確率は約15%です。この数を大きくすると雪が多くなります。フレーム時間が60 msなら、雪の粒は6秒でLED 100個分を降りてきます。きらめき(星):fadeToBlackByはフレームごとにすべてのLEDを約8%暗くします。同時に、ランダムに選んだLEDを1個、赤・緑・金色・白のどれかで最大輝度に点灯させます。昔ながらのクリスマスライトを思わせながら、ずっと生き生きとしたきらめきになります。

新しいエフェクトを追加するには、関数を書き、MODE_COUNTを1つ増やし、FRAME_MS配列にその速さを追加して、loopの中の選択部分に新しい行を加えます。たとえばツリー全体を1色に塗るならfill_solid(leds, NUM_LEDS, CRGB::Red)だけで十分です。これを1秒ごとに赤と緑で切り替えれば、定番のクリスマスエフェクトになります。

ESP32で作るクリスマスツリー(Adafruit NeoPixel)

ESP32でもFastLEDは動きますが、ここでは同じプロジェクトをAdafruit NeoPixelライブラリで書きます。こうすれば人気のある2つのライブラリの両方に触れられます。このライブラリの最新版は、ESP32 Arduinoコアの2.xと3.xで同じコードのままコンパイルでき、ハードウェアのRMTユニットで信号を生成します。Adafruit NeoPixelではsetBrightnessで暗くした色を読み戻すと崩れることがあるため、エフェクトは独自の明るさの配列(level)で計算し、フレームごとにテープへ最初から書き直しています。データピンはGPIO 13、ボタンはGPIO 4です。あとでツリーをスマホから操作したくなったら、WLEDのセットアップの記事で、すぐに使える操作画面を紹介しています。

C++ (Arduino IDE)
1#include <Adafruit_NeoPixel.h>
2
3#define LED_PIN     13     // şeridin DIN girişi (330 ohm üzerinden) / strip DIN input (via 330 ohm)
4#define BUTTON_PIN  4      // buton, diğer bacak GND / button, other leg to GND
5#define NUM_LEDS    100    // şeritteki LED sayısı / number of LEDs on the strip
6
7Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
8
9const uint8_t MODE_COUNT = 3;                          // 0 gökkuşağı, 1 kar, 2 yıldız / 0 rainbow, 1 snow, 2 twinkle
10const uint16_t FRAME_MS[MODE_COUNT] = {20, 60, 30};    // kare süreleri (ms) / frame times (ms)
11const uint8_t PALETTE[4][3] = {{255, 0, 0}, {0, 255, 0}, {255, 160, 0}, {255, 255, 255}};
12
13uint8_t level[NUM_LEDS];      // LED başına parlaklık / per-LED level
14uint8_t colorIdx[NUM_LEDS];   // yıldız rengi / star colour index
15uint8_t mode = 0;
16uint16_t hue = 0;
17
18void setup() {
19  pinMode(BUTTON_PIN, INPUT_PULLUP);
20  strip.begin();
21  strip.setBrightness(110);   // genel parlaklık / global brightness
22  strip.clear();
23  strip.show();
24}
25
26void checkButton() {
27  static bool lastState = HIGH;
28  static unsigned long lastChange = 0;
29  bool state = digitalRead(BUTTON_PIN);
30  if (state != lastState && millis() - lastChange > 50) {  // 50 ms zıplama filtresi / 50 ms debounce
31    lastChange = millis();
32    lastState = state;
33    if (state == LOW) {                                     // basıldı / pressed
34      mode = (mode + 1) % MODE_COUNT;
35      memset(level, 0, sizeof(level));                      // efekt belleğini sıfırla / reset effect buffer
36      strip.clear();
37    }
38  }
39}
40
41void rainbow() {
42  for (int i = 0; i < NUM_LEDS; i++) {
43    uint16_t h = hue + (uint32_t)i * 65536UL / NUM_LEDS;   // LED'e göre ton / hue per LED
44    strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(h)));
45  }
46  hue += 256;                                              // renkler döner / colours rotate
47}
48
49void snowfall() {
50  for (int i = 0; i < NUM_LEDS - 1; i++) level[i] = level[i + 1];   // bir LED aşağı kaydır / shift one LED down
51  level[NUM_LEDS - 1] = (random(100) < 15) ? 255 : 0;               // tepede yeni kar / new flake on top
52  for (int i = 0; i < NUM_LEDS; i++) {
53    if (level[i]) strip.setPixelColor(i, 255, 255, 255);            // kar tanesi / snowflake
54    else strip.setPixelColor(i, 0, 0, 24);                          // koyu mavi gece / dark blue night
55  }
56}
57
58void twinkle() {
59  for (int i = 0; i < NUM_LEDS; i++) {
60    level[i] = (level[i] > 12) ? level[i] - 12 : 0;                 // yavaşça sön / fade out
61  }
62  if (random(100) < 30) {
63    int p = random(NUM_LEDS);
64    level[p] = 255;                                                 // yeni yıldız / new star
65    colorIdx[p] = random(4);
66  }
67  for (int i = 0; i < NUM_LEDS; i++) {
68    const uint8_t *c = PALETTE[colorIdx[i]];
69    strip.setPixelColor(i, c[0] * level[i] / 255, c[1] * level[i] / 255, c[2] * level[i] / 255);
70  }
71}
72
73void loop() {
74  checkButton();
75  static unsigned long lastFrame = 0;
76  if (millis() - lastFrame >= FRAME_MS[mode]) {
77    lastFrame = millis();
78    if (mode == 0) rainbow();
79    else if (mode == 1) snowfall();
80    else twinkle();
81    strip.show();                                                   // renkleri şeride gönder / push colours to the strip
82  }
83}

Raspberry Pi PicoとMicroPythonで作るクリスマスツリー

Raspberry Pi PicoのMicroPythonにはneopixelモジュールが最初から入っているので、追加で何かをインストールする必要はありません。このモジュールがWS2812Bの精密なタイミングを自分で処理するため、どのGPピンでも使えます。下の例では、データをGP0に、ボタンをGP15につないでいます。MicroPythonには全体の明るさの設定がないので、BRIGHT係数で色を自分で暗くしています。PythonはC++より動作が遅いため、LED 100個ならエフェクトはなめらかですが、300個を超えるとフレーム時間が長くなることがあります。MicroPythonが初めてなら、MicroPythonの基本の記事から始めてみてください。

MicroPython
1from machine import Pin
2import neopixel, time, random
3
4NUM_LEDS = 100
5BRIGHT = 0.4                                   # 0-1 parlaklık / brightness
6np = neopixel.NeoPixel(Pin(0), NUM_LEDS)       # veri GP0 / data on GP0
7button = Pin(15, Pin.IN, Pin.PULL_UP)          # buton GP15-GND / button GP15-GND
8
9mode = 0
10MODE_COUNT = 3                                 # 0 gökkuşağı, 1 kar, 2 yıldız / 0 rainbow, 1 snow, 2 twinkle
11FRAME_MS = (20, 60, 30)                        # kare süreleri / frame times
12level = [0] * NUM_LEDS                         # LED başına parlaklık / per-LED level
13color_idx = [0] * NUM_LEDS                     # yıldız rengi / star colour index
14PALETTE = ((255, 0, 0), (0, 255, 0), (255, 160, 0), (255, 255, 255))
15hue = 0
16
17def scale(r, g, b):
18    return (int(r * BRIGHT), int(g * BRIGHT), int(b * BRIGHT))
19
20def wheel(pos):
21    # 0-255 -> gökkuşağı rengi / rainbow colour
22    pos = pos & 255
23    if pos < 85:
24        return (255 - pos * 3, pos * 3, 0)
25    if pos < 170:
26        pos -= 85
27        return (0, 255 - pos * 3, pos * 3)
28    pos -= 170
29    return (pos * 3, 0, 255 - pos * 3)
30
31def rainbow():
32    global hue
33    for i in range(NUM_LEDS):
34        np[i] = scale(*wheel(hue + i * 256 // NUM_LEDS))
35    hue = (hue + 2) & 255                      # renkler döner / colours rotate
36
37def snowfall():
38    for i in range(NUM_LEDS - 1):
39        level[i] = level[i + 1]                # bir LED aşağı kaydır / shift one LED down
40    level[-1] = 255 if random.randint(0, 99) < 15 else 0
41    for i in range(NUM_LEDS):
42        np[i] = scale(255, 255, 255) if level[i] else scale(0, 0, 24)
43
44def twinkle():
45    for i in range(NUM_LEDS):
46        level[i] = level[i] - 12 if level[i] > 12 else 0   # yavaşça sön / fade out
47    if random.randint(0, 99) < 30:
48        p = random.randint(0, NUM_LEDS - 1)
49        level[p] = 255                         # yeni yıldız / new star
50        color_idx[p] = random.randint(0, 3)
51    for i in range(NUM_LEDS):
52        r, g, b = PALETTE[color_idx[i]]
53        k = level[i] * BRIGHT / 255
54        np[i] = (int(r * k), int(g * k), int(b * k))
55
56effects = (rainbow, snowfall, twinkle)
57last_btn = 1
58last_change = time.ticks_ms()
59last_frame = time.ticks_ms()
60
61while True:
62    now = time.ticks_ms()
63    state = button.value()
64    if state != last_btn and time.ticks_diff(now, last_change) > 50:   # zıplama filtresi / debounce
65        last_change = now
66        last_btn = state
67        if state == 0:                         # basıldı / pressed
68            mode = (mode + 1) % MODE_COUNT
69            for i in range(NUM_LEDS):
70                level[i] = 0
71    if time.ticks_diff(now, last_frame) >= FRAME_MS[mode]:
72        last_frame = now
73        effects[mode]()
74        np.write()                             # şeride gönder / push to the strip

テープをツリーに取り付ける方法と安全対策

  • 下から始める:テープのDIN側をツリーの根元、制御ボックスの横に置き、らせん状に上へ巻いていきます。こうすると雪のエフェクトがてっぺんから下へ流れ、データ線も短くできます。
  • らせんの間隔:1.8 mのツリーなら、20〜25 cm間隔で巻くと5 mのテープが枝にバランスよく広がります。ツリーの上に行くほど1周の直径が小さくなるので、間隔を少しせまくしてもかまいません。
  • 縦方向のテープ:テープを上から下、下から上へとジグザグに配置することもできます。この配置では、雪のエフェクトの向きが1本おきに逆になるため、テープの番号からLEDの順番を計算する小さな修正が必要です。
  • 発熱:WS2812Bのテープは明るさが高いと熱くなります。紙の飾りや乾いた枝に強く押しつけないでください。明るさを100〜150くらいにしておくと、発熱も電流も減らせます。
  • 電源の安全:220 V側に自作の回路を組まないでください(日本の商用電源は100V(50/60Hz)です)。CEマーク付き(日本ではPSEマーク付き)で、ケースに収まった市販の5 V電源を使ってください。制御ボックスは水や植木の水やりから離し、外出するときはツリーの電源を切ってください。
  • ヒューズ:5 Aを超えるシステムでは、電源の出力に適切な定格のブレードヒューズを入れておくと、万一のショートへの備えになります。

クリスマスツリーのプロジェクトアイデア

  • 音楽に反応するツリー:マイクを使って、曲のリズムに合わせてライトを光らせます。詳しくは音楽に反応するLEDの記事をご覧ください。
  • 新年のカウントダウン:深夜0時までの残り時間をディスプレイに表示し、00:00になったらツリーで花火のエフェクトを始めます。新年のカウントダウンタイマーの記事をご覧ください。
  • 自動で点灯するツリー:LDR光センサーで、暗くなったら自動でライトを点灯させます。
  • 近づくと明るくなるツリー:部屋に人が入ったらPIR人感センサーで明るさを上げ、誰もいないときは暗くします。
  • スマホから操作:ESP32でWebページを開き、エフェクトや色をスマホから選びます。ESP32のWebサーバーの記事が出発点としておすすめです。
  • てっぺんの星のディスプレイ:ツリーのてっぺんに小さなWS2812B LEDマトリクスを付けて、星や雪の結晶のアニメーションを再生します。

よくあるミスと対処法

症状考えられる原因対処法
LEDが1個も点灯しないデータがDOUT側につながっている、またはGNDが共通になっていない矢印の向きを確認してDIN側につなぎ、ボードと電源のGNDをつなぐ
最初のほうのLEDがちらつく、ランダムな色になるデータ信号が弱い、3.3 Vのレベル、データ線が長い330 Ωの抵抗をテープに近づけ、データ線を短くし、74AHCT125を使う
色が違う(赤のはずが緑)色の順番の設定ミスFastLEDではGRB、NeoPixelではNEO_GRBを使う。RGBの順番のテープもある
テープの終端が黄色っぽく暗い電圧降下中央と終端にも給電を追加し、太い電線を使う
白にするとボードがリセットする電源の容量不足、急な電流の消費電源を大きくし、MAX_MAの制限を下げ、1000 µFのコンデンサを追加する
ボタンを1回押すとモードが2つ進むボタンのチャタリングチャタリング対策の時間を50 msから80 msに延ばし、ボタンの配線を短くする
Picoでエフェクトの動きが遅いLEDが多すぎる、Pythonの計算NUM_LEDSを減らすか、フレーム時間を長くするか、Arduino IDEとC++に切り替える
テープをツリーに取り付ける前に、机の上で数分間明るさを高めにして動かし、電源・端子・電線が熱くなっていないか手で確認してください。電線がぬるい程度より熱くなる場合は、太い電線を使うか、MAX_MAの値を下げてください。ボタンの配線の考え方をおさらいしたい場合は、Arduinoに押しボタンをつなぐ方法の記事をご覧ください。

数メートルのLEDテープ、ボタン1個、適切な容量の5 V電源があれば、クリスマスツリーは毎年新しいエフェクトで楽しめるプログラム可能な光のショーに変わります。カラーパレットやフレーム時間をいろいろ変えて、オリジナルのエフェクトを作ってみてください。電源や配線で迷ったときは、Arduinoの電源の取り方のガイドを読み返してください。BlueGraysアプリでは、WS2812Bを使った流れるLED、ナイトライダー、パトランプ、アニメーションのプロジェクトのほか、ESP32でのNeoPixelテープの制御も、回路図とコードつきでステップごとに紹介しています。

よくある質問

クリスマスツリーにはLEDが何個必要ですか?

高さ1.5〜1.8 mのツリーなら、LED 150〜300個、つまり30 LED/mのテープ5 mか、60 LED/mのテープ2.5〜5 mで、にぎやかで生き生きとした見た目になります。もっと少なくても動きますが、エフェクトがまばらに見えます。LEDの数が増えるほど、電源の電流とボードのRAM(LED1個あたり3バイト)も考慮する必要があります。

WS2812BのLEDテープには何アンペアの電源が必要ですか?

LED1個は白の最大輝度で約60 mAを消費するので、100個では最悪の場合6 Aになります。カラフルなエフェクトでは実際の電流はその3分の1程度なので、FastLEDのsetMaxPowerInVoltsAndMilliamps関数で電流を3200 mAに制限すれば、LED 100個に5 V 4 Aの電源で足ります。白の最大輝度で長時間使う場合は、最悪の場合に合わせて電源を選んでください。

WS2812Bのテープは12 Vで動きますか?

いいえ。WS2812Bは5 V用のテープで、12 Vをつなぐと LEDがすぐに壊れます。12 Vで動くアドレサブルLEDテープがほしい場合は、WS2811かWS2815のタイプを選んでください。手持ちの12 V電源を小さなテープに使いたい場合は、LM2596のような降圧コンバーターで5 Vを作れますが、こうしたモジュールは約2〜3 Aまでに限られます。

FastLEDとAdafruit NeoPixelのどちらを使えばいいですか?

どちらもWS2812Bを問題なく駆動できます。FastLEDは虹、カラーパレット、減光、電流制限などの関数がそろっていてエフェクトを書きやすく、たいていこちらのほうが高速です。Adafruit NeoPixelはよりシンプルなAPIです。初めてなら、どちらか一方から始めて、そのあともう一方を試すのがよい方法です。

Arduino UnoではWS2812BのLEDを最大何個まで制御できますか?

上限はRAMと速度で決まります。Unoの2 KBのRAMではLED1個に3バイト使うので、ほかの変数も含めると実用上は500個くらいが限界です。また、LED1個にデータを送るのに30 µsかかるため、1000個では1フレームが30 msになります。ESP32やPicoはRAMが豊富なので数千個も可能で、本当の制限は電源になります。

LEDテープの終端が黄色っぽく、または暗く光るのはなぜですか?

これは電圧降下のサインです。テープの細い銅のパターンでは、電流が増えるほど電圧が下がります。4 Vを下回ると終端のLEDは青と緑が弱くなり、白が黄色寄りになります。テープの中央と終端に電源から別の5VとGNDの電線を引き、明るさを少し下げれば解決します。

全プロジェクトを見る
WS2812B LEDテープの使い方
#69中級
プレミアム

WS2812B LEDテープの使い方

1つずつ自由に色を変えられるスマートLEDテープを使ってみます。Arduinoが最初の5個のLEDを赤く点灯し、1秒後に残りの5個を青く点灯します。その後すべて消灯し、最初から繰り返します。1本の配線で何十個ものLEDを個別の色にするための第一歩です。このようなテープは、装飾用のライトや部屋の照明にも使われています。

4.8(54)
70
WS2812Bで作るパトカー風ライト
#70中級
プレミアム

WS2812Bで作るパトカー風ライト

パトカーの屋根にある赤と青の点滅灯を、机の上で再現します。10個のLEDを備えたWS2812Bテープの半分が赤で素早く3回点滅し、続いて残りの半分が青で3回点滅します。このパターンを繰り返し続けます。1本のデータ線につながったカラーLEDを、それぞれ好きな色に設定する方法がわかります。

4.8(67)
86
WS2812Bで流れるLED
#71中級
プレミアム

WS2812Bで流れるLED

10個のLEDが並ぶテープで、緑の光が端から端へ1個ずつ進み、最後まで来ると先頭に戻ります。各LEDは3分の1秒ずつ点灯します。WS2812Bテープでは、1本のデータ線で各LEDを個別に制御でき、Arduinoへの接続も3本の配線だけで済みます。カラフルなLEDテープを使う第一歩です。

4.8(58)
75
WS2812Bで流れるLED(積み上げ点灯)
#72中級
プレミアム

WS2812Bで流れるLED(積み上げ点灯)

コップに水を注ぐように、光が満ちては減っていくLEDテープです。Arduinoが10個のカラーLEDをオレンジ色に1個ずつ点灯し、点灯したままにします。すべて点灯すると、同じ順番で1個ずつ消灯し、最初から繰り返します。このシンプルなアニメーションで、1本の配線から各LEDを個別に制御する方法がわかります。

4.7(50)
65
WS2812Bのナイトライダー風ライト
#73中級
プレミアム

WS2812Bのナイトライダー風ライト

スマートLEDテープの赤い光が端から端へ移動して戻り、往復を繰り返し続けます。Arduinoは各ステップで1個のLEDだけを点灯し、0.1秒待ってから隣へ移ります。6個の個別のLEDと何十本もの配線を使う代わりに、1本のテープと1本のデータ線で同じ流れる光を実現できます。

4.9(73)
94
WS2812Bアニメーション1
#75中級
プレミアム

WS2812Bアニメーション1

56個のLEDが並ぶテープで、虹のすべての色が隣り合って途切れずに流れます。まるで光の川がテープの上を流れるようです。各LEDは1つ前のLEDと少し違う色に光り、色が移り変わるたびにテープが生き生きと見えます。部屋や机を彩る、いちばん手軽な方法です。

4.9(69)
89
WS2812Bアニメーション2
#76中級
プレミアム

WS2812Bアニメーション2

自動で色が変わる光のショーを部屋に作ります。Arduinoが30個のLEDを備えたテープに色を流し続け、数秒ごとに新しい配色へ切り替えます。虹色、紫と緑の縞模様、白黒の縞模様、雲を思わせる色、パーティー向けの色、ランダムな色の組み合わせが登場します。何も操作せずに、テープが1分間のショーを最初から最後まで再生します。

4.8(65)
84
ESP32 WS2812B NeoPixel LEDテープの制御
#126中級
プレミアム

ESP32 WS2812B NeoPixel LEDテープの制御

WS2812B(NeoPixel)は、1本のデータピンで連結したLEDを個別に制御できるスマートなRGB LEDです。このプロジェクトでは、8個のLEDを備えたWS2812BテープをAdafruit_NeoPixelライブラリで制御し、滑らかな虹色のアニメーションを作ります。ESP32の3.3VロジックレベルはほとんどのWS2812Bのロットで問題なく動作しますが、不安定な場合に備え、470Ωの直列抵抗と1000µFのコンデンサを使う対策も紹介します。アニメーションは、HSV色空間の色相(hue)をずらして作ります。

4.9(19)
30