Riferimento API di rbdimmerESP32
Aggiornato per v2.0.0 -- l'API pubblica rimane invariata, ma l'architettura interna è completamente modulare.
Panoramica
La libreria rbdimmerESP32 fornisce un'API completa per controllare i dimmer AC con microcontrollori ESP32. L'API è stata progettata con un occhio alla sicurezza, alle prestazioni e alla facilità d'uso, integrando timer hardware e funzionamento basato su interrupt.
Principi di Progettazione Chiave
- Thread-Safe: Tutte le funzioni sono sicure per essere chiamate da più task FreeRTOS
- Ottimizzate per Hardware: Utilizza i timer hardware ESP32 per una precisione a livello di microsecondo
- Gestione delle Risorse: Cleanup automatico e gestione degli errori
- Estensibile: Supporto per più fasi e canali
- Modulare (v2.0.0): L'architettura interna è completamente modulare -- il motore delle curve, il backend del timer e il rilevatore zero-cross sono componenti indipendenti
Tipi di Dati
Tipi Opachi
rbdimmer_channel_t
typedef struct rbdimmer_channel_s rbdimmer_channel_t;Handle opaco che rappresenta un canale dimmer. Tutte le operazioni sui canali utilizzano questo handle.
Note di Utilizzo:
- Creato da rbdimmer_create_channel()
- Deve essere distrutto correttamente con rbdimmer_delete_channel()
- Non può essere copiato o serializzato
Strutture di Configurazione
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;Struttura di configurazione per la creazione dei canali dimmer.
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
Esempio:
rbdimmer_config_t config = {
.gpio_pin = 4,
.phase = 0,
.initial_level = 50,
.curve_type = RBDIMMER_CURVE_RMS
};Enumerazioni
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;Definisce il tipo di curva di luminosità per il calcolo della potenza.
Tipi di Curva: - LINEAR: Conversione diretta da percentuale a angolo di fase - RMS: Potenza compensata per carichi resistivi (lampadine a incandescenza) - LOGARITHMIC: Perceptualmente lineare per carichi LED - CUSTOM: Riservato per implementazioni future di curve personalizzate
Limitazione dei livelli (v2.0.0): Tutti i calcoli delle curve applicano i limiti LEVEL_MIN e LEVEL_MAX. I livelli >= 100% sono limitati a RBDIMMER_LEVEL_MAX (99% per impostazione predefinita). I livelli inferiori a RBDIMMER_LEVEL_MIN (3% per impostazione predefinita) restituiscono un ritardo = 0, il che significa che il canale è SPENTO. Ciò previene accensioni TRIAC inaffidabili con angoli di conduzione quasi pari a zero o quasi pieni.
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;Codici di errore restituiti dalle funzioni della libreria.
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;Enumerazione dello stato interno del timer (utilizzata internamente dalla libreria).
Costanti
Limiti di Sistema
#define RBDIMMER_MAX_PHASES 4 // Maximum number of phases
#define RBDIMMER_MAX_CHANNELS 8 // Maximum number of channelsCostanti di Timing
#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)Noise Gate Zero-Cross (v2.0.0)
#define RBDIMMER_ZC_DEBOUNCE_US 3000 // Noise gate window in microsecondsDopo che un interrupt di zero-crossing si attiva, gli interrupt successivi entro questa finestra vengono ignorati. Questo elimina i falsi trigger causati dal rumore elettrico vicino al punto di zero-cross. Il valore predefinito di 3000 us funziona bene sia per la corrente alternata a 50 Hz che a 60 Hz (il mezzo ciclo è 8333 us a 60 Hz e 10000 us a 50 Hz, quindi 3 ms è sicuramente al di sotto di entrambi).
Costanti di Limite del Livello (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 valueQueste costanti definiscono l'intervallo di funzionamento effettivo per tutti i calcoli delle curve:
- RBDIMMER_LEVEL_MIN (3%): Richiedere un livello al di sotto di questa soglia produce un ritardo di 0, il che significa che il TRIAC non si attiva mai e il canale è completamente SPENTO. Questo evita la conduzione inaffidabile con cicli di lavoro molto bassi.
- RBDIMMER_LEVEL_MAX (99%): Richiedere un livello del 100% o superiore viene limitato a questo valore. Ciò garantisce che un ritardo minimo venga sempre applicato, prevenendo la sovrapposizione dell'impulso TRIAC con il punto di zero-cross.
Configurabilità: Nei progetti ESP-IDF, queste costanti possono essere sovrascritte tramite Kconfig (menuconfig). Nei progetti Arduino, fungono da impostazioni predefinite in fase di compilazione e possono essere ridefinite prima di includere l'intestazione della libreria.
Costanti di Frequenza
#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 measurementFunzioni di Inizializzazione
rbdimmer_init()
rbdimmer_err_t rbdimmer_init(void);Inizializza la libreria rbdimmerESP32. Deve essere chiamata prima di qualsiasi altra funzione della libreria.
Restituisce:
- RBDIMMER_OK: Inizializzazione completata
- RBDIMMER_ERR_NO_MEMORY: Allocazione della memoria fallita
Esempio:
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");
}Note: - Inizializza le strutture dati interne - Prepara le tabelle di ricerca per le curve di luminosità - Deve essere chiamata dal task principale/funzione di setup
rbdimmer_deinit()
rbdimmer_err_t rbdimmer_deinit(void);Deinicializza la libreria e rilascia tutte le risorse.
Restituisce:
- RBDIMMER_OK: Deinizializzazione completata
Esempio:
void cleanup() {
rbdimmer_deinit();
Serial.println("Library deinitialized");
}Note: - Elimina automaticamente tutti i canali - Rimuove tutti i gestori di interrupt - Rilascia le risorse GPIO - Chiamare prima del riavvio del sistema o del deep sleep
Gestione Zero-Cross
rbdimmer_register_zero_cross()
rbdimmer_err_t rbdimmer_register_zero_cross(uint8_t pin, uint8_t phase, uint16_t frequency);Registra un rilevatore di zero-crossing per la sincronizzazione AC.
Parametri:
- pin: Pin GPIO collegato al rilevatore zero-cross (0-39)
- phase: Identificatore della fase (0-3)
- frequency: Frequenza della rete prevista in Hz (0 per auto-rilevamento, 50, 60)
Restituisce:
- RBDIMMER_OK: Registrazione completata
- RBDIMMER_ERR_INVALID_ARG: Pin o numero di fase non valido
- RBDIMMER_ERR_ALREADY_EXIST: Fase già registrata
- RBDIMMER_ERR_NO_MEMORY: Numero massimo di fasi raggiunto
- RBDIMMER_ERR_GPIO_FAILED: Configurazione GPIO fallita
Esempio:
// 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);Note: - Deve essere chiamata prima di creare canali sulla stessa fase - Il pin verrà configurato come input con interrupt sul fronte di salita - La frequenza 0 abilita il rilevamento automatico (consigliato) - Ogni fase richiede un rilevatore zero-cross separato
Noise gate (v2.0.0): Dopo ogni zero-crossing rilevato, l'ISR ignora gli interrupt successivi sulla stessa fase per RBDIMMER_ZC_DEBOUNCE_US microsecondi (predefinito 3000). Ciò sopprime i falsi trigger causati da rumore, oscillazioni o segnali zero-cross a salita lenta. La finestra di debounce viene applicata per fase, quindi i sistemi multifase vengono gestiti indipendentemente.
Gestione dei Canali
rbdimmer_create_channel()
rbdimmer_err_t rbdimmer_create_channel(rbdimmer_config_t* config, rbdimmer_channel_t** channel);Crea un nuovo canale dimmer con la configurazione specificata.
Parametri:
- config: Puntatore alla struttura di configurazione
- channel: Puntatore per memorizzare l'handle del canale creato
Restituisce:
- RBDIMMER_OK: Canale creato correttamente
- RBDIMMER_ERR_INVALID_ARG: Configurazione non valida o puntatori NULL
- RBDIMMER_ERR_NOT_FOUND: Fase riferita non registrata
- RBDIMMER_ERR_NO_MEMORY: Allocazione della memoria fallita o numero massimo di canali raggiunto
- RBDIMMER_ERR_GPIO_FAILED: Configurazione GPIO fallita
- RBDIMMER_ERR_TIMER_FAILED: Creazione del timer fallita
Esempio:
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");
}Note: - Il pin GPIO verrà configurato come output - Il canale inizia nello stato attivo - Due timer hardware vengono allocati per ogni canale - Il livello iniziale viene applicato immediatamente
rbdimmer_delete_channel()
rbdimmer_err_t rbdimmer_delete_channel(rbdimmer_channel_t* channel);Elimina un canale dimmer e rilascia tutte le risorse associate.
Parametri:
- channel: Handle del canale da eliminare
Restituisce:
- RBDIMMER_OK: Canale eliminato correttamente
- RBDIMMER_ERR_INVALID_ARG: Handle del canale NULL
- RBDIMMER_ERR_NOT_FOUND: Canale non trovato nel manager
Esempio:
rbdimmer_err_t err = rbdimmer_delete_channel(my_channel);
if (err == RBDIMMER_OK) {
my_channel = NULL; // Prevent accidental reuse
Serial.println("Channel deleted successfully");
}Note: - Interrompe tutti i timer in esecuzione - Imposta l'output GPIO su LOW - Rilascia la memoria allocata - L'handle del canale diventa invalido dopo l'eliminazione
Controllo del Livello
rbdimmer_set_level()
rbdimmer_err_t rbdimmer_set_level(rbdimmer_channel_t* channel, uint8_t level_percent);Imposta il livello di luminosità di un canale dimmer immediatamente.
Parametri:
- channel: Handle del canale di destinazione
- level_percent: Livello di luminosità (0-100%)
Restituisce:
- RBDIMMER_OK: Livello impostato correttamente
- RBDIMMER_ERR_INVALID_ARG: Handle del canale NULL
Esempio:
// 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);Note: - Le modifiche al livello hanno effetto al prossimo zero-crossing - I valori >= 100 vengono limitati a RBDIMMER_LEVEL_MAX (99%) - I valori inferiori a RBDIMMER_LEVEL_MIN (3%) risultano nel canale essere SPENTO (ritardo = 0) - Livello 0 = completamente spento - Thread-safe - può essere chiamato da qualsiasi task
rbdimmer_set_level_transition()
rbdimmer_err_t rbdimmer_set_level_transition(rbdimmer_channel_t* channel, uint8_t level_percent, uint32_t transition_ms);Imposta il livello di luminosità con una transizione fluida nel tempo.
Parametri:
- channel: Handle del canale di destinazione
- level_percent: Livello di luminosità di destinazione (0-100%)
- transition_ms: Durata della transizione in millisecondi
Restituisce:
- RBDIMMER_OK: Transizione avviata correttamente
- RBDIMMER_ERR_INVALID_ARG: Handle del canale NULL
- RBDIMMER_ERR_NO_MEMORY: Creazione del task di transizione fallita
Esempio:
// 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);Note:
- Crea un task FreeRTOS per transizioni fluide
- Non bloccante - restituisce immediatamente
- Il tempo minimo di transizione è 50ms
- Le transizioni più brevi di 50ms utilizzano l'impostazione immediata
- Le transizioni multiple possono essere eseguite simultaneamente su canali diversi
- Il livello di destinazione è soggetto agli stessi limiti LEVEL_MIN / LEVEL_MAX come rbdimmer_set_level()
Funzioni di Configurazione
rbdimmer_set_curve()
rbdimmer_err_t rbdimmer_set_curve(rbdimmer_channel_t* channel, rbdimmer_curve_t curve_type);Imposta il tipo di curva di luminosità per un canale.
Parametri:
- channel: Handle del canale di destinazione
- curve_type: Tipo di curva desiderato
Restituisce:
- RBDIMMER_OK: Curva impostata correttamente
- RBDIMMER_ERR_INVALID_ARG: Handle del canale NULL
Esempio:
// 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);Note: - La modifica ha effetto al prossimo zero-crossing - Le diverse curve si ottimizzano per diversi tipi di carico - Può essere modificato durante il funzionamento senza riavvio - Tutte le curve applicano i limiti LEVEL_MIN / LEVEL_MAX
rbdimmer_set_active()
rbdimmer_err_t rbdimmer_set_active(rbdimmer_channel_t* channel, bool active);Abilita o disabilita un canale dimmer.
Parametri:
- channel: Handle del canale di destinazione
- active: true per abilitare, false per disabilitare
Restituisce:
- RBDIMMER_OK: Stato modificato correttamente
- RBDIMMER_ERR_INVALID_ARG: Handle del canale NULL
Esempio:
// Enable channel
rbdimmer_set_active(my_channel, true);
// Disable channel (output goes to 0)
rbdimmer_set_active(my_channel, false);Note: - I canali disabilitati non consumano tempo di CPU - L'output viene immediatamente impostato su LOW se disabilitato - La configurazione del canale viene preservata se disabilitato - La riabilitazione riprende l'operazione precedente
Recupero delle Informazioni
rbdimmer_get_level()
uint8_t rbdimmer_get_level(rbdimmer_channel_t* channel);Ottiene il livello di luminosità attuale di un canale.
Parametri:
- channel: Handle del canale da interrogare
Restituisce: - Livello di luminosità attuale (0-100%), o 0 se il canale è NULL
Esempio:
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);Ottiene la frequenza della rete misurata per una fase specifica.
Parametri:
- phase: Numero della fase da interrogare (0-3)
Restituisce: - Frequenza misurata in Hz, o 0 se non è stata ancora misurata o la fase non è stata trovata
Esempio:
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");
}Note: - Restituisce 0 durante il periodo di misurazione iniziale - Il rilevamento della frequenza richiede circa 20 cicli AC - Utile per il monitoraggio della qualità dell'alimentazione
rbdimmer_is_active()
bool rbdimmer_is_active(rbdimmer_channel_t* channel);Controlla se un canale è attualmente attivo.
Parametri:
- channel: Handle del canale da interrogare
Restituisce:
- true se il canale è attivo, false se inattivo o NULL
Esempio:
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);Ottiene il tipo di curva attuale di un canale.
Parametri:
- channel: Handle del canale da interrogare
Restituisce:
- Tipo di curva attuale, o RBDIMMER_CURVE_LINEAR se il canale è NULL
Esempio:
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);Ottiene l'impostazione del ritardo attuale in microsecondi.
Parametri:
- channel: Handle del canale da interrogare
Restituisce: - Ritardo attuale in microsecondi, o 0 se il canale è NULL
Esempio:
uint32_t delay_us = rbdimmer_get_delay(my_channel);
Serial.printf("Current delay: %d microseconds\n", delay_us);Note: - Utile per il debugging e l'ottimizzazione - Il ritardo varia con il livello di luminosità e il tipo di curva - Misurato dal zero-crossing all'attivazione del TRIAC - Restituisce 0 quando il livello è al di sotto di RBDIMMER_LEVEL_MIN (canale SPENTO) - Il valore minimo diverso da zero è RBDIMMER_MIN_DELAY_US (100 us)
Funzioni di Callback
rbdimmer_set_callback()
rbdimmer_err_t rbdimmer_set_callback(uint8_t phase, void (*callback)(void*), void* user_data);Imposta una funzione di callback da chiamare su eventi zero-crossing.
Parametri:
- phase: Numero della fase (0-3)
- callback: Funzione da chiamare su zero-crossing (NULL per disabilitare)
- user_data: Puntatore ai dati dell'utente passato al callback
Restituisce:
- RBDIMMER_OK: Callback impostato correttamente
- RBDIMMER_ERR_NOT_FOUND: Fase non registrata
Firma della Funzione di Callback:
void zero_cross_callback(void* user_data);Esempio:
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);Note Importanti: - Il callback viene eseguito nel contesto di interrupt (ISR) - Mantenere il codice del callback minimo e veloce - Nessuna operazione di blocco (ritardi, stampe, ecc.) - Utilizzare le code FreeRTOS per la comunicazione con i task - Il callback viene chiamato ad ogni zero-crossing (100-120 volte al secondo) - In v2.0.0, il callback si attiva solo per gli zero-crossing validi che superano il noise gate (debounce). I trigger spuri entro RBDIMMER_ZC_DEBOUNCE_US di un crossing precedente non invocano il callback.
Funzioni Utilitarie
rbdimmer_update_all()
rbdimmer_err_t rbdimmer_update_all(void);Forza un aggiornamento immediato di tutti i canali attivi.
Restituisce:
- RBDIMMER_OK: Tutti i canali aggiornati correttamente
Esempio:
// After changing multiple channel parameters
rbdimmer_update_all();Note: - Normalmente non è necessario - i canali si aggiornano automaticamente - Utile dopo modifiche di configurazione in blocco - Ricalcola i tempi per tutti i canali attivi
Gestione degli Errori
Descrizioni dei Codici di Errore
| Codice di Errore | Descrizione | Cause Comuni |
|---|---|---|
RBDIMMER_OK |
Successo | Operazione completata normalmente |
RBDIMMER_ERR_INVALID_ARG |
Argomento non valido | Puntatori NULL, valori fuori intervallo |
RBDIMMER_ERR_NO_MEMORY |
Allocazione della memoria fallita | Memoria heap insufficiente |
RBDIMMER_ERR_NOT_FOUND |
Oggetto non trovato | Fase non registrata, canale non trovato |
RBDIMMER_ERR_ALREADY_EXIST |
L'oggetto esiste già | Fase già registrata |
RBDIMMER_ERR_TIMER_FAILED |
Operazione del timer fallita | Timer hardware non disponibile |
RBDIMMER_ERR_GPIO_FAILED |
Operazione GPIO fallita | Pin non valido, pin già in uso |
Migliori Pratiche di Gestione degli Errori
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;
}Esempi di Codice
Setup di Base Completo
#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);
} Controllo Multi-Canale
#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);
} Utilizzo Avanzato di Callback
#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);
} Considerazioni sulle Prestazioni
Utilizzo della Memoria
- Ogni canale utilizza circa 200 byte di RAM
- Overhead della libreria globale: ~1KB RAM
- Utilizzo di memoria flash: ~32KB
Precisione del Timing
- Rilevamento dello zero-crossing: +/-10 microsecondi (dopo il filtraggio del noise gate)
- Attivazione del TRIAC: +/-1 microsecondo
- Misurazione della frequenza: +/-0.1 Hz
Overhead CPU
- Gestione dell'interrupt: <50 microsecondi per zero-crossing
- Elaborazione di background: <1% utilizzo CPU
- Task di transizione: Impatto minimo sulle altre operazioni
Limitazioni
- Massimo 8 canali per ESP32
- Massimo 4 fasi indipendenti
- Larghezza di impulso minima: 50 microsecondi
- Ritardo di attivazione minimo: 100 microsecondi (RBDIMMER_MIN_DELAY_US)
- Intervallo di dimmerazione effettivo: 3%-99% (RBDIMMER_LEVEL_MIN a RBDIMMER_LEVEL_MAX)
- Tempo di transizione massimo: Limitato dalla memoria disponibile per i task
Questo riferimento API copre tutte le funzioni pubbliche e i tipi di dati in rbdimmerESP32 v2.0.0