💡
ラズパイを使って、シリアルLEDを制御する
ラズパイを使って、シリアルLEDを制御するメモです。
シリアルLED(WS2812B)とは、マイコンやArduino等からSPIで簡単に制御できるRGBのドットマトリックスLEDパネルです。
デモ
最終的に作るものは、以下となります。
※16x16のLEDパネルを4つ使って32x32ドットの表示を行います。
32x32のパネルであれば、もっと簡単に実現できます。
システム図
機材一覧
no | 部品名 | 個数 | 備考 | |
---|---|---|---|---|
1 | ラズベリーパイ | 1 | 今回は4Bで確認 | |
2 | シリアルLED(16x16) | 4 | BTF-LIGHTING WS2812B ECO RGB合金ワイヤー 16X16cm 265ピクセル LED | |
3 | ACアダプター 5V 4A | 1 | ACアダプター 5V 4A出力プラグ外径5.5mm | 3A以上は必須 |
4 | DCジャック変換プラグ | 1 | DCジャック変換プラグ | |
5 | ジャンパー線 | 適量 | - |
開発環境
- ラズベリーパイ
- Linux rpi 5.10.17-v7l+ #1403 SMP Mon Feb 22 11:33:35 GMT 2021 armv7l GNU/Linux
- Python
- Python 3.7.3 (default, Jan 22 2021, 20:04:44)
接続
全体図
- 正面から見たシリアルLED
- 背面から見たシリアルLED(接続)
接続表
ws281x | 接続先 | 備考 |
---|---|---|
[A]①3pin - 5V | - | つながない |
[A]①3pin - GND | ラズベリーパイ-GND | - |
[A]①3pin - DIN | [pi]① ラズベリーパイ-[PHY]12([BCM]18) | [PHY]は物理ピン, [BCM]はプログラムで指定 |
[A]②2pin - 5V | 外部電源-5V | DCジャック変換プラグを介して、ACアダプタに接続 |
[A]②2pin - GND | 外部電源-GND | DCジャック変換プラグを介して、ACアダプタに接続 |
[A]③3pin - 5V | ws281x - [B]③3pin - 5V | 専用のコネクタで接続する |
[A]③3pin - GND | ws281x - [B]③3pin - GND | 専用のコネクタで接続する |
[A]③3pin - DOUT | ws281x - [B]③3pin - DIN | 専用のコネクタで接続する |
[B]④3pin - 5V | ws281x - [C]④3pin - 5V | 専用のコネクタで接続する |
[B]④3pin - GND | ws281x - [C]④3pin - GND | 専用のコネクタで接続する |
[B]④3pin - DOUT | ws281x - [C]④3pin - DIN | 専用のコネクタで接続する |
[C]④3pin - 5V | ws281x - [D]④3pin - 5V | 専用のコネクタで接続する |
[C]④3pin - GND | ws281x - [D]④3pin - GND | 専用のコネクタで接続する |
[C]④3pin - DOUT | ws281x - [D]④3pin - DIN | 専用のコネクタで接続する |
- 専用コネクタは、シリアルLEDに付属されている
ラズベリーパイの接続部分
準備
シリアルLEDの使い方
adafruit-circuitpython-neopixelというをライブラリを使用することで、シリアルLEDを制御することができます。
本モジュールを使用する場合は、sudo権限が必要です。
インストールが紹介されている公式サイトは、下記となります。
環境の構築
- シリアルLEDを動かすには以下
$ python3 -m venv env_sled
$ source env_sled/bin/activate
(env_sled) $ pip install adafruit-circuitpython-neopixel
(env_sled) $ sudo ./env_sled/bin/python
- デモ用コードではopencvを使用しているので以下を追加
(env_sled) $ pip install opencv-python
シンプルなサンプルコード
下記のコードは、⚪🔵🟢🔴([RED][GREEN][BLUE][WHITE])を点灯→消灯します。
- コード
(env_sled) $ sudo ./env_sled/bin/python
Python 3.7.3 (default, Jan 22 2021, 20:04:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> import board
>>> import neopixel
>>>
>>> pixel_pin = board.D18
>>> num_pixels = 64 # 64のLEDを制御
>>>
>>> ORDER = neopixel.GRB
>>>
>>> pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.010, auto_write=False, pixel_order=ORDER)
>>>
>>> # 0番目をRED指定
>>> pixels[0] = (255, 0, 0)
>>> # 1番目をGREEN指定
>>> pixels[1] = (0, 255, 0)
>>> # 2番目をBLUE指定
>>> pixels[2] = (0, 0, 255)
>>> # 3番目をWHITE指定
>>> pixels[3] = (255, 255, 255)
>>> # LEDの状態を更新(ここで点灯)
>>> pixels.show()
>>>
>>> # num_pixelsのLEDにBLACK(消灯)指定
>>> pixels.fill((0, 0, 0))
>>> # LEDの状態を更新(ここで消灯)
>>> pixels.show()
>>>
- 結果
- 注意事項
- LEDの順番は、奇数行と偶数行ことなります
- 以下がデータの並びです
デモの説明
以下の画像を読み込んで、水平方向に1dotずつシフトする画像を表示します。
※画像は、200x32となっています
コード
ポイントや注意事項は、コメントを参照してください。
scroll_moji.py
import board
import neopixel
import time
import numpy as np
import cv2
IMG_PATH = "image_zenn.png"
# シリアルLEDの初期化
pixel_pin = board.D18
num_pixels = 32*32
ORDER = neopixel.GRB
# brightnessをあげると光が強くなりますが、極端に上げるとほぼ白く見える
# auto_writeをTrueにすると、pixels[]にアクセスした時点でLEDが点灯(/消灯)する
pixels = neopixel.NeoPixel(
pixel_pin, num_pixels, brightness=0.010, auto_write=False, pixel_order=ORDER
)
def show32x32_pixel(np_rgb):
"""今回のシステム用の並べ替え
"""
global pixels
for cnt in range(32):
if cnt%2 == 0:
# [D],[C]エリア - 偶数行の並べ替え
for scnt, val in enumerate(np_rgb[cnt,:16,]):
pixels[1023 - cnt*16 - scnt] = (val[0], val[1], val[2])
# [A],[B]エリア - 偶数行の並べ替え
for scnt, val in enumerate(np_rgb[cnt,16:,]):
pixels[cnt*16 + 16 - 1 - scnt] = (val[0], val[1], val[2])
else:
# [D],[C]エリア - 奇数行の並べ替え
for scnt, val in enumerate(np_rgb[cnt,:16:,]):
pixels[1024 - (cnt+1)*16 + scnt] = (val[0], val[1], val[2])
# [A],[B]エリア - 奇数行の並べ替え
for scnt, val in enumerate(np_rgb[cnt,16:,]):
pixels[cnt*16 + scnt] = (val[0], val[1], val[2])
pixels.show()
return
def main():
# 消灯
pixels.fill((0, 0, 0))
pixels.show()
cap = cv2.VideoCapture(IMG_PATH)
while True:
ret, frame = cap.read()
if ret == False:
break
h, w, _ = frame.shape
# スクロール表示
for srt in range(w-32):
show32x32_pixel(cv2.cvtColor(frame[:,srt:srt+32,:], cv2.COLOR_BGR2RGB))
time.sleep(0.1)
# LED消灯
pixels.fill((0, 0, 0))
pixels.show()
if __name__ == "__main__":
main()
実行の仕方
$ sudo ../env_sled/bin/python scroll_moji.py
DEMOの動作になればOKです🎊。
最後に
今回は、スクロールで表示しましたが、gifなどのアニメーションを渡すことで、
アニメーションを表示することもできます。
Discussion