diff --git a/flame.c b/flame.c index fba2c350e53e6d6ccdd93a857fded5c086ecbd52..1a9dabbf2045f55451d24192e68149caf687536b 100644 --- a/flame.c +++ b/flame.c @@ -8,91 +8,101 @@ #include <time.h> #include <signal.h> -#define BUFFER_MAX 3 -#define DIRECTION_MAX 256 -#define VALUE_MAX 256 - -#define IN 0 -#define OUT 1 -#define LOW 0 -#define HIGH 1 - -#define BUFFER_SIZE 1024 -#define POUT 23 // 초음파 트리거 핀 -#define PIN 24 // 초음파 에코 핀 -#define FLAME 21 // 불꽃 센서 핀 -#define GREEN 17 // 초록색 LED 핀 -#define RED 22 // 적색 LED 핀 -#define BUZZER 27 // 부저 핀 - +// 상수 정의 +#define BUFFER_MAX 3 // 버퍼 크기 +#define DIRECTION_MAX 256 // 방향 경로 최대 길이 +#define VALUE_MAX 256 // 값 경로 최대 길이 + +#define IN 0 // GPIO 입력 모드 +#define OUT 1 // GPIO 출력 모드 +#define LOW 0 // GPIO LOW 상태 +#define HIGH 1 // GPIO HIGH 상태 + +#define BUFFER_SIZE 1024 // 소켓 버퍼 크기 +#define POUT 23 // 초음파 트리거 핀 +#define PIN 24 // 초음파 에코 핀 +#define FLAME 21 // 불꽃 센서 핀 +#define GREEN 17 // 초록색 LED 핀 +#define RED 22 // 적색 LED 핀 +#define BUZZER 27 // 부저 핀 + +// 부저 알림용 음계 배열 int fireAlarmNotes[] = { 880, 880, 0, 880, 880, 0, 988, 988, 0, 880, 880, 0 }; -struct sockaddr_in server_addr; -int park = 0; // 주차 상태: 0 = 주차되지 않음, 1 = 주차됨 -int setFire = 1; -int sock; -int redLed = 2; -int CLEAR = 1; +// 전역 변수 +struct sockaddr_in server_addr; // 서버 주소 구조체 +int park = 0; // 주차 상태: 0 = 비어있음, 1 = 주차됨 +int setFire = 1; // 화재 상태: 1 = 정상, 0 = 화재 발생 +int sock; // 소켓 디스크립터 +int redLed = 2; // 초기 LED 상태 +int CLEAR = 1; // 초기 화재 진압상태 1 = 화재 진압 상태 0 = 화재 미진압 상태 +/* 스레드 변수 */ pthread_t ultra_thread, flame_thread, receive_thread; +// GPIO 핀 제어 함수 선언 int GPIOExport(int pin); int GPIOUnexport(int pin); int GPIODirection(int pin, int dir); int GPIORead(int pin); int GPIOWrite(int pin, int value); +/* 인터럽트 신호 처리 함수 */ void signal_handler(int no); -// PWM 기반 부저 소리 발생 함수 +/*부저 알림음 생성 함수*/ +/* PWM 방식으로 핀을 토글하며 특정 주파수로 소리를 발생시킴 */ void buzzerTone(int pin, int frequency, int duration) { - int period = 1000000 / frequency; // 주기 (마이크로초) + int period = 1000000 / frequency; // 주기 (마이크로초 단위) int halfPeriod = period / 2; for (int i = 0; i < (duration * 1000 / period); i++) { - GPIOWrite(pin, HIGH); - usleep(halfPeriod); - GPIOWrite(pin, LOW); - usleep(halfPeriod); + GPIOWrite(pin, HIGH); + usleep(halfPeriod); + GPIOWrite(pin, LOW); + usleep(halfPeriod); } } +/* 초음파 센서를 통한 거리 측정 및 주차 상태 관리 스레드 함수 */ void *ultrasonic_sensor(void *arg) { - clock_t start_t, end_t; + clock_t start_t, end_t; // 에코 신호 시간을 측정하기 위한 변수 double time; while (1) { - GPIOWrite(POUT, HIGH); - usleep(10); - GPIOWrite(POUT, LOW); + GPIOWrite(POUT, HIGH); // 트리거 신호 발생 + usleep(10); // 10마이크로초 유지 + GPIOWrite(POUT, LOW); // 트리거 신호 종료 + /* 에코 신호 수신 시작 */ while (GPIORead(PIN) == LOW) start_t = clock(); while (GPIORead(PIN) == HIGH) end_t = clock(); - time = (double)(end_t - start_t) / CLOCKS_PER_SEC; - double distance = time / 2 * 34000; + time = (double)(end_t - start_t) / CLOCKS_PER_SEC; // 에코 시간 계산 + double distance = time / 2 * 34000; // 거리 계산 (cm 단위) + /* 상태에 따른 LED 제어 및 서버 메시지 전송 */ if (redLed == 2) { GPIOWrite(RED, HIGH); redLed = 1; } if (park == 0 && distance <= 10 && redLed == 1) { - GPIOWrite(GREEN, HIGH); - GPIOWrite(RED, LOW); - park = 1; + GPIOWrite(GREEN, HIGH); // 초록색 LED 켜기 + GPIOWrite(RED, LOW); // 적색 LED 끄기 + park = 1; // 주차 상태 변경 redLed = 0; printf("0-PARK\n"); - send(sock, "0-PARK", strlen("0-PARK"), 0); + send(sock, "0-PARK", strlen("0-PARK"), 0); // 서버로 주차 메시지 전송 } else if (park == 1 && distance > 10 && redLed == 0) { GPIOWrite(GREEN, LOW); GPIOWrite(RED, HIGH); - park = 0; + park = 0; // 주차 해제 redLed = 1; printf("0-EXIT\n"); - send(sock, "0-EXIT", strlen("0-EXIT"), 0); + send(sock, "0-EXIT", strlen("0-EXIT"), 0); // 서버로 주차 해제 메시지 전송 } usleep(500000); @@ -101,27 +111,29 @@ void *ultrasonic_sensor(void *arg) { return NULL; } +/* 불꽃 센서를 통한 화재 감지 및 부저 알림 스레드 함수 */ void *flame_sensor(void *arg) { - printf("초기 FLAME 값은 %d\n", GPIORead(FLAME)); + printf("초기 FLAME 값: %d\n", GPIORead(FLAME)); while (1) { - if (GPIORead(FLAME) == 0 && setFire == 1) { + if (GPIORead(FLAME) == 0 && setFire == 1) { // 화재 발생 감지 printf("0-FIRE\n"); - send(sock, "0-FIRE", strlen("0-FIRE"), 0); - setFire = 0; - CLEAR = 0; + send(sock, "0-FIRE", strlen("0-FIRE"), 0); // 서버로 화재 메시지 전송 + setFire = 0; // 화재 상태 변경 + CLEAR = 0; // 화재 진압 상태 변경 printf("FLAME 값: %d\n", GPIORead(FLAME)); } + /* CLEAR 상태가 0일 때 화재 경고음 발생 */ while (CLEAR == 0) { for (int i = 0; i < sizeof(fireAlarmNotes) / sizeof(int); i++) { if (CLEAR != 0) { break; } if (fireAlarmNotes[i] > 0) { - buzzerTone(BUZZER, fireAlarmNotes[i], 200); + buzzerTone(BUZZER, fireAlarmNotes[i], 200); // 알림음 발생 } else { - usleep(200000); + usleep(200000); // 음 사이 간격 } } if (CLEAR != 0) { @@ -130,22 +142,24 @@ void *flame_sensor(void *arg) { } GPIOWrite(BUZZER, LOW); - usleep(200000); + usleep(200000); } return NULL; } +/* 서버와 메시지를 주고받는 스레드 함수 */ void *receive_message(void *arg) { char buffer[BUFFER_SIZE]; int valread; while (1) { - valread = read(sock, buffer, BUFFER_SIZE - 1); - if (valread <= 0) { + valread = read(sock, buffer, BUFFER_SIZE - 1); // 서버로부터 메시지 읽기 + if (valread <= 0) { // 서버 연결 끊김 감지 printf("서버와의 연결이 종료되었습니다. 재연결을 시도합니다...\n"); close(sock); + /* 서버 재연결 시도 */ while (1) { sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { @@ -168,7 +182,7 @@ void *receive_message(void *arg) { buffer[valread] = '\0'; printf("서버로부터 받은 메시지: %s\n", buffer); buffer[strcspn(buffer, "\r\n")] = '\0'; - if (strcmp(buffer, "CLEAR") == 0) { + if (strcmp(buffer, "CLEAR") == 0) { // CLEAR 명령어 처리 setFire = 1; CLEAR = 1; printf("setFire 및 CLEAR가 %d, %d로 설정되었습니다.\n", setFire, CLEAR); @@ -180,24 +194,26 @@ void *receive_message(void *arg) { } int main() { - + /* SIGINT 신호 (Ctrl + C) 처리 핸들러 등록 */ signal(SIGINT, (void *)signal_handler); - // 소켓 생성 + + /* 소켓 생성 */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket creation error"); return -1; } + /* 서버 주소 설정 */ server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(12345); // 서버 포트 설정 + server_addr.sin_port = htons(12345); // 서버 포트 설정 - // localhost IP 주소 설정 - if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) { + /* 서버 IP 주소 설정 (127.0.0.1: localhost) */ + if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) { perror("Invalid address / Address not supported"); return -1; } - // 서버 연결 + /* 서버 연결 시도 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Connection failed"); return -1; @@ -205,30 +221,34 @@ int main() { printf("서버에 연결되었습니다.\n"); - // GPIO 핀 설정 - if (GPIOExport(POUT) == -1 || GPIOExport(PIN) == -1 || GPIOExport(FLAME) == -1 || GPIOExport(GREEN) == -1 || GPIOExport(RED) == -1 || GPIOExport(BUZZER) == -1) { + /* GPIO 핀 초기화 */ + if (GPIOExport(POUT) == -1 || GPIOExport(PIN) == -1 || GPIOExport(FLAME) == -1 || + GPIOExport(GREEN) == -1 || GPIOExport(RED) == -1 || GPIOExport(BUZZER) == -1) { fprintf(stderr, "GPIO Export Error\n"); return 1; } - usleep(100000); // GPIO 설정 대기 + usleep(100000); // GPIO 설정 대기 - if (GPIODirection(POUT, OUT) == -1 || GPIODirection(PIN, IN) == -1 || GPIODirection(FLAME, IN) == -1 || GPIODirection(GREEN, OUT) == -1|| GPIODirection(RED, OUT) == -1 || GPIODirection(BUZZER, OUT) == -1) { + /* GPIO 핀 방향 설정 */ + if (GPIODirection(POUT, OUT) == -1 || GPIODirection(PIN, IN) == -1 || + GPIODirection(FLAME, IN) == -1 || GPIODirection(GREEN, OUT) == -1 || + GPIODirection(RED, OUT) == -1 || GPIODirection(BUZZER, OUT) == -1) { fprintf(stderr, "GPIO Direction Error\n"); return 2; } - // 스레드 생성 + /* 초음파 센서, 불꽃 센서, 서버 메시지 처리 스레드 생성 */ pthread_create(&ultra_thread, NULL, ultrasonic_sensor, NULL); pthread_create(&flame_thread, NULL, flame_sensor, NULL); pthread_create(&receive_thread, NULL, receive_message, NULL); - // 스레드 종료 대기 + /* 스레드 종료 대기 */ pthread_join(ultra_thread, NULL); pthread_join(flame_thread, NULL); pthread_join(receive_thread, NULL); - // 소켓 및 GPIO 정리 + /* 종료 시 소켓 및 GPIO 정리 */ close(sock); GPIOUnexport(POUT); GPIOUnexport(PIN); @@ -239,111 +259,126 @@ int main() { return 0; } - +/* SIGINT 신호 처리 함수 */ +/* 시스템 종료 시 GPIO 상태 정리 및 프로그램 종료 */ void signal_handler(int no) { printf("System Interrupt.\n"); - GPIOWrite(GREEN, LOW); - GPIOWrite(RED, LOW); - GPIOWrite(BUZZER, LOW); - close(sock); - exit(0); + GPIOWrite(GREEN, LOW); + GPIOWrite(RED, LOW); + GPIOWrite(BUZZER, LOW); + GPIOUnexport(POUT); + GPIOUnexport(PIN); + GPIOUnexport(FLAME); + GPIOUnexport(GREEN); + GPIOUnexport(RED); + GPIOUnexport(BUZZER); + close(sock); + exit(0); } - +/* GPIO 핀 활성화 함수 */ +/* 핀 번호를 "/sys/class/gpio/export"에 기록하여 활성화 */ int GPIOExport(int pin) { - char buffer[BUFFER_MAX]; - ssize_t bytes_written; - int fd; - - fd = open("/sys/class/gpio/export", O_WRONLY); - if (-1 == fd) { - fprintf(stderr, "Failed to open export for writing!\n"); - return (-1); - } - - bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); - write(fd, buffer, bytes_written); - close(fd); - return (0); + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/export", O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open export for writing!\n"); + return (-1); + } + + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return (0); } +/* GPIO 핀 비활성화 함수 */ +/* 핀 번호를 "/sys/class/gpio/unexport"에 기록하여 비활성화 */ int GPIOUnexport(int pin) { - char buffer[BUFFER_MAX]; - ssize_t bytes_written; - int fd; - - fd = open("/sys/class/gpio/unexport", O_WRONLY); - if (-1 == fd) { - fprintf(stderr, "Failed to open unexport for writing!\n"); - return (-1); - } - bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); - write(fd, buffer, bytes_written); - close(fd); - return (0); + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/unexport", O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open unexport for writing!\n"); + return (-1); + } + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return (0); } +/* GPIO 핀 방향 설정 함수 */ +/* 핀의 입력(IN) 또는 출력(OUT) 방향을 설정 */ int GPIODirection(int pin, int dir) { - static const char s_directions_str[] = "in\0out"; - char path[DIRECTION_MAX] = "/sys/class/gpio/gpio%d/direction"; - int fd; + static const char s_directions_str[] = "in\0out"; + char path[DIRECTION_MAX]; + int fd; - snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin); + snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin); - fd = open(path, O_WRONLY); - if (-1 == fd) { - fprintf(stderr, "Failed to open gpio direction for writing!\n"); - return (-1); - } + fd = open(path, O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open gpio direction for writing!\n"); + return (-1); + } - if (-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)) { - fprintf(stderr, "Failed to set direction!\n"); - return (-1); - } + if (-1 == write(fd, &s_directions_str[IN == dir ? 0 : 3], IN == dir ? 2 : 3)) { + fprintf(stderr, "Failed to set direction!\n"); + return (-1); + } - close(fd); - return (0); + close(fd); + return (0); } +/* GPIO 핀 값 읽기 함수 */ +/* 핀의 현재 상태(0 또는 1)를 읽어 반환 */ int GPIORead(int pin) { - char path[VALUE_MAX]; - char value_str[3]; - int fd; - - snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); - fd = open(path, O_RDONLY); - if (-1 == fd) { - fprintf(stderr, "Failed to open gpio value for reading!\n"); - return (-1); - } - - if (-1 == read(fd, value_str, 3)) { - fprintf(stderr, "Failed to read value!\n"); - return (-1); - } + char path[VALUE_MAX]; + char value_str[3]; + int fd; + + snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); + fd = open(path, O_RDONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open gpio value for reading!\n"); + return (-1); + } - close(fd); + if (-1 == read(fd, value_str, 3)) { + fprintf(stderr, "Failed to read value!\n"); + return (-1); + } - return (atoi(value_str)); + close(fd); + return (atoi(value_str)); // 읽은 값을 정수로 변환 후 반환 } +/* GPIO 핀 값 쓰기 함수 */ +/* 핀에 0(LOW) 또는 1(HIGH) 값을 기록 */ int GPIOWrite(int pin, int value) { - static const char s_values_str[] = "01"; - char path[VALUE_MAX]; - int fd; - - snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); - fd = open(path, O_WRONLY); - if (-1 == fd) { - fprintf(stderr, "Failed to open gpio value for writing!\n"); - return (-1); - } - - if (1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) { - fprintf(stderr, "Failed to write value!\n"); - return (-1); - } + static const char s_values_str[] = "01"; + char path[VALUE_MAX]; + int fd; + + snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); + fd = open(path, O_WRONLY); + if (-1 == fd) { + fprintf(stderr, "Failed to open gpio value for writing!\n"); + return (-1); + } + + if (1 != write(fd, &s_values_str[LOW == value ? 0 : 1], 1)) { + fprintf(stderr, "Failed to write value!\n"); + return (-1); + } - close(fd); - return (0); -} \ No newline at end of file + close(fd); + return (0); +}