Raspberry Pi Pico(d_37)NeoPixel シリアルLED
NeoPixel RGB LED
Raspberry Pi PicoでNeoPixelを使ってみました。
「NeoPixel」とは通信でRGB値が制御できるLEDのことようです。シリアルLED、アドレッサブルLEDとも言うそうです。
WorldSemi社のDriver IC(WS2811)を搭載したRGB LED(WS2812B)を連結した集まりでadafruitの商品名らしいです。
※micro:bitの記事e_25~28を参考にしています。WS2812B(RGB LED)の制御方法など参考して下さい。
この記事では主に<class ‘NeoPixel’>の使い方を記載しています。
外観
動作確認に使用したNeoPixel RGB LEDです。8個のIC付RGB LEDが連結されています。ICたぶんWS2812Bが実装されています。
RGB LED(WS2812B)の外観写真です。RGB LEDとDriver IC(WS2811)が見えます。
接続例
WS2811、WS2812Bの電源電圧は3.5~5.5Vです。5V動作させるので別途電源が必要です。
Raspberry Pi PicoのGP16ピンを出力としてレベルコンバータを介してNeoPixelのDINと接続しています。
class ‘NeoPixel’の説明
Raspberry Pi PicoのMicroPythonにNeoPixelで使うneopixel.pyがあります。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。
「neopixel」をインポートするとclass ‘NeoPixel’が使えます。(メソッド bitstream も使えます)
class ‘NeoPixel’にはメソッド fill、writeと定数 ORDERがあります。
■fill((r,g,b))
全LEDに同じPWM値(r,g,b)を設定します。
各PWM値は8bitです。0~255になります。
■write()
NeoPixelにデータを送ります。
データは LED数x 3(PWM値(r,g,b))です。8連LEDなら8×3=24bytesです。
■ORDER
(1, 0, 2, 3)の定数です。実送信データの順番がG,R,B,Wになります。
使用するLEDによっては変更が必要です。R,G,B,Wの場合は(0, 1, 2, 3)にする必要があります。
先の写真のようなNeoPixel 8連のRGB LED を接続図のようにGP16ピンで駆動させる場合、
出力ピンの設定を
p0 = Pin(16,Pin.OUT)
NeoPixelの初期化を
np = neopixel.NeoPixel(p0, 8) #出力ピン設定、8連LED
LED 0~7を個別にデータを設定します。
np[0]=PWM値(r,g,b)
np[1]=PWM値(r,g,b)
…
np[7]=PWM値(r,g,b)
LED 0~7 の個別PWM値を返します。
np[0]
np[1]
…
np[7]
全数を同値で設定します。
np.fill((0,0,0)) #全数クリアされます
np.fill((255,0,0)) #全数 赤、明るさ最大値で設定
np.fill((255,255,255)) #全数 白、明るさ最大値で設定
送信の順番を変えます。
np.ORDER = (0, 1, 2, 3) #R,G,B,Wの順になります。
動作確認
動作確認のスクリプトは以下のようにしました。以下の順で点灯動作します。
個別にpos0、pos2、pos4を各々R、G、Bで点灯
fillを使ってクリア(消灯)
ORDERを変更して動作確認
※Raspberry Pi Pico単独で動作させるには’main.py’としてRaspberry Pi Picoにuploadして使います。
pico_np_test_01b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import Pin
import neopixel, time
# 出力ピン指定
p0=Pin(16,Pin.OUT)
np=neopixel.NeoPixel(p0, 8) # addressable LED 8pcs 0 ~ 7 #
# data clear
def cls():
np.fill((0,0,0)) #全指定設定
np.write()
dat=25 #PWM値
# 個別に設定
np[0] = (dat, 0, 0) #Pos0 Red
np[2] = (0, dat, 0) #Pos4 Green
np[4] = (0, 0, dat) #Pos6 Blue
print(np[0], np[1], np[2], np[3], np[4]) #Pos0~4のPWM値
np.write()
time.sleep(2)
#クリア
cls()
# 全同値設定 white
np.fill((dat,dat,dat))
np.write()
time.sleep(2)
cls()
# ORDER定数の変更確認
print('ORDER=',np.ORDER) #(1, 0, 2, 3) ALED GRBW G:0 R:1 B:2 W:3
np[0] = (dat, 0, 0) #RGB
np.write() #Pos0 RED
time.sleep(2)
cls()
np.ORDER=(0, 1, 2, 3) #ALED GRBW
print('ORDER=',np.ORDER)
np[0] = (dat, 0, 0) #GRB
np.write() #Pos0 Green
time.sleep(2)
cls()
np.ORDER=(2, 0, 1, 3) # ALED GRBW
print('ORDER=',np.ORDER)
np[0] = (dat, 0, 0) #BGR
np.write() #Pos0 Blue
time.sleep(2)
cls()
実行結果
結果は以下の動画ようになります。また Thonnyのshellに表示されます。
動画 NeoPixel_01.mp4
>>> %Run -c $EDITOR_CONTENT
(25, 0, 0) (0, 0, 0) (0, 25, 0) (0, 0, 0) (0, 0, 25) #pos0,1,2,3 LEDのpwm値
ORDER= (1, 0, 2, 3) #変更したORDER値確認
ORDER= (0, 1, 2, 3)
ORDER= (2, 0, 1, 3)
>>>
シフト動作など
シフト動作など試してみました。スクリプトは以下のようにしました。
以下の順で点灯動作します。
8連LEDのColor-listデータを点灯させます。順次3パターンを点灯させています。
左右にシフト動作させます。Pos0の赤を左に7、その後右に15シフトさせています。
データは残したままLEDをoffします。元データで再点灯させます。
pico_np_test_02b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import Pin
import neopixel, time
#OUT GPIO-Pin
p0=Pin(16,Pin.OUT)
np=neopixel.NeoPixel(p0, 8) # leds=8
# Colorデータ RGB-PWM data
RED=[255, 0, 0]
ORANGE=(0xff,0xfA,0)
YELLOW=(255, 150, 0)
GREEN=(0, 255, 0)
CYAN=(0, 255, 255)
BLUE=(0, 0, 255)
PURPLE=(180, 0, 255)
WHITE=(0xff,0xff,0xfd)
ALL=(255,255,255)
# Color-list data LED 0 ~ 7 の色を設定
C0=[RED,GREEN,RED,GREEN,RED,GREEN,RED,GREEN] #1
C1=[RED,YELLOW,GREEN,BLUE,RED,YELLOW,GREEN,BLUE] #2
C2=[RED,ORANGE,YELLOW,GREEN,CYAN,BLUE,PURPLE,WHITE] #3
dec=0.05 # data ratio
# 明るさ減 pwm data x dec
def xdat(ldat=[0,0,0]):
da=[]
for d in ldat:
da.append(int(d*dec))
return da
# data clear
def cls():
np.fill((0,0,0))
np.write()
# Colors list data, LED on-time(msec)
def CLed(Cdat,tms=0):
i=0
for d in Cdat:
np[i] = xdat(d)
i=i+1
np.write()
time.sleep_ms(tms)
# 右(上)シフト 移動数、点灯時間
def Rshf(n=1,tms=0):
a=np.buf # np.buf bytearray(leds*3)
#print(a)
for i in range(n):
# right shift
mdat=a[-3:] # move data
cdat=a[:-3] # clipped data
#print(mdat,cdat)
mdat.extend(cdat)
a=mdat
if tms !=0:
np.buf=mdat
np.write()
time.sleep_ms(tms)
else:
np.buf=mdat
np.write()
# 左(下)シフト 移動数、点灯時間
def Lshf(n=1,tms=0):
a=np.buf # np.buf bytearray(leds*3)
#print(a)
for i in range(n):
# right shift
mdat=a[3:] # move data
cdat=a[:3] # clipped data
#print(mdat,cdat)
mdat.extend(cdat)
a=mdat
if tms !=0:
np.buf=mdat
np.write()
time.sleep_ms(tms)
else:
np.buf=mdat
np.write()
#print(mdat)
# LED Off 元の値は残っている
def d_off():
cbuf=np.buf #current buf-data
dbuf=bytearray(8*3) # delete all 0x00 data
np.buf=dbuf
np.write()
np.buf=cbuf # undo buf-data
## example
# data clear
cls()
time.sleep(5)
## Colors listで点灯確認
ton=1500
CLed(C0,ton)
cls()
time.sleep_ms(500)
CLed(C1,ton)
cls()
time.sleep_ms(500)
CLed(C2,ton)
cls()
time.sleep_ms(500)
time.sleep(2)
## シフト動作確認
np[0]=xdat(RED) #Pos0-赤でon
np.write()
time.sleep_ms(1000)
# 右(上)シフト 移動7、点灯500ms
Rshf(7,500)
time.sleep(1)
# 左(上)シフト 移動15、点灯500ms
Lshf(15,300)
cls()
time.sleep(2)
## LED OFF動作
#元データ残存
CLed(C2,1000)
d_off() #OFF
time.sleep(1)
np.write() #元データでLED-on
time.sleep(1)
# データクリア LED OFF
cls()
関数 部分説明
■cls()
PWMデータをクリアします。
■CLed(Cdat,tms=0)
Cdat:NeoPixel LEDの個数分のRGB PWM値のリストデータ
tms:待機時間です。単位はmsecです。0なら実質データ送信だけです。
■Rshf(n=1,tms=0)
右側(上)にシフトします。
n:シフト数
tms:シフト間隔の時間です。単位はmsecです。0なら実質データ送信だけです。
■Lshf(n=1,tms=0)
左側(下)にシフトします。
n:シフト数
tms:シフト間隔の時間です。単位はmsecです。0なら実質データ送信だけです。
■d_off()
LEDをoffします。元のデータは消えていません。
実行結果
結果は以下の動画ようになりました。シフト動作などが確認できました。
動画 NeoPixel_02.mp4
まとめ
Raspberry Pi Picoでclass ‘NeoPixel’を使ってNeoPixel シリアルLEDの動作確認ができました。