Ir al contenido

Referencia de API de rbdimmerESP32

Actualizado para v2.0.0 -- la API pública no ha cambiado, pero la arquitectura interna es completamente modular.

Descripción General

La biblioteca rbdimmerESP32 proporciona una API completa para controlar dimmers AC con microcontroladores ESP32. La API está diseñada teniendo en cuenta la seguridad, el rendimiento y la facilidad de uso, con integración de temporizadores de hardware y operación controlada por interrupciones.

Principios de Diseño Clave

  • Segura para Hilos: Todas las funciones son seguras para llamarse desde múltiples tareas FreeRTOS
  • Optimizada por Hardware: Utiliza temporizadores de hardware ESP32 para precisión de microsegundos
  • Gestión de Recursos: Limpieza automática y manejo de errores
  • Extensible: Soporte para múltiples fases y canales
  • Modular (v2.0.0): La arquitectura interna es completamente modular -- el motor de curvas, el backend del temporizador y el detector de cruce cero son componentes independientes

Tipos de Datos

Tipos Opacos

rbdimmer_channel_t

c
typedef struct rbdimmer_channel_s rbdimmer_channel_t;

Identificador opaco que representa un canal dimmer. Todas las operaciones del canal utilizan este identificador.

Notas de Uso: - Creado por rbdimmer_create_channel() - Debe ser destruido correctamente con rbdimmer_delete_channel() - No puede ser copiado o serializado

Estructuras de Configuración

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;

Estructura de configuración para crear canales 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

Ejemplo:

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

Enumeraciones

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;

Define el tipo de curva de brillo para el cálculo de potencia.

Tipos de Curva: - LINEAR: Conversión directa de porcentaje a ángulo de fase - RMS: Potencia compensada para cargas resistivas (bombillas incandescentes) - LOGARITHMIC: Lineal perceptivamente para cargas LED - CUSTOM: Reservado para implementación de curva personalizada futura

Limitación de nivel (v2.0.0): Todos los cálculos de curva aplican límites LEVEL_MIN y LEVEL_MAX. Los niveles >= 100% se limitan a RBDIMMER_LEVEL_MAX (99% por defecto). Los niveles por debajo de RBDIMMER_LEVEL_MIN (3% por defecto) devuelven delay = 0, lo que significa que el canal está APAGADO. Esto evita disparo TRIAC no confiable en ángulos de conducción casi cero o casi completos.

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;

Códigos de error devueltos por funciones de la biblioteca.

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;

Enumeración de estado de temporizador interno (utilizada internamente por la biblioteca).

Constantes

Límites del Sistema

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

Constantes de Temporización

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)

Puerta de Ruido de Cruce Cero (v2.0.0)

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

Después de que se dispara una interrupción de cruce cero, las interrupciones posteriores dentro de esta ventana se ignoran. Esto elimina los disparos falsos causados por ruido eléctrico cerca del punto de cruce cero. El valor predeterminado de 3000 µs funciona bien tanto para 50 Hz como para 60 Hz (medio ciclo es 8333 µs a 60 Hz y 10000 µs a 50 Hz, por lo que 3 ms está seguramente por debajo de cualquiera).

Constantes de Límite de Nivel (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

Estas constantes definen el rango operativo efectivo para todos los cálculos de curva:

  • RBDIMMER_LEVEL_MIN (3%): Solicitar un nivel por debajo de este umbral produce un delay de 0, lo que significa que el TRIAC nunca se dispara y el canal está completamente APAGADO. Esto evita conducción parcial no confiable en ciclos de trabajo muy bajos.
  • RBDIMMER_LEVEL_MAX (99%): Solicitar un nivel del 100% o superior se limita a este valor. Esto asegura que siempre se aplique un delay mínimo, evitando que el pulso TRIAC se superponga con el punto de cruce cero.

Configurabilidad: En proyectos ESP-IDF, estas constantes pueden ser anuladas a través de Kconfig (menuconfig). En proyectos Arduino, actúan como valores predeterminados en tiempo de compilación y pueden ser redefinidos antes de incluir el encabezado de la biblioteca.

Constantes de Frecuencia

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

Funciones de Inicialización

rbdimmer_init()

c
rbdimmer_err_t rbdimmer_init(void);

Inicializa la biblioteca rbdimmerESP32. Debe ser llamada antes de cualquier otra función de la biblioteca.

Devuelve: - RBDIMMER_OK: Inicialización exitosa - RBDIMMER_ERR_NO_MEMORY: Falló la asignación de memoria

Ejemplo:

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

Notas: - Inicializa estructuras de datos internas - Prepara tablas de búsqueda para curvas de brillo - Debe ser llamada desde la tarea principal/función setup

rbdimmer_deinit()

c
rbdimmer_err_t rbdimmer_deinit(void);

Desinicializa la biblioteca y libera todos los recursos.

Devuelve: - RBDIMMER_OK: Desinicialization exitosa

Ejemplo:

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

Notas: - Elimina automáticamente todos los canales - Elimina todos los manejadores de interrupciones - Libera recursos GPIO - Llame antes de reiniciar el sistema o dormir profundamente

Gestión de Cruce Cero

rbdimmer_register_zero_cross()

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

Registra un detector de cruce cero para sincronización AC.

Parámetros: - pin: Pin GPIO conectado al detector de cruce cero (0-39) - phase: Identificador de fase (0-3) - frequency: Frecuencia de red esperada en Hz (0 para auto-detección, 50, 60)

Devuelve: - RBDIMMER_OK: Registro exitoso - RBDIMMER_ERR_INVALID_ARG: Pin o número de fase inválido - RBDIMMER_ERR_ALREADY_EXIST: Fase ya registrada - RBDIMMER_ERR_NO_MEMORY: Máximo de fases alcanzado - RBDIMMER_ERR_GPIO_FAILED: Falló la configuración de GPIO

Ejemplo:

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

Notas: - Debe ser llamada antes de crear canales en la misma fase - El pin será configurado como entrada con interrupción en flanco ascendente - Frecuencia 0 habilita la detección automática (recomendado) - Cada fase requiere un detector de cruce cero separado

Puerta de ruido (v2.0.0): Después de cada cruce cero detectado, el ISR ignora interrupciones adicionales en la misma fase durante RBDIMMER_ZC_DEBOUNCE_US microsegundos (3000 por defecto). Esto suprime disparos falsos causados por ruido, ringing o señales de cruce cero de aumento lento. La ventana de debounce se aplica por fase, por lo que los sistemas multifase se manejan independientemente.

Gestión de Canales

rbdimmer_create_channel()

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

Crea un nuevo canal dimmer con la configuración especificada.

Parámetros: - config: Puntero a la estructura de configuración - channel: Puntero para almacenar el identificador del canal creado

Devuelve: - RBDIMMER_OK: Canal creado exitosamente - RBDIMMER_ERR_INVALID_ARG: Configuración inválida o punteros NULL - RBDIMMER_ERR_NOT_FOUND: Fase referenciada no registrada - RBDIMMER_ERR_NO_MEMORY: Falló la asignación de memoria o máximo de canales alcanzado - RBDIMMER_ERR_GPIO_FAILED: Falló la configuración de GPIO - RBDIMMER_ERR_TIMER_FAILED: Falló la creación del temporizador

Ejemplo:

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

Notas: - El pin GPIO será configurado como salida - El canal comienza en estado activo - Se asignan dos temporizadores de hardware por canal - El nivel inicial se aplica inmediatamente

rbdimmer_delete_channel()

c
rbdimmer_err_t rbdimmer_delete_channel(rbdimmer_channel_t* channel);

Elimina un canal dimmer y libera todos los recursos asociados.

Parámetros: - channel: Identificador del canal a eliminar

Devuelve: - RBDIMMER_OK: Canal eliminado exitosamente - RBDIMMER_ERR_INVALID_ARG: Identificador de canal NULL - RBDIMMER_ERR_NOT_FOUND: Canal no encontrado en el gestor

Ejemplo:

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

Notas: - Detiene todos los temporizadores en ejecución - Establece la salida GPIO en LOW - Libera memoria asignada - El identificador del canal se vuelve inválido después de la eliminación

Control de Nivel

rbdimmer_set_level()

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

Establece el nivel de brillo de un canal dimmer inmediatamente.

Parámetros: - channel: Identificador del canal destino - level_percent: Nivel de brillo (0-100%)

Devuelve: - RBDIMMER_OK: Nivel establecido exitosamente - RBDIMMER_ERR_INVALID_ARG: Identificador de canal NULL

Ejemplo:

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

Notas: - Los cambios de nivel toman efecto en el próximo cruce cero - Los valores >= 100 se limitan a RBDIMMER_LEVEL_MAX (99%) - Los valores por debajo de RBDIMMER_LEVEL_MIN (3%) resultan en que el canal esté APAGADO (delay = 0) - Nivel 0 = completamente apagado - Seguro para hilos - puede ser llamado desde cualquier tarea

rbdimmer_set_level_transition()

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

Establece el nivel de brillo con una transición suave en el tiempo.

Parámetros: - channel: Identificador del canal destino - level_percent: Nivel de brillo objetivo (0-100%) - transition_ms: Duración de la transición en milisegundos

Devuelve: - RBDIMMER_OK: Transición iniciada exitosamente - RBDIMMER_ERR_INVALID_ARG: Identificador de canal NULL - RBDIMMER_ERR_NO_MEMORY: Falló la creación de la tarea de transición

Ejemplo:

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

Notas: - Crea una tarea FreeRTOS para transiciones suaves - No bloqueante - devuelve inmediatamente - El tiempo mínimo de transición es 50ms - Las transiciones más cortas que 50ms usan configuración inmediata - Múltiples transiciones pueden ejecutarse simultáneamente en diferentes canales - El nivel objetivo está sujeto a la misma limitación LEVEL_MIN / LEVEL_MAX que rbdimmer_set_level()

Funciones de Configuración

rbdimmer_set_curve()

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

Establece el tipo de curva de brillo para un canal.

Parámetros: - channel: Identificador del canal destino - curve_type: Tipo de curva deseado

Devuelve: - RBDIMMER_OK: Curva establecida exitosamente - RBDIMMER_ERR_INVALID_ARG: Identificador de canal NULL

Ejemplo:

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

Notas: - El cambio toma efecto en el próximo cruce cero - Diferentes curvas optimizan para diferentes tipos de carga - Puede ser cambiado durante la operación sin reinicio - Todas las curvas aplican límites LEVEL_MIN / LEVEL_MAX

rbdimmer_set_active()

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

Habilita o deshabilita un canal dimmer.

Parámetros: - channel: Identificador del canal destino - active: true para habilitar, false para deshabilitar

Devuelve: - RBDIMMER_OK: Estado cambiado exitosamente - RBDIMMER_ERR_INVALID_ARG: Identificador de canal NULL

Ejemplo:

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

Notas: - Los canales deshabilitados no consumen tiempo de CPU - La salida se establece inmediatamente en LOW cuando está deshabilitada - La configuración del canal se conserva cuando está deshabilitado - La reactivación reanuda la operación anterior

Recuperación de Información

rbdimmer_get_level()

c
uint8_t rbdimmer_get_level(rbdimmer_channel_t* channel);

Obtiene el nivel de brillo actual de un canal.

Parámetros: - channel: Identificador del canal a consultar

Devuelve: - Nivel de brillo actual (0-100%), o 0 si el canal es NULL

Ejemplo:

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

Obtiene la frecuencia de red medida para una fase específica.

Parámetros: - phase: Número de fase a consultar (0-3)

Devuelve: - Frecuencia medida en Hz, o 0 si aún no se ha medido o la fase no se encontró

Ejemplo:

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

Notas: - Devuelve 0 durante el período de medición inicial - La detección de frecuencia toma aproximadamente 20 ciclos AC - Útil para monitoreo de calidad de potencia

rbdimmer_is_active()

c
bool rbdimmer_is_active(rbdimmer_channel_t* channel);

Verifica si un canal está activo actualmente.

Parámetros: - channel: Identificador del canal a consultar

Devuelve: - true si el canal está activo, false si está inactivo o NULL

Ejemplo:

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

Obtiene el tipo de curva actual de un canal.

Parámetros: - channel: Identificador del canal a consultar

Devuelve: - Tipo de curva actual, o RBDIMMER_CURVE_LINEAR si el canal es NULL

Ejemplo:

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

Obtiene la configuración de delay actual en microsegundos.

Parámetros: - channel: Identificador del canal a consultar

Devuelve: - Delay actual en microsegundos, o 0 si el canal es NULL

Ejemplo:

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

Notas: - Útil para depuración y optimización - El delay varía con el nivel de brillo y tipo de curva - Medido desde cruce cero a disparo TRIAC - Devuelve 0 cuando el nivel está por debajo de RBDIMMER_LEVEL_MIN (canal APAGADO) - El valor no cero mínimo es RBDIMMER_MIN_DELAY_US (100 µs)

Funciones de Callback

rbdimmer_set_callback()

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

Establece una función de callback para ser llamada en eventos de cruce cero.

Parámetros: - phase: Número de fase (0-3) - callback: Función a llamar en cruce cero (NULL para deshabilitar) - user_data: Puntero de datos de usuario pasado al callback

Devuelve: - RBDIMMER_OK: Callback establecido exitosamente - RBDIMMER_ERR_NOT_FOUND: Fase no registrada

Firma de Función de Callback:

c
void zero_cross_callback(void* user_data);

Ejemplo:

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

Notas Importantes: - El callback se ejecuta en contexto de interrupción (ISR) - Mantenga el código del callback mínimo y rápido - No hay operaciones de bloqueo (delays, prints, etc.) - Use colas FreeRTOS para comunicación con tareas - El callback se llama en cada cruce cero (100-120 veces por segundo) - En v2.0.0, el callback se dispara solo para cruces cero válidos que pasan la puerta de ruido (debounce). Los disparos espurios dentro de RBDIMMER_ZC_DEBOUNCE_US de un cruce anterior no invocan el callback.

Funciones de Utilidad

rbdimmer_update_all()

c
rbdimmer_err_t rbdimmer_update_all(void);

Fuerza una actualización inmediata de todos los canales activos.

Devuelve: - RBDIMMER_OK: Todos los canales actualizados exitosamente

Ejemplo:

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

Notas: - Normalmente no es necesario - los canales se actualizan automáticamente - Útil después de cambios de configuración en bulk - Recalcula la temporización para todos los canales activos

Manejo de Errores

Descripción de Códigos de Error

Código de Error Descripción Causas Comunes
RBDIMMER_OK Éxito Operación completada normalmente
RBDIMMER_ERR_INVALID_ARG Argumento inválido Punteros NULL, valores fuera de rango
RBDIMMER_ERR_NO_MEMORY Falló la asignación de memoria Memoria heap insuficiente
RBDIMMER_ERR_NOT_FOUND Objeto no encontrado Fase no registrada, canal no encontrado
RBDIMMER_ERR_ALREADY_EXIST Objeto ya existe Fase ya registrada
RBDIMMER_ERR_TIMER_FAILED Falló la operación del temporizador Temporizador de hardware no disponible
RBDIMMER_ERR_GPIO_FAILED Falló la operación de GPIO Pin inválido, pin ya en uso

Mejores Prácticas de Manejo de Errores

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

Ejemplos de Código

Configuración Básica Completa

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

Control Multicanal

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

Uso de Callback Avanzado

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

Consideraciones de Rendimiento

Uso de Memoria

  • Cada canal utiliza aproximadamente 200 bytes de RAM
  • Sobrecarga de biblioteca global: ~1KB RAM
  • Uso de memoria flash: ~32KB

Precisión de Temporización

  • Detección de cruce cero: +/-10 microsegundos (después del filtrado de puerta de ruido)
  • Disparo TRIAC: +/-1 microsegundo
  • Medición de frecuencia: +/-0.1 Hz

Sobrecarga de CPU

  • Manejo de interrupciones: <50 microsegundos por cruce cero
  • Procesamiento en background: <1% de uso de CPU
  • Tareas de transición: Impacto mínimo en otras operaciones

Limitaciones

  • Máximo 8 canales por ESP32
  • Máximo 4 fases independientes
  • Ancho de pulso mínimo: 50 microsegundos
  • Delay de disparo mínimo: 100 microsegundos (RBDIMMER_MIN_DELAY_US)
  • Rango de dimming efectivo: 3%-99% (RBDIMMER_LEVEL_MIN a RBDIMMER_LEVEL_MAX)
  • Tiempo de transición máximo: Limitado por memoria disponible para tareas

Esta referencia de API cubre todas las funciones públicas y tipos de datos en rbdimmerESP32 v2.0.0