50連フルカラーLEDを制御してお家クリスマスイルミネーション

この記事は HRBrain Advent Calendar 2021 11日目の記事です。

qiita.com

こんにちは。
HRBrainで人事評価サービスのフロントエンド開発を担当している川口です。

去年のAdvent Calendarでは真面目にフロントエンドの記事を書いてましたが、今年はかなり脱線して電子工作でクリスマスツリーにイルミネーションを設置した話をご紹介します。

去年の記事もよかったらこちらからどうぞ。

times.hrbrain.co.jp

times.hrbrain.co.jp

完成品のクリスマスツリー

こんな感じでビカビカになります。

youtu.be

必要な部品

Raspberry Pi

3や4が望ましいです。
最新のRaspberryPi OSをインストールして初期設定を完了させておいてください。

50連フルカラーLED

WS2811というICチップを内蔵している50連フルカラーLEDライトです。
以下の商品などで大丈夫です。

www.amazon.co.jp

5V ACアダプター

LEDの電源供給用です。
50連LEDをRaspbery Piから給電してしまうと壊れてしまうため、別途電源を用意します。
以下の商品などで大丈夫です。

www.amazon.co.jp

ブレッドボード用DCジャック

ブレッドボードとACアダプターを接続するためのDCジャックです。
以下の商品などで大丈夫です。

akizukidenshi.com

ブレッドボードとジャンパワイヤ

適当なもので大丈夫です。

配線

以下の図のように部品を配線します。

f:id:hrb-goodtea0223:20211211004333p:plain

テキストで記すと以下の配線になってます。

Raspberry Pi GND <-----> DCジャックのマイナス
Raspberry Pi GPIO 18 <-----> LEDのData in (リンクの商品だと緑線)
DCジャックのマイナス <-----> LEDのGND (リンクの商品だと白線)
DCジャックのプラス <-----> LEDの+5V (リンクの商品だと赤線)

あとはDCジャックにACアダプタを挿せばOKです。

ライブラリインストール

Raspberry Pi

$ git clone https://github.com/jgarff/rpi_ws281x
$ sudo apt-get install scons
$ cd ./rpi_ws281x
$ scons

Python

$ sudo pip3 install rpi_ws281x

サンプルの実行

PythonでフルカラーLEDを制御するサンプルを落としてきて実行します。

サンプルコードはこちらからも確認できます。
https://github.com/rpi-ws281x/rpi-ws281x-python/tree/master/examples

$ git clone https://github.com/rpi-ws281x/rpi-ws281x-python
$ cd ./rpi-ws281x-python/example
$ chmod 755 *.py
$ sudo python3 strandtest.py

どうでしょうか?
うまくいけば動画のようにビカビカになるかと思います。
(まだコードを修正していないので16個しか光りません)

サンプルコードをいじっていい感じにする

さて、サンプルのままでは全てのLEDが光らなかったりイルミネーションが物足りなかったりするため、いい感じにいじっていきます。

LEDの数を指定

今回は50連LEDを使っているため50を指定します。

# LED_COUNT = 16        # Number of LED pixels.
LED_COUNT = 50

GPIOの番号を指定

今回はRaspberryPi上のGPIO 18とLEDのData inを接続しているため、18を指定します。
(サンプルでは初めから18が設定されているためそのままでOKです。)

LED_PIN = 18          # GPIO pin connected to the pixels (18 uses PWM!).

イルミネーションOFFの処理を追加

イルミネーションをOFFにする際、きれいに消えるように専用の処理を追加しておきます。

def cleanup(strip):
    colorWipe(strip, Color(0, 0, 0), 10)
    sys.exit(1)

mainの処理を変更

元のサンプルだと決められた順番で決められたイルミネーションがループし続け味気ないため、以下のような修正を加えていきます。

  • 5種類のイルミネーションをランダムで実行
  • イルミネーションのカラーを追加してバリエーションを増やす
  • 12回ごとに30秒の小休憩を入れる
  • プロセス終了時に cleanup 関数を走らせる
# Main program logic follows:
if __name__ == '__main__':
    # Process arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit')
    args = parser.parse_args()

    # Create NeoPixel object with appropriate configuration.
    strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
    # Intialize the library (must be called once before other functions).
    strip.begin()

    # プロセス終了時にcleanupを実行
    sig_handler = lambda signum, frame, strip2=strip: cleanup(strip2)
    signal.signal(signal.SIGTERM, sig_handler)
    signal.signal(signal.SIGINT, sig_handler)

    print('Press Ctrl-C to quit.')
    if not args.clear:
        print('Use "-c" argument to clear LEDs on exit')

    try:
        count = 0
        while True:
            num = random.randint(1, 5)

            if num == 1:
                print('1: Color wipe animations.\n')
                colorWipe(strip, Color(255, 0, 0), 20)  # Red wipe
                colorWipe(strip, Color(255, 255, 0), 20)
                colorWipe(strip, Color(0, 255, 0), 20)  # Blue wipe
                colorWipe(strip, Color(0, 255, 255), 20)
                colorWipe(strip, Color(0, 0, 255), 20)  # Green wipe
            elif num == 2:
                print('2: Theater chase animations.\n')
                theaterChase(strip, Color(255, 0, 0), 150, 5)  # White theater chase
                theaterChase(strip, Color(255, 255, 0), 150, 5)
                theaterChase(strip, Color(0, 255, 0), 150, 5)  # Red theater chase
                theaterChase(strip, Color(0, 255, 255), 150, 5)
                theaterChase(strip, Color(0, 0, 255), 150, 5)  # Blue theater chase
            elif num == 3:
                print('3: Rainbow animations.\n')
                rainbow(strip, 15, 6)
                colorWipe(strip, Color(255, 255, 255), 15)
            elif num == 4:
                rainbowCycle(strip, 15, 6)
                colorWipe(strip, Color(255, 255, 255), 15)
            elif num == 5:
                print('5: Rainbow chase animations.\n')
                theaterChaseRainbow(strip, 150)

            count += 1

            if count % 12 == 0:
                colorWipe(strip, Color(255, 255, 255), 10)
                colorWipe(strip, Color(0, 0, 0), 10)
                time.sleep(30)

    except KeyboardInterrupt:
        if args.clear:
            colorWipe(strip, Color(0, 0, 0), 10)

修正済みサンプルコード

上記の修正をすべて入れたサンプルコードを以下に用意してますので、よかったら参考にしてみてください。

https://gist.github.com/hrb-kawaguchi-kazuya/88949defad578d5929db81d37bc159c8

参考にしたサイト

ラズベリーパイでNeoPixelを使う - Qiita

ラズパイでLEDスティック点灯

まとめ

今回の記事はどうだったでしょうか?
業務に関連した記事が多い中、思いっきり趣味の記事を投稿してしまいましたが楽しんでいただけたでしょうか。
これをきっかけにRaspberry Piを使った電子工作に挑戦してみるのも良いと思います。
では皆さん良いクリスマスを!