doc: updated readme
This commit is contained in:
1 parent
f02dc77b28
commit
5dfc8b9033
3 files changed
+45
-799
No files matched your search
@@ -1,13 +1,5 @@
|
|||||||
# ESP32 ESP-IDF component for AC dimmer for 115V/400Hz
|
# ESP32 ESP-IDF component for AC dimmer for 115V/400Hz
|
||||||
|
|
||||||
## Wiki
|
|
||||||
|
|
||||||
[EN](WIKI_EN.md) | [RU](WIKI_RU.md)
|
|
||||||
|
|
||||||
## Tested on
|
|
||||||
|
|
||||||
1. [ESP32 ESP-IDF v6.0.0](https://docs.espressif.com/projects/esp-idf/en/v6.0/esp32/index.html)
|
|
||||||
|
|
||||||
## SAST Tools
|
## SAST Tools
|
||||||
|
|
||||||
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) — static analyzer for C, C++, C#, and Java code.
|
[PVS-Studio](https://pvs-studio.com/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source) — static analyzer for C, C++, C#, and Java code.
|
||||||
@@ -19,11 +11,22 @@
|
|||||||
3. IRAM-safe ISR and callback functions for reliable operation.
|
3. IRAM-safe ISR and callback functions for reliable operation.
|
||||||
4. Thread-safe start/stop/set/get API.
|
4. Thread-safe start/stop/set/get API.
|
||||||
|
|
||||||
|
## Note
|
||||||
|
|
||||||
|
Enable the following settings in menuconfig:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GPIO_CTRL_FUNC_IN_IRAM
|
||||||
|
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM
|
||||||
|
CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM
|
||||||
|
CONFIG_GPTIMER_ISR_CACHE_SAFE
|
||||||
|
```
|
||||||
|
|
||||||
## Using
|
## Using
|
||||||
|
|
||||||
In an existing project, run the following command to install the component:
|
In an existing project, run the following command to install the component:
|
||||||
|
|
||||||
```text
|
```bash
|
||||||
cd ../your_project/components
|
cd ../your_project/components
|
||||||
git clone https://github.com/aZholtikov/zh_ac_dimmer
|
git clone https://github.com/aZholtikov/zh_ac_dimmer
|
||||||
```
|
```
|
||||||
@@ -34,6 +37,37 @@ In the application, add the component:
|
|||||||
#include "zh_ac_dimmer.h"
|
#include "zh_ac_dimmer.h"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Example
|
||||||
|
|
||||||
See Wiki [EN](WIKI_EN.md#usage-examples) | [RU](WIKI_RU.md#примеры-использования)
|
```c
|
||||||
|
#include "zh_ac_dimmer.h"
|
||||||
|
|
||||||
|
zh_ac_dimmer_handle_t *ac_dimmer_handle = NULL;
|
||||||
|
|
||||||
|
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 = GPIO_NUM_16;
|
||||||
|
config.triac_gpio = GPIO_NUM_17;
|
||||||
|
zh_ac_dimmer_init(&config, &ac_dimmer_handle);
|
||||||
|
zh_ac_dimmer_start(&ac_dimmer_handle);
|
||||||
|
uint8_t value = 0;
|
||||||
|
for (uint8_t i = 0; i <= 100; ++i)
|
||||||
|
{
|
||||||
|
zh_ac_dimmer_set(&ac_dimmer_handle, i);
|
||||||
|
zh_ac_dimmer_get(&ac_dimmer_handle, &value);
|
||||||
|
printf("Dimmer value: %d.\n", value);
|
||||||
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
for (uint8_t i = 100; i > 0; --i)
|
||||||
|
{
|
||||||
|
zh_ac_dimmer_set(&ac_dimmer_handle, i);
|
||||||
|
zh_ac_dimmer_get(&ac_dimmer_handle, &value);
|
||||||
|
printf("Dimmer value: %d.\n", value);
|
||||||
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
zh_ac_dimmer_stop(&ac_dimmer_handle);
|
||||||
|
zh_ac_dimmer_deinit(&ac_dimmer_handle);
|
||||||
|
}
|
||||||
|
```
|
||||||
-394
@@ -1,394 +0,0 @@
|
|||||||
# zh_ac_dimmer - AC Dimmer Component for ESP-IDF
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Overview](#overview)
|
|
||||||
- [Features](#features)
|
|
||||||
- [Installation](#installation)
|
|
||||||
- [API Reference](#api-reference)
|
|
||||||
- [Usage Examples](#usage-examples)
|
|
||||||
- [Technical Specifications](#technical-specifications)
|
|
||||||
- [Error Codes](#error-codes)
|
|
||||||
- [Contributing](#contributing)
|
|
||||||
- [License](#license)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
`zh_ac_dimmer` is a lightweight ESP-IDF component for AC dimmer control. It provides a simple API to control AC load power using zero-crossing detection and TRIAC control. The component is designed specifically for ESP32 microcontrollers and uses ESP-IDF v5.0+ drivers (GPTimer, GPIO).
|
|
||||||
|
|
||||||
The component supports AC frequency of 400 Hz and uses hardware timers for precise timing control.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
1. **AC Power Control**: Controls AC load power from 0% to 100%
|
|
||||||
2. **Zero-Crossing Detection**: Uses GPIO interrupt for precise timing
|
|
||||||
3. **TRIAC Control**: Controls TRIAC gate with precise timing via GPTimer
|
|
||||||
4. **Hardware Timer**: Uses GPTimer with 1 MHz resolution (1 µs)
|
|
||||||
5. **IRAM-safe ISR and Callback**: Interrupts and callbacks are placed in IRAM for reliable operation
|
|
||||||
6. **Error Handling**: Comprehensive error checking and configuration validation
|
|
||||||
7. **Thread-Safe**: Uses ESP-IDF drivers (thread-safe)
|
|
||||||
8. **Minimal Memory Footprint**: Low memory overhead
|
|
||||||
9. **Simple API**: Lightweight interface with start/stop/set/get support
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Navigate to your project's components directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ../your_project/components
|
|
||||||
```
|
|
||||||
|
|
||||||
Clone the repository:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/aZholtikov/zh_ac_dimmer.git
|
|
||||||
```
|
|
||||||
|
|
||||||
In your application, include the header:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include "zh_ac_dimmer.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
The component will be automatically built with your project.
|
|
||||||
|
|
||||||
### Required Configuration
|
|
||||||
|
|
||||||
For correct operation, please enable the following settings in menuconfig:
|
|
||||||
|
|
||||||
```text
|
|
||||||
GPIO_CTRL_FUNC_IN_IRAM
|
|
||||||
CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM
|
|
||||||
CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM
|
|
||||||
CONFIG_GPTIMER_ISR_CACHE_SAFE
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### zh_ac_dimmer_init_config_t Structure
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
gpio_num_t zero_cross_gpio; // Zero-crossing detection GPIO
|
|
||||||
gpio_num_t triac_gpio; // TRIAC control GPIO
|
|
||||||
} zh_ac_dimmer_init_config_t;
|
|
||||||
```
|
|
||||||
|
|
||||||
Use the `ZH_AC_DIMMER_INIT_CONFIG_DEFAULT()` macro to initialize with default values:
|
|
||||||
|
|
||||||
- `zero_cross_gpio`: GPIO_NUM_MAX
|
|
||||||
- `triac_gpio`: GPIO_NUM_MAX
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_handle_t Structure
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct _zh_ac_dimmer_handle_t zh_ac_dimmer_handle_t;
|
|
||||||
```
|
|
||||||
|
|
||||||
Opaque instance descriptor.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_init()
|
|
||||||
|
|
||||||
Initializes AC dimmer control.
|
|
||||||
|
|
||||||
Allocates memory for handle, validates configuration, initializes GPIO pins (TRIAC as output, zero-crossing as input with positive edge interrupt), sets up ISR service and creates gptimer instance.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
|
|
||||||
- `config` - Pointer to initialization configuration structure. Must not be NULL
|
|
||||||
- `handle` - Pointer to pointer to receive the created handle. Must be NULL
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
|
||||||
- `ESP_ERR_INVALID_ARG` - Invalid argument (NULL handle or invalid GPIO)
|
|
||||||
- `ESP_ERR_INVALID_STATE` - AC dimmer is already initialized
|
|
||||||
- `ESP_ERR_NO_MEM` - Memory allocation failed
|
|
||||||
- `ESP_FAIL` - Initialization error (GPIO, ISR service or timer)
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
|
|
||||||
```c
|
|
||||||
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()
|
|
||||||
|
|
||||||
Deinitializes AC dimmer control and releases resources.
|
|
||||||
|
|
||||||
Stops and deletes gptimer, removes GPIO ISR handler, resets GPIO pins to input mode, frees handle and sets the output pointer to NULL.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
|
|
||||||
- `handle` - Pointer to handle. Must not be NULL
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle or *handle is NULL
|
|
||||||
- `ESP_FAIL` - Timer stop, detach or delete error, or GPIO reset error
|
|
||||||
|
|
||||||
**Important:** After calling this function, the handle becomes invalid. To reinitialize, call `zh_ac_dimmer_init()` again.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_start()
|
|
||||||
|
|
||||||
Starts AC dimmer operation.
|
|
||||||
|
|
||||||
Enables the dimmer so that zero-crossing events trigger TRIAC firing according to the current dimming value.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
|
|
||||||
- `handle` - Pointer to handle. Must not be NULL
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle or *handle is NULL
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_stop()
|
|
||||||
|
|
||||||
Stops AC dimmer operation.
|
|
||||||
|
|
||||||
Disables TRIAC firing on zero-crossing events. The dimmer can be restarted with `zh_ac_dimmer_start()`.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
|
|
||||||
- `handle` - Pointer to handle. Must not be NULL
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle or *handle is NULL
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_set()
|
|
||||||
|
|
||||||
Sets the AC dimmer dimming value.
|
|
||||||
|
|
||||||
Sets the dimming percentage that will be applied on the next zero-crossing event.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
|
|
||||||
- `handle` - Pointer to handle. Must not be NULL
|
|
||||||
- `value` - Dimming level from 0 (off) to 100 (full power)
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle, *handle or value is invalid
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_get()
|
|
||||||
|
|
||||||
Gets the current AC dimmer dimming value.
|
|
||||||
|
|
||||||
**Parameters:**
|
|
||||||
|
|
||||||
- `handle` - Pointer to handle. Must not be NULL
|
|
||||||
- `value` - Pointer to receive the current dimming level (0–100). Must not be NULL
|
|
||||||
|
|
||||||
**Returns:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Success
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle, *handle or value is NULL
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Usage Examples
|
|
||||||
|
|
||||||
### Basic Example: Dimmer Control
|
|
||||||
|
|
||||||
```c
|
|
||||||
#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("Dimmer value: %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("Dimmer value: %d.\n", value);
|
|
||||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|
||||||
}
|
|
||||||
zh_ac_dimmer_stop(&dimmer);
|
|
||||||
zh_ac_dimmer_deinit(&dimmer);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Example: Dimmer with Button Control
|
|
||||||
|
|
||||||
```c
|
|
||||||
#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("Dimmer value: %d\n", dimmer_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
esp_log_level_set("zh_ac_dimmer", ESP_LOG_ERROR);
|
|
||||||
// Initialize dimmer
|
|
||||||
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);
|
|
||||||
// Initialize button
|
|
||||||
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);
|
|
||||||
// Start dimmer
|
|
||||||
zh_ac_dimmer_start(&dimmer);
|
|
||||||
printf("Dimmer initialized. Button on GPIO %d changes dimmer value.\n", BUTTON_GPIO);
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
|
||||||
uint8_t current_value;
|
|
||||||
zh_ac_dimmer_get(&dimmer, ¤t_value);
|
|
||||||
printf("Current dimmer value: %d\n", current_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Technical Specifications
|
|
||||||
|
|
||||||
| Parameter | Value |
|
|
||||||
|-----------|-------|
|
|
||||||
| **Dimming Range** | 0–100% (0 = off, 100 = full power) |
|
|
||||||
| **AC Frequency** | 400 Hz (zero-crossing period: 1250 µs) |
|
|
||||||
| **Zero-Crossing Detection** | GPIO interrupt (positive edge) |
|
|
||||||
| **TRIAC Control** | GPIO output |
|
|
||||||
| **Timer Resolution** | 1 MHz (1 µs) |
|
|
||||||
| **Measurement Time** | ~1250 µs per half-cycle |
|
|
||||||
| **Base TRIAC Delay** | 330 µs (measured with logic analyzer) |
|
|
||||||
| **ESP-IDF Version** | >= 5.0 |
|
|
||||||
| **Platform** | ESP32 family |
|
|
||||||
| **Language** | C (C99) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Error Codes
|
|
||||||
|
|
||||||
| Error Code | Description |
|
|
||||||
|------------|-------------|
|
|
||||||
| `ESP_OK` | Operation successful |
|
|
||||||
| `ESP_ERR_INVALID_ARG` | Invalid argument (NULL pointer, invalid GPIO or invalid dimming value) |
|
|
||||||
| `ESP_ERR_INVALID_STATE` | AC dimmer is already initialized (only for `zh_ac_dimmer_init`) |
|
|
||||||
| `ESP_ERR_NO_MEM` | Memory allocation failed (only for `zh_ac_dimmer_init`) |
|
|
||||||
| `ESP_FAIL` | General error (GPIO, ISR service, timer initialization/deinitialization) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Contributions are welcome! To contribute:
|
|
||||||
|
|
||||||
1. Fork the repository
|
|
||||||
2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
|
|
||||||
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
||||||
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
||||||
5. Open a Pull Request
|
|
||||||
|
|
||||||
Please ensure your code follows the existing style and includes appropriate documentation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the Apache License, Version 2.0 - see the [LICENSE](LICENSE) file for details.
|
|
||||||
|
|
||||||
### Apache License, Version 2.0
|
|
||||||
|
|
||||||
Copyright (c) 2026 Alexey Zholtikov
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Additional Notes
|
|
||||||
|
|
||||||
- **AC Frequency**: Currently only 400 Hz frequency is supported (aviation frequency). The period between zero-crossings is 1250 µs.
|
|
||||||
- **Zero-Crossing Timing**: 1250 µs period (400 Hz) with 330 µs compensation for timer delay. Calculation formula: `alarm_count = (((1250 - 330) / 100) * (100 - dimmer_value)) + 330`.
|
|
||||||
- **GPIO Interrupt**: Zero-crossing detection uses positive edge interrupt with debounce protection (interrupts arriving earlier than 90% of the period are ignored).
|
|
||||||
- **IRAM Requirements**: For correct operation, enable `GPIO_CTRL_FUNC_IN_IRAM`, `CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM`, `CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM` and `CONFIG_GPTIMER_ISR_CACHE_SAFE` in menuconfig.
|
|
||||||
- **Thread Safety**: The component uses ESP-IDF drivers which are thread-safe.
|
|
||||||
- **Safety**: This module interacts with mains voltage. Incorrect wiring or insufficient isolation may result in electric shock or equipment damage. Ensure proper optoisolation and safety compliance before deployment.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Generated for zh_ac_dimmer v3.0.0*
|
|
||||||
-394
@@ -1,394 +0,0 @@
|
|||||||
# zh_ac_dimmer - Компонент управления освещением переменного тока для ESP-IDF
|
|
||||||
|
|
||||||
## Содержание
|
|
||||||
|
|
||||||
- [Обзор](#обзор)
|
|
||||||
- [Возможности](#возможности)
|
|
||||||
- [Установка](#установка)
|
|
||||||
- [Справочник API](#справочник-api)
|
|
||||||
- [Примеры использования](#примеры-использования)
|
|
||||||
- [Технические характеристики](#технические-характеристики)
|
|
||||||
- [Коды ошибок](#коды-ошибок)
|
|
||||||
- [Вклад в проект](#вклад-в-проект)
|
|
||||||
- [Лицензия](#лицензия)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Обзор
|
|
||||||
|
|
||||||
`zh_ac_dimmer` - это легковесный компонент ESP-IDF для управления освещением переменного тока. Он предоставляет простой API для управления мощностью нагрузки переменного тока с использованием детекции перехода через ноль и управления TRIAC. Компонент разработан специально для микроконтроллеров ESP32 и использует драйверы ESP-IDF v5.0+ (GPTimer, GPIO).
|
|
||||||
|
|
||||||
Компонент поддерживает частоту переменного тока 400 Гц и использует аппаратные таймеры для точного управления временем.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Возможности
|
|
||||||
|
|
||||||
1. **Управление мощностью переменного тока**: Управление мощностью нагрузки от 0% до 100%
|
|
||||||
2. **Детекция перехода через ноль**: Использует прерывание GPIO для точного тайминга
|
|
||||||
3. **Управление TRIAC**: Управление затвором TRIAC с точным таймингом через GPTimer
|
|
||||||
4. **Аппаратный таймер**: Использует GPTimer с разрешением 1 МГц (1 мкс)
|
|
||||||
5. **IRAM-safe ISR и callback**: Прерывания и колбэки размещаются в IRAM для надёжной работы
|
|
||||||
6. **Обработка ошибок**: Комплексная проверка ошибок и валидация конфигурации
|
|
||||||
7. **Потокобезопасность**: Использует драйверы ESP-IDF (потокобезопасно)
|
|
||||||
8. **Минимальный объем памяти**: Низкие накладные расходы на память
|
|
||||||
9. **Простой API**: Легковесный интерфейс с поддержкой start/stop/set/get
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Установка
|
|
||||||
|
|
||||||
Перейдите в каталог компонентов вашего проекта:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ../ваш_проект/components
|
|
||||||
```
|
|
||||||
|
|
||||||
Клонируйте репозиторий:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/aZholtikov/zh_ac_dimmer.git
|
|
||||||
```
|
|
||||||
|
|
||||||
В вашем приложении подключите заголовочный файл:
|
|
||||||
|
|
||||||
```c
|
|
||||||
#include "zh_ac_dimmer.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
Компонент будет автоматически собран вместе с вашим проектом.
|
|
||||||
|
|
||||||
### Необходимая конфигурация
|
|
||||||
|
|
||||||
Для правильной работы включите следующие настройки в menuconfig:
|
|
||||||
|
|
||||||
```text
|
|
||||||
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
|
|
||||||
|
|
||||||
```c
|
|
||||||
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_MAX
|
|
||||||
- `triac_gpio`: GPIO_NUM_MAX
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Структура zh_ac_dimmer_handle_t
|
|
||||||
|
|
||||||
```c
|
|
||||||
typedef struct _zh_ac_dimmer_handle_t zh_ac_dimmer_handle_t;
|
|
||||||
```
|
|
||||||
|
|
||||||
Непрозрачный дескриптор экземпляра устройства.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_init()
|
|
||||||
|
|
||||||
Инициализирует управление освещением переменного тока.
|
|
||||||
|
|
||||||
Выделяет память для handle, валидирует конфигурацию, инициализирует GPIO пины (TRIAC как выход, переход через ноль как вход с прерыванием по положительному фронту), устанавливает ISR-сервис и создаёт экземпляр gptimer.
|
|
||||||
|
|
||||||
**Параметры:**
|
|
||||||
|
|
||||||
- `config` - Указатель на структуру конфигурации инициализации. Не должен быть NULL
|
|
||||||
- `handle` - Указатель на указатель для получения созданного handle. Должен быть NULL
|
|
||||||
|
|
||||||
**Возвращает:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
|
||||||
- `ESP_ERR_INVALID_ARG` - Неверный аргумент (NULL handle или неверный GPIO)
|
|
||||||
- `ESP_ERR_INVALID_STATE` - Освещение переменного тока уже инициализировано
|
|
||||||
- `ESP_ERR_NO_MEM` - Не удалось выделить память
|
|
||||||
- `ESP_FAIL` - Ошибка инициализации (GPIO, ISR-сервис или таймер)
|
|
||||||
|
|
||||||
**Пример:**
|
|
||||||
|
|
||||||
```c
|
|
||||||
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 равен NULL
|
|
||||||
- `ESP_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. Не должен быть NULL
|
|
||||||
- `value` - Уровень затухания от 0 (выключено) до 100 (полная мощность)
|
|
||||||
|
|
||||||
**Возвращает:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle, *handle или value недействительны
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### zh_ac_dimmer_get()
|
|
||||||
|
|
||||||
Получает текущее значение затухания освещения переменного тока.
|
|
||||||
|
|
||||||
**Параметры:**
|
|
||||||
|
|
||||||
- `handle` - Указатель на handle. Не должен быть NULL
|
|
||||||
- `value` - Указатель для получения текущего уровня затухания (0–100). Не должен быть NULL
|
|
||||||
|
|
||||||
**Возвращает:**
|
|
||||||
|
|
||||||
- `ESP_OK` - Успех
|
|
||||||
- `ESP_ERR_INVALID_ARG` - handle, *handle или value равен NULL
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Примеры использования
|
|
||||||
|
|
||||||
### Базовый пример: Управление затуханием
|
|
||||||
|
|
||||||
```c
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Пример: Управление затуханием с кнопкой
|
|
||||||
|
|
||||||
```c
|
|
||||||
#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-сервис, инициализация/деинициализация таймера) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Вклад в проект
|
|
||||||
|
|
||||||
Вклад приветствуется! Чтобы внести свой вклад:
|
|
||||||
|
|
||||||
1. Сделайте форк репозитория
|
|
||||||
2. Создайте ветку функции (`git checkout -b feature/AmazingFeature`)
|
|
||||||
3. Закоммитьте ваши изменения (`git commit -m 'Add some AmazingFeature'`)
|
|
||||||
4. Отправьте в ветку (`git push origin feature/AmazingFeature`)
|
|
||||||
5. Откройте Pull Request
|
|
||||||
|
|
||||||
Пожалуйста, убедитесь, что ваш код следует существующему стилю и включает соответствующую документацию.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Лицензия
|
|
||||||
|
|
||||||
Этот проект лицензирован по лицензии Apache, версия 2.0 - см. файл [LICENSE](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*
|
|
||||||
Reference in new issue
Block a user