Skip to content

Commit ed54295

Browse files
Sodapop465Hermanoidyameatmeyourdead
authored
Led strip (#58)
* Import lovely WS2812 library for Jetson from random github man * Implemented WS2812 and it builds * Hopefully fixed runtime errors, needs actual testing * Added off function and brightness control * Add customizable spi bus and device to WS2812 library * Add HSV rainbow cycle, implemented hermanoid's changes * Rainbow cycle precalculations, limit the brightness * Rainbow and other animations loop, smoother rainbow, boot up animation * New library for new RGB strip * Used new library in led_controller node * Testing needed, Fixed RGB to RGBW scaling, threading, pulse anim, solid anim, off anim * Fixed timing * Fixed color of new LEDs * Added Ring and Strip support * Corrected number of LEDs in ring --------- Co-authored-by: Lucas Niewohner <lucasniewohner@gmail.com> Co-authored-by: Zac Stanton <zac71113@gmail.com>
1 parent abb6ac6 commit ed54295

6 files changed

Lines changed: 506 additions & 237 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import spidev
2+
import sys
3+
import time
4+
5+
class SPItoSK():
6+
def __init__(self, numLeds, bus = 1, device = 0):
7+
self.ledCount = numLeds
8+
self.ledBrightness = 1.0
9+
self.spi = spidev.SpiDev()
10+
self.spi.open(bus, device)
11+
self.spi.max_speed_hz = 2500000
12+
# string of bits to send to spi
13+
self.binMsg = 0b100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100
14+
for i in range(numLeds - 1):
15+
# 96 bits per led, 3 bits per real bit
16+
self.binMsg = (self.binMsg << 96) | 0b100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100
17+
18+
def __del__(self):
19+
self.spi.close()
20+
print("destructor")
21+
22+
def set_LED_color(self, ledNum, R, G, B, W):
23+
"""
24+
Adjust self.binMsg to the color desired
25+
:param ledNum: the led to change starting with index 0
26+
:param R, G, B, W: RGBW values from 0-255
27+
"""
28+
if (R > 255) or (G > 255) or (B > 255) or (W > 255) or (R < 0) or (G < 0) or (B < 0) or (W < 0):
29+
print("RGBW values must be in the range 0-255")
30+
sys.exit(-1)
31+
msgStartPos = (ledNum * 96) + 2
32+
# Set G in binary message
33+
self._formatBinMsg(msgStartPos, int(round(G * self.ledBrightness)))
34+
# Set R in binary message
35+
self._formatBinMsg(msgStartPos + 24, int(round(R * self.ledBrightness)))
36+
# Set B in binary message
37+
self._formatBinMsg(msgStartPos + (24 * 2), int(round(B * self.ledBrightness)))
38+
# Set W in binary message
39+
self._formatBinMsg(msgStartPos + (24 * 3), int(round(W * self.ledBrightness)))
40+
41+
# debug
42+
# print("led_num: %d, R: %d G: %d B: %d W: %d" % (ledNum, round(R * self.ledBrightness), round(G * self.ledBrightness), round(B * self.ledBrightness), round(W * self.ledBrightness)))
43+
44+
def LED_show(self):
45+
"""
46+
Signals the LEDs
47+
"""
48+
bytesToSend = []
49+
binMsgCpy = self.binMsg
50+
while binMsgCpy:
51+
bytesToSend.insert(0, binMsgCpy & ((1 << 8) - 1)) # Extract lowest 8 bits
52+
binMsgCpy >>= 8 # Shift right by 8 bits
53+
54+
self.spi.xfer3(bytesToSend, 2500000, 0, 8)
55+
56+
# debug
57+
# print(bin(self.binMsg))
58+
# offString = 100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100
59+
# print()
60+
# for i in bytesToSend:
61+
# print(bin(i))
62+
# time.sleep(80e-6)
63+
64+
def set_brightness(self, brightness):
65+
"""
66+
Set the global brightness of LEDs
67+
:param brightness: Brightness of LEDs 0-1, clamps if values are outside the range
68+
"""
69+
brightness = max(0.0, min(brightness, 1.0))
70+
self.ledBrightness = brightness
71+
72+
def LED_OFF_ALL(self):
73+
"""
74+
Turns off LEDs
75+
"""
76+
self.binMsg = 0b100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100
77+
for i in range(self.ledCount - 1):
78+
# 96 bits per led, 3 bits per real bit
79+
self.binMsg = (self.binMsg << 96) | 0b100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100100
80+
self.LED_show()
81+
82+
def _formatBinMsg(self, startPos, colorNum):
83+
number = format(colorNum, '08b')
84+
for i in range(8):
85+
msgIndexPos = startPos + (3 * i)
86+
colorBit = number[i]
87+
if (colorBit == "0") and bin(self.binMsg)[msgIndexPos:msgIndexPos + 3] == "110":
88+
self._flipBit(msgIndexPos)
89+
elif (colorBit == "1") and bin(self.binMsg)[msgIndexPos:msgIndexPos + 3] == "100":
90+
self._flipBit(msgIndexPos)
91+
92+
def _flipBit(self, position):
93+
mask = 1 << len(bin(self.binMsg)[2:]) - position
94+
self.binMsg = self.binMsg ^ mask
95+
96+
97+
if __name__ == "__main__":
98+
ledStrip = SPItoSK(1)
99+
ledStrip.set_LED_color(0, 255, 255, 255, 255)
100+
ledStrip.LED_show()
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# lifted from this lovely repo: https://github.com/seitomatsubara/Jetson-nano-WS2812-LED-
2+
3+
import spidev
4+
import sys
5+
6+
class SPItoWS():
7+
def __init__(self, ledc, bus=1, device=0):
8+
self.led_count = ledc
9+
self.X = '' # X is signal of WS281x
10+
for i in range(self.led_count):
11+
self.X = self.X + "100100100100100100100100100100100100100100100100100100100100100100100100"
12+
self.led_brightness = 1.0
13+
self.spi = spidev.SpiDev()
14+
self.spi.open(bus, device)
15+
self.spi.max_speed_hz = 2400000
16+
17+
def __del__(self):
18+
self.spi.close()
19+
print("destructor")
20+
21+
def _Bytesto3Bytes(self, num, RGB): # num is number of signal, RGB is 8 bits (1 byte) str
22+
for i in range(8):
23+
if RGB[i] == '0':
24+
self.X = self.X[:num * 3 * 8 + i * 3] + '100' + self.X[num * 3 * 8 + i * 3 + 3:]
25+
elif RGB[i] == '1':
26+
self.X = self.X[:num * 3 * 8 + i * 3] + '110' + self.X[num * 3 * 8 + i * 3 + 3:]
27+
28+
def _BytesToHex(self, Bytes):
29+
return ''.join(["0x%02X " % x for x in Bytes]).strip()
30+
31+
def LED_show(self):
32+
Y = []
33+
for i in range(self.led_count * 9):
34+
Y.append(int(self.X[i*8:(i+1)*8],2))
35+
WS = self._BytesToHex(Y)
36+
self.spi.xfer3(Y, 2400000,0,8)
37+
38+
def set_LED_color(self, led_num, R, G, B):
39+
if (R > 255 or G > 255 or B > 255):
40+
print("Invalid Value: RGB is over 255\n")
41+
sys.exit(1)
42+
if (led_num > self.led_count - 1):
43+
print("Invalid Value: The number is over the number of LED")
44+
sys.exit(1)
45+
RR = format(round(R * self.led_brightness), '08b')
46+
GG = format(round(G * self.led_brightness), '08b')
47+
BB = format(round(B * self.led_brightness), '08b')
48+
self._Bytesto3Bytes(led_num * 3, GG)
49+
self._Bytesto3Bytes(led_num * 3 + 1, RR)
50+
self._Bytesto3Bytes(led_num * 3 + 2, BB)
51+
52+
# debug
53+
# print("led_num: %d, R: %d G: %d B: %d" % (led_num, round(R * self.led_brightness), round(G * self.led_brightness), round(B * self.led_brightness)))
54+
55+
def LED_OFF_ALL(self):
56+
self.X = ''
57+
for i in range(self.led_count):
58+
self.X = self.X + "100100100100100100100100100100100100100100100100100100100100100100100100"
59+
self.LED_show()
60+
61+
def set_brightness(self, brightness):
62+
self.led_brightness = brightness
63+
64+
65+
if __name__ == "__main__":
66+
import time
67+
LED_COUNT = 3
68+
sig = SPItoWS(LED_COUNT)
69+
sig.RGBto3Bytes(0, 255, 0, 0)
70+
sig.RGBto3Bytes(1, 0, 255, 0)
71+
sig.RGBto3Bytes(2, 0, 0, 255)
72+
sig.LED_show()
73+
time.sleep(1)
74+
sig.LED_OFF_ALL()

0 commit comments

Comments
 (0)