// 수정된 시뮬레이션 https://wokwi.com/projects/421571444490103809
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#define BUZZER_PIN 9 // 피에조 부저 핀
#define BUTTON_PIN 10 // 알람 중지 버튼 핀
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 rtc; // DS3231 RTC 모듈 사용
// 알람 관련 변수
bool alarmActive = false;
int alarmHour = 17;
int alarmMin = 7;
int alarmSec = 30;
const long ALARM_DURATION = 10000;
// 버튼 디바운싱 관련 변수 수정
const unsigned long debounceDelay = 50; // 디바운싱 딜레이
int buttonState = HIGH; // 현재 버튼 상태
int lastButtonState = HIGH; // 이전 버튼 상태
unsigned long lastDebounceTime = 0; // 마지막 디바운싱 시간
void setup()
{
Serial.begin(9600);
Wire.begin();
// RTC 초기화
if (!rtc.begin())
{
Serial.println("RTC를 찾을 수 없습니다");
while (1)
;
}
// RTC 시간이 유효하지 않은 경우에만 시간 설정
if (rtc.lostPower())
{
// 2025년 1월 30일 8:18:10 설정
rtc.adjust(DateTime(2025, 1, 30, 8, 18, 10));
}
lcd.init();
lcd.backlight();
pinMode(BUZZER_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop()
{
DateTime now = rtc.now(); // 현재 시간 읽기
// LCD에 날짜와 시간 표시
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.print(now.year(), DEC);
lcd.print("/");
lcd.print(now.month(), DEC);
lcd.print("/");
lcd.print(now.day(), DEC);
lcd.print(" ");
imprime_dia_da_semana(now.dayOfTheWeek());
lcd.setCursor(2, 1);
// 시간 표시 (앞에 0 붙이기)
if (now.hour() < 10)
lcd.print("0");
lcd.print(now.hour(), DEC);
lcd.print(":");
if (now.minute() < 10)
lcd.print("0");
lcd.print(now.minute(), DEC);
lcd.print(":");
if (now.second() < 10)
lcd.print("0");
lcd.print(now.second(), DEC);
// 알람 체크
if (now.hour() == alarmHour && now.minute() == alarmMin && now.second() == alarmSec)
{
alarmActive = true;
tone(BUZZER_PIN, 1000);
soundAlarm(now);
}
// 버튼으로 알람 끄기 (디바운싱 적용)
if (alarmActive && checkButton())
{
noTone(BUZZER_PIN);
alarmActive = false;
Serial.println("Alarm stopped"); // 디버깅용 시리얼 출력
}
//delay(100);
}
// 버튼 디바운싱 처리 함수 수정
bool checkButton() {
bool buttonPressed = false;
int reading = digitalRead(BUTTON_PIN);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
// 버튼이 떼어질 때(HIGH)만 true 반환
if (buttonState == HIGH) {
buttonPressed = true;
}
}
}
lastButtonState = reading;
return buttonPressed;
}
void soundAlarm(DateTime now)
{
lcd.setCursor(0, 1);
lcd.print("ALARM! ");
if (now.hour() < 10)
lcd.print("0");
lcd.print(now.hour(), DEC);
lcd.print(":");
if (now.minute() < 10)
lcd.print("0");
lcd.print(now.minute(), DEC);
lcd.print(":");
if (now.second() < 10)
lcd.print("0");
lcd.print(now.second(), DEC);
}
void imprime_dia_da_semana(int dayofweek)
{
const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
lcd.print(days[dayofweek]);
}