Files
VersaMCU/doc/05_led_system.md
T

4.1 KiB
Raw Blame History

LED-System (WS2812)

Dateien: hal/ws2812.h, hal/ws2812.cpp, CButton.h, CButton.cpp

Hardware-Treiber (ws2812 HAL)

Dünner Wrapper um Adafruit NeoPixel (bit-bang, kein DMA, kein SERCOM).

Funktion Bedeutung
ws2812_init() begin() + clear() + show()
ws2812_set(idx, r, g, b) setPixelColor() schreibt in RAM-Puffer
ws2812_fill(r, g, b) Alle LEDs gleiche Farbe
ws2812_show() Bit-Bang-Übertragung (~600 µs, Interrupts gesperrt)
ws2812_clear() clear() + show()

ws2812_show() wird in CMainController::updateLEDs() nur aufgerufen, wenn mindestens ein Button dirty war oder eine Animation läuft. Bei einer endlos laufenden Animation wird daher in jedem Loop ein Frame übertragen.

Der Treiber nutzt Adafruit NeoPixel per Bit-Banging; es gibt keinen DMA-/SERCOM-Ausgabepfad.

2-Schicht-Modell (CButton)

Jeder MX-Button hat zwei LED-Schichten:

override (aktiv wenn set_override() aufgerufen)  ← temporär (GUI-Benachrichtigungen)
base     (Idle-Farbe aus NVM)                    ← dauerhaft

Aktive Farbe = override wenn aktiv, sonst base. clear_override() kehrt sofort zu base zurück, ohne base zu verändern.

Animationen

Animation Typ Verhalten Endbedingung
STATIC Feste Farbe
BLINK Helligkeit erste Hälfte an, zweite Hälfte aus; period_ms = Vollperiode endlos
PULSE Helligkeit Lineares Dreieck 0→255→0 endlos
FADE_IN Helligkeit Einmalig schwarz → voll → STATIC (voll)
FADE_OUT Helligkeit Einmalig voll → schwarz → STATIC (base=schwarz)
COLOR_CYCLE Farbe Hue-Sweep, ignoriert base/override endlos
COLOR_FADE Farbe Crossfade from→to → STATIC (base=to)

Helligkeits-Animationen (compute_scale): Multiplizieren die aktive Farbe mit einem Skalierungsfaktor 0255. Formel: (channel * scale) / 255.

Farb-Animationen (compute_rgb): Berechnen RGB direkt; base/override werden nicht verändert (außer bei Abschluss).

Die globale und LED-spezifische Helligkeit werden beim Initialisieren in die Base-Farbe eingerechnet. COLOR_CYCLE ignoriert diese Base-Farbe und rendert mit einem festen Faktor von 40 %. Auch CDC-Overrides werden von COLOR_CYCLE/COLOR_FADE visuell überdeckt, solange die Farbanimation aktiv ist.

COLOR_CYCLE Hue-Arithmetik (kein Float)

Hue 0255 aufgeteilt in 6 Segmente à 43 Einheiten. Innerhalb jedes Segments steigt/fällt ein Kanal linear:

Seg 0: R=255, G steigt     (Rot → Gelb)
Seg 1: R fällt, G=255      (Gelb → Grün)
Seg 2: G=255, B steigt     (Grün → Cyan)
Seg 3: G fällt, B=255      (Cyan → Blau)
Seg 4: B=255, R steigt     (Blau → Magenta)
Seg 5: R=255, B fällt      (Magenta → Rot)

Ausgabe wird auf 40 % Helligkeit skaliert (Faktor 102/255) damit die LEDs nicht blenden.

Die Firmware verwendet eine eigene ganzzahlige Hue-Umrechnung und ruft Adafruit_NeoPixel::ColorHSV() nicht auf.

Für PULSE muss period_ms >= 2 gelten, da der Code durch die halbe Periode teilt. Eingehende Configs validieren diesen Grenzwert aktuell nicht.

COLOR_FADE benötigt set_color_fade(to, period_ms), weil dort Start- und Zielfarbe gesetzt werden. Ein bloßes set_anim(COLOR_FADE, ...), wie es beim direkten Laden dieses Enum-Werts aus der Config geschieht, initialisiert diese Farben nicht aus den Configdaten.

Phasenversatz (Regenbogen-Wellen)

set_anim(COLOR_CYCLE, period, phase_offset_ms): m_anim_start_ms = millis() - phase_offset_ms. Die 20 MX-Buttons werden in init_buttons() gleichmäßig phasenverschoben initialisiert:

uint16_t phase = (mx_idx * period) / 20;

Render-Pipeline

CMainController::updateLEDs()
  für jeden CButton:
    CButton::render_led()
      if !dirty && !is_animating(): return false
      rgb = compute_rgb()
      ws2812_set(led_index, rgb.r, rgb.g, rgb.b)
      dirty = false
      return true
  if any returned true:
    ws2812_show()

dirty wird gesetzt bei: init(), set_base(), set_override(), clear_override(), set_anim(), clear_anim(), Animations-Abschluss.