Tanuki_Bayashin’s diary

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

Neopixel を使ってカラフルな表示をした~その2

※なにか気になる点がありましたらコメント欄にご記入ください。また、工作や回路を製作する場合には、細かい作業などに対して、細心の注意を払われるようお願いいたします。

目次

1.はじめに

前に以下の記事を書きました。
tanuki-bayashin.hatenablog.com

今回、上の記事の内容をバージョンアップしたのでご紹介します。

免責事項:
この記事は電子工作レベルのお話です。実用に際し、いかなる損害も自己責任でお願いします。
筆者はいかなる場合においても、一切の責任がないことをご承知おきください。

2.変更内容

変更した内容は以下の2点です。

  1. データの書き込みを1個のセルずつ行っていたのを、100個まとめて行うようにした
  2. オーバークロックが気軽に行えることを知ったので、試してみた

2の変更点に関しては、知人であるもりしーさん(@kotaMorishita)のYoutubeの番組内で知りました。
また、具体的記述の仕方については、こちらの方の記事を参考にしました。
お二方共々、ありがとうございました。

MicroPythonでRaspberry Pi PicoのPIOを動かしてみる

3.ソースコード

リスト1に前回分のソースコードを再掲します。

リスト1 main.py (再掲)

#必用なライブラリをインポートします
import array, utime, math
from machine import Pin
import rp2
from rp2 import PIO, StateMachine, asm_pio

#WS2812 のLEDの数を指定します
NUM_LEDS = 100
# Pico特有のstate machine を用いてWS2812の制御を行っています
#このあたりの処理はリスト1の下のリンク先の図書より引用しました
# 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]

# Create the StateMachine with the ws2812 program, outputting on Pin(16)().
sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(16))

# start the StateMachine, it will wait for data on its FIFO.
sm.active(1)

# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])

#position の位置のLEDをred, green, blue の値にて指定します
def ar_color(position, red, green, blue):
    ar[position] = (green<<16) + (red<<8) + blue

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

# 色をカラフルに表示するための仕掛けが(ちょこっと)秘められています
def triangle(x):
    if x < 20.0:
        y = int(1.5 * x)
    elif x < 40.0:
        y = 60 - int(1.5 * x)
    else:
        y = 0
    return y

# 6個のリストのメモリーを確保しています
red   = [0.0 for i in range(NUM_LEDS)]
green = [0.0 for i in range(NUM_LEDS)]
blue  = [0.0 for i in range(NUM_LEDS)]

y_red   = [0.0 for i in range(NUM_LEDS)]
y_green = [0.0 for i in range(NUM_LEDS)]
y_blue  = [0.0 for i in range(NUM_LEDS)]

#ここから処理がスタートします
if __name__ == '__main__':
    # Process arguments
    print('Press Ctrl-C to quit.')

    # Neopixelを同心円上に色を変化させて表示するための計算です
    r_max = math.sqrt(4.5 * 4.5 * 2)
    for i in range(NUM_LEDS):
        x = float(i % 10) - 4.5        # 左から何列目かを計算し、4.5を引いています
        y = float(i) / 10.0 - 4.5        # 下から何段目かを計算し、4.5を引いています

        # 中心(4.5, 4.5)からの距離を求め、最大値を1に規格化しています
        r = math.sqrt(x*x + y*y) / r_max

        # 同心円状に色を変えて表示するための処理です。20、0、40と値をずらしています
        red[i]   = (r * 40 + 20.0) % 60.0
        green[i] = (r * 40 + 0.0 ) % 60.0
        blue[i]  = (r * 40 + 40.0) % 60.0
    
    
    try:
        # 無限ループです
        while True:

            #それぞれのLEDの色を計算し、表示しています
            for i in range(NUM_LEDS):
            
                # 1ステップ前から色を1つずらします
                red[i]   = (red[i]   - 1.0) % 60
                green[i] = (green[i] - 1.0) % 60
                blue[i]  = (blue[i]  - 1.0) % 60

                # 関数triangle() により色を計算しています
                y_red[i]   = triangle(red[i])
                y_green[i] = triangle(green[i])
                y_blue[i]  = triangle(blue[i])

                # 色を表示しています
                ar_color(i, y_red[i], y_green[i], y_blue[i])
                sm.put(ar,8)
                utime.sleep_us(100)
            utime.sleep_us(1)

    # ctl-C が押されたときの処理です
    except KeyboardInterrupt:
        #### clear ws2812b
        clear_all()


【変更その1】
今回変更したのは102-104行と部分です。

                sm.put(ar,8)
                utime.sleep_us(100)
            utime.sleep_us(1)

ここを

            sm.put(ar,8)

と変更しました。要は Neopixel への書き込みを、セル1個ずつ行っていたのを、100個まとめて行ったということです。(インデントを1段減らしています)
また、100μsや1μsの時間待ちは、今回の書き方に変えたところ、必要なくなりました。(理由は分かりません)

【変更その2】
以下の文をリスト1の7行の手前に付け加えました。

from machine import freq

machine.freq(250_000_000)

これはラズパイpicoのクロック周波数を250MHzに変更するというものです。(デフォルトでは125MHz。いわゆるオーバークロックです)

こうすることにより確かに動作速度が格段に速くなりました。
ただ動作の安定性や異常が発生しないかという点について筆者はそれほど詳しくないので、使用する際には注意していただきたいと思います。

4.動画

動作している様子を示します。

【動画1】データの書き替えを100個分まとめて行った
youtu.be

【動画2】さらに動作クロックを250MHzにした
youtu.be

以上になります。ありがとうございました。