Files
HECO2/program/User/My_Hood.c
T
jeon 5a96a696b1 chore: HERV 통합 저장소 초기 커밋
- 펌웨어(program), C# 대시보드(TestProgram), 시뮬레이터(Simulator),
  프로토콜/문서(Protocol, doc) 전체를 단일 저장소로 통합
- program 폴더의 별도 git 저장소를 제거하고 통합 저장소에 흡수
- 빌드 산출물(program/build, bin/obj, *.o/.elf/.bin/.hex 등) .gitignore 처리
- 사내 Synology NAS Git 원격 연결 예정

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 21:44:23 +09:00

249 lines
6.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "My_define.h"
////////////////////////////////////////////////////////////////////////////////
//////////////////////// HOOD 485 //////////////////////////////////////////////
extern uint16_t Hood_polling_timer;
extern uint8_t rx_hood_485_TimeOut;
uint8_t Tx_Hood_Buff[20], Rx_Hood_Buff[20];
uint8_t Yeungong_Status = 0;
uint8_t Hood_Power_On = 0;
uint8_t Hood_Fan_Mode = 0;
uint8_t Hood_Control = 0;
uint8_t Hood_Rx_Complete = 0;
uint8_t Hood_Status = 0;
uint8_t CheckSum_Creator(uint8_t *buf, uint8_t len)
{
uint8_t i, rt;
rt = 0;
for(i=0; i<len; i++)
{
rt ^= buf[i];
}
return(rt);
}
uint8_t Rx_hood_Pos = 0;
void rx_hood_check(uint8_t data)
{
uint8_t Tmp = 0, cksum = 0;
if(rx_hood_485_TimeOut == 0)Rx_hood_Pos = 0;
switch(Rx_hood_Pos)
{
case 0:
if(data != 0xAA)break;
Rx_Hood_Buff[Rx_hood_Pos++] = data;
break;
case 1:
if(data != 0x11)
{
Rx_hood_Pos = 0;
}
Rx_Hood_Buff[Rx_hood_Pos++] = data;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
Rx_Hood_Buff[Rx_hood_Pos++] = data;
break;
case 12:
Rx_Hood_Buff[Rx_hood_Pos++] = data;
cksum = data;
if(cksum == CheckSum_Creator(Rx_Hood_Buff, 12))
{
Hood_Rx_Complete = 1;
}
Rx_hood_Pos = 0;
break;
default:
Rx_hood_Pos = 0;
break;
}
}
//-------------------------------------
void UART0_HANDLE()
{
uint8_t u8InChar=0xFF;
uint32_t u32IntSts= UART0->ISR;
if(u32IntSts & UART_ISR_RDA_IS_Msk)
{
u8InChar = UART_READ(UART0); /* Rx trigger level is 1 byte*/
rx_hood_check(u8InChar);
rx_hood_485_TimeOut = 10;
}
if(u32IntSts & UART_ISR_THRE_IS_Msk)
{
;
}
}
void UART0_IRQHandler(void)
{
UART0_HANDLE();
}
//----------------------------------
void Hood_Tx_packet(void)
{
Tx_Hood_Buff[0] = 0xAA;
Tx_Hood_Buff[1] = 0x21;
Tx_Hood_Buff[2] = 0x01;
Tx_Hood_Buff[3] = Run_Mode;
Tx_Hood_Buff[4] = Fan_Mode;
Tx_Hood_Buff[5] = Hood_YeunDong_Enable;
Tx_Hood_Buff[6] = Yeungong_Status;
Tx_Hood_Buff[7] = 0x00;
Tx_Hood_Buff[8] = Hood_Power_On | Hood_Control;
Tx_Hood_Buff[9] = Hood_Fan_Mode | Hood_Control;
Tx_Hood_Buff[10] = 0x00;
Tx_Hood_Buff[11] = 0x00;
Tx_Hood_Buff[12] = CheckSum_Creator(Tx_Hood_Buff, 12);
if(Hood_Control == 0x80)Hood_Control = 0;
HOOD_485_DIR = 1; // DIR
UART_Write(UART0,Tx_Hood_Buff, 13);
while ( !(UART0->FSR & UART_FSR_TX_EMPTY_F_Msk) );
while ( !(UART0->FSR & UART_FSR_TE_F_Msk) );
HOOD_485_DIR = 0; // DIR;
}
void Hood_RS485_process(void)
{
if(Hood_Rx_Complete == 1)
{
Hood_Rx_Complete = 0;
Hood_Conn_Timeout = 1500; /* 유효 응답 수신 -> 통신연결 생존(폴 500ms 기준 ~3회 누락 허용) */
Hood_Status = Rx_Hood_Buff[3];
// if((Hood_Status == 1)&&(Hood_Yeundong_flag == 0))Command_request_type |= TYPE_HOOD_STATE;// add 2022.1.25
// if((Hood_Status == 0)&&(Hood_Yeundong_flag == 1))Command_request_type |= TYPE_HOOD_STATE;// add 2022.1.25
// Hood_Yeundong_flag = Hood_Status;
}
else
{
if(Hood_polling_timer == 0)
{
Hood_polling_timer = 500;
Hood_Tx_packet();
}
}
}
uint8_t HREV_Hood_Control = 0;
uint16_t Hood_Warming_up_Timer = 0;
uint8_t Pre_Hood_Status = 0;
uint8_t Tx_Yeundong_Delay = 0;
/* 후드 단수 -> 환기장치 풍량 추종 매핑(사양 260613 9p 3.2) : 1->1,2->2,3->3,4->4,5->4 */
static uint8_t Hood_Step_To_Fan(uint8_t hs)
{
if(hs == 0) return 0;
return (hs > 4) ? 4 : hs;
}
uint8_t Hood_process(void)//200ms
{
if((Hood_YeunDong_Enable == 0)||(HREV_Hood_Control == 1))return(0);
if(Hood_Status != Pre_Hood_Status)
{
if((Pre_Hood_Status == 0)&&(Hood_Status != 0)) // 후드 ON : 메이크업 에어 진입(자동/수동 일시정지)
{
My_Memory_Run_Mode = Run_Mode;
if((Run_Mode == MODE_AUTO)&&(Fan_Mode == 0))My_Memory_Fan_Mode = 1;
else My_Memory_Fan_Mode = Fan_Mode;
Set_Run_Mode = MODE_VENTILATION;
Set_Fan_Mode = Hood_Step_To_Fan(Hood_Status); // 후드 단수 추종(사양 260613 9p 3.2)
if(Set_Reserve_timer_sec != 0)
{
Set_Reserve_timer_sec = 0;
Command_request_type |= (TYPE_RESERVATION);
}
Command_request_type |= (TYPE_MODE|TYPE_FAN_SPEED);
Tx_Yeundong_Delay = 30;
}
else if(Hood_Status == 0) // 후드 OFF : 즉시 원래 모드/풍량 복귀 (메이크업 유지는 후드측 담당, 사양 260613 9p 3.3)
{
Set_Run_Mode = My_Memory_Run_Mode;
Set_Fan_Mode = My_Memory_Fan_Mode;
if(Set_Reserve_timer_sec != 0)
{
Set_Reserve_timer_sec = 0;
Command_request_type |= (TYPE_RESERVATION);
}
Command_request_type |= (TYPE_MODE|TYPE_FAN_SPEED|TYPE_HOOD_STATE);
Hood_Yeundong_flag = 0;
Hood_Warming_up_Timer = 0;
Tx_Yeundong_Delay = 0;
}
else // 후드 단수 변경(1~5) : 메이크업 풍량 단수 추종 갱신
{
uint8_t f = Hood_Step_To_Fan(Hood_Status);
if(Set_Fan_Mode != f)
{
Set_Fan_Mode = f;
Command_request_type |= (TYPE_FAN_SPEED);
Tx_Yeundong_Delay = 30; // 룸컨(My_RJ2)이 연동 풍량변경을 수동명령으로 오인하지 않도록 디바운스
}
}
}
/* 메이크업 진입/단수변경 MODE/FAN 전송 후 연동 플래그 set + 룸컨 통지.
Tx_Yeundong_Delay 는 룸컨(My_RJ2)이 연동 명령을 사용자 수동명령과 구분하는 데 사용(불변).
조리 종료 후 잔여 배출(메이크업 유지)은 후드측이 담당하므로 여기서 롤백 타이머는 두지 않음. */
if(Tx_Yeundong_Delay)
{
Tx_Yeundong_Delay--;
if(Tx_Yeundong_Delay == 0)
{
Hood_Yeundong_flag = 1;
Command_request_type |= TYPE_HOOD_STATE;// add 2022.1.25
}
}
Pre_Hood_Status = Hood_Status;
return(1);
}