digispark FastLEDでイルミネーションを

これもよくありがちな題材ではありますが，楽しむつもりでやってみました。

使ったのはこれ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/59c12e2d-dad9-1792-2656-18dd26855832.png)

https://ae01.alicdn.com/kf/HTB1oq9GaLBNTKJjSszbq6yFrFXaR.jpg

https://ja.aliexpress.com/item/32834127593.html?spm=a2g0s.9042311.0.0.65ab4c4dOew0cd

テープ状にたくさん実装されたものを使うのも定番のようですが，リビングにちょこっと置くことを考えて，これにしてみました。

ライブラリーは， NeoPixel という名前で， Adafruit から提供されていました。また，調べていくと，FastLEDというライブラリーも存在しました。

使うチップですが，いくつか種類があるようでした。

結果としては，Adafruit， FastLEDどちらのライブラリーも，ほぼそのままで動きました。

何となくですが，FastLEDを以下では使いました。

```C++
#include <FastLED.h>
#define NUM_LEDS 8
#define DATA_PIN PB0
CRGB leds[NUM_LEDS];

#define MAX_LEDS 3

struct led {
  uint8_t position; // 0 to (NUM_LEDS - 1)
  uint8_t brightness; // 0 to 7. 0 is max brightness.
  int8_t brightnessChangeMode; // positive or negative
  uint16_t nextTime;
};

struct led led[MAX_LEDS] = {
  // position, initial brightness, mode, next time
  {0,  0,  1, 1},
  {2,  3,  1, 1},
  {4,  7, -1, 1}
};

uint32_t alarm1 = 0;

void setup() {
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(150);
}

void loop() {
  for (int i = 0; i < MAX_LEDS; i++) {
    leds[led[i].position].setRGB(
      (random(220, 256)) >> led[i].brightness,
      (random(220, 256)) >> led[i].brightness,
      (random(220, 256)) >> led[i].brightness);
    FastLED.show();
    delay(100);

    if (millis() / 1000 > led[i].nextTime) {
      led[i].nextTime += random(20, 40);
      if (led[i].brightness == 0) {
        led[i].brightnessChangeMode = 1;
      }
      if (led[i].brightness == 7) {
        led[i].brightnessChangeMode = -1;
        leds[led[i].position].setRGB(0, 0, 0);
        do {
          led[i].position = random(NUM_LEDS);
        } while (leds[led[i].position]);
      }
      led[i].brightness += led[i].brightnessChangeMode;
    }
  }
}
```

~~ああ， `for`ループが意図せず二重になってますね... あとで直します...~~ 修正しました。思い出しましたが，コンパイル時警告が出ますが，問題なく書き込み実行できます。

結線は，Digisparkから，電源，グランド，PB0を接続します。

すぐに光り出したのはいいのですが，恐ろしいほどの輝度です... `  FastLED.setBrightness(150);` で全体が少し下がります。

さて，インテリアとして，どのように光らせるか，自信がありませんが，私のセンスが問われますね... 

- 基本的に「白」く光らせることにしました。リビング内は「電球色」の照明が多いのですが，多少人工的，それでも人工的過ぎず，ということで決めてみました。
- 「星のまたたき」をイメージして，少し「チラチラ」させてみました。試した結果，`random(220, 256)`を用いて，RGBの各値を「少しだけ減らす」と，いい具合に「チラチラ」しました。
- 薄暗いところからスタート，だんだん明るくし，また徐々に暗くして，最後は消えて別の場所に，という感じにしました。ある程度明るい時に突然別の場所に写すと，「人工的な感じ」がするように思えたからです。
- 8個中，3個光らせることにしました。「次への移動場所」はランダムに決めるのですが，すでに光っている場所でも良いことにしました。したがって，全体として2個だけ光っている時もあるのですが，まあそれも「いい感じ」のように思えました。

スケッチ作成で気をつけた，および気づいたところです。

- 初めて「構造体」を使って3個のLEDのデータ整理をしました。今時はclassを使うべきなのかもしれませんが，まだその方法は知りませんし...
- 個々のLEDの輝度を変える方法がわかりません。そのため，各RGB値を減らしていく，という方法にしました。この方法により，色味を維持しながら暗くすることができました。厳密な方法ではないかと思いますが，今回はこれで十分かと。この部分です。

```C++
    leds[led[i].position].setRGB(
      (random(220, 256)) >> led[i].brightness,
      (random(220, 256)) >> led[i].brightness,
      (random(220, 256)) >> led[i].brightness);
```

以下のページを参考にさせていただきました。まとめて感謝いたします。

- https://rephtone.com/electronics/arduino-neopixel/
- https://homemadegarbage.com/halloween2016
- https://www.instructables.com/id/USB-NeoPixel-Deco-Lights-via-Digispark-ATtiny85/
- https://dotstud.io/blog/gyaruden-kyoko-led-cassette/