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
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
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:
rbdimmer_config_t config = {
.gpio_pin = 4,
.phase = 0,
.initial_level = 50,
.curve_type = RBDIMMER_CURVE_RMS
};Enumerationen
rbdimmer_curve_t
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
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
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
#define RBDIMMER_MAX_PHASES 4 // Maximum number of phases
#define RBDIMMER_MAX_CHANNELS 8 // Maximum number of channelsTiming-Konstanten
#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)
#define RBDIMMER_ZC_DEBOUNCE_US 3000 // Noise gate window in microsecondsNachdem 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)
#define RBDIMMER_LEVEL_MIN 3 // Levels below this -> OFF (delay = 0)
#define RBDIMMER_LEVEL_MAX 99 // Levels above this -> capped to this valueDiese 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
#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 measurementInitialisierungsfunktionen
rbdimmer_init()
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:
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()
rbdimmer_err_t rbdimmer_deinit(void);Deinitialisiert die Bibliothek und gibt alle Ressourcen frei.
Rückgabe:
- RBDIMMER_OK: Deinitialisierung erfolgreich
Beispiel:
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()
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:
// 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()
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:
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()
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:
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()
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:
// 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()
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:
// 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()
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:
// 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()
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:
// 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()
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:
uint8_t current_level = rbdimmer_get_level(my_channel);
Serial.printf("Current brightness: %d%%\n", current_level);rbdimmer_get_frequency()
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:
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()
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:
if (rbdimmer_is_active(my_channel)) {
Serial.println("Channel is active");
} else {
Serial.println("Channel is inactive");
}rbdimmer_get_curve()
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:
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()
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:
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()
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:
void zero_cross_callback(void* user_data);Beispiel:
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()
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:
// 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
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
#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
#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
#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