NeoPixel
- 端子
pin | 内容 |
---|---|
S | 信号線 |
V | 電源 |
G | グランド |
-
動作
-
GP16を信号線として使う
-
8000000(8MHZ)= 125 nsec
-
0 の場合
- H: 220ns~380ns
- L: 580ns~1µs
-
1 の場合
- H: 580ns~1µs
- L: 580ns~1µs
-
RESET の場合
- L: 280ns以上
-
上位ビットからGRBの8x3=24ビット
-
-
06.1_Neopixel/06.1_Neopixel.py
06.1_Neopixel.py
import time
from machine import Pin
from neopixel import myNeopixel
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
white = (255, 255, 255)
close = (0, 0, 0)
COLORS = [red, green, blue, white, close]
NUM_LEDS = 8
np = myNeopixel(NUM_LEDS, 16)
np.brightness(10) #brightness: 0 ~ 255
while True:
for color in COLORS:
np.fill(color[0], color[1], color[2])
np.show()
time.sleep(0.5)
neopixel.py
import array, time
from machine import Pin
import rp2
#PIO を使って表示する
@rp2.asm_pio(
sideset_init=rp2.PIO.OUT_LOW, # サイドセットの初期値はLOW
out_shiftdir=rp2.PIO.SHIFT_LEFT, # MSBから書き出す
autopull=True, # 24bitを超えたら自動的にpullする
pull_thresh=24
)
def ws2812():
T1 = 2 # 250 nsec
T2 = 5 # 625 nsec
T3 = 8 # 1 μsec
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1] # reset = 1μsec Lowにする
jmp(not_x, "do_zero") .side(1) [T1 - 1] # 250nsec Highにする
jmp("bitloop") .side(1) [T2 - 1] # 値1の場合、+625nsec(計875nsec) Highにする
label("do_zero")
nop() .side(0) [T2 - 1] # 値0の場合、625nsec Lowにする
wrap
class myNeopixel:
def __init__(self, num_leds, pin, delay_ms=1):
self.pixels = array.array("I", [0 for _ in range(num_leds)])
self.state_machine = 0
self.sm = rp2.StateMachine(
self.state_machine,
ws2812,
freq=8000000,
sideset_base=Pin(pin)
)
self.sm.active(1)
self.num_leds = num_leds
self.delay_ms = delay_ms
self.brightnessvalue = 255
def brightness(self, brightness = None):
if brightness == None:
return self.brightnessvalue
else:
if (brightness < 1):
brightness = 1
if (brightness > 255):
brightness = 255
self.brightnessvalue = brightness
def set_pixel_line_gradient(self, pixel1, pixel2, left_r, left_g, left_b, right_r, right_g, right_b):
if pixel2 - pixel1 == 0: return
right_pixel = max(pixel1, pixel2)
left_pixel = min(pixel1, pixel2)
for i in range(right_pixel - left_pixel + 1):
fraction = i / (right_pixel - left_pixel)
red = round((right_r - left_r) * fraction + left_r)
green = round((right_g - left_g) * fraction + left_g)
blue = round((right_b - left_b) * fraction + left_b)
self.set_pixel(left_pixel + i, red, green, blue)
def set_pixel_line(self, pixel1, pixel2, r, g, b):
for i in range(pixel1, pixel2+1):
self.set_pixel(i, r, g, b)
def set_pixel(self, pixel_num, r, g, b):
blue = round(b * (self.brightness() / 255))
red = round(r * (self.brightness() / 255))
green = round(g * (self.brightness() / 255))
self.pixels[pixel_num] = blue | red << 8 | green << 16
def rotate_left(self, num_of_pixels):
if num_of_pixels == None:
num_of_pixels = 1
self.pixels = self.pixels[num_of_pixels:] + self.pixels[:num_of_pixels]
def rotate_right(self, num_of_pixels):
if num_of_pixels == None:
num_of_pixels = 1
num_of_pixels = -1 * num_of_pixels
self.pixels = self.pixels[num_of_pixels:] + self.pixels[:num_of_pixels]
def show(self):
for i in range(self.num_leds):
self.sm.put(self.pixels[i],8) # ワードは32ビットで24ビットしか使わないので8ビットシフトして渡す
time.sleep_ms(self.delay_ms)
def fill(self, r, g, b):
for i in range(self.num_leds):
self.set_pixel(i, r, g, b)
time.sleep_ms(self.delay_ms)