Passa al contenuto

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

c
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

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;

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:

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

Enumerazioni

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;

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

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;

Codici di errore restituiti dalle funzioni della libreria.

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;

Enumerazione dello stato interno del timer (utilizzata internamente dalla libreria).

Costanti

Limiti di Sistema

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

Costanti di Timing

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)

Noise Gate Zero-Cross (v2.0.0)

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

Dopo 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)

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

Queste 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

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

Funzioni di Inizializzazione

rbdimmer_init()

c
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:

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");
}

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()

c
rbdimmer_err_t rbdimmer_deinit(void);

Deinicializza la libreria e rilascia tutte le risorse.

Restituisce: - RBDIMMER_OK: Deinizializzazione completata

Esempio:

c
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()

c
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:

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);

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()

c
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:

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");
}

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()

c
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:

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");
}

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()

c
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:

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);

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()

c
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:

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);

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()

c
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:

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);

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()

c
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:

c
// 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()

c
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:

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);

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:

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");
}

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()

c
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:

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);

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:

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);

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:

c
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()

c
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:

c
void zero_cross_callback(void* user_data);

Esempio:

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);

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()

c
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:

c
// 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

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;
}

Esempi di Codice

Setup di Base Completo

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);
}

Controllo Multi-Canale

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);
}

Utilizzo Avanzato di Callback

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);
}

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