Skip to content

Commit 5865350

Browse files
authored
Merge pull request #576 from bitcraze/rik/hprgbw
Add LED Deck Example Scripts
2 parents 6d96620 + 4f2a4ed commit 5865350

File tree

3 files changed

+345
-0
lines changed

3 files changed

+345
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# ,---------, ____ _ __
4+
# | ,-^-, | / __ )(_) /_______________ _____ ___
5+
# | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
6+
# | / ,--' | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
7+
# +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
8+
#
9+
# Copyright (C) 2025 Bitcraze AB
10+
#
11+
# This program is free software: you can redistribute it and/or modify
12+
# it under the terms of the GNU General Public License as published by
13+
# the Free Software Foundation, in version 3.
14+
#
15+
# This program is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
import time
23+
24+
import cflib.crtp
25+
from cflib.crazyflie import Crazyflie
26+
from cflib.crazyflie.log import LogConfig
27+
from cflib.crazyflie.syncCrazyflie import SyncCrazyflie
28+
from cflib.utils import uri_helper
29+
30+
# URI to the Crazyflie to connect to
31+
URI = uri_helper.uri_from_env(default='radio://0/80/2M/E7E7E7E7E7')
32+
33+
34+
class wrgb:
35+
def __init__(self, w: int, r: int, g: int, b: int):
36+
self.w = w
37+
self.r = r
38+
self.g = g
39+
self.b = b
40+
41+
42+
class hsv:
43+
def __init__(self, h: int, s: int, v: int):
44+
self.h = h
45+
self.s = s
46+
self.v = v
47+
48+
49+
def hsv_to_wrgb(input: hsv) -> wrgb:
50+
h, s, v = input.h, input.s / 255.0, input.v / 255.0
51+
52+
if s == 0:
53+
r = g = b = v
54+
else:
55+
h = h / 60.0
56+
i = int(h)
57+
f = h - i
58+
p = v * (1.0 - s)
59+
q = v * (1.0 - s * f)
60+
t = v * (1.0 - s * (1.0 - f))
61+
62+
if i == 0:
63+
r, g, b = v, t, p
64+
elif i == 1:
65+
r, g, b = q, v, p
66+
elif i == 2:
67+
r, g, b = p, v, t
68+
elif i == 3:
69+
r, g, b = p, q, v
70+
elif i == 4:
71+
r, g, b = t, p, v
72+
else:
73+
r, g, b = v, p, q
74+
75+
return wrgb(0, int(r * 255), int(g * 255), int(b * 255))
76+
77+
78+
def cycle_colors(step: int) -> wrgb:
79+
h = step % 360
80+
s = 255
81+
v = 255
82+
return hsv_to_wrgb(hsv(h, s, v))
83+
84+
85+
def pack_wrgb(input: wrgb) -> int:
86+
"""Pack WRGB values into uint32 format: 0xWWRRGGBB"""
87+
return (input.w << 24) | (input.r << 16) | (input.g << 8) | input.b
88+
89+
90+
if __name__ == '__main__':
91+
# Initialize the low-level drivers
92+
cflib.crtp.init_drivers()
93+
94+
with SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) as scf:
95+
cf = scf.cf
96+
97+
# Thermal status callback
98+
def thermal_status_callback(timestamp, data, logconf):
99+
throttle_pct = data['colorled.throttlePct']
100+
if throttle_pct > 0:
101+
temp = data['colorled.deckTemp']
102+
print(f'WARNING: Thermal throttling active! Temp: {temp}°C, Throttle: {throttle_pct}%')
103+
104+
# Setup log configuration for thermal monitoring
105+
log_conf = LogConfig(name='ThermalStatus', period_in_ms=100)
106+
log_conf.add_variable('colorled.deckTemp', 'uint8_t')
107+
log_conf.add_variable('colorled.throttlePct', 'uint8_t')
108+
109+
cf.log.add_config(log_conf)
110+
log_conf.data_received_cb.add_callback(thermal_status_callback)
111+
log_conf.start()
112+
113+
# Brightness correction: balances luminance across W/R/G/B channels
114+
# Set to 1 (enabled, default) for perceptually uniform colors
115+
# Set to 0 (disabled) for maximum brightness per channel
116+
cf.param.set_value('colorled.brightnessCorr', 1)
117+
time.sleep(0.1)
118+
119+
try:
120+
print('Cycling through colors. Press Ctrl-C to stop.')
121+
while True:
122+
for i in range(0, 360, 1):
123+
color: wrgb = cycle_colors(i)
124+
# print(color.r, color.g, color.b)
125+
color_uint32 = pack_wrgb(color)
126+
cf.param.set_value('colorled.wrgb8888', str(color_uint32))
127+
time.sleep(0.01)
128+
except KeyboardInterrupt:
129+
print('\nStopping and turning off LED...')
130+
cf.param.set_value('colorled.wrgb8888', '0')
131+
time.sleep(0.1)
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# ,---------, ____ _ __
4+
# | ,-^-, | / __ )(_) /_______________ _____ ___
5+
# | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
6+
# | / ,--' | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
7+
# +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
8+
#
9+
# Copyright (C) 2025 Bitcraze AB
10+
#
11+
# This program is free software: you can redistribute it and/or modify
12+
# it under the terms of the GNU General Public License as published by
13+
# the Free Software Foundation, in version 3.
14+
#
15+
# This program is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
import time
23+
24+
import cflib.crtp
25+
from cflib.crazyflie import Crazyflie
26+
from cflib.crazyflie.log import LogConfig
27+
from cflib.crazyflie.syncCrazyflie import SyncCrazyflie
28+
from cflib.utils import uri_helper
29+
30+
# URI to the Crazyflie to connect to
31+
URI = uri_helper.uri_from_env(default='radio://0/80/2M/E7E7E7E7E7')
32+
33+
34+
class wrgb:
35+
def __init__(self, w: int, r: int, g: int, b: int):
36+
self.w = w
37+
self.r = r
38+
self.g = g
39+
self.b = b
40+
41+
42+
class rgb:
43+
def __init__(self, r: int, g: int, b: int):
44+
self.w = min(r, g, b)
45+
self.r = r - self.w
46+
self.g = g - self.w
47+
self.b = b - self.w
48+
49+
50+
def pack_wrgb(input: wrgb | rgb) -> int:
51+
"""Pack WRGB values into uint32 format: 0xWWRRGGBB"""
52+
return (input.w << 24) | (input.r << 16) | (input.g << 8) | input.b
53+
54+
55+
if __name__ == '__main__':
56+
# Initialize the low-level drivers
57+
cflib.crtp.init_drivers()
58+
59+
with SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) as scf:
60+
cf = scf.cf
61+
62+
# Thermal status callback
63+
def thermal_status_callback(timestamp, data, logconf):
64+
throttle_pct = data['colorled.throttlePct']
65+
if throttle_pct > 0:
66+
temp = data['colorled.deckTemp']
67+
print(f'WARNING: Thermal throttling active! Temp: {temp}°C, Throttle: {throttle_pct}%')
68+
69+
# Setup log configuration for thermal monitoring
70+
log_conf = LogConfig(name='ThermalStatus', period_in_ms=100)
71+
log_conf.add_variable('colorled.deckTemp', 'uint8_t')
72+
log_conf.add_variable('colorled.throttlePct', 'uint8_t')
73+
74+
cf.log.add_config(log_conf)
75+
log_conf.data_received_cb.add_callback(thermal_status_callback)
76+
log_conf.start()
77+
78+
# Brightness correction: balances luminance across R/G/B/W channels
79+
# Set to 1 (enabled, default) for perceptually uniform colors
80+
# Set to 0 (disabled) for maximum brightness per channel
81+
cf.param.set_value('colorled.brightnessCorr', 1)
82+
time.sleep(0.1)
83+
84+
try:
85+
# ========================================
86+
# Set your desired color here:
87+
# ========================================
88+
# Examples:
89+
# color = wrgb(w=0, r=255, g=0, b=0) # Pure red
90+
# color = wrgb(w=0, r=0, g=255, b=0) # Pure green
91+
# color = wrgb(w=0, r=0, g=0, b=255) # Pure blue
92+
# color = wrgb(w=255, r=0, g=0, b=0) # Pure white LED
93+
# color = wrgb(w=50, r=255, g=128, b=0) # Orange + white
94+
# color = rgb(r=255, g=255, b=255) # White (auto W extraction)
95+
96+
color = wrgb(w=0, r=255, g=0, b=100)
97+
# ========================================
98+
99+
color_uint32 = pack_wrgb(color)
100+
cf.param.set_value('colorled.wrgb8888', color_uint32)
101+
time.sleep(0.01)
102+
print(f'Setting LED to R={color.r}, G={color.g}, B={color.b}, W={color.w}')
103+
print('Press Ctrl-C to turn off LED and exit.')
104+
while True:
105+
time.sleep(0.1)
106+
except KeyboardInterrupt:
107+
print('\nStopping and turning off LED...')
108+
cf.param.set_value('colorled.wrgb8888', 0)
109+
time.sleep(0.1)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# -*- coding: utf-8 -*-
2+
#
3+
# ,---------, ____ _ __
4+
# | ,-^-, | / __ )(_) /_______________ _____ ___
5+
# | ( O ) | / __ / / __/ ___/ ___/ __ `/_ / / _ \
6+
# | / ,--' | / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
7+
# +------` /_____/_/\__/\___/_/ \__,_/ /___/\___/
8+
#
9+
# Copyright (C) 2025 Bitcraze AB
10+
#
11+
# This program is free software: you can redistribute it and/or modify
12+
# it under the terms of the GNU General Public License as published by
13+
# the Free Software Foundation, in version 3.
14+
#
15+
# This program is distributed in the hope that it will be useful,
16+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
# GNU General Public License for more details.
19+
#
20+
# You should have received a copy of the GNU General Public License
21+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
import time
23+
24+
import cflib.crtp
25+
from cflib.crazyflie import Crazyflie
26+
from cflib.crazyflie.syncCrazyflie import SyncCrazyflie
27+
from cflib.utils import uri_helper
28+
29+
# URI to the Crazyflie to connect to
30+
URI = uri_helper.uri_from_env(default='radio://0/80/2M/E7E7E7E7E7')
31+
32+
33+
class rgb:
34+
def __init__(self, r: int, g: int, b: int):
35+
self.r = r
36+
self.g = g
37+
self.b = b
38+
39+
40+
class hsv:
41+
def __init__(self, h: int, s: int, v: int):
42+
self.h = h
43+
self.s = s
44+
self.v = v
45+
46+
47+
def hsv_to_rgb(input: hsv) -> rgb:
48+
h, s, v = input.h, input.s / 255.0, input.v / 255.0
49+
50+
if s == 0:
51+
r = g = b = v
52+
else:
53+
h = h / 60.0
54+
i = int(h)
55+
f = h - i
56+
p = v * (1.0 - s)
57+
q = v * (1.0 - s * f)
58+
t = v * (1.0 - s * (1.0 - f))
59+
60+
if i == 0:
61+
r, g, b = v, t, p
62+
elif i == 1:
63+
r, g, b = q, v, p
64+
elif i == 2:
65+
r, g, b = p, v, t
66+
elif i == 3:
67+
r, g, b = p, q, v
68+
elif i == 4:
69+
r, g, b = t, p, v
70+
else:
71+
r, g, b = v, p, q
72+
73+
return rgb(int(r * 255), int(g * 255), int(b * 255))
74+
75+
76+
def cycle_colors(step: int) -> rgb:
77+
h = step % 360
78+
s = 255
79+
v = 255
80+
return hsv_to_rgb(hsv(h, s, v))
81+
82+
83+
def construct_uint32_color(input: rgb) -> int:
84+
return (input.r << 16) | (input.g << 8) | input.b
85+
86+
87+
if __name__ == '__main__':
88+
# Initialize the low-level drivers
89+
cflib.crtp.init_drivers()
90+
91+
with SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) as scf:
92+
cf = scf.cf
93+
94+
try:
95+
print('Cycling through colors. Press Ctrl-C to stop.')
96+
while True:
97+
for i in range(0, 360, 1):
98+
color = cycle_colors(i)
99+
color_uint32 = construct_uint32_color(color)
100+
cf.param.set_value('led_deck_ctrl.rgb888', str(color_uint32))
101+
time.sleep(0.01)
102+
except KeyboardInterrupt:
103+
print('\nStopping and turning off LED...')
104+
cf.param.set_value('led_deck_ctrl.rgb888', '0')
105+
time.sleep(0.1)

0 commit comments

Comments
 (0)