import time import spidev import wiringpi # 0码 t0H 220ns~380ns # (python 中GPIO口无法翻转这么快,python 可能执行一行代码需要800ns) # ws2812 波特率如果设置为800kHZ, 1/0.8M=1.25us (0码或者1码所需要的时间) # 使用SPI产生ws2812时序,产生1码和0码,则可以使用传输一个byte 来代表一个0码或者1码,如下: # 1111 1000 0xF8 #1码 高电平时间长,低电平时间短 # 1100 0000 0xC0 #0码 高电平时间短,低电平时间长 # 则得出SPI 波特率应该设置为800K*8 sig_1 = 0xf8 sig_0 = 0xc0 def flatten_arrays(arrays): return [element for sublist in arrays for element in sublist] class WS2812: def __init__(self, led_num=1): self.led_num = led_num self.ws2812_data = [[sig_0 for _ in range(24)] for _ in range(led_num)] spi = spidev.SpiDev() # 设置一下下拉,否则第一盏灯的时序可能不正确 wiringpi.wiringPiSetup() wiringpi.pullUpDnControl(11, 1) spi.open(0, 0) spi.max_speed_hz = 6400000 spi.mode = 0 self.spi = spi def ws2812_send_data(self): default_tx = self.ws2812_data self.spi.xfer2(bytes(flatten_arrays(default_tx))) def ws2812_light_led(self, red, green, blue, pix_led): default_tx = self.ws2812_data color = green << 16 | red << 8 | blue for i in range(24): if color >> (24 - i - 1) & 1: default_tx[pix_led][i] = sig_1 else: default_tx[pix_led][i] = sig_0 def ws2812_light_one_led(self, red, green, blue, pix_led): self.ws2812_light_led(red, green, blue, pix_led) self.ws2812_send_data() def ws2812_light_all_led(self, red, green, blue): for i in range(self.led_num): self.ws2812_light_led(red, green, blue, i) self.ws2812_send_data() def ws2812_rainbow(self): colors = [[0xff, 0, 0], [0, 0xff, 0], [0, 0, 0xff]] for i in range(self.led_num): cur_color = colors[i % 3] self.ws2812_light_led(cur_color[0], cur_color[1], cur_color[2], i) self.ws2812_send_data() def ws2812_water_lamp(self, red, green, blue, interval_time): self.ws2812_shutoff_all() for i in range(self.led_num): self.ws2812_light_one_led(red, green, blue, i) time.sleep(interval_time) self.ws2812_shutoff_all() def ws2812_shutoff_led(self, n): self.ws2812_light_led(0, 0, 0, n) self.ws2812_send_data() def ws2812_shutoff_all(self): for i in range(self.led_num): self.ws2812_light_led(0, 0, 0, i) self.ws2812_send_data() if __name__ == '__main__': ws2812 = WS2812(8) while True: ws2812.ws2812_light_all_led(0, 0, 0xff) time.sleep(0.5) ws2812.ws2812_light_all_led(0xff, 0, 0) time.sleep(0.5) ws2812.ws2812_light_all_led(0, 0xff, 0) time.sleep(0.5) # ws2812.ws2812_water_lamp(0xff, 0, 0, 0.2) # time.sleep(0.5)