ラズPicoでカラーLEDを点灯させよう〜その3〜 スイッチで光り方を切り替える

2024年1月12日(金)は、6割ほどの出席率でした。引き続き、カラーLEDを光らせるプログラムを制作します。

  • 18時00分~18時25分 タイピング練習
  • 18時25分~18時35分 プログラミングコンテンストに応募しよう
  • 18時35分~18時45分 ブレッドボードの使い方
  • 18時45分~19時50分 カラーLEDのプログラミング
  • 19時50分~20時00分 あとかたづけ

タイピング練習

今回のタイピングの練習も、英語入力にしました。使う教材は、下のサイトのWebアプリです。

https://manabi.benesse.ne.jp/gakushu/typing/

すこし余裕があったので、一人ひとりの指使いを確認しながらアドバイスしました。もちろん、タイピング練習を始めるときに基本的な進め方はすでに説明してあります。しかし、その説明をどのように解釈して実践しているかは、個別に確認しないとわかりません。みんな一斉におなじように説明しても、三者三様で受け取り方はさまざまなのです。

ましてやタッチタイピングは、頭で理解すればできるものではありません。身体(指)の動かし方は、何度も練習して習得するものです。それぞれの身体の癖が出てきます。メンバー一人ひとりを見て回ることで、その癖を修正することができるのです。

プログラミングコンテストに応募しよう~2回目~

前回、プログラミングコンテストに応募しようという話をして、メンバーの食いつきがいまいちでした。でも、わたしはあきらめません。なんどでもしつこくプロコン参加を促します

今日は、前回も説明したプロコンのサイトで、動画があったのでそれをメンバーで見ました。

https://pcn.club/

動画を見せると、メンバーもイメージがふくらんだようです。「え、この程度の作品でいいの?」「これくらいなら、作れそう」という反応が出てきました。もちろん、作り出したらうまくいかないところがたくさん出てくると思います。それでも、今は自分でも作れそうと思えることが大切です。

メンバーが、「自分でもできそう」から「自分でも作って応募してみたい」に心持ちが変わるまで、しつこく続けますよ~

ブレッドボードの使い方

正確には、ブレッドボードとジャンパーワイヤーの使い方の復習をしました。

ジャンパーワイヤーは、色によって長さが違います。下の写真を見ると一目瞭然だと思います。

そして、ジャンパーワイヤーの長さは、ブレッドボードの穴の位置に足が刺さるように調整されています。したがって、適切なジャンパーワイヤーを使えば、スムーズに電子回路を組み立てられます。デバイスの配置は、パズルみたいなものです。ジャンパーワイヤーをうまく配線できる場所にデバイスを配置しましょう。

ところで、こんな質問を受けました。「ジャンパーワイヤーの長さと色の関係は、メーカーを問わずおなじですか?」という質問です。

答えは、「メーカーにより長さと色の関係はバラバラ」です。下の写真は、わたしがジャンパーワイヤーを製作しているところです。

このように、ジャンパーワイヤーは誰でもかんたんに加工して作れるものです。長さと色について明確なルールはありませんし、誰でも自由に作れるものとして、ジャンパーワイヤーを使ってください。

カラーLED(WS2812B)にスイッチで制御する

引き続きカラーLED(WS2812B)を光らせるプログラミングに取り組みます。前回まで、カラーLEDが「全部点灯する(8色)」「追いかけるように次々に点灯する(8色)」「虹色に点灯する」の3種類の光り方をするプログラムを作りました。今回は、スイッチを一つつけて、押すたびに光り方が変わるプログラムを作ります

では、まず回路は下のとおりです。

ラズPicoのGP15にスイッチをつないだ部分が、増えた部分です。それ以外の部分は、前回までで作ったものと変更ありません。

カラーLED(WS2812B)にスイッチで制御するプログラムコード

次に、プログラムを書きましょう。書くべきプログラムは下のとおりです。

import array, time
from machine import Pin
import rp2

# Configure the number of WS2812 LEDs.
NUM_LEDS = 8
PIN_NUM = 17
brightness = 0.2

@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()


# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))

# 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)])

##########################################################################
def pixels_show():
    dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
    for i,c in enumerate(ar):
        r = int(((c >> 8) & 0xFF) * brightness)
        g = int(((c >> 16) & 0xFF) * brightness)
        b = int((c & 0xFF) * brightness)
        dimmer_ar[i] = (g<<16) + (r<<8) + b
    sm.put(dimmer_ar, 8)
    time.sleep_ms(10)

def pixels_set(i, color):
    ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]

def pixels_fill(color):
    for i in range(len(ar)):
        pixels_set(i, color)

def color_chase(color, wait):
    for i in range(NUM_LEDS):
        pixels_set(i, color)
        time.sleep(wait)
        pixels_show()
    time.sleep(0.2)
 
def wheel(pos):
    # Input a value 0 to 255 to get a color value.
    # The colours are a transition r - g - b - back to r.
    if pos < 0 or pos > 255:
        return (0, 0, 0)
    if pos < 85:
        return (255 - pos * 3, pos * 3, 0)
    if pos < 170:
        pos -= 85
        return (0, 255 - pos * 3, pos * 3)
    pos -= 170
    return (pos * 3, 0, 255 - pos * 3)
 
 
def rainbow_cycle(wait):
    for j in range(255):
        for i in range(NUM_LEDS):
            rc_index = (i * 256 // NUM_LEDS) + j
            pixels_set(i, wheel(rc_index & 255))
        pixels_show()
        time.sleep(wait)

def select_led(p):
    global cnt
    cnt += 1
    
    if cnt%3 == 0:
        print("fills")
        for color in COLORS:       
            pixels_fill(color)
            pixels_show()
            time.sleep(0.2) 
    
    if cnt%3 == 1:
        print("chases")
        for color in COLORS:       
            color_chase(color, 0.01)
    
    if cnt%3 == 2:
        print("rainbow")
        rainbow_cycle(0)
    
    pixels_fill(BLACK)
    pixels_show()

#色の設定
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255) 
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)

#タクトスイッチの設定
SW_PIN = 15

sw = Pin(SW_PIN, Pin.IN, Pin.PULL_DOWN)
sw.irq(trigger = Pin.IRQ_RISING, handler = select_led)
cnt = 0

while True:
    time.sleep(0.5)
    print(cnt) 

上のコードの中で、背景が少し色の違う81~102行目と116~125行目が今回新しく出てきた記述です。そのほかは前回までとおなじなので、よく見比べながら適切な場所に入力してください。また、不要なコードを削除してください。

一回で出来上がるメンバーはいませんでした。やはり入力ミスが多いのです。「b」を「d」と入力したり、「Pin」を「pin」と入力したり。結局エラーの解析に時間がかかっています。もう少し短いコードで練習しようかな。

ちなみに、このプログラムは仕様上おかしなところがあります。あえて答えを書きませんので、解析してみてください。