Chat
Search
Ithy Logo

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

ESP32 and addressable LED strip setup

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

  1. Laden Sie die neueste Firmware von der offiziellen MicroPython-Website herunter: MicroPython ESP32 Firmware.
  2. Verbinden Sie den ESP32 mit Ihrem Computer.
  3. Nutzen Sie ein Tool wie esptool.py zur Installation der Firmware:
  4. esptool.py --chip esp32 --port COM3 erase_flash
    esptool.py --chip esp32 --port COM3 write_flash -z 0x1000 esp32-xxxxxx.bin
  5. Nach erfolgreicher Installation können Sie über eine serielle Verbindung auf den MicroPython-Interpreter zugreifen.

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

  1. Verbinden Sie den ESP32 über USB mit Ihrem Computer.
  2. Nutzen Sie ein Tool wie ampy oder PyMakr, um den Code auf den ESP32 zu übertragen.
  3. 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
Ask Ithy AI
Export Article
Delete Article