18 KiB
zh_ac_dimmer - Компонент управления освещением переменного тока для ESP-IDF
Содержание
- Обзор
- Возможности
- Установка
- Справочник API
- Примеры использования
- Технические характеристики
- Коды ошибок
- Вклад в проект
- Лицензия
Обзор
zh_ac_dimmer - это легковесный компонент ESP-IDF для управления освещением переменного тока. Он предоставляет простой API для управления мощностью нагрузки переменного тока с использованием детекции перехода через ноль и управления TRIAC. Компонент разработан специально для микроконтроллеров ESP32 и использует драйверы ESP-IDF v5.0+ (GPTimer, GPIO).
Компонент поддерживает частоту переменного тока 400 Гц и использует аппаратные таймеры для точного управления временем.
Возможности
- Управление мощностью переменного тока: Управление мощностью нагрузки от 0% до 100%
- Детекция перехода через ноль: Использует прерывание GPIO для точного тайминга
- Управление TRIAC: Управление затвором TRIAC с точным таймингом через GPTimer
- Аппаратный таймер: Использует GPTimer с разрешением 1 МГц (1 мкс)
- IRAM-safe ISR и callback: Прерывания и колбэки размещаются в IRAM для надёжной работы
- Обработка ошибок: Комплексная проверка ошибок и валидация конфигурации
- Потокобезопасность: Использует драйверы ESP-IDF (потокобезопасно)
- Минимальный объем памяти: Низкие накладные расходы на память
- Простой API: Легковесный интерфейс с поддержкой start/stop/set/get
Установка
Перейдите в каталог компонентов вашего проекта:
cd ../ваш_проект/components
Клонируйте репозиторий:
git clone https://github.com/aZholtikov/zh_ac_dimmer.git
В вашем приложении подключите заголовочный файл:
#include "zh_ac_dimmer.h"
Компонент будет автоматически собран вместе с вашим проектом.
Необходимая конфигурация
Для правильной работы включите следующие настройки в menuconfig:
GPIO_CTRL_FUNC_IN_IRAM
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM
CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM
CONFIG_GPTIMER_ISR_CACHE_SAFE
Справочник API
Структура zh_ac_dimmer_init_config_t
typedef struct
{
gpio_num_t zero_cross_gpio; // GPIO детекции перехода через ноль
gpio_num_t triac_gpio; // GPIO управления TRIAC
} zh_ac_dimmer_init_config_t;
Используйте макрос ZH_AC_DIMMER_INIT_CONFIG_DEFAULT() для инициализации значениями по умолчанию:
zero_cross_gpio: GPIO_NUM_MAXtriac_gpio: GPIO_NUM_MAX
Структура zh_ac_dimmer_handle_t
typedef struct _zh_ac_dimmer_handle_t zh_ac_dimmer_handle_t;
Непрозрачный дескриптор экземпляра устройства.
zh_ac_dimmer_init()
Инициализирует управление освещением переменного тока.
Выделяет память для handle, валидирует конфигурацию, инициализирует GPIO пины (TRIAC как выход, переход через ноль как вход с прерыванием по положительному фронту), устанавливает ISR-сервис и создаёт экземпляр gptimer.
Параметры:
config- Указатель на структуру конфигурации инициализации. Не должен быть NULLhandle- Указатель на указатель для получения созданного handle. Должен быть NULL
Возвращает:
ESP_OK- УспехESP_ERR_INVALID_ARG- Неверный аргумент (NULL handle или неверный GPIO)ESP_ERR_INVALID_STATE- Освещение переменного тока уже инициализированоESP_ERR_NO_MEM- Не удалось выделить памятьESP_FAIL- Ошибка инициализации (GPIO, ISR-сервис или таймер)
Пример:
zh_ac_dimmer_handle_t *dimmer = NULL;
zh_ac_dimmer_init_config_t config = ZH_AC_DIMMER_INIT_CONFIG_DEFAULT();
config.zero_cross_gpio = GPIO_NUM_16;
config.triac_gpio = GPIO_NUM_17;
esp_err_t err = zh_ac_dimmer_init(&config, &dimmer);
zh_ac_dimmer_deinit()
Деинициализирует управление освещением переменного тока и освобождает ресурсы.
Останавливает и удаляет gptimer, удаляет ISR-обработчик GPIO, сбрасывает пины GPIO в режим ввода, освобождает handle и устанавливает выходной указатель в NULL.
Параметры:
handle- Указатель на handle. Не должен быть NULL
Возвращает:
ESP_OK- УспехESP_ERR_INVALID_ARG- handle или *handle равен NULLESP_FAIL- Ошибка остановки таймера, отключения или удаления, или сброса GPIO
Важно: После вызова этой функции handle становится недействительным. Для повторной инициализации вызовите zh_ac_dimmer_init() заново.
zh_ac_dimmer_start()
Запускает работу освещения переменного тока.
Включает диммер, чтобы события перехода через ноль запускали срабатывание TRIAC в соответствии с текущим значением затухания.
Параметры:
handle- Указатель на handle. Не должен быть NULL
Возвращает:
ESP_OK- УспехESP_ERR_INVALID_ARG- handle или *handle равен NULL
zh_ac_dimmer_stop()
Останавливает работу освещения переменного тока.
Отключает срабатывание TRIAC на событиях перехода через ноль. Диммер может быть перезапущен с помощью zh_ac_dimmer_start().
Параметры:
handle- Указатель на handle. Не должен быть NULL
Возвращает:
ESP_OK- УспехESP_ERR_INVALID_ARG- handle или *handle равен NULL
zh_ac_dimmer_set()
Устанавливает значение затухания освещения переменного тока.
Устанавливает процент затухания, который будет применён на следующем событии перехода через ноль.
Параметры:
handle- Указатель на handle. Не должен быть NULLvalue- Уровень затухания от 0 (выключено) до 100 (полная мощность)
Возвращает:
ESP_OK- УспехESP_ERR_INVALID_ARG- handle, *handle или value недействительны
zh_ac_dimmer_get()
Получает текущее значение затухания освещения переменного тока.
Параметры:
handle- Указатель на handle. Не должен быть NULLvalue- Указатель для получения текущего уровня затухания (0–100). Не должен быть NULL
Возвращает:
ESP_OK- УспехESP_ERR_INVALID_ARG- handle, *handle или value равен NULL
Примеры использования
Базовый пример: Управление затуханием
#include "zh_ac_dimmer.h"
void app_main(void)
{
esp_log_level_set("zh_ac_dimmer", ESP_LOG_ERROR);
zh_ac_dimmer_handle_t *dimmer = NULL;
zh_ac_dimmer_init_config_t config = ZH_AC_DIMMER_INIT_CONFIG_DEFAULT();
config.zero_cross_gpio = GPIO_NUM_16;
config.triac_gpio = GPIO_NUM_17;
zh_ac_dimmer_init(&config, &dimmer);
zh_ac_dimmer_start(&dimmer);
uint8_t value = 0;
for (uint8_t i = 0; i <= 100; ++i)
{
zh_ac_dimmer_set(&dimmer, i);
zh_ac_dimmer_get(&dimmer, &value);
printf("Значение затухания: %d.\n", value);
vTaskDelay(100 / portTICK_PERIOD_MS);
}
for (uint8_t i = 100; i > 0; --i)
{
zh_ac_dimmer_set(&dimmer, i);
zh_ac_dimmer_get(&dimmer, &value);
printf("Значение затухания: %d.\n", value);
vTaskDelay(100 / portTICK_PERIOD_MS);
}
zh_ac_dimmer_stop(&dimmer);
zh_ac_dimmer_deinit(&dimmer);
}
Пример: Управление затуханием с кнопкой
#include "zh_ac_dimmer.h"
#define ZERO_CROSS_GPIO GPIO_NUM_16
#define TRIAC_GPIO GPIO_NUM_17
#define BUTTON_GPIO GPIO_NUM_0
static uint8_t dimmer_value = 50;
static zh_ac_dimmer_handle_t *dimmer = NULL;
static void IRAM_ATTR button_isr_handler(void *arg)
{
(void)arg;
dimmer_value = (dimmer_value + 10) % 110;
if (dimmer_value > 100)
{
dimmer_value = 0;
}
zh_ac_dimmer_set(&dimmer, dimmer_value);
printf("Значение затухания: %d\n", dimmer_value);
}
void app_main(void)
{
esp_log_level_set("zh_ac_dimmer", ESP_LOG_ERROR);
// Инициализация затухания
zh_ac_dimmer_init_config_t config = ZH_AC_DIMMER_INIT_CONFIG_DEFAULT();
config.zero_cross_gpio = ZERO_CROSS_GPIO;
config.triac_gpio = TRIAC_GPIO;
zh_ac_dimmer_init(&config, &dimmer);
// Инициализация кнопки
gpio_config_t button_config = {
.intr_type = GPIO_INTR_POSEDGE,
.mode = GPIO_MODE_INPUT,
.pin_bit_mask = (1ULL << BUTTON_GPIO),
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.pull_up_en = GPIO_PULLUP_ENABLE,
};
gpio_config(&button_config);
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
gpio_isr_handler_add(BUTTON_GPIO, button_isr_handler, NULL);
// Запуск затухания
zh_ac_dimmer_start(&dimmer);
printf("Затухание инициализировано. Кнопка на GPIO %d меняет значение затухания.\n", BUTTON_GPIO);
for (;;)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
uint8_t current_value;
zh_ac_dimmer_get(&dimmer, ¤t_value);
printf("Текущее значение затухания: %d\n", current_value);
}
}
Технические характеристики
| Параметр | Значение |
|---|---|
| Диапазон затухания | 0–100% (0 = выкл, 100 = полная мощность) |
| Частота переменного тока | 400 Гц (период перехода через ноль: 1250 мкс) |
| Детекция перехода через ноль | Прерывание GPIO (положительный фронт) |
| Управление TRIAC | Выход GPIO |
| Разрешение таймера | 1 МГц (1 мкс) |
| Время измерения | ~1250 мкс на полупериод |
| Базовая задержка TRIAC | 330 мкс (измерено логическим анализатором) |
| Версия ESP-IDF | >= 5.0 |
| Платформа | Семейство ESP32 |
| Язык | C (C99) |
Коды ошибок
| Код ошибки | Описание |
|---|---|
ESP_OK |
Операция выполнена успешно |
ESP_ERR_INVALID_ARG |
Неверный аргумент (NULL указатель, неверный GPIO или неверное значение затухания) |
ESP_ERR_INVALID_STATE |
Освещение переменного тока уже инициализировано (только для zh_ac_dimmer_init) |
ESP_ERR_NO_MEM |
Не удалось выделить память (только для zh_ac_dimmer_init) |
ESP_FAIL |
Общая ошибка (GPIO, ISR-сервис, инициализация/деинициализация таймера) |
Вклад в проект
Вклад приветствуется! Чтобы внести свой вклад:
- Сделайте форк репозитория
- Создайте ветку функции (
git checkout -b feature/AmazingFeature) - Закоммитьте ваши изменения (
git commit -m 'Add some AmazingFeature') - Отправьте в ветку (
git push origin feature/AmazingFeature) - Откройте Pull Request
Пожалуйста, убедитесь, что ваш код следует существующему стилю и включает соответствующую документацию.
Лицензия
Этот проект лицензирован по лицензии Apache, версия 2.0 - см. файл LICENSE для подробной информации.
Apache License, Version 2.0
Авторское право (c) 2026 Алексей Жолтиков
Лицензировано по лицензии Apache License, Version 2.0 (далее — "Лицензия"); вы не можете использовать этот файл, кроме случаев, предусмотренных Лицензией. Копию Лицензии можно получить по адресу:
http://www.apache.org/licenses/LICENSE-2.0
Если иное не требуется действующим законодательством или не согласовано в письменном виде, программное обеспечение, распространяемое по Лицензии, распространяется на условиях "КАК ЕСТЬ", БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, явных или подразумеваемых, включая, но не ограничиваясь, гарантии ТОВАРНОГО СОСТОЯНИЯ, ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ И НЕНАРУШЕНИЯ ПРАВ. Смотрите Лицензию для получения конкретных прав и ограничений.
Дополнительные заметки
- Частота переменного тока: В настоящее время поддерживается только частота 400 Гц (авиационная частота). Период между переходами через ноль составляет 1250 мкс.
- Тайминг перехода через ноль: 1250 мкс период (400 Гц) с компенсацией 330 мкс для задержки таймера. Формула расчёта:
alarm_count = (((1250 - 330) / 100) * (100 - dimmer_value)) + 330. - Прерывание GPIO: Детекция перехода через ноль использует прерывание положительного фронта с защитой от дребезга (игнорируются прерывания, пришедшие ранее 90% от периода).
- Требования IRAM: Для правильной работы включите
GPIO_CTRL_FUNC_IN_IRAM,CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM,CONFIG_GPTIMER_CTRL_FUNC_IN_IRAMиCONFIG_GPTIMER_ISR_CACHE_SAFEв menuconfig. - Потокобезопасность: Компонент использует драйверы ESP-IDF, которые являются потокобезопасными.
- Безопасность: Данный модуль взаимодействует с сетевым напряжением. Неправильное подключение или недостаточная изоляция могут привести к поражению электрическим током или повреждению оборудования. Убедитесь в наличии правильной оптоизоляции и соблюдении требований безопасности перед развёртыванием.
Сгенерировано для zh_ac_dimmer v3.0.0