Skip to content

Commit 58cdc85

Browse files
committed
stellar: add encoder wheel demo
1 parent 6b67f65 commit 58cdc85

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

micropython/examples/stellar_unicorn/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
- [NumPy Examples](#numpy-examples)
2424
- [Other Examples](#other-examples)
2525
- [CO2](#co2)
26+
- [Encoder Wheel](#encoder-wheel)
2627
- [Launch (Demo Reel)](#launch-demo-reel)
2728

2829
## About Stellar Unicorn
@@ -187,6 +188,11 @@ Add a [SCD41 sensor breakout](https://shop.pimoroni.com/products/scd41-co2-senso
187188

188189
This example uses a custom tiny bitmap font, find 3x5.bitmapfont in [fonts](../../common/fonts) and copy it to your Pico W.
189190

191+
### Encoder Wheel
192+
[encoder_wheel.py](encoder_wheel.py)
193+
194+
This example uses [RGB Encoder Wheel breakout](https://shop.pimoroni.com/products/rgb-encoder-wheel-breakout) to make an RGB colour picker. Use the encoder wheel to pick a hue and view the RGB breakdown of that colour on the Unicorn display (you can adjust saturation and brightness using the buttons on the breakout too).
195+
190196
### Launch (Demo Reel)
191197

192198
[launch](launch)
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import time
2+
from pimoroni_i2c import PimoroniI2C
3+
from pimoroni import BREAKOUT_GARDEN_I2C_PINS
4+
from breakout_encoder_wheel import BreakoutEncoderWheel, UP, DOWN, LEFT, RIGHT, CENTRE, NUM_LEDS
5+
from stellar import StellarUnicorn
6+
from picographics import PicoGraphics, DISPLAY_STELLAR_UNICORN
7+
8+
"""
9+
Create a colour wheel on the Encoder Wheel's LED ring, and use all functions of the wheel to interact with it.
10+
Draw bars on the Unicorn to represent the currently selected RGB value
11+
12+
13+
Rotate the wheel to select a Hue
14+
Press the up direction to increase Brightness
15+
Press the down direction to decrease Brightness
16+
Press the left direction to decrease Saturation
17+
Press the right direction to increase Saturation
18+
Press the centre to hide the selection marker
19+
20+
Press Ctrl+C to stop the program.
21+
"""
22+
23+
# Constants
24+
BRIGHTNESS_STEP = 0.01 # How much to increase or decrease the brightness each update
25+
SATURATION_STEP = 0.01 # How much to increase or decrease the saturation each update
26+
UPDATES = 50 # How many times to update the LEDs per second
27+
UPDATE_RATE_US = 1000000 // UPDATES
28+
29+
# Create a new BreakoutEncoderWheel
30+
i2c = PimoroniI2C(**BREAKOUT_GARDEN_I2C_PINS)
31+
wheel = BreakoutEncoderWheel(i2c)
32+
33+
# Set up the Unicron
34+
su = StellarUnicorn()
35+
su.set_brightness(1.0)
36+
graphics = PicoGraphics(DISPLAY_STELLAR_UNICORN)
37+
38+
# Variables
39+
brightness = 1.0
40+
saturation = 1.0
41+
position = 0
42+
changed = True
43+
last_centre_pressed = False
44+
45+
46+
# From CPython Lib/colorsys.py
47+
def hsv_to_rgb(h, s, v):
48+
if s == 0.0:
49+
return v, v, v
50+
i = int(h * 6.0)
51+
f = (h * 6.0) - i
52+
p = v * (1.0 - s)
53+
q = v * (1.0 - s * f)
54+
t = v * (1.0 - s * (1.0 - f))
55+
i = i % 6
56+
if i == 0:
57+
return v, t, p
58+
if i == 1:
59+
return q, v, p
60+
if i == 2:
61+
return p, v, t
62+
if i == 3:
63+
return p, q, v
64+
if i == 4:
65+
return t, p, v
66+
if i == 5:
67+
return v, p, q
68+
69+
70+
# Simple function to clamp a value between 0.0 and 1.0
71+
def clamp01(value):
72+
return max(min(value, 1.0), 0.0)
73+
74+
75+
# Sleep until a specific time in the future. Use this instead of time.sleep() to correct for
76+
# inconsistent timings when dealing with complex operations or external communication
77+
def sleep_until(end_time):
78+
time_to_sleep = time.ticks_diff(end_time, time.ticks_us())
79+
if time_to_sleep > 0:
80+
time.sleep_us(time_to_sleep)
81+
82+
83+
while True:
84+
# Record the start time of this loop
85+
start_time = time.ticks_us()
86+
87+
# If up is pressed, increase the brightness
88+
if wheel.pressed(UP):
89+
brightness += BRIGHTNESS_STEP
90+
changed = True # Trigger a change
91+
92+
# If down is pressed, decrease the brightness
93+
if wheel.pressed(DOWN):
94+
brightness -= BRIGHTNESS_STEP
95+
changed = True # Trigger a change
96+
97+
# If right is pressed, increase the saturation
98+
if wheel.pressed(RIGHT):
99+
saturation += SATURATION_STEP
100+
changed = True # Trigger a change
101+
102+
# If left is pressed, decrease the saturation
103+
if wheel.pressed(LEFT):
104+
saturation -= SATURATION_STEP
105+
changed = True # Trigger a change
106+
107+
# Limit the brightness and saturation between 0.0 and 1.0
108+
brightness = clamp01(brightness)
109+
saturation = clamp01(saturation)
110+
111+
# Check if the encoder has been turned
112+
if wheel.delta() != 0:
113+
# Update the position based on the count change
114+
position = wheel.step()
115+
changed = True # Trigger a change
116+
117+
# If centre is pressed, trigger a change
118+
centre_pressed = wheel.pressed(CENTRE)
119+
if centre_pressed != last_centre_pressed:
120+
changed = True
121+
last_centre_pressed = centre_pressed
122+
123+
# Was a change triggered?
124+
if changed:
125+
# Print the colour at the current hue, saturation, and brightness
126+
r, g, b = [int(c * 255) for c in hsv_to_rgb(position / NUM_LEDS, saturation, brightness)]
127+
128+
# Set the LED at the current position to either the actual colour,
129+
# or an inverted version to show a "selection marker"
130+
if centre_pressed:
131+
wheel.set_rgb(position, r, g, b)
132+
else:
133+
wheel.set_rgb(position, 255, 255, 255)
134+
135+
# Set the LEDs below the current position
136+
for i in range(0, position):
137+
wheel.set_hsv(i, i / NUM_LEDS, saturation, brightness)
138+
139+
# Set the LEDs after the current position
140+
for i in range(position + 1, NUM_LEDS):
141+
wheel.set_hsv(i, i / NUM_LEDS, saturation, brightness)
142+
wheel.show()
143+
changed = False
144+
145+
# set unicron
146+
graphics.set_pen(graphics.create_pen(0, 0, 0))
147+
graphics.clear()
148+
# draw background
149+
graphics.set_pen(graphics.create_pen(30, 30, 30))
150+
graphics.rectangle(0, 1, 16, 4)
151+
graphics.rectangle(0, 6, 16, 4)
152+
graphics.rectangle(0, 11, 16, 4)
153+
# draw bars
154+
graphics.set_pen(graphics.create_pen(r, g, b))
155+
graphics.rectangle(0, 1, int(r / 255 * 16), 4)
156+
graphics.rectangle(0, 6, int(g / 255 * 16), 4)
157+
graphics.rectangle(0, 11, int(b / 255 * 16), 4)
158+
# draw labels
159+
graphics.set_pen(graphics.create_pen(255, 0, 0))
160+
graphics.rectangle(0, 1, 1, 4)
161+
graphics.set_pen(graphics.create_pen(0, 255, 0))
162+
graphics.rectangle(0, 6, 1, 4)
163+
graphics.set_pen(graphics.create_pen(0, 0, 255))
164+
graphics.rectangle(0, 11, 1, 4)
165+
su.update(graphics)
166+
167+
# Sleep until the next update, accounting for how long the above operations took to perform
168+
sleep_until(time.ticks_add(start_time, UPDATE_RATE_US))

0 commit comments

Comments
 (0)