This commit is contained in:
2025-09-26 10:43:35 +03:00
parent a1a7327e39
commit 514ddd1a3b
2 changed files with 81 additions and 48 deletions

258
src/ate0003.c Normal file
View File

@@ -0,0 +1,258 @@
#include "FreeRTOS.h"
#include "task.h"
#include "avr/io.h"
#include "zh_avr_160x_i2c.h"
#include "zh_avr_encoder.h"
#include "zh_avr_ac_dimmer.h"
#include "ate0003.h"
// #define DEBUG
const component_t component[] = {
{"ANY", "RED", "GREEN", "BLUE", "WHITE", 0xF},
{"334230", "RED", "", "", "", 0x8},
{"334303", "RED", "", "", "", 0x8},
{"334711", "RED", "", "", "", 0x8},
{"334612", "400W", "600W", "", "", 0xC},
};
#ifdef DEBUG
#define BAUD_RATE 9600
#define BAUD_PRESCALE (F_CPU / 16 / BAUD_RATE - 1)
int usart(char byte, FILE *stream)
{
while ((UCSR0A & (1 << UDRE0)) == 0)
{
}
UDR0 = byte;
return 0;
}
FILE uart = FDEV_SETUP_STREAM(usart, NULL, _FDEV_SETUP_WRITE);
#endif
void system_setup_task(void *pvParameters);
#ifdef DEBUG
TaskHandle_t system_setup_task_handle = {0};
#endif
zh_avr_pcf8574_handle_t button_handle = {0};
zh_avr_pcf8574_handle_t led1_handle = {0};
zh_avr_pcf8574_handle_t led2_handle = {0};
zh_avr_pcf8574_handle_t relay_handle = {0};
zh_avr_pcf8574_handle_t lcd_handle = {0};
zh_avr_encoder_handle_t power_encoder_handle = {0};
zh_avr_encoder_handle_t component_encoder_handle = {0};
volatile bool is_work = false;
volatile bool is_dmm = false; // DMM using status.
volatile bool is_fix = false;
volatile uint8_t component_num = 0;
int main(void)
{
//** Encoders init **/
zh_avr_encoder_init_config_t encoder_init_config = ZH_AVR_ENCODER_INIT_CONFIG_DEFAULT();
encoder_init_config.gpio_port = AVR_PORTC;
encoder_init_config.a_gpio_number = PORTC0;
encoder_init_config.b_gpio_number = PORTC1;
encoder_init_config.encoder_min_value = 0;
encoder_init_config.encoder_max_value = 100;
encoder_init_config.encoder_number = POWER_ENCODER;
zh_avr_encoder_init(&encoder_init_config, &power_encoder_handle);
zh_avr_encoder_set(&power_encoder_handle, 100);
encoder_init_config.a_gpio_number = PORTC2;
encoder_init_config.b_gpio_number = PORTC3;
encoder_init_config.encoder_min_value = 0;
encoder_init_config.encoder_max_value = (sizeof(component) / sizeof(component[0])) - 1;
encoder_init_config.encoder_number = COMPONENT_ENCODER;
zh_avr_encoder_init(&encoder_init_config, &component_encoder_handle);
zh_avr_encoder_set(&component_encoder_handle, 0);
//** AC dimmer init **/
zh_avr_ac_dimmer_init_config_t ac_dimmer_init_config = ZH_AVR_AC_DIMMER_INIT_CONFIG_DEFAULT();
ac_dimmer_init_config.ac_dimmer_frequency = ZH_50HZ;
ac_dimmer_init_config.zero_cross_port = AVR_PORTD;
ac_dimmer_init_config.zero_cross_gpio = PORTD3;
ac_dimmer_init_config.triac_port = AVR_PORTD;
ac_dimmer_init_config.triac_gpio = PORTD4;
zh_avr_ac_dimmer_init(&ac_dimmer_init_config);
#ifdef DEBUG
UBRR0H = (BAUD_PRESCALE >> 8);
UBRR0L = BAUD_PRESCALE;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
stdout = &uart;
xTaskCreate(system_setup_task, "system_setup", 107, NULL, tskIDLE_PRIORITY, &system_setup_task_handle);
#else
xTaskCreate(system_setup_task, NULL, 150, NULL, tskIDLE_PRIORITY, NULL);
#endif
vTaskStartScheduler();
return 0;
}
void system_setup_task(void *pvParameters)
{
zh_avr_i2c_master_init(false);
zh_avr_pcf8574_init_config_t pcf8574_init_config = ZH_AVR_PCF8574_INIT_CONFIG_DEFAULT();
pcf8574_init_config.stack_size = 255;
pcf8574_init_config.i2c_address = LED1_I2C_ADDRESS;
zh_avr_pcf8574_init(&pcf8574_init_config, &led1_handle);
zh_avr_pcf8574_write(&led1_handle, 0xFF);
pcf8574_init_config.i2c_address = LED2_I2C_ADDRESS;
zh_avr_pcf8574_init(&pcf8574_init_config, &led2_handle);
zh_avr_pcf8574_write(&led2_handle, 0x0F);
pcf8574_init_config.i2c_address = RELAY_I2C_ADDRESS;
zh_avr_pcf8574_init(&pcf8574_init_config, &relay_handle);
pcf8574_init_config.i2c_address = LCD_I2C_ADDRESS;
zh_avr_pcf8574_init(&pcf8574_init_config, &lcd_handle);
pcf8574_init_config.p0_gpio_work_mode = true;
pcf8574_init_config.p1_gpio_work_mode = true;
pcf8574_init_config.p2_gpio_work_mode = true;
pcf8574_init_config.p3_gpio_work_mode = true;
pcf8574_init_config.p4_gpio_work_mode = true;
pcf8574_init_config.p5_gpio_work_mode = true;
pcf8574_init_config.interrupt_port = AVR_PORTD;
pcf8574_init_config.interrupt_gpio = PORTD2;
pcf8574_init_config.i2c_address = BUTTON_I2C_ADDRESS;
zh_avr_pcf8574_init(&pcf8574_init_config, &button_handle);
zh_avr_160x_init(&lcd_handle, ZH_LCD_16X4);
zh_avr_160x_set_cursor(&lcd_handle, 0, 0);
zh_avr_160x_print_char(&lcd_handle, "LLC AEROTECH");
zh_avr_160x_set_cursor(&lcd_handle, 1, 0);
zh_avr_160x_print_char(&lcd_handle, "ATE0003.000.000");
zh_avr_160x_set_cursor(&lcd_handle, 2, 0);
zh_avr_160x_print_char(&lcd_handle, "Firmware v1.0.0");
zh_avr_160x_set_cursor(&lcd_handle, 3, 0);
zh_avr_160x_print_char(&lcd_handle, "Loading: ");
for (uint8_t i = 0; i <= 100; ++i)
{
zh_avr_160x_set_cursor(&lcd_handle, 3, 10);
zh_avr_160x_print_int(&lcd_handle, i);
zh_avr_160x_print_char(&lcd_handle, "%");
vTaskDelay(50 / portTICK_PERIOD_MS);
}
zh_avr_160x_lcd_clear(&lcd_handle);
zh_avr_160x_set_cursor(&lcd_handle, 0, 0);
zh_avr_160x_print_char(&lcd_handle, "AC POWER: ");
zh_avr_160x_set_cursor(&lcd_handle, 1, 0);
zh_avr_160x_print_char(&lcd_handle, "COMPONENT: ");
vTaskDelete(NULL);
}
#ifdef DEBUG
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{
printf("Task %s Remaining Stack Size %d.\n", pcTaskName, uxTaskGetStackHighWaterMark(xTask));
}
#endif
void zh_avr_pcf8574_event_handler(zh_avr_pcf8574_event_on_isr_t *event)
{
switch (event->gpio_number)
{
case DMM_BUTTON:
if (event->gpio_level == LOW && is_work == false)
{
if (is_dmm == true)
{
zh_avr_pcf8574_write_gpio(&relay_handle, DMM_RELAY, RELAY_ON);
zh_avr_pcf8574_write_gpio(&led1_handle, DMM_LED_RED, LED_ON);
zh_avr_pcf8574_write_gpio(&led1_handle, DMM_LED_GREEN, LED_OFF);
is_dmm = false;
}
else
{
zh_avr_pcf8574_write_gpio(&relay_handle, DMM_RELAY, RELAY_OFF);
zh_avr_pcf8574_write_gpio(&led1_handle, DMM_LED_RED, LED_OFF);
zh_avr_pcf8574_write_gpio(&led1_handle, DMM_LED_GREEN, LED_ON);
is_dmm = true;
}
}
break;
case FIX_BUTTON:
if (event->gpio_level == LOW)
{
zh_avr_pcf8574_write_gpio(&led1_handle, FIX_LED_BLUE, LED_OFF);
zh_avr_pcf8574_write_gpio(&led1_handle, FIX_LED_GREEN, LED_ON);
is_fix = true;
}
else
{
zh_avr_pcf8574_write_gpio(&led1_handle, FIX_LED_BLUE, LED_ON);
zh_avr_pcf8574_write_gpio(&led1_handle, FIX_LED_GREEN, LED_OFF);
is_fix = false;
}
break;
case NUM1_BUTTON:
break;
case NUM2_BUTTON:
break;
case NUM3_BUTTON:
break;
case NUM4_BUTTON:
break;
default:
break;
}
#ifdef DEBUG
printf("Interrupt happened on device address 0x%02X on GPIO number %d at level %d.\n", event->i2c_address, event->gpio_number, event->gpio_level);
#endif
}
void zh_avr_encoder_event_handler(zh_avr_encoder_event_on_isr_t *event)
{
switch (event->encoder_number)
{
case POWER_ENCODER:
zh_avr_ac_dimmer_set(event->encoder_position);
zh_avr_160x_set_cursor(&lcd_handle, 0, 10);
zh_avr_160x_print_int(&lcd_handle, (uint8_t)event->encoder_position);
zh_avr_160x_print_char(&lcd_handle, "% ");
break;
case COMPONENT_ENCODER:
zh_avr_160x_set_cursor(&lcd_handle, 1, 10);
// Set system.
break;
default:
break;
}
#ifdef DEBUG
printf("Encoder number %d position %0.2f.\n", event->encoder_number, event->encoder_position);
#endif
}
ISR(PCINT1_vect)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (zh_avr_encoder_isr_handler(&power_encoder_handle) == pdTRUE)
{
xHigherPriorityTaskWoken = pdTRUE;
}
if (is_work == false)
{
if (zh_avr_encoder_isr_handler(&component_encoder_handle) == pdTRUE)
{
xHigherPriorityTaskWoken = pdTRUE;
}
}
if (xHigherPriorityTaskWoken == pdTRUE)
{
portYIELD();
}
}
ISR(PCINT2_vect)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
zh_avr_ac_dimmer_isr_handler();
if (zh_avr_pcf8574_isr_handler() == pdTRUE)
{
xHigherPriorityTaskWoken = pdTRUE;
}
if (xHigherPriorityTaskWoken == pdTRUE)
{
portYIELD();
}
}