diff --git a/include/zh_avr_ac_dimmer.h b/include/zh_avr_ac_dimmer.h index 2dd9bc7..fd71481 100644 --- a/include/zh_avr_ac_dimmer.h +++ b/include/zh_avr_ac_dimmer.h @@ -1,62 +1,76 @@ #pragma once -// #include "FreeRTOS.h" -// #include "semphr.h" +#include "stdio.h" #include "avr_err.h" +#include "avr_port.h" #include "stdbool.h" #include "avr/interrupt.h" -#include "avr/pgmspace.h" +// #include "avr/pgmspace.h" #define ZH_AVR_AC_DIMMER_INIT_CONFIG_DEFAULT() \ { \ - .task_priority = configMAX_PRIORITIES, \ - .stack_size = 124, \ - .queue_size = 1, \ - .a_gpio_number = 0, \ - .b_gpio_number = 0, \ - .pullup = false, \ - .encoder_min_value = -100, \ - .encoder_max_value = 100, \ - .encoder_step = 1, \ - .encoder_number = 0} + .ac_dimmer_frequency = ZH_50HZ, \ + .zero_cross_gpio = 0xFF, \ + .zero_cross_port = 0, \ + .triac_gpio = 0xFF, \ + .triac_port = 0} #ifdef __cplusplus extern "C" { #endif + typedef enum + { + ZH_50HZ = 1, + ZH_60HZ, + ZH_400HZ + } zh_avr_ac_dimmer_frequency_t; + typedef struct // Structure for initial initialization of AC dimmer. { - uint8_t task_priority; // Task priority for the PCF8574 expander isr processing. @note It is not recommended to set a value less than configMAX_PRIORITIES. - uint8_t stack_size; // Stack size for task for the PCF8574 expander isr processing processing. @note The minimum size is 124 byte. - uint8_t i2c_address; // Expander I2C address. - bool p0_gpio_work_mode; // Expander GPIO PO work mode. True for input, false for output. - bool p1_gpio_work_mode; // Expander GPIO P1 work mode. True for input, false for output. - bool p2_gpio_work_mode; // Expander GPIO P2 work mode. True for input, false for output. - bool p3_gpio_work_mode; // Expander GPIO P3 work mode. True for input, false for output. - bool p4_gpio_work_mode; // Expander GPIO P4 work mode. True for input, false for output. - bool p5_gpio_work_mode; // Expander GPIO P5 work mode. True for input, false for output. - bool p6_gpio_work_mode; // Expander GPIO P6 work mode. True for input, false for output. - bool p7_gpio_work_mode; // Expander GPIO P7 work mode. True for input, false for output. - uint8_t interrupt_gpio; // Interrupt GPIO. @attention Must be same for all PCF8574 expanders. - uint8_t interrupt_port; // Interrupt port. - } zh_avr_pcf8574_init_config_t; + uint8_t ac_dimmer_frequency; // AC frequency. + uint8_t zero_cross_gpio; // Zero cross GPIO. + uint8_t zero_cross_port; // Zero cross port. + uint8_t triac_gpio; // Triac GPIO. + uint8_t triac_port; // Triac port. + } zh_avr_ac_dimmer_init_config_t; /** - * @brief Initialize PCF8574 expander. + * @brief Initialize AC dimmer. * - * @param[in] config Pointer to PCF8574 initialized configuration structure. Can point to a temporary variable. - * @param[out] handle Pointer to unique PCF8574 handle. + * @param[in] config Pointer to AC dimmer initialized configuration structure. Can point to a temporary variable. * - * @attention I2C driver must be initialized first. + * @note Before initialize the expander recommend initialize zh_avr_ac_dimmer_init_config_t structure with default values. * - * @note Before initialize the expander recommend initialize zh_avr_pcf8574_init_config_t structure with default values. - * - * @code zh_avr_pcf8574_init_config_t config = ZH_AVR_PCF8574_INIT_CONFIG_DEFAULT() @endcode + * @code zh_avr_ac_dimmer_init_config_t config = ZH_AVR_AC_DIMMER_INIT_CONFIG_DEFAULT @endcode * * @return AVR_OK if success or an error code otherwise. */ - avr_err_t zh_avr_pcf8574_init(const zh_avr_pcf8574_init_config_t *config, zh_avr_pcf8574_handle_t *handle); + avr_err_t zh_avr_ac_dimmer_init(const zh_avr_ac_dimmer_init_config_t *config); + + /** + * @brief Start AC dimmer. + * + * @return AVR_OK if success or an error code otherwise. + */ + avr_err_t zh_avr_ac_dimmer_start(void); + + /** + * @brief Stop AC dimmer. + * + * @return AVR_OK if success or an error code otherwise. + */ + avr_err_t zh_avr_ac_dimmer_stop(void); + + /** + * @brief Set AC dimmer dimming value. + * + * @param[in] value Dimming value (0 to 100). + * + * @return AVR_OK if success or an error code otherwise. + */ + avr_err_t zh_avr_ac_dimmer_set(uint8_t value); #ifdef __cplusplus } diff --git a/triac_400hz_delay — копия.xlsx b/triac_400hz_delay — копия.xlsx new file mode 100644 index 0000000..aa41f37 Binary files /dev/null and b/triac_400hz_delay — копия.xlsx differ diff --git a/zh_avr_ac_dimmer.c b/zh_avr_ac_dimmer.c index 7b5dbeb..cbfb82e 100644 --- a/zh_avr_ac_dimmer.c +++ b/zh_avr_ac_dimmer.c @@ -1,12 +1,88 @@ #include "zh_avr_ac_dimmer.h" -const static uint8_t _triac_400hz_delay[100] PROGMEM = {0, 155, 153, 152, 150, 148, 147, 145, 144, 142, - 141, 139, 137, 136, 134, 133, 131, 130, 128, 127, - 125, 123, 122, 120, 119, 117, 116, 114, 112, 111, - 109, 108, 106, 105, 103, 102, 100, 98, 97, 95, - 94, 92, 91, 89, 87, 86, 84, 83, 81, 80, - 78, 77, 75, 73, 72, 70, 69, 67, 66, 64, - 62, 61, 59, 58, 56, 55, 53, 52, 50, 48, - 47, 45, 44, 42, 41, 39, 37, 36, 34, 33, - 31, 30, 28, 27, 25, 23, 22, 20, 19, 17, - 16, 14, 12, 11, 9, 8, 6, 5, 3, 2}; +volatile static bool _is_dimmer_work = false; +volatile static uint8_t _dimmer_value = 0; +static bool _is_initialized = false; + +static avr_err_t _zh_avr_ac_dimmer_validate_config(const zh_avr_ac_dimmer_init_config_t *config); + +static avr_err_t zh_avr_ac_dimmer_init(const zh_avr_ac_dimmer_init_config_t *config) +{ + ZH_ERROR_CHECK(_is_initialized == false, AVR_ERR_INVALID_STATE); + avr_err_t err = _zh_avr_pcf8574_validate_config(config); + ZH_ERROR_CHECK(err == AVR_OK, err); + switch (config->zero_cross_port) + { + case AVR_PORTB: + DDRB &= ~(1 << config->zero_cross_gpio); + PORTB |= (1 << config->zero_cross_gpio); + PCICR |= (1 << PCIE0); + PCMSK0 |= (1 << config->zero_cross_gpio); + break; + case AVR_PORTC: + DDRC &= ~(1 << config->zero_cross_gpio); + PORTC |= (1 << config->zero_cross_gpio); + PCICR |= (1 << PCIE1); + PCMSK1 |= (1 << config->zero_cross_gpio); + break; + case AVR_PORTD: + DDRD &= ~(1 << config->zero_cross_gpio); + PORTD |= (1 << config->zero_cross_gpio); + PCICR |= (1 << PCIE2); + PCMSK2 |= (1 << config->zero_cross_gpio); + break; + default: + break; + } + switch (config->triac_port) + { + case AVR_PORTB: + DDRB |= (1 << config->triac_gpio); + PORTB &= ~(1 << config->triac_gpio); + break; + case AVR_PORTC: + DDRC |= (1 << config->triac_gpio); + PORTC &= ~(1 << config->triac_gpio); + break; + case AVR_PORTD: + DDRD |= (1 << config->triac_gpio); + PORTD &= ~(1 << config->triac_gpio); + break; + default: + break; + } + _is_initialized = true; + return AVR_OK; +} + +static avr_err_t zh_avr_ac_dimmer_start(void) +{ + ZH_ERROR_CHECK(_is_initialized == true, AVR_ERR_NOT_FOUND); + _is_dimmer_work = true; + return AVR_OK; +} + +static avr_err_t zh_avr_ac_dimmer_stop(void) +{ + ZH_ERROR_CHECK(_is_initialized == true, AVR_ERR_NOT_FOUND); + _is_dimmer_work = false; + return AVR_OK; +} + +static avr_err_t zh_avr_ac_dimmer_set(uint8_t value) +{ + ZH_ERROR_CHECK(_dimmer_value <= 100, AVR_ERR_INVALID_ARG); + _dimmer_value = value; + return AVR_OK; +} + +static avr_err_t _zh_avr_ac_dimmer_validate_config(const zh_avr_ac_dimmer_init_config_t *config) +{ + ZH_ERROR_CHECK(config != NULL, AVR_ERR_INVALID_ARG); + ZH_ERROR_CHECK((config->zero_cross_gpio >= 0 && config->zero_cross_gpio <= 7), AVR_ERR_INVALID_ARG); + ZH_ERROR_CHECK((config->triac_gpio >= 0 && config->triac_gpio <= 7), AVR_ERR_INVALID_ARG); + ZH_ERROR_CHECK(config->zero_cross_port >= AVR_PORTB && config->zero_cross_port <= AVR_PORTD, AVR_ERR_INVALID_ARG); + ZH_ERROR_CHECK(config->triac_port >= AVR_PORTB && config->triac_port <= AVR_PORTD, AVR_ERR_INVALID_ARG); + ZH_ERROR_CHECK(config->ac_dimmer_frequency >= ZH_50HZ && config->ac_dimmer_frequency <= ZH_400HZ, AVR_ERR_INVALID_ARG); + return AVR_OK; +} \ No newline at end of file