Tanuki_Bayashin’s diary

電子工作を趣味としています。最近はラズベリーパイPicoというマイコンを使って楽しんでいます

【ラズベリーパイPico】フルカラーLEDで遊ぶ

※なにか気になる点がありましたらコメント欄からお伝えください。また、回路を製作する場合には電源を切るなど、注意を払って行うようお願いいたします。

目次

1.はじめに

 フルカラーLED(Neopixel)を用いて、ラズベリーパイPico(以下Picoと記述)により赤と緑と青の色を発色することを試みようと思います。
 ※この回路は、カラーセンサーの動作を確認するための照明用として製作しました。

リング状のフルカラーエルイーディーの写真ラズベリーパイピコの写真
図1 左:フルカラーLED(Neopixel) 右:ラズベリーパイPico

2.構成図

フルカラーLEDで遊ぶときの回路図
図2 全体構成図

 PicoとフルカラーLEDを図2のようにつなぎます。Neopixelに関する説明はここを参照してください。この回路図で、押しボタンswがありますが、プログラムでPico 内のプルダウン抵抗を使うように指定してあるので、回路ではプルダウン抵抗はつないでいないです。
(この記事ではカラーセンサーは使用しません)

3.Neopixelのライブラリのコード

3.1 ソースコード

 ライブラリという程でもないですが、Neopixelを制御するためのコードを以下に示します。以前の記事と内容を変更しています。(LED表示用の2つの関数もライブラリ内にまとめました)
※プログラム中、WS2812Bと記述しています。Neopixelと書いたほうが良いようですが、不用意に変えるとどこでバグが出るか分からないため、このようにしてあります。

リスト1 ファイル名:Class_ws2812b_Ver2.py

import array
from machine import Pin
import rp2
from rp2 import PIO, StateMachine, asm_pio

# PIO State Machine to display ws2812
@asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True,\
         pull_thresh=24)
def ws2812():
    T1 = 2
    T2 = 5
    T3 = 3
    label("bitloop")
    out(x, 1)                .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")    .side(1)    [T1 - 1]
    jmp("bitloop")           .side(1)    [T2 - 1]
    label("do_zero")
    nop()                    .side(0)    [T2 - 1]

class Class_WS2812B:

    def __init__(self):
        self.sm_no = 0         # state machine No(0-7)
        self.freq = 8000000    # frequency 8M[Hz]
        self.Pin_No = 16       # the Number of conected Pin(GPIO)
        self.NUM_LEDS = 16     # numbers of LEDs (WS2812B)

    def init_ws2812b(self, sm_no, freq, Pin_No, NUM_LEDS):
        self.sm_no = sm_no
        self.freq = freq
        self.Pin_No = Pin_No
        self.NUM_LEDS = NUM_LEDS

        # Create the StateMachine with the ws2812 program,
        #  outputting on Pin_No.
        self.sm = StateMachine(self.sm_no, ws2812, self.freq, \
                          sideset_base=Pin(self.Pin_No))

        # start the StateMachine, it will wait for data on its FIFO.
        self.sm.active(1)
        # array for each LEDs
        self.ar = array.array("I", [0 for _ in range(self.NUM_LEDS)])


    # すべてのNeopixelの色を、指定された値にする
    def ar_color_all(self, red, green, blue):
        for i in range(self.NUM_LEDS):
            self.ar[i] = (green<<16) + (red<<8) + blue
        self.sm.put(self.ar,8)

    # すべてのLED を消灯する
    def clear_all(self):
        for i in range(self.NUM_LEDS):
            self.ar[i] = 0
        self.sm.put(self.ar,8)

3.2 解説

 以前の記事から変更した部分を解説します。
 26、32行目: NUM_LEDS(Neopixel全体を構成するフルカラーLEDの数)も変数としてライブラリで扱うこととしました。
 36、37行目: Neopixelの初期設定をしています。
 39~55行目: すべて以前の記事で、ライブラリを利用する側のソースコードに含まれていた部分です。必要な変数には "self." を付けています。

4.実行プログラム

4.1 実際にNeopixelを動かすためのコード

 ソースコードを載せておきます。3つの押しボタンswで赤、緑、青を切り替えています。

スト2 ファイル名:test_Class_ws2812b_Ver2.py(ライブラリは”Oct_2021”というフォルダーに入っています)

import utime
from Oct_2021 import Class_ws2812b_Ver2

#Configure the number of WS2812 LEDs.
NUM_LEDS = 16

# Create the StateMachine with the ws2812 program, outputting on Pin(0).
ws = Class_ws2812b_Ver2.Class_WS2812B()

# StateMachine(0, ws2812, freq=8MHz, sideset_base=Pin(16), NUM_LEDS)
ws.init_ws2812b(0, 8000000, 16, NUM_LEDS)

Red_On   = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_DOWN)
Green_On = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_DOWN)
Blue_On  = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)

if __name__ == '__main__':
    # Process arguments
    print('Press Ctrl-C to quit.')

    try:
        while True:
        # ar_color_all(red, green, blue)
            if Red_On.value() == 1:
                ws.ar_color_all(255, 0, 0) # 赤
                utime.sleep(0.1)

            elif Green_On.value() == 1:
                ws.ar_color_all( 0, 255, 0) # 緑
                utime.sleep(0.1)

            elif Blue_On.value() == 1:
                ws.ar_color_all( 0, 0, 255) # 青
                utime.sleep(0.1)

    except KeyboardInterrupt:
        #### clear ws2812b
        ws.clear_all()
        print('program is finished')

4.2 解説

 ライブラリに関数などを詰め込んだので、こちらはその分処理が少なくなりました。(その反面ソースコードの管理が複雑になりますね。自己都合の仕様変更、混乱します)
   1,2行目: ライブラリを読み込んでいます。
    5行目: NUM_LEDS の値を指定しています。
    8行目: クラスからインスタンスを得ています。
   11行目: Neopixelを初期設定しています。
 13~15行目: 押しボタンswの初期設定です。GPIOのピンを割り当て、入力、プルダウンの設定をしています。
17,21,36行目: メインルーチンに入ります。Ctrl-Cにより以下へと無限ループから抜け出せます。
 22~34行目: while による無限ループです。押しボタンswのうちどれが押されたかで発光色が変わります。
 37~39行目: Ctrl-C が押された後の処理です。フルカラーLEDを消灯し、プログラムを終了します。

5.動画

 動作しているところを動画にしました。確認の意味で載せています。

youtu.be

6.まとめ

 Neopixelを制御するライブラリを更新し、動作の確認を行いました。
※この回路はカラーセンサーの動作確認に用いるために製作しました。