Перейти к содержимому

rbdimmerESP32 API Справочник

Обновлено для v2.0.0 -- публичный API не изменился, но внутренняя архитектура полностью модульная.

Обзор

Библиотека rbdimmerESP32 предоставляет комплексный API для управления AC диммерами с микроконтроллерами ESP32. API разработан с учётом безопасности, производительности и удобства использования, включая интеграцию с аппаратными таймерами и прерывание-управляемую работу.

Ключевые принципы проектирования

  • Потокобезопасность: Все функции безопасны для вызова из нескольких задач FreeRTOS
  • Аппаратная оптимизация: Использует аппаратные таймеры ESP32 для микросекундной точности
  • Управление ресурсами: Автоматическая очистка и обработка ошибок
  • Расширяемость: Поддержка нескольких фаз и каналов
  • Модульность (v2.0.0): Внутренняя архитектура полностью модульная -- engine кривых, backend таймера и детектор zero-cross являются независимыми компонентами

Типы данных

Непрозрачные типы

rbdimmer_channel_t

c
typedef struct rbdimmer_channel_s rbdimmer_channel_t;

Непрозрачный дескриптор, представляющий канал диммера. Все операции с каналом используют этот дескриптор.

Примечания к использованию: - Создаётся функцией rbdimmer_create_channel() - Должен быть должным образом удалён с помощью rbdimmer_delete_channel() - Не может быть скопирован или сериализован

Структуры конфигурации

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;

Структура конфигурации для создания каналов диммера.

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

Пример:

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

Перечисления

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;

Определяет тип кривой яркости для расчёта мощности.

Типы кривых: - LINEAR: Прямое преобразование процента в угол фазы - RMS: Компенсированная по мощности для резистивных нагрузок (лампы накаливания) - LOGARITHMIC: Перцептивно линейная для LED нагрузок - CUSTOM: Зарезервирована для будущей реализации пользовательской кривой

Зажим уровня (v2.0.0): Все расчёты кривых применяют границы LEVEL_MIN и LEVEL_MAX. Уровни >= 100% зажимаются до RBDIMMER_LEVEL_MAX (99% по умолчанию). Уровни ниже RBDIMMER_LEVEL_MIN (3% по умолчанию) возвращают delay = 0, что означает, что канал выключен. Это предотвращает ненадёжное срабатывание TRIAC при близких к нулю или близких к полной проводимости углах.

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;

Коды ошибок, возвращаемые функциями библиотеки.

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;

Внутреннее перечисление состояния таймера (используется внутренне библиотекой).

Константы

Системные лимиты

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

Константы времени

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

Шумовой фильтр Zero-Cross (v2.0.0)

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

После срабатывания прерывания zero-crossing, последующие прерывания в пределах этого окна игнорируются. Это исключает ложные срабатывания от электрических помех вблизи точки zero-cross. Значение по умолчанию 3000 мкс хорошо работает как для сетей 50 Гц, так и 60 Гц (полупериод составляет 8333 мкс при 60 Гц и 10000 мкс при 50 Гц, поэтому 3 мс безопасно ниже любого из них).

Константы границ уровня (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

Эти константы определяют эффективный диапазон работы для всех расчётов кривых:

  • RBDIMMER_LEVEL_MIN (3%): Запрос уровня ниже этого порога производит delay = 0, то есть TRIAC никогда не срабатывает и канал полностью выключен. Это избегает ненадёжной частичной проводимости при очень низких коэффициентах заполнения.
  • RBDIMMER_LEVEL_MAX (99%): Запрос уровня 100% или выше зажимается до этого значения. Это гарантирует, что минимальное время задержки всегда применяется, предотвращая перекрытие импульса TRIAC с точкой zero-cross.

Конфигурируемость: В проектах ESP-IDF эти константы можно переопределить через Kconfig (menuconfig). В проектах Arduino они действуют как значения по умолчанию времени компиляции и могут быть переопределены перед включением заголовка библиотеки.

Константы частоты

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

Функции инициализации

rbdimmer_init()

c
rbdimmer_err_t rbdimmer_init(void);

Инициализирует библиотеку rbdimmerESP32. Должна быть вызвана перед любыми другими функциями библиотеки.

Возвращает: - RBDIMMER_OK: Инициализация успешна - RBDIMMER_ERR_NO_MEMORY: Ошибка выделения памяти

Пример:

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

Примечания: - Инициализирует внутренние структуры данных - Подготавливает таблицы поиска для кривых яркости - Должна быть вызвана из главной задачи/функции setup

rbdimmer_deinit()

c
rbdimmer_err_t rbdimmer_deinit(void);

Деинициализирует библиотеку и освобождает все ресурсы.

Возвращает: - RBDIMMER_OK: Деинициализация успешна

Пример:

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

Примечания: - Автоматически удаляет все каналы - Удаляет все обработчики прерываний - Освобождает GPIO ресурсы - Вызовите перед перезагрузкой системы или глубоким сном

Управление zero-cross

rbdimmer_register_zero_cross()

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

Регистрирует детектор zero-crossing для синхронизации AC.

Параметры: - pin: GPIO pin, подключённый к детектору zero-cross (0-39) - phase: Идентификатор фазы (0-3) - frequency: Ожидаемая частота сети в Гц (0 для автоопределения, 50, 60)

Возвращает: - RBDIMMER_OK: Регистрация успешна - RBDIMMER_ERR_INVALID_ARG: Неправильный pin или номер фазы - RBDIMMER_ERR_ALREADY_EXIST: Фаза уже зарегистрирована - RBDIMMER_ERR_NO_MEMORY: Достигнут максимум фаз - RBDIMMER_ERR_GPIO_FAILED: Ошибка конфигурации GPIO

Пример:

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

Примечания: - Должна быть вызвана перед созданием каналов на той же фазе - Pin будет настроен как вход с прерыванием по растущему фронту - Частота 0 включает автоматическое обнаружение (рекомендуется) - Каждая фаза требует отдельного детектора zero-cross

Шумовой фильтр (v2.0.0): После каждого обнаруженного zero-crossing, ISR игнорирует дальнейшие прерывания на той же фазе в течение RBDIMMER_ZC_DEBOUNCE_US микросекунд (по умолчанию 3000). Это подавляет ложные срабатывания, вызванные помехами, звоном или медленным нарастанием сигнала zero-cross. Окно debounce применяется для каждой фазы, поэтому многофазные системы обрабатываются независимо.

Управление каналами

rbdimmer_create_channel()

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

Создаёт новый канал диммера с указанной конфигурацией.

Параметры: - config: Указатель на структуру конфигурации - channel: Указатель для сохранения дескриптора созданного канала

Возвращает: - RBDIMMER_OK: Канал успешно создан - RBDIMMER_ERR_INVALID_ARG: Неправильная конфигурация или NULL указатели - RBDIMMER_ERR_NOT_FOUND: Указанная фаза не зарегистрирована - RBDIMMER_ERR_NO_MEMORY: Ошибка выделения памяти или превышен максимум каналов - RBDIMMER_ERR_GPIO_FAILED: Ошибка конфигурации GPIO - RBDIMMER_ERR_TIMER_FAILED: Ошибка создания таймера

Пример:

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

Примечания: - GPIO pin будет настроен как выход - Канал начинает работу в активном состоянии - Два аппаратных таймера выделяются для каждого канала - Начальный уровень применяется сразу же

rbdimmer_delete_channel()

c
rbdimmer_err_t rbdimmer_delete_channel(rbdimmer_channel_t* channel);

Удаляет канал диммера и освобождает все связанные ресурсы.

Параметры: - channel: Дескриптор канала для удаления

Возвращает: - RBDIMMER_OK: Канал успешно удалён - RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала - RBDIMMER_ERR_NOT_FOUND: Канал не найден в менеджере

Пример:

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

Примечания: - Останавливает все запущенные таймеры - Устанавливает выход GPIO в LOW - Освобождает выделенную память - Дескриптор канала становится недействительным после удаления

Управление уровнем

rbdimmer_set_level()

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

Немедленно устанавливает уровень яркости канала диммера.

Параметры: - channel: Дескриптор целевого канала - level_percent: Уровень яркости (0-100%)

Возвращает: - RBDIMMER_OK: Уровень успешно установлен - RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала

Пример:

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

Примечания: - Изменение уровня вступает в силу на следующем zero-crossing - Значения >= 100 зажимаются до RBDIMMER_LEVEL_MAX (99%) - Значения ниже RBDIMMER_LEVEL_MIN (3%) приводят к отключению канала (delay = 0) - Уровень 0 = полностью выключен - Потокобезопасна - может быть вызвана из любой задачи

rbdimmer_set_level_transition()

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

Устанавливает уровень яркости с плавным переходом во времени.

Параметры: - channel: Дескриптор целевого канала - level_percent: Целевой уровень яркости (0-100%) - transition_ms: Продолжительность переходов в миллисекундах

Возвращает: - RBDIMMER_OK: Переход успешно начат - RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала - RBDIMMER_ERR_NO_MEMORY: Ошибка создания задачи переходов

Пример:

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

Примечания: - Создаёт задачу FreeRTOS для плавных переходов - Неблокирующая - возвращает управление сразу же - Минимальное время переходов 50мс - Переходы короче 50мс используют немедленную установку - Множественные переходы могут выполняться одновременно на разных каналах - Целевой уровень подлежит тому же зажиму LEVEL_MIN / LEVEL_MAX что и rbdimmer_set_level()

Функции конфигурации

rbdimmer_set_curve()

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

Устанавливает тип кривой яркости для канала.

Параметры: - channel: Дескриптор целевого канала - curve_type: Желаемый тип кривой

Возвращает: - RBDIMMER_OK: Кривая успешно установлена - RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала

Пример:

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

Примечания: - Изменение вступает в силу на следующем zero-crossing - Различные кривые оптимизированы для разных типов нагрузок - Может быть изменена во время операции без перезагрузки - Все кривые применяют границы LEVEL_MIN / LEVEL_MAX

rbdimmer_set_active()

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

Включает или отключает канал диммера.

Параметры: - channel: Дескриптор целевого канала - active: true для включения, false для отключения

Возвращает: - RBDIMMER_OK: Состояние успешно изменено - RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала

Пример:

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

Примечания: - Отключённые каналы не потребляют время CPU - Выход немедленно устанавливается в LOW при отключении - Конфигурация канала сохраняется при отключении - Повторное включение возобновляет предыдущую операцию

Получение информации

rbdimmer_get_level()

c
uint8_t rbdimmer_get_level(rbdimmer_channel_t* channel);

Получает текущий уровень яркости канала.

Параметры: - channel: Дескриптор канала для запроса

Возвращает: - Текущий уровень яркости (0-100%), или 0 если канал NULL

Пример:

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

Получает измеренную частоту сети для конкретной фазы.

Параметры: - phase: Номер фазы для запроса (0-3)

Возвращает: - Измеренная частота в Гц, или 0 если она ещё не измерена или фаза не найдена

Пример:

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

Примечания: - Возвращает 0 во время начального периода измерения - Обнаружение частоты занимает около 20 циклов AC - Полезно для мониторинга качества электроэнергии

rbdimmer_is_active()

c
bool rbdimmer_is_active(rbdimmer_channel_t* channel);

Проверяет, активен ли в настоящий момент канал.

Параметры: - channel: Дескриптор канала для запроса

Возвращает: - true если канал активен, false если неактивен или NULL

Пример:

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

Получает текущий тип кривой канала.

Параметры: - channel: Дескриптор канала для запроса

Возвращает: - Текущий тип кривой, или RBDIMMER_CURVE_LINEAR если канал NULL

Пример:

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

Получает текущую установку задержки в микросекундах.

Параметры: - channel: Дескриптор канала для запроса

Возвращает: - Текущая задержка в микросекундах, или 0 если канал NULL

Пример:

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

Примечания: - Полезна для отладки и оптимизации - Задержка варьируется с уровнем яркости и типом кривой - Измеряется от zero-crossing до срабатывания TRIAC - Возвращает 0 когда уровень ниже RBDIMMER_LEVEL_MIN (канал выключен) - Минимальное ненулевое значение RBDIMMER_MIN_DELAY_US (100 мкс)

Функции обратного вызова

rbdimmer_set_callback()

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

Устанавливает функцию обратного вызова для событий zero-crossing.

Параметры: - phase: Номер фазы (0-3) - callback: Функция для вызова при zero-crossing (NULL для отключения) - user_data: Указатель на пользовательские данные, передаваемый в обратный вызов

Возвращает: - RBDIMMER_OK: Обратный вызов успешно установлен - RBDIMMER_ERR_NOT_FOUND: Фаза не зарегистрирована

Сигнатура функции обратного вызова:

c
void zero_cross_callback(void* user_data);

Пример:

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

Важные примечания: - Обратный вызов выполняется в контексте прерывания (ISR) - Держите код обратного вызова минимальным и быстрым - Не используйте блокирующие операции (задержки, печать и т.д.) - Используйте очереди FreeRTOS для обмена данными с задачами - Обратный вызов вызывается на каждом zero-crossing (100-120 раз в секунду) - В v2.0.0 обратный вызов срабатывает только для действительных zero-crossings, прошедших шумовой фильтр (debounce). Ложные срабатывания в пределах RBDIMMER_ZC_DEBOUNCE_US после предыдущего перехода не вызывают обратный вызов.

Вспомогательные функции

rbdimmer_update_all()

c
rbdimmer_err_t rbdimmer_update_all(void);

Принудительно обновляет все активные каналы немедленно.

Возвращает: - RBDIMMER_OK: Все каналы успешно обновлены

Пример:

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

Примечания: - Обычно не требуется - каналы обновляются автоматически - Полезна после массовых изменений конфигурации - Пересчитывает синхронизацию для всех активных каналов

Обработка ошибок

Описание кодов ошибок

Код ошибки Описание Частые причины
RBDIMMER_OK Успех Операция завершена нормально
RBDIMMER_ERR_INVALID_ARG Неправильный аргумент NULL указатели, значения вне диапазона
RBDIMMER_ERR_NO_MEMORY Ошибка выделения памяти Недостаточно памяти кучи
RBDIMMER_ERR_NOT_FOUND Объект не найден Фаза не зарегистрирована, канал не найден
RBDIMMER_ERR_ALREADY_EXIST Объект уже существует Фаза уже зарегистрирована
RBDIMMER_ERR_TIMER_FAILED Ошибка операции таймера Аппаратный таймер недоступен
RBDIMMER_ERR_GPIO_FAILED Ошибка операции GPIO Неправильный pin, pin уже в использовании

Лучшие практики обработки ошибок

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

Примеры кода

Полная базовая установка

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

Управление несколькими каналами

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

Продвинутое использование обратного вызова

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

Соображения по производительности

Использование памяти

  • Каждый канал использует примерно 200 байт RAM
  • Глобальные накладные расходы библиотеки: ~1KB RAM
  • Использование Flash памяти: ~32KB

Точность синхронизации

  • Обнаружение zero-crossing: +/-10 микросекунд (после фильтрации шумов)
  • Срабатывание TRIAC: +/-1 микросекунда
  • Измерение частоты: +/-0.1 Гц

Нагрузка на CPU

  • Обработка прерыванийчения: <50 микросекунд на zero-crossing
  • Фоновая обработка: <1% использования CPU
  • Задачи переходов: Минимальное воздействие на другие операции

Ограничения

  • Максимум 8 каналов на ESP32
  • Максимум 4 независимых фазы
  • Минимальная ширина импульса: 50 микросекунд
  • Минимальная задержка срабатывания: 100 микросекунд (RBDIMMER_MIN_DELAY_US)
  • Эффективный диапазон затемнения: 3%-99% (RBDIMMER_LEVEL_MIN до RBDIMMER_LEVEL_MAX)
  • Максимальное время переходов: Ограничено доступной памятью для задач

Этот справочник API охватывает все публичные функции и типы данных в rbdimmerESP32 v2.0.0