Zum Inhalt springen

rbdimmerESP32 API-Referenz

Aktualisiert für v2.0.0 – Die öffentliche API ist unverändert, aber die interne Architektur ist vollständig modular.

Übersicht

Die rbdimmerESP32-Bibliothek bietet eine umfassende API zur Steuerung von AC-Dimmern mit ESP32-Mikrocontrollern. Die API ist mit Fokus auf Sicherheit, Leistung und Benutzerfreundlichkeit entworfen und bietet Hardware-Timer-Integration und Interrupt-gesteuerten Betrieb.

Grundlegende Designprinzipien

  • Thread-sicher: Alle Funktionen können sicher von mehreren FreeRTOS-Tasks aufgerufen werden
  • Hardware-optimiert: Nutzt ESP32-Hardware-Timer für Mikrosekunden-Präzision
  • Ressourcenverwaltung: Automatische Bereinigung und Fehlerbehandlung
  • Erweiterbar: Unterstützung für mehrere Phasen und Kanäle
  • Modular (v2.0.0): Die interne Architektur ist vollständig modular – Curve-Engine, Timer-Backend und Zero-Cross-Detektor sind unabhängige Komponenten

Datentypen

Opake Typen

rbdimmer_channel_t

c
typedef struct rbdimmer_channel_s rbdimmer_channel_t;

Opakes Handle, das einen Dimmer-Kanal darstellt. Alle Kanaloperationen verwenden dieses Handle.

Verwendungshinweise: - Erstellt von rbdimmer_create_channel() - Muss ordnungsgemäß mit rbdimmer_delete_channel() gelöscht werden - Kann nicht kopiert oder serialisiert werden

Konfigurationsstrukturen

rbdimmer_config_t

c
typedef struct {
    uint8_t gpio_pin;                 // Output signal pin
    uint8_t phase;                    // Phase number (for multi-phase systems)
    uint8_t initial_level;            // Initial level percentage (0-100)
    rbdimmer_curve_t curve_type;      // Level curve type
} rbdimmer_config_t;

Konfigurationsstruktur zum Erstellen von Dimmer-Kanälen.

Fields: - gpio_pin: GPIO pin connected to the dimmer's gate control (0-39) - phase: Phase identifier (0-3) - must be registered first - initial_level: Starting brightness level (0-100%) - curve_type: Brightness curve algorithm

Beispiel:

c
rbdimmer_config_t config = {
    .gpio_pin = 4,
    .phase = 0,
    .initial_level = 50,
    .curve_type = RBDIMMER_CURVE_RMS
};

Enumerationen

rbdimmer_curve_t

c
typedef enum {
    RBDIMMER_CURVE_LINEAR,        // Linear curve (no RMS consideration)
    RBDIMMER_CURVE_RMS,           // RMS-compensated curve
    RBDIMMER_CURVE_LOGARITHMIC,   // Logarithmic curve (for LEDs)
    RBDIMMER_CURVE_CUSTOM         // Custom curve (reserved)
} rbdimmer_curve_t;

Definiert den Helligkeitskurven-Typ für die Leistungsberechnung.

Kurventypen: - LINEAR: Direkte Umrechnung von Prozentsatz zu Phasenwinkel - RMS: Leistungskompensiert für ohmsche Lasten (Glühbirnen) - LOGARITHMIC: Wahrnehmungslinar für LED-Lasten - CUSTOM: Reserviert für zukünftige benutzerdefinierte Kurven-Implementierung

Helligkeitsbegrenzung (v2.0.0): Alle Kurvenberechnungen erzwingen LEVEL_MIN und LEVEL_MAX Grenzen. Level >= 100% werden auf RBDIMMER_LEVEL_MAX (standardmäßig 99%) begrenzt. Level unterhalb RBDIMMER_LEVEL_MIN (standardmäßig 3%) führen zu einer Verzögerung von 0, was bedeutet, dass der Kanal AUS ist. Dies verhindert unzuverlässiges TRIAC-Zünden bei nahezu Null oder nahezu vollständigen Leitungswinkeln.

rbdimmer_err_t

c
typedef enum {
    RBDIMMER_OK = 0,                  // Operation completed successfully
    RBDIMMER_ERR_INVALID_ARG,         // Invalid argument
    RBDIMMER_ERR_NO_MEMORY,           // Memory allocation failed
    RBDIMMER_ERR_NOT_FOUND,           // Object not found
    RBDIMMER_ERR_ALREADY_EXIST,       // Object already exists
    RBDIMMER_ERR_TIMER_FAILED,        // Timer initialization failed
    RBDIMMER_ERR_GPIO_FAILED          // GPIO initialization failed
} rbdimmer_err_t;

Fehlercodes, die von Bibliotheksfunktionen zurückgegeben werden.

timer_state_t

c
typedef enum {
    TIMER_STATE_IDLE,        // Waiting for zero-crossing
    TIMER_STATE_DELAY,       // Waiting for delay to finish
    TIMER_STATE_PULSE_ON,    // Pulse is active, waiting to turn off
} timer_state_t;

Interne Timer-Status-Enumeration (intern von der Bibliothek verwendet).

Konstanten

Systemgrenzen

c
#define RBDIMMER_MAX_PHASES 4                 // Maximum number of phases
#define RBDIMMER_MAX_CHANNELS 8               // Maximum number of channels

Timing-Konstanten

c
#define RBDIMMER_DEFAULT_PULSE_WIDTH_US 50    // Default pulse width in microseconds
#define RBDIMMER_MIN_DELAY_US 100             // Minimum delay for safe triac operation (was 50 in v1)

Zero-Cross-Noise-Gate (v2.0.0)

c
#define RBDIMMER_ZC_DEBOUNCE_US 3000          // Noise gate window in microseconds

Nachdem eine Zero-Crossing-Interrupt ausgelöst wird, werden nachfolgende Interrupts innerhalb dieses Fensters ignoriert. Dies eliminiert falsche Auslösungen durch elektrisches Rauschen in der Nähe des Zero-Cross-Punkts. Der Standard von 3000 us funktioniert gut für 50 Hz und 60 Hz Netzspannung (Halbzyklus beträgt 8333 us bei 60 Hz und 10000 us bei 50 Hz, daher sind 3 ms sicher unterhalb beider).

Level-Grenz-Konstanten (v2.0.0)

c
#define RBDIMMER_LEVEL_MIN 3                  // Levels below this -> OFF (delay = 0)
#define RBDIMMER_LEVEL_MAX 99                 // Levels above this -> capped to this value

Diese Konstanten definieren den effektiven Betriebsbereich für alle Kurvenberechnungen:

  • RBDIMMER_LEVEL_MIN (3%): Die Anforderung eines Levels unterhalb dieses Schwellwerts erzeugt eine Verzögerung von 0, was bedeutet, dass der TRIAC niemals zündet und der Kanal vollständig AUS ist. Dies vermeidet unzuverlässige Teilleitungen bei sehr niedrigen Tastverhältnissen.
  • RBDIMMER_LEVEL_MAX (99%): Die Anforderung eines Levels von 100% oder höher wird auf diesen Wert begrenzt. Dies stellt sicher, dass immer eine minimale Verzögerung angewendet wird, um zu verhindern, dass der TRIAC-Impuls den Zero-Cross-Punkt überlappt.

Konfigurierbarkeit: In ESP-IDF-Projekten können diese Konstanten über Kconfig (menuconfig) überschrieben werden. In Arduino-Projekten fungieren sie als Compile-Zeit-Defaults und können vor dem Einbinden des Bibliotheks-Headers neu definiert werden.

Frequenz-Konstanten

c
#define RBDIMMER_DEFAULT_FREQUENCY 0          // Auto-detect frequency
#define RBDIMMER_FREQUENCY_MIN 45             // Minimum allowed frequency
#define RBDIMMER_FREQUENCY_MAX 65             // Maximum allowed frequency
#define RBDIMMER_MEASURE_CYCLES 10            // Number of cycles for measurement

Initialisierungsfunktionen

rbdimmer_init()

c
rbdimmer_err_t rbdimmer_init(void);

Initialisiert die rbdimmerESP32-Bibliothek. Muss vor allen anderen Bibliotheksfunktionen aufgerufen werden.

Rückgabe: - RBDIMMER_OK: Initialisierung erfolgreich - RBDIMMER_ERR_NO_MEMORY: Speicherallokation fehlgeschlagen

Beispiel:

c
void setup() {
    rbdimmer_err_t err = rbdimmer_init();
    if (err != RBDIMMER_OK) {
        Serial.println("Failed to initialize rbdimmer library");
        return;
    }
    Serial.println("rbdimmer initialized successfully");
}

Hinweise: - Initialisiert interne Datenstrukturen - Bereitet Lookup-Tabellen für Helligkeitskurven vor - Muss von der Haupt-Task/Setup-Funktion aufgerufen werden

rbdimmer_deinit()

c
rbdimmer_err_t rbdimmer_deinit(void);

Deinitialisiert die Bibliothek und gibt alle Ressourcen frei.

Rückgabe: - RBDIMMER_OK: Deinitialisierung erfolgreich

Beispiel:

c
void cleanup() {
    rbdimmer_deinit();
    Serial.println("Library deinitialized");
}

Hinweise: - Löscht automatisch alle Kanäle - Entfernt alle Interrupt-Handler - Gibt GPIO-Ressourcen frei - Vor Systemnestart oder Deep Sleep aufrufen

Zero-Cross-Verwaltung

rbdimmer_register_zero_cross()

c
rbdimmer_err_t rbdimmer_register_zero_cross(uint8_t pin, uint8_t phase, uint16_t frequency);

Registriert einen Zero-Crossing-Detektor für AC-Synchronisation.

Parameter: - pin: GPIO-Pin verbunden mit Zero-Cross-Detektor (0-39) - phase: Phasenkennung (0-3) - frequency: Erwartete Netzfrequenz in Hz (0 für Auto-Erkennung, 50, 60)

Rückgabe: - RBDIMMER_OK: Registrierung erfolgreich - RBDIMMER_ERR_INVALID_ARG: Ungültiger Pin oder Phasennummer - RBDIMMER_ERR_ALREADY_EXIST: Phase bereits registriert - RBDIMMER_ERR_NO_MEMORY: Maximale Phasenzahl erreicht - RBDIMMER_ERR_GPIO_FAILED: GPIO-Konfiguration fehlgeschlagen

Beispiel:

c
// Auto-detect frequency on phase 0
rbdimmer_err_t err = rbdimmer_register_zero_cross(2, 0, 0);
if (err == RBDIMMER_OK) {
    Serial.println("Zero-cross detector registered on pin 2");
}
// Fixed 60Hz frequency on phase 1
rbdimmer_register_zero_cross(3, 1, 60);

Hinweise: - Muss vor dem Erstellen von Kanälen in der gleichen Phase aufgerufen werden - Pin wird als Eingang mit Interrupt bei steigender Flanke konfiguriert - Frequenz 0 ermöglicht automatische Erkennung (empfohlen) - Jede Phase benötigt einen separaten Zero-Cross-Detektor

Noise-Gate (v2.0.0): Nach jeder erkannten Zero-Crossing ignoriert der ISR weitere Interrupts auf der gleichen Phase für RBDIMMER_ZC_DEBOUNCE_US Mikrosekunden (Standard 3000). Dies unterdrückt falsche Auslösungen durch Rauschen, Klingeln oder langsam ansteigende Zero-Cross-Signale. Das Debounce-Fenster wird pro Phase angewendet, daher werden Multi-Phasen-Systeme unabhängig behandelt.

Kanalverwaltung

rbdimmer_create_channel()

c
rbdimmer_err_t rbdimmer_create_channel(rbdimmer_config_t* config, rbdimmer_channel_t** channel);

Erstellt einen neuen Dimmer-Kanal mit spezifizierter Konfiguration.

Parameter: - config: Zeiger auf Konfigurationsstruktur - channel: Zeiger zum Speichern des erstellten Kanal-Handles

Rückgabe: - RBDIMMER_OK: Kanal erfolgreich erstellt - RBDIMMER_ERR_INVALID_ARG: Ungültige Konfiguration oder NULL-Zeiger - RBDIMMER_ERR_NOT_FOUND: Referenzierte Phase nicht registriert - RBDIMMER_ERR_NO_MEMORY: Speicherallokation fehlgeschlagen oder max. Kanäle erreicht - RBDIMMER_ERR_GPIO_FAILED: GPIO-Konfiguration fehlgeschlagen - RBDIMMER_ERR_TIMER_FAILED: Timer-Erstellung fehlgeschlagen

Beispiel:

c
rbdimmer_channel_t* my_channel;
rbdimmer_config_t config = {
    .gpio_pin = 4,
    .phase = 0,
    .initial_level = 0,
    .curve_type = RBDIMMER_CURVE_RMS
};
rbdimmer_err_t err = rbdimmer_create_channel(&config, &my_channel);
if (err == RBDIMMER_OK) {
    Serial.println("Channel created successfully");
}

Hinweise: - GPIO-Pin wird als Ausgang konfiguriert - Kanal startet im aktiven Zustand - Zwei Hardware-Timer werden pro Kanal allokiert - Anfangs-Level wird sofort angewendet

rbdimmer_delete_channel()

c
rbdimmer_err_t rbdimmer_delete_channel(rbdimmer_channel_t* channel);

Löscht einen Dimmer-Kanal und gibt alle zugeordneten Ressourcen frei.

Parameter: - channel: Zu löschendes Kanal-Handle

Rückgabe: - RBDIMMER_OK: Kanal erfolgreich gelöscht - RBDIMMER_ERR_INVALID_ARG: NULL-Kanal-Handle - RBDIMMER_ERR_NOT_FOUND: Kanal nicht im Manager gefunden

Beispiel:

c
rbdimmer_err_t err = rbdimmer_delete_channel(my_channel);
if (err == RBDIMMER_OK) {
    my_channel = NULL; // Prevent accidental reuse
    Serial.println("Channel deleted successfully");
}

Hinweise: - Stoppt alle laufenden Timer - Setzt GPIO-Ausgang auf LOW - Gibt allokierten Speicher frei - Kanal-Handle wird ungültig nach dem Löschen

Helligkeitssteuerung

rbdimmer_set_level()

c
rbdimmer_err_t rbdimmer_set_level(rbdimmer_channel_t* channel, uint8_t level_percent);

Setzt das Helligkeitslevel eines Dimmer-Kanals sofort.

Parameter: - channel: Ziel-Kanal-Handle - level_percent: Helligkeitslevel (0-100%)

Rückgabe: - RBDIMMER_OK: Level erfolgreich gesetzt - RBDIMMER_ERR_INVALID_ARG: NULL-Kanal-Handle

Beispiel:

c
// Set to 50% brightness
rbdimmer_set_level(my_channel, 50);
// Turn off
rbdimmer_set_level(my_channel, 0);
// Full brightness (clamped to LEVEL_MAX = 99%)
rbdimmer_set_level(my_channel, 100);

Hinweise: - Level-Änderungen treten beim nächsten Zero-Crossing in Kraft - Werte >= 100 werden auf RBDIMMER_LEVEL_MAX (99%) begrenzt - Werte unterhalb RBDIMMER_LEVEL_MIN (3%) führen dazu, dass der Kanal AUS ist (Verzögerung = 0) - Level 0 = vollständig aus - Thread-sicher – kann von jeder Task aufgerufen werden

rbdimmer_set_level_transition()

c
rbdimmer_err_t rbdimmer_set_level_transition(rbdimmer_channel_t* channel, uint8_t level_percent, uint32_t transition_ms);

Setzt das Helligkeitslevel mit sanfter Übergangsbewegung über die Zeit.

Parameter: - channel: Ziel-Kanal-Handle - level_percent: Ziel-Helligkeitslevel (0-100%) - transition_ms: Übergangsdauer in Millisekunden

Rückgabe: - RBDIMMER_OK: Übergang erfolgreich gestartet - RBDIMMER_ERR_INVALID_ARG: NULL-Kanal-Handle - RBDIMMER_ERR_NO_MEMORY: Erstellen der Übergangs-Task fehlgeschlagen

Beispiel:

c
// Fade to 75% over 3 seconds
rbdimmer_set_level_transition(my_channel, 75, 3000);
// Quick fade to off over 500ms
rbdimmer_set_level_transition(my_channel, 0, 500);

Hinweise: - Erstellt eine FreeRTOS-Task für sanfte Übergänge - Nicht blockierend – gibt sofort zurück - Minimale Übergangsdauer ist 50 ms - Übergänge kürzer als 50 ms verwenden sofortige Einstellung - Mehrere Übergänge können gleichzeitig auf verschiedenen Kanälen laufen - Ziel-Level unterliegt der gleichen LEVEL_MIN / LEVEL_MAX Begrenzung wie rbdimmer_set_level()

Konfigurationsfunktionen

rbdimmer_set_curve()

c
rbdimmer_err_t rbdimmer_set_curve(rbdimmer_channel_t* channel, rbdimmer_curve_t curve_type);

Setzt den Helligkeitskurven-Typ für einen Kanal.

Parameter: - channel: Ziel-Kanal-Handle - curve_type: Gewünschter Kurventyp

Rückgabe: - RBDIMMER_OK: Kurve erfolgreich gesetzt - RBDIMMER_ERR_INVALID_ARG: NULL-Kanal-Handle

Beispiel:

c
// For incandescent bulbs
rbdimmer_set_curve(my_channel, RBDIMMER_CURVE_RMS);
// For LED strips
rbdimmer_set_curve(my_channel, RBDIMMER_CURVE_LOGARITHMIC);
// For motor control
rbdimmer_set_curve(my_channel, RBDIMMER_CURVE_LINEAR);

Hinweise: - Änderung tritt beim nächsten Zero-Crossing in Kraft - Verschiedene Kurven optimieren für unterschiedliche Lasttypen - Kann während des Betriebs geändert werden ohne Neustart - Alle Kurven erzwingen LEVEL_MIN / LEVEL_MAX Grenzen

rbdimmer_set_active()

c
rbdimmer_err_t rbdimmer_set_active(rbdimmer_channel_t* channel, bool active);

Aktiviert oder deaktiviert einen Dimmer-Kanal.

Parameter: - channel: Ziel-Kanal-Handle - active: true zum Aktivieren, false zum Deaktivieren

Rückgabe: - RBDIMMER_OK: Zustand erfolgreich geändert - RBDIMMER_ERR_INVALID_ARG: NULL-Kanal-Handle

Beispiel:

c
// Enable channel
rbdimmer_set_active(my_channel, true);
// Disable channel (output goes to 0)
rbdimmer_set_active(my_channel, false);

Hinweise: - Deaktivierte Kanäle verbrauchen keine CPU-Zeit - Ausgang wird sofort auf LOW gesetzt wenn deaktiviert - Kanal-Konfiguration wird beibehalten wenn deaktiviert - Wiederherstellen setzt Betrieb fort

Informationsabruf

rbdimmer_get_level()

c
uint8_t rbdimmer_get_level(rbdimmer_channel_t* channel);

Ruft das aktuelle Helligkeitslevel eines Kanals ab.

Parameter: - channel: Abzufragendes Kanal-Handle

Rückgabe: - Aktuelles Helligkeitslevel (0-100%), oder 0 wenn Kanal NULL ist

Beispiel:

c
uint8_t current_level = rbdimmer_get_level(my_channel);
Serial.printf("Current brightness: %d%%\n", current_level);

rbdimmer_get_frequency()

c
uint16_t rbdimmer_get_frequency(uint8_t phase);

Ruft die gemessene Netzfrequenz für eine spezifische Phase ab.

Parameter: - phase: Abzufragende Phasennummer (0-3)

Rückgabe: - Gemessene Frequenz in Hz, oder 0 wenn noch nicht gemessen oder Phase nicht gefunden

Beispiel:

c
uint16_t freq = rbdimmer_get_frequency(0);
if (freq > 0) {
    Serial.printf("Mains frequency: %d Hz\n", freq);
} else {
    Serial.println("Frequency not measured yet");
}

Hinweise: - Gibt 0 während der initialen Messdauer zurück - Frequenzerkennung dauert etwa 20 AC-Zyklen - Nützlich für Stromqualitätsüberwachung

rbdimmer_is_active()

c
bool rbdimmer_is_active(rbdimmer_channel_t* channel);

Prüft, ob ein Kanal aktuell aktiv ist.

Parameter: - channel: Abzufragendes Kanal-Handle

Rückgabe: - true wenn Kanal aktiv ist, false wenn inaktiv oder NULL

Beispiel:

c
if (rbdimmer_is_active(my_channel)) {
    Serial.println("Channel is active");
} else {
    Serial.println("Channel is inactive");
}

rbdimmer_get_curve()

c
rbdimmer_curve_t rbdimmer_get_curve(rbdimmer_channel_t* channel);

Ruft den aktuellen Kurventyp eines Kanals ab.

Parameter: - channel: Abzufragendes Kanal-Handle

Rückgabe: - Aktueller Kurventyp, oder RBDIMMER_CURVE_LINEAR wenn Kanal NULL ist

Beispiel:

c
rbdimmer_curve_t curve = rbdimmer_get_curve(my_channel);
switch(curve) {
    case RBDIMMER_CURVE_LINEAR:
        Serial.println("Using linear curve");
        break;
    case RBDIMMER_CURVE_RMS:
        Serial.println("Using RMS curve");
        break;
    case RBDIMMER_CURVE_LOGARITHMIC:
        Serial.println("Using logarithmic curve");
        break;
}

rbdimmer_get_delay()

c
uint32_t rbdimmer_get_delay(rbdimmer_channel_t* channel);

Ruft die aktuelle Verzögerungseinstellung in Mikrosekunden ab.

Parameter: - channel: Abzufragendes Kanal-Handle

Rückgabe: - Aktuelle Verzögerung in Mikrosekunden, oder 0 wenn Kanal NULL ist

Beispiel:

c
uint32_t delay_us = rbdimmer_get_delay(my_channel);
Serial.printf("Current delay: %d microseconds\n", delay_us);

Hinweise: - Nützlich zum Debuggen und Optimieren - Verzögerung variiert mit Helligkeitslevel und Kurventyp - Gemessen von Zero-Crossing bis TRIAC-Auslösung - Gibt 0 zurück wenn Level unterhalb RBDIMMER_LEVEL_MIN liegt (Kanal AUS) - Minimaler Nicht-Null-Wert ist RBDIMMER_MIN_DELAY_US (100 us)

Callback-Funktionen

rbdimmer_set_callback()

c
rbdimmer_err_t rbdimmer_set_callback(uint8_t phase, void (*callback)(void*), void* user_data);

Setzt eine Callback-Funktion, die bei Zero-Crossing-Ereignissen aufgerufen wird.

Parameter: - phase: Phasennummer (0-3) - callback: Bei Zero-Crossing aufzurufende Funktion (NULL zum Deaktivieren) - user_data: Zeiger auf Benutzerdaten, die an Callback übergeben werden

Rückgabe: - RBDIMMER_OK: Callback erfolgreich gesetzt - RBDIMMER_ERR_NOT_FOUND: Phase nicht registriert

Callback-Funktionssignatur:

c
void zero_cross_callback(void* user_data);

Beispiel:

c
typedef struct {
    uint32_t cross_count;
    unsigned long last_time;
} callback_data_t;
callback_data_t cb_data = {0, 0};
void my_zero_cross_callback(void* user_data) {
    callback_data_t* data = (callback_data_t*)user_data;
    data->cross_count++;
    data->last_time = millis();
    // Note: Keep ISR code minimal and fast!
    if (data->cross_count % 100 == 0) {
        // Schedule a task to print statistics
        // Don't use Serial.print() directly in ISR!
    }
}
// Register the callback
rbdimmer_set_callback(0, my_zero_cross_callback, &cb_data);

Wichtige Hinweise: - Callback läuft im Interrupt-Kontext (ISR) - Callback-Code minimal und schnell halten - Keine blockierenden Operationen (Verzögerungen, Ausgaben usw.) - FreeRTOS-Warteschlangen für Kommunikation mit Tasks verwenden - Callback wird bei jedem Zero-Crossing aufgerufen (100–120 Mal pro Sekunde) - In v2.0.0 wird der Callback nur für gültige Zero-Crossings aufgerufen, die das Noise-Gate (Debounce) passieren. Spurious Trigger innerhalb RBDIMMER_ZC_DEBOUNCE_US eines vorherigen Crossing rufen den Callback nicht auf.

Hilfsfunktionen

rbdimmer_update_all()

c
rbdimmer_err_t rbdimmer_update_all(void);

Erzwingt eine sofortige Aktualisierung aller aktiven Kanäle.

Rückgabe: - RBDIMMER_OK: Alle Kanäle erfolgreich aktualisiert

Beispiel:

c
// After changing multiple channel parameters
rbdimmer_update_all();

Hinweise: - Normalerweise nicht erforderlich – Kanäle aktualisieren sich automatisch - Nützlich nach Massen-Konfigurationsänderungen - Berechnet Timing für alle aktiven Kanäle neu

Fehlerbehandlung

Fehlercodes-Beschreibungen

Fehlercode Beschreibung Häufige Ursachen
RBDIMMER_OK Erfolg Operation erfolgreich abgeschlossen
RBDIMMER_ERR_INVALID_ARG Ungültiges Argument NULL-Zeiger, Werte außerhalb des Bereichs
RBDIMMER_ERR_NO_MEMORY Speicherallokation fehlgeschlagen Unzureichender Heap-Speicher
RBDIMMER_ERR_NOT_FOUND Objekt nicht gefunden Phase nicht registriert, Kanal nicht gefunden
RBDIMMER_ERR_ALREADY_EXIST Objekt existiert bereits Phase bereits registriert
RBDIMMER_ERR_TIMER_FAILED Timer-Operation fehlgeschlagen Hardware-Timer nicht verfügbar
RBDIMMER_ERR_GPIO_FAILED GPIO-Operation fehlgeschlagen Ungültiger Pin, Pin bereits in Verwendung

Best Practices für Fehlerbehandlung

c
rbdimmer_err_t err;
rbdimmer_channel_t* channel;
// Always check return values
err = rbdimmer_init();
if (err != RBDIMMER_OK) {
    Serial.printf("Initialization failed: %d\n", err);
    return;
}
// Handle specific error conditions
err = rbdimmer_register_zero_cross(2, 0, 0);
switch (err) {
    case RBDIMMER_OK:
        Serial.println("Zero-cross registered successfully");
        break;
    case RBDIMMER_ERR_ALREADY_EXIST:
        Serial.println("Phase already registered - continuing");
        break;
    case RBDIMMER_ERR_GPIO_FAILED:
        Serial.println("GPIO configuration failed - check wiring");
        return;
    default:
        Serial.printf("Unexpected error: %d\n", err);
        return;
}

Codebeispiele

Vollständiges Basis-Setup

c
#include 
rbdimmer_channel_t* dimmer;
void setup() {
    Serial.begin(115200);
    // Initialize library
    if (rbdimmer_init() != RBDIMMER_OK) {
        Serial.println("Library initialization failed");
        return;
    }
    // Register zero-cross detector
    if (rbdimmer_register_zero_cross(2, 0, 0) != RBDIMMER_OK) {
        Serial.println("Zero-cross registration failed");
        return;
    }
    // Create dimmer channel
    rbdimmer_config_t config = {
        .gpio_pin = 4,
        .phase = 0,
        .initial_level = 0,
        .curve_type = RBDIMMER_CURVE_RMS
    };
    if (rbdimmer_create_channel(&config, &dimmer) != RBDIMMER_OK) {
        Serial.println("Channel creation failed");
        return;
    }
    Serial.println("Setup complete");
}
void loop() {
    // Fade up over 2 seconds
    rbdimmer_set_level_transition(dimmer, 100, 2000);
    delay(3000);
    // Fade down over 1 second
    rbdimmer_set_level_transition(dimmer, 0, 1000);
    delay(2000);
}

Multi-Kanal-Steuerung

c
#include 
#define NUM_CHANNELS 3
rbdimmer_channel_t* channels[NUM_CHANNELS];
uint8_t dimmer_pins[] = {4, 5, 6};
void setup() {
    Serial.begin(115200);
    rbdimmer_init();
    rbdimmer_register_zero_cross(2, 0, 0);
    // Create multiple channels
    for (int i = 0; i < NUM_CHANNELS; i++) {
        rbdimmer_config_t config = {
            .gpio_pin = dimmer_pins[i],
            .phase = 0,
            .initial_level = 0,
            .curve_type = RBDIMMER_CURVE_RMS
        };
        rbdimmer_create_channel(&config, &channels[i]);
    }
    Serial.println("Multi-channel setup complete");
}
void loop() {
    // Sequential fade effect
    for (int i = 0; i < NUM_CHANNELS; i++) {
        rbdimmer_set_level_transition(channels[i], 100, 1000);
        delay(500);
    }
    delay(2000);
    // All off together
    for (int i = 0; i < NUM_CHANNELS; i++) {
        rbdimmer_set_level_transition(channels[i], 0, 1000);
    }
    delay(2000);
}

Erweiterte Callback-Verwendung

c
#include 
typedef struct {
    uint32_t zero_cross_count;
    uint16_t frequency;
    bool frequency_stable;
} system_stats_t;
system_stats_t stats = {0, 0, false};
rbdimmer_channel_t* dimmer;
void zero_cross_isr(void* user_data) {
    system_stats_t* s = (system_stats_t*)user_data;
    s->zero_cross_count++;
    // Check frequency every 100 crossings (avoid frequent updates)
    if (s->zero_cross_count % 100 == 0) {
        s->frequency = rbdimmer_get_frequency(0);
        s->frequency_stable = (s->frequency == 50 || s->frequency == 60);
    }
}
void setup() {
    Serial.begin(115200);
    rbdimmer_init();
    rbdimmer_register_zero_cross(2, 0, 0);
    // Set up callback for monitoring
    rbdimmer_set_callback(0, zero_cross_isr, &stats);
    rbdimmer_config_t config = {
        .gpio_pin = 4,
        .phase = 0,
        .initial_level = 50,
        .curve_type = RBDIMMER_CURVE_RMS
    };
    rbdimmer_create_channel(&config, &dimmer);
}
void loop() {
    // Print statistics every 5 seconds
    static unsigned long last_print = 0;
    if (millis() - last_print > 5000) {
        Serial.printf("Zero crossings: %d\n", stats.zero_cross_count);
        Serial.printf("Frequency: %d Hz\n", stats.frequency);
        Serial.printf("Frequency stable: %s\n", stats.frequency_stable ? "Yes" : "No");
        Serial.printf("Current level: %d%%\n", rbdimmer_get_level(dimmer));
        Serial.println("---");
        last_print = millis();
    }
    delay(100);
}

Leistungsaspekte

Speicherverbrauch

  • Jeder Kanal verwendet ungefähr 200 Bytes RAM
  • Globaler Bibliotheks-Overhead: ~1KB RAM
  • Flash-Speicherverbrauch: ~32KB

Timing-Präzision

  • Zero-Crossing-Erkennung: +/-10 Mikrosekunden (nach Noise-Gate-Filterung)
  • TRIAC-Auslösung: +/-1 Mikrosekunde
  • Frequenzmessung: +/-0,1 Hz

CPU-Overhead

  • Interrupt-Handling: <50 Mikrosekunden pro Zero-Crossing
  • Hintergrund-Verarbeitung: <1% CPU-Auslastung
  • Übergangs-Tasks: Minimale Auswirkung auf andere Operationen

Einschränkungen

  • Maximal 8 Kanäle pro ESP32
  • Maximal 4 unabhängige Phasen
  • Minimale Impulsbreite: 50 Mikrosekunden
  • Minimale Verzögerung beim Zünden: 100 Mikrosekunden (RBDIMMER_MIN_DELAY_US)
  • Effektiver Dimm-Bereich: 3%-99% (RBDIMMER_LEVEL_MIN bis RBDIMMER_LEVEL_MAX)
  • Maximale Übergangsdauer: Begrenzt durch verfügbaren Speicher für Tasks

Diese API-Referenz deckt alle öffentlichen Funktionen und Datentypen in rbdimmerESP32 v2.0.0 ab