rbdimmerESP32 API Справочник
Обновлено для v2.0.0 -- публичный API не изменился, но внутренняя архитектура полностью модульная.
Обзор
Библиотека rbdimmerESP32 предоставляет комплексный API для управления AC диммерами с микроконтроллерами ESP32. API разработан с учётом безопасности, производительности и удобства использования, включая интеграцию с аппаратными таймерами и прерывание-управляемую работу.
Ключевые принципы проектирования
- Потокобезопасность: Все функции безопасны для вызова из нескольких задач FreeRTOS
- Аппаратная оптимизация: Использует аппаратные таймеры ESP32 для микросекундной точности
- Управление ресурсами: Автоматическая очистка и обработка ошибок
- Расширяемость: Поддержка нескольких фаз и каналов
- Модульность (v2.0.0): Внутренняя архитектура полностью модульная -- engine кривых, backend таймера и детектор zero-cross являются независимыми компонентами
Типы данных
Непрозрачные типы
rbdimmer_channel_t
typedef struct rbdimmer_channel_s rbdimmer_channel_t;Непрозрачный дескриптор, представляющий канал диммера. Все операции с каналом используют этот дескриптор.
Примечания к использованию:
- Создаётся функцией rbdimmer_create_channel()
- Должен быть должным образом удалён с помощью rbdimmer_delete_channel()
- Не может быть скопирован или сериализован
Структуры конфигурации
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;Структура конфигурации для создания каналов диммера.
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
Пример:
rbdimmer_config_t config = {
.gpio_pin = 4,
.phase = 0,
.initial_level = 50,
.curve_type = RBDIMMER_CURVE_RMS
};Перечисления
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;Определяет тип кривой яркости для расчёта мощности.
Типы кривых: - 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
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
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;Внутреннее перечисление состояния таймера (используется внутренне библиотекой).
Константы
Системные лимиты
#define RBDIMMER_MAX_PHASES 4 // Maximum number of phases
#define RBDIMMER_MAX_CHANNELS 8 // Maximum number of channelsКонстанты времени
#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)
#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)
#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 они действуют как значения по умолчанию времени компиляции и могут быть переопределены перед включением заголовка библиотеки.
Константы частоты
#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()
rbdimmer_err_t rbdimmer_init(void);Инициализирует библиотеку rbdimmerESP32. Должна быть вызвана перед любыми другими функциями библиотеки.
Возвращает:
- RBDIMMER_OK: Инициализация успешна
- RBDIMMER_ERR_NO_MEMORY: Ошибка выделения памяти
Пример:
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()
rbdimmer_err_t rbdimmer_deinit(void);Деинициализирует библиотеку и освобождает все ресурсы.
Возвращает:
- RBDIMMER_OK: Деинициализация успешна
Пример:
void cleanup() {
rbdimmer_deinit();
Serial.println("Library deinitialized");
}Примечания: - Автоматически удаляет все каналы - Удаляет все обработчики прерываний - Освобождает GPIO ресурсы - Вызовите перед перезагрузкой системы или глубоким сном
Управление zero-cross
rbdimmer_register_zero_cross()
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
Пример:
// 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()
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: Ошибка создания таймера
Пример:
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()
rbdimmer_err_t rbdimmer_delete_channel(rbdimmer_channel_t* channel);Удаляет канал диммера и освобождает все связанные ресурсы.
Параметры:
- channel: Дескриптор канала для удаления
Возвращает:
- RBDIMMER_OK: Канал успешно удалён
- RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала
- RBDIMMER_ERR_NOT_FOUND: Канал не найден в менеджере
Пример:
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()
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 дескриптор канала
Пример:
// 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()
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: Ошибка создания задачи переходов
Пример:
// 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()
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 дескриптор канала
Пример:
// 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()
rbdimmer_err_t rbdimmer_set_active(rbdimmer_channel_t* channel, bool active);Включает или отключает канал диммера.
Параметры:
- channel: Дескриптор целевого канала
- active: true для включения, false для отключения
Возвращает:
- RBDIMMER_OK: Состояние успешно изменено
- RBDIMMER_ERR_INVALID_ARG: NULL дескриптор канала
Пример:
// 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()
uint8_t rbdimmer_get_level(rbdimmer_channel_t* channel);Получает текущий уровень яркости канала.
Параметры:
- channel: Дескриптор канала для запроса
Возвращает: - Текущий уровень яркости (0-100%), или 0 если канал NULL
Пример:
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);Получает измеренную частоту сети для конкретной фазы.
Параметры:
- phase: Номер фазы для запроса (0-3)
Возвращает: - Измеренная частота в Гц, или 0 если она ещё не измерена или фаза не найдена
Пример:
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()
bool rbdimmer_is_active(rbdimmer_channel_t* channel);Проверяет, активен ли в настоящий момент канал.
Параметры:
- channel: Дескриптор канала для запроса
Возвращает:
- true если канал активен, false если неактивен или NULL
Пример:
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);Получает текущий тип кривой канала.
Параметры:
- channel: Дескриптор канала для запроса
Возвращает:
- Текущий тип кривой, или RBDIMMER_CURVE_LINEAR если канал NULL
Пример:
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);Получает текущую установку задержки в микросекундах.
Параметры:
- channel: Дескриптор канала для запроса
Возвращает: - Текущая задержка в микросекундах, или 0 если канал NULL
Пример:
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()
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: Фаза не зарегистрирована
Сигнатура функции обратного вызова:
void zero_cross_callback(void* user_data);Пример:
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()
rbdimmer_err_t rbdimmer_update_all(void);Принудительно обновляет все активные каналы немедленно.
Возвращает:
- RBDIMMER_OK: Все каналы успешно обновлены
Пример:
// 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 уже в использовании |
Лучшие практики обработки ошибок
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;
}Примеры кода
Полная базовая установка
#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);
} Управление несколькими каналами
#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);
} Продвинутое использование обратного вызова
#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