Umfangreiche Anleitung zur Steuerung eines adressierbaren LED-Streifens mit einem Puck-Gerät mittels ESP32 und Python
Erstellen Sie ein vielseitiges LED-Steuerungssystem mit präziser Kontrolle und flexiblen Anpassungsmöglichkeiten
Wichtige Erkenntnisse
- Hardware-Komponenten sorgfältig auswählen und verbinden: Der Erfolg Ihres Projekts hängt maßgeblich von der richtigen Auswahl und korrekten Verbindung der Hardware-Komponenten ab.
- Software-Implementierung mit MicroPython: Nutzen Sie die Flexibilität von MicroPython auf dem ESP32, um eine reaktionsschnelle und erweiterbare Steuerung zu gewährleisten.
- Benutzerfreundliche Interaktion durch den Puck: Durch den Einsatz eines drehbaren Außenrings und eines mittleren Buttons ermöglichen Sie eine intuitive Steuerung der LED-Streifen-Funktionen.
Einführung
Die Steuerung von adressierbaren LED-Streifen mit einem benutzerdefinierten Controller wie einem Puck-Gerät bietet eine spannende Möglichkeit, individuelle Lichtsetzungen zu realisieren. In diesem Leitfaden wird erläutert, wie Sie mit einem ESP32 und Python (MicroPython) eine präzise und flexible Steuerung implementieren können. Der Fokus liegt auf der Verwendung eines Puck-Geräts mit einem drehbaren Außenring und einem zentralen Button, um LEDs einzeln zu steuern und die Breite des Lichtpunkts dynamisch anzupassen.
Hardware-Komponenten und Aufbau
Benötigte Komponenten
- ESP32 Mikrocontroller: Das Herzstück des Systems, das die Steuerung und Kommunikation übernimmt.
- Adressierbarer LED-Streifen (z.B. WS2812B): Ermöglicht die individuelle Steuerung jeder einzelnen LED.
- Puck-Gerät: Ein Hardware-Controller mit einem drehbaren Außenring (Rotary Encoder) und einem zentralen Button zur Eingabe von Befehlen.
- Stromversorgung: Eine zuverlässige 5V Stromquelle zur Versorgung des ESP32 und des LED-Streifens.
- Widerstände und Kondensatoren: Ein 330-Ohm-Widerstand für die Datensicherung und ein 1000 µF Glättungskondensator zur Stabilisierung der Stromversorgung.
- Verbindungskabel und Breadboard: Zum Herstellen der Verbindungen zwischen den Komponenten.
Schaltungsaufbau
Der Aufbau der Hardware erfordert eine präzise Verbindung der einzelnen Komponenten. Folgen Sie diesen Schritten, um eine stabile und funktionale Schaltung zu erstellen:
1. Verbindung des LED-Streifens
- Schließen Sie den Datenpin des WS2812B LED-Streifens an einen GPIO-Pin des ESP32 (z.B. GPIO5) an.
- Setzen Sie einen 330-Ohm-Widerstand in die Datenleitung, um potenzielle Signalstörungen zu minimieren.
- Verbinden Sie die Stromversorgung des LED-Streifens mit der 5V Quelle und GND.
- Platzieren Sie einen 1000 µF Kondensator zwischen 5V und GND nahe dem LED-Streifen, um Spannungsschwankungen zu glätten.
2. Anschluss des Rotary Encoders
- Verbinden Sie die beiden Signalleitungen des Rotary Encoders (CLK und DT) mit den GPIO-Pins des ESP32 (z.B. GPIO18 und GPIO19).
- Schließen Sie die gemeinsame Masseleitung (GND) des Encoders an den GND-Pin des ESP32 an.
3. Anschluss des Buttons
- Schließen Sie den Button an einen weiteren GPIO-Pin des ESP32 (z.B. GPIO23) und an GND an.
4. Stromversorgung sicherstellen
- Stellen Sie sicher, dass sowohl der ESP32 als auch der LED-Streifen ausreichend mit 5V versorgt werden.
- Verwenden Sie eine stabile 5V Quelle mit ausreichender Stromstärke, um die LEDs und den ESP32 gleichzeitig zu betreiben.
Schaltplanübersicht
| Komponente | Verbindung |
|---|---|
| ESP32 GPIO5 | Datenpin des WS2812B LED-Streifens (über 330Ω Widerstand) |
| ESP32 GPIO18 | CLK-Pin des Rotary Encoders |
| ESP32 GPIO19 | DT-Pin des Rotary Encoders |
| ESP32 GPIO23 | Button |
| 5V | LED-Streifen und ESP32 Vcc |
| GND | Alle Komponenten |
Software-Implementierung mit Python
Einführung in MicroPython
MicroPython ist eine schlanke Implementierung von Python 3, die speziell für Mikrocontroller wie den ESP32 entwickelt wurde. Es ermöglicht eine einfache und effiziente Programmierung zur Steuerung der Hardware-Komponenten.
Installation von MicroPython auf dem ESP32
- Laden Sie die neueste Firmware von der offiziellen MicroPython-Website herunter: MicroPython ESP32 Firmware.
- Verbinden Sie den ESP32 mit Ihrem Computer.
- Nutzen Sie ein Tool wie esptool.py zur Installation der Firmware:
- Nach erfolgreicher Installation können Sie über eine serielle Verbindung auf den MicroPython-Interpreter zugreifen.
esptool.py --chip esp32 --port COM3 erase_flash
esptool.py --chip esp32 --port COM3 write_flash -z 0x1000 esp32-xxxxxx.bin
Bibliotheken und Module
Für die Steuerung der LEDs und die Verarbeitung der Eingaben vom Rotary Encoder und dem Button sind spezifische Bibliotheken erforderlich:
- machine: Zum Zugriff auf die GPIO-Pins.
- neopixel: Zur Steuerung der WS2812B LEDs.
- rotary_irq_esp: Für die effiziente Verarbeitung von Rotary Encoder-Ereignissen.
- time: Für Zeitsteuerungen und Verzögerungen.
Beispielcode
Der folgende Code zeigt eine grundlegende Implementierung zur Steuerung des LED-Streifens mit dem Puck-Gerät:
from machine import Pin
import neopixel
import time
from rotary_irq_esp import RotaryIRQ
# Pin-Definitionen
LED_PIN = 5
NUM_LEDS = 60
ENCODER_CLK = 18
ENCODER_DT = 19
BUTTON_PIN = 23
# Initialisierung der LEDs
strip = neopixel.NeoPixel(Pin(LED_PIN), NUM_LEDS)
# Initialisierung des Rotary Encoders
rotary = RotaryIRQ(pin_num_clk=ENCODER_CLK, pin_num_dt=ENCODER_DT, min_val=0, max_val=NUM_LEDS-1, reverse=False, range_mode=RotaryIRQ.RANGE_WRAP)
# Initialisierung des Buttons
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# Zustandsvariable
mode = 'single' # 'single' oder 'width'
current_pos = 0
light_width = 1
def clear_strip():
for i in range(NUM_LEDS):
strip[i] = (0, 0, 0)
strip.write()
def update_strip(position, width):
clear_strip()
start = max(0, position - (width // 2))
end = min(NUM_LEDS, position + (width // 2) + 1)
for i in range(start, end):
strip[i] = (255, 255, 255) # Weiß
strip.write()
def handle_button(pin):
global mode, light_width
if not pin.value():
time.sleep_ms(20) # Entprellen
if not pin.value():
# Doppelklick-Logik oder Moduswechsel
if mode == 'single':
mode = 'width'
elif mode == 'width':
mode = 'single'
update_strip(current_pos, light_width)
def handle_rotation():
global current_pos, light_width
delta = rotary.value()
if delta != current_pos:
current_pos = delta
if mode == 'single':
light_width = 1
elif mode == 'width':
light_width = min(NUM_LEDS, max(1, light_width))
update_strip(current_pos, light_width)
# Interrupt für den Button
button.irq(trigger=Pin.IRQ_FALLING, handler=handle_button)
# Hauptschleife
while True:
handle_rotation()
time.sleep_ms(10)
Erklärung des Codes
- Initialisierung: Definiert die GPIO-Pins für die LEDs, den Rotary Encoder und den Button sowie die Anzahl der LEDs im Streifen.
- clear_strip: Schaltet alle LEDs aus.
- update_strip: Aktualisiert die LEDs basierend auf der aktuellen Position und der Breite des Lichtpunkts.
- handle_button: Verarbeitet Button-Klicks, um zwischen den Modi 'single' und 'width' zu wechseln.
- handle_rotation: Verarbeitet Drehungen des Encoders, um die Position oder Breite des Lichtpunkts zu ändern.
Modifikation für Doppelklick und Breitensteuerung
Um die Funktionalität für Doppelklicks und die dynamische Anpassung der Lichtbreite zu erweitern, kann der Code wie folgt angepasst werden:
from machine import Pin
import neopixel
import time
from rotary_irq_esp import RotaryIRQ
# Pin-Definitionen
LED_PIN = 5
NUM_LEDS = 60
ENCODER_CLK = 18
ENCODER_DT = 19
BUTTON_PIN = 23
# Initialisierung der LEDs
strip = neopixel.NeoPixel(Pin(LED_PIN), NUM_LEDS)
# Initialisierung des Rotary Encoders
rotary = RotaryIRQ(pin_num_clk=ENCODER_CLK, pin_num_dt=ENCODER_DT, min_val=0, max_val=NUM_LEDS-1, reverse=False, range_mode=RotaryIRQ.RANGE_WRAP)
# Initialisierung des Buttons
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# Zustandsvariablen
mode = 'single' # 'single' oder 'width'
current_pos = 0
light_width = 1
last_click_time = 0
click_count = 0
def clear_strip():
for i in range(NUM_LEDS):
strip[i] = (0, 0, 0)
strip.write()
def update_strip(position, width):
clear_strip()
start = max(0, position - (width // 2))
end = min(NUM_LEDS, position + (width // 2) + 1)
for i in range(start, end):
strip[i] = (255, 255, 255) # Weiß
strip.write()
def handle_button(pin):
global mode, light_width, last_click_time, click_count
if not pin.value():
current_time = time.ticks_ms()
if time.ticks_diff(current_time, last_click_time) < 300:
click_count += 1
else:
click_count = 1
last_click_time = current_time
time.sleep_ms(20) # Entprellen
if click_count == 1:
# Einzelklick: Einschalten/Ausschalten
if mode == 'off':
mode = 'single'
update_strip(current_pos, light_width)
else:
mode = 'off'
clear_strip()
elif click_count == 2:
# Doppelklick: Moduswechsel zu Breitensteuerung
if mode == 'single':
mode = 'width'
elif mode == 'width':
mode = 'single'
update_strip(current_pos, light_width)
def handle_rotation():
global current_pos, light_width
delta = rotary.value()
if delta != current_pos:
current_pos = delta
if mode == 'single':
light_width = 1
elif mode == 'width':
light_width = min(NUM_LEDS, max(1, light_width))
update_strip(current_pos, light_width)
# Interrupt für den Button
button.irq(trigger=Pin.IRQ_FALLING, handler=handle_button)
# Hauptschleife
while True:
handle_rotation()
time.sleep_ms(10)
Funktionen und Logik
- Einzelklick: Ein einzelner Klick schaltet die LED-Steuerung ein oder aus.
- Doppelklick: Zwei schnelle Klicks wechseln zwischen dem Einzel- und Breitenmodus.
- Drehbewegung im Einzelmodus: Verschiebt die aktive LED entlang des Streifens.
- Drehbewegung im Breitenmodus: Erweitert oder verengt die Breite des Lichtpunkts um die Haupt-LED.
- Minimaler LED-Betrieb: Es bleibt stets mindestens eine LED aktiv, um die Hauptposition anzuzeigen.
Erweiterte Funktionen und Optimierungen
Farbsteuerung
Zusätzlich zur Steuerung der Position und Breite der LEDs können Farben dynamisch angepasst werden. Dies erhöht die visuelle Attraktivität und Flexibilität des Systems.
def update_strip(position, width, color=(255, 255, 255)):
clear_strip()
start = max(0, position - (width // 2))
end = min(NUM_LEDS, position + (width // 2) + 1)
for i in range(start, end):
strip[i] = color
strip.write()
Animationen und Effekte
Implementieren Sie sanfte Übergänge und Animationen, um die Bewegungen der LEDs flüssiger und ansprechender zu gestalten.
def smooth_update(position, width, color=(255, 255, 255)):
for i in range(NUM_LEDS):
current_color = strip[i]
target_color = color if (i >= position - (width // 2) and i <= position + (width // 2)) else (0, 0, 0)
new_color = tuple(min(255, current_color[j] + (target_color[j] - current_color[j]) // 10) for j in range(3))
strip[i] = new_color
strip.write()
Speicherung der Einstellungen
Um benutzerdefinierte Einstellungen wie aktuelle Position, Breite und Farbe zu speichern, können diese Werte im Flash-Speicher des ESP32 abgelegt werden. Dies ermöglicht eine Wiederherstellung der letzten Konfiguration nach einem Neustart.
import json
import ujson
def save_settings(position, width, mode):
settings = {
'position': position,
'width': width,
'mode': mode
}
with open('settings.json', 'w') as f:
f.write(ujson.dumps(settings))
def load_settings():
try:
with open('settings.json', 'r') as f:
settings = ujson.loads(f.read())
return settings['position'], settings['width'], settings['mode']
except:
return 0, 1, 'single'
# Beim Start
current_pos, light_width, mode = load_settings()
update_strip(current_pos, light_width)
# Beim Ändern
def handle_button(pin):
global mode, light_width, last_click_time, click_count, current_pos
if not pin.value():
current_time = time.ticks_ms()
if time.ticks_diff(current_time, last_click_time) < 300:
click_count += 1
else:
click_count = 1
last_click_time = current_time
time.sleep_ms(20) # Entprellen
if click_count == 1:
if mode == 'off':
mode = 'single'
update_strip(current_pos, light_width)
else:
mode = 'off'
clear_strip()
elif click_count == 2:
if mode == 'single':
mode = 'width'
elif mode == 'width':
mode = 'single'
update_strip(current_pos, light_width)
save_settings(current_pos, light_width, mode)
Testen und Anpassen
Nach der Implementierung der Hardware und Software ist es entscheidend, das System gründlich zu testen und anzupassen, um eine reibungslose Funktionalität zu gewährleisten.
Schritt 1: Code auf den ESP32 hochladen
- Verbinden Sie den ESP32 über USB mit Ihrem Computer.
- Nutzen Sie ein Tool wie ampy oder PyMakr, um den Code auf den ESP32 zu übertragen.
- Stellen Sie sicher, dass keine Fehler während des Uploads auftreten.
Schritt 2: Funktionalität überprüfen
- Überprüfen Sie, ob der ESP32 korrekt mit dem LED-Streifen kommuniziert und alle LEDs ordnungsgemäß ansteuert.
- Testen Sie den Button auf Einzel- und Doppelklicks und stellen Sie sicher, dass die Modi korrekt wechseln.
- Drehen Sie den Außenring, um die LED-Position und Breite anzupassen, und stellen Sie sicher, dass die LEDs entsprechend reagieren.
Schritt 3: Anpassungen vornehmen
Basierend auf den Testergebnissen passen Sie den Code und die Hardware-Verbindungen an, um eine optimale Leistung zu erzielen:
- Kalibrieren Sie die Drehbewegungen des Encoders, um eine präzise Steuerung zu gewährleisten.
- Passen Sie die LED-Anzahl und GPIO-Pins entsprechend Ihrer spezifischen Hardware an.
- Fügen Sie zusätzliche Funktionen wie Farbwechsel oder weitere Modi hinzu, um die Vielseitigkeit des Systems zu erhöhen.
Schritt 4: Langzeitbetrieb testen
Stellen Sie sicher, dass das System stabil im Langzeitbetrieb funktioniert:
-
Überprüfen Sie die Stromversorgung auf Stabilität und ausreichende Leistung.
-
Testen Sie die Haltbarkeit und Zuverlässigkeit der Schaltung über einen längeren Zeitraum.
-
Sicherstellen, dass alle Verbindungen fest und sicher sind, um unbeabsichtigte Unterbrechungen zu vermeiden.
Zusammenfassung und Fazit
Die Steuerung eines adressierbaren LED-Streifens mit einem ESP32 und einem Puck-Gerät bietet eine flexible und leistungsstarke Lösung für individuelle Lichtprojekte. Durch die sorgfältige Auswahl und Verbindung der Hardware-Komponenten sowie eine durchdachte Software-Implementierung mit MicroPython können Benutzer eine intuitive und anpassbare Steuerung realisieren. Die Möglichkeit, LED-Position und -Breite dynamisch zu steuern, eröffnet vielfältige kreative Möglichkeiten für Lichtdesigns.
Referenzen
Last updated January 24, 2025