見出し画像

ラズパイ Pico互換機のRGB LEDを使う方法

Aliexpressで購入したラズパイ互換機

 本家の Raspberry Pi Pico (以下、ラズパイ Picoと略)は接続端子が USB-micro B なので、USB-C の互換機を探した。Aliexpress で探すと沢山あって、メモリーが16MBのもので2個でも送料込み千円で購入できるものを見つけた。
1個だと送料が安かったものの、郵送方法の違いで1ヶ月を要するのだった。2個以上だと送料が割高になるが2週間で届き、送料の差額も少ないので2個買ってみた。中国製なので1個ダメでもという感覚もある。
 この互換機には、RGB LED が一個オンボードで付いていた。(本家には付いていない)説明書などは同封されていなかったので、使い方は?と思ったが、動作確認のため1個を開封してMacに繋ぐと RGB LEDが光った。Thony を起動してみると内部に main.py があって RGB LEDを駆動するサンプルプログラムがあった。
サンプルが入っているので安心して、main.py を自分のプログラムで上書きして使っていた。

RGB LED を使ってみようとしたら…

 余裕ができたので、オマケで付いてきたオンボードの RGB LED を使ってみようと、2個目の互換機を開封して Thony に接続したら….無い! main.py が入っていないのだった。あちゃー中国製品あるある?
実は、1個目に入っていたmain.py は2個目にもあると思い込んで、保存もしなかったし、よく読まずに上書きで消してしまっていたのだ。

ダメもとで販売元に問い合わせ

Aliexpress の注文履歴から販売元に RGB LED のサンプルプログラムか、接続されているピン番号を教えて欲しいと問い合わせた。

ネットで調べる

問い合わせへの回答を待ちつつ、ラズパイ Pico で RGB LED を使う方法をネットで調べると、NeoPixel ライブラリーを使う方法以外に、ラズパイPico に付いているPIO(GPIOを制御するための処理ユニット)を使う方法が見つかった。

このサイトは RGB LED の詳細な説明から詳しく書いていて、とても参考になりました。

販売元からの回答が来た!

2日も待たずに販売元から連絡があり、資料を送るので宛先のメールアドレスを教て欲しいとの事だった。念の為、使い捨てメールアドレスを教えると翌日にはサンプルプログラムと互換機の詳細な回路図が送られてきた。この販売元は信頼できる。
 回路図をみると、RGB LEDの Din は RGB23 に接続されていて、Dout はどこにも繋がっていない事がわかった。(芋づる式には使えない)
RGB23は、トップ画像のように基盤の 37番ホール(23と記載されてる)に繋がっていることは、回路図にも記載されていた。

作ったコード

上記のサイトと販売元からの情報で以下のコードを作成。
接続は以下のように、オンボードのRGB LEDと同じ23にした。
(オンボードのものも最初のLEDとして動作する)
36番(3v3) -  シリアルLEDの電源に
37番(RGB23) - シリアルLEDの Din へ
38番(G) - シリアルLEDのGへ

import array, time
from machine import Pin
import rp2

# NeoPixel WS2812Bの指定
NUM_LEDS = 10  # NeoPixelの数
LED_PIN = 23   # NeoPixel信号接続端子

# 以下はNeoPixelを使用するための設定、PIOを制御するプログラム -----------------------
# NeoPixcel WS2812の制御タイミングに合わせたパルスを生成するための設定をアセンブラで指定
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():    
  T1 = 2
  T2 = 5
  T3 = 3
  wrap_target()
  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]
  wrap()

# クラスStateMachineを使用して、正確なパルスを出力するための設定を行う
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(LED_PIN))
# 設定したクラスStateMachineを有効にして使えるようにする。
sm.active(1)

# LEDのRGBの値を指定する24bit(8bit x 3)の配列をNeoPixelの数で準備
# 24ビットは順に GGRRBB になっている
ar = array.array("I", [0 for _ in range(NUM_LEDS)])

# NeoPixelの個別に色を設定する関数 ------------------
def drawpix(num, red, green, blue):
  ar[num] = green << 16 | red << 8 | blue  # NeoPixel用の24bitデータを左ビットシフトとORで生成

# 全てのLEDを同じ色に設定して100ms表示する関数 -------
def ar_color_all(red, green, blue):
    for i in range(NUM_LEDS):
        ar[i] = (green<<16) + (red<<8) + blue
    sm.put(ar, 8)
    time.sleep_ms(150)
    
#------------------
# 1個を白色点灯(複数ある場合は最初の1番目のみ点灯)
# 点灯させたいNeoPixelの番号(num)とRGB(赤緑青)の明るさを0〜255(30程でも十分明るい)で指定
drawpix(0, 10, 10, 10) # LED個別に色を設定する関数呼び出し(num, R, G, B)
sm.put(ar, 8)   # 点灯実行(NeoPixel制御パルス出力)
time.sleep_ms(1000)    # 指定したミリ秒待つ

# 光を順番に回す
for i in range(4 * NUM_LEDS):
    for j in range(NUM_LEDS):
        g = j * 100 // (NUM_LEDS)
        b = 100 - j * 100 // (NUM_LEDS)
        if j != i % NUM_LEDS:
            g >>= 3
            b >>= 3
        drawpix(j, 0, g, b)
    sm.put(ar, 8)
    time.sleep_ms(50)

# 全てのLEDを同色で表示
for i in range(4):
    for j in range(1, 10):
        ar_color_all(j, 0, 0)   # Red
        ar_color_all(j, j, 0)   # Yellow
        ar_color_all(0, 0, j)   # Blue

動作している様子

オンボードのRGB LED とシリアルLEDが同時に動作

ということで、ラズパイPico でシリアル(RGB)LEDを動作させることができた。
備忘録を兼ねて note に投稿しておく。

この記事が気に入ったらサポートをしてみませんか?