稼働中

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が実装されています。
NeoPixel_01
RGB LED(WS2812B)の外観写真です。RGB LEDとDriver IC(WS2811)が見えます。
NeoPixel_02

接続例

WS2811、WS2812Bの電源電圧は3.5~5.5Vです。5V動作させるので別途電源が必要です。
Raspberry Pi PicoのGP16ピンを出力としてレベルコンバータを介してNeoPixelのDINと接続しています。
NeoPixel_03

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の動作確認ができました。