콘텐츠 대표 이미지 - ESP8266으로 만드는 나만의 웹 타이머 & 알람 시스템 🕒

ESP8266으로 만드는 나만의 웹 타이머 & 알람 시스템 🕒

ESP8266 웹 타이머 인터페이스 00:05:30 시작 정지 ESP8266 웹 타이머 & 알람 시스템 초보자도 쉽게 따라할 수 있는 IoT 프로젝트

안녕? 오늘은 초소형 와이파이 모듈 ESP8266을 이용해서
웹으로 제어할 수 있는 타이머와 알람 시스템을 만들어볼 거야! 🚀

🌟 ESP8266으로 뭘 할 수 있을까?

요즘 IoT(사물인터넷)가 대세라는 건 알지? 근데 "어렵겠지~"라고 생각했다면 오산이야! ESP8266이라는 작은 칩 하나로 인터넷에 연결되는 멋진 프로젝트를 뚝딱 만들 수 있어. 오늘 우리가 만들 웹 타이머 시스템은 스마트폰이나 PC에서 웹 브라우저로 접속해서 타이머를 설정하고, 시간이 되면 알람이 울리는 초간단 IoT 프로젝트야.

이 글을 따라오다 보면 넌 다음과 같은 것들을 배울 수 있어:

  1. ESP8266 기본 셋업 방법
  2. 와이파이 연결 및 웹서버 구축
  3. HTML, CSS, JavaScript로 웹 인터페이스 만들기
  4. 타이머 및 알람 기능 구현
  5. 실시간으로 웹에서 디바이스 제어하기

재능넷에서 프로그래밍 관련 재능을 찾아보면 IoT 프로젝트 개발을 도와줄 수 있는 전문가들도 많이 있지만, 이 글을 통해 직접 해보면 더 재밌을 거야! 😉

🔍 알고 가자! ESP8266은 약 $3~5 정도의 저렴한 가격에 와이파이 기능을 갖춘 마이크로컨트롤러야. Arduino보다 성능이 좋으면서 가격은 더 저렴하지. 특히 NodeMCU나 Wemos D1 Mini 같은 개발 보드는 USB 연결도 지원해서 초보자도 쉽게 시작할 수 있어!

🛒 준비물

프로젝트를 시작하기 전에 다음 준비물들을 모아보자:

  1. ESP8266 개발 보드 (NodeMCU 또는 Wemos D1 Mini 추천) 📟
  2. 마이크로 USB 케이블 (보드 연결용) 🔌
  3. 빵판(브레드보드) 및 점퍼 와이어 🧩
  4. 부저 (알람용) 🔊
  5. LED 몇 개 (상태 표시용) 💡
  6. 저항 (LED용 220Ω 또는 330Ω) ⚡
  7. Arduino IDE (프로그래밍용) 💻

이 정도면 충분해! 총 비용은 만원 이하로 가능하니 부담 없이 시작할 수 있어. 재능넷에서 전자부품 관련 재능을 찾아보면 필요한 부품 목록을 추천받을 수도 있을 거야.

ESP8266 웹 타이머 프로젝트 준비물 ESP8266 보드 USB 케이블 브레드보드 부저 LED 저항 점퍼 와이어 Arduino IDE 웹 타이머 00:05:30 완성 프로젝트

🔧 개발 환경 설정하기

자, 이제 본격적으로 시작해볼까? 먼저 개발 환경부터 설정해보자!

1. Arduino IDE 설치 및 설정

ESP8266을 프로그래밍하기 위해 Arduino IDE를 사용할 거야. 이미 설치되어 있다면 넘어가도 좋아.

  1. Arduino 공식 사이트에서 IDE 다운로드 및 설치
  2. Arduino IDE 실행 후 상단 메뉴에서 [파일] → [환경설정]
  3. 추가적인 보드 매니저 URLs에 다음 주소 입력:
    http://arduino.esp8266.com/stable/package_esp8266com_index.json
  4. [도구] → [보드] → [보드 매니저]에서 "esp8266"을 검색하고 설치

💡 팁: 최신 버전의 ESP8266 라이브러리를 설치하는 것이 좋아! 기능이 계속 추가되고 버그가 수정되거든.

2. ESP8266 보드 선택

Arduino IDE에서 사용할 ESP8266 보드를 선택해야 해:

  1. [도구] → [보드] → "NodeMCU 1.0 (ESP-12E Module)" 또는 사용 중인 보드 선택
  2. [도구] → [포트]에서 ESP8266이 연결된 COM 포트 선택
  3. [도구] → [Upload Speed]는 115200으로 설정 (안정적인 업로드 속도)

이제 기본 설정은 끝났어! 간단하지? 🙌

📶 와이파이 연결 설정하기

ESP8266의 핵심 기능은 와이파이 연결이야. 먼저 ESP8266을 와이파이에 연결하는 기본 코드를 작성해보자.


#include <ESP8266WiFi.h>

// 와이파이 설정
const char* ssid = "너의_와이파이_이름";
const char* password = "너의_와이파이_비밀번호";

void setup() {
  Serial.begin(115200);
  delay(10);
  
  // 와이파이 연결 시작
  Serial.println();
  Serial.print("와이파이에 연결 중... ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.println("와이파이 연결 완료!");
  
  // IP 주소 출력
  Serial.print("IP 주소: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  // 여기에 메인 코드가 들어갈 거야
}
    

이 코드에서 "너의_와이파이_이름"과 "너의_와이파이_비밀번호" 부분을 실제 네트워크 정보로 바꿔줘야 해! 코드를 업로드하고 시리얼 모니터(115200 속도)를 열면 ESP8266이 와이파이에 연결되고 IP 주소를 보여줄 거야.

ESP8266 와이파이 연결 과정 ESP8266 와이파이 라우터 1. 초기화 2. SSID/PW 설정 3. 연결 시도 4. IP 주소 할당 5. 연결 완료 와이파이에 연결 중... MyWiFi ............ IP 주소: 192.168.1.104

와이파이 연결이 성공했다면 이제 웹서버를 만들 준비가 된 거야! 🎉

🌐 웹서버 구축하기

ESP8266은 간단한 웹서버를 호스팅할 수 있어. 이제 기본적인 웹서버를 만들어보자!


#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

// 와이파이 설정
const char* ssid = "너의_와이파이_이름";
const char* password = "너의_와이파이_비밀번호";

// 웹서버 객체 생성 (포트 80)
ESP8266WebServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);
  
  // 와이파이 연결
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  // 웹서버 라우트 설정
  server.on("/", handleRoot);
  
  // 서버 시작
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  // 클라이언트 요청 처리
  server.handleClient();
}

// 루트 페이지 처리 함수
void handleRoot() {
  String html = "<!DOCTYPE html>";
  html += "<html>";
  html += "<head>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
  html += "<title>ESP8266 웹 타이머</title>";
  html += "<style>";
  html += "body { font-family: Arial, sans-serif; text-align: center; margin: 0; padding: 20px; }";
  html += "h1 { color: #2c3e50; }";
  html += "</style>";
  html += "</head>";
  html += "<body>";
  html += "<h1>ESP8266 웹 타이머</h1>";
  html += "<p>환영합니다! 웹 타이머 시스템이 작동 중입니다.</p>";
  html += "</body>";
  html += "</html>";
  
  server.send(200, "text/html", html);
}
    

이 코드를 ESP8266에 업로드하고 시리얼 모니터에서 표시된 IP 주소로 웹 브라우저에서 접속해보자. "ESP8266 웹 타이머"라는 제목과 환영 메시지가 표시되면 성공! 🎯

✅ 성공 확인: 웹 브라우저에서 ESP8266의 IP 주소(예: 192.168.1.104)를 입력했을 때 웹페이지가 표시되면 웹서버가 제대로 작동하는 거야!

HTML 페이지 최적화하기

ESP8266의 메모리는 제한적이라 HTML 코드가 너무 길면 문제가 생길 수 있어. 몇 가지 최적화 팁을 알려줄게:

  1. 불필요한 공백과 줄바꿈 제거하기
  2. CSS와 JavaScript는 최소화하기
  3. 큰 이미지는 피하고 SVG나 작은 아이콘 사용하기
  4. SPIFFS(ESP8266 파일 시스템)를 사용해 HTML 파일 저장하기

이제 기본적인 웹서버가 작동하니 다음 단계로 넘어가자!

⏱️ 타이머 인터페이스 만들기

이제 타이머를 설정하고 제어할 수 있는 웹 인터페이스를 만들어보자. HTML, CSS, JavaScript를 사용해서 멋진 UI를 구현할 거야!


void handleRoot() {
  String html = "<!DOCTYPE html>"
                "<html>"
                "<head>"
                "<meta name='viewport' content='width=device-width, initial-scale=1.0'>"
                "<title>ESP8266 웹 타이머</title>"
                "<style>"
                "body{font-family:Arial,sans-serif;text-align:center;margin:0;padding:20px;background-color:#f5f7fa;}"
                "h1{color:#2c3e50;}"
                ".timer-container{max-width:500px;margin:0 auto;background-color:white;border-radius:10px;padding:20px;box-shadow:0 4px 6px rgba(0,0,0,0.1);}"
                ".display{font-size:3em;margin:20px 0;font-weight:bold;color:#3498db;font-family:monospace;}"
                ".controls{display:flex;justify-content:center;gap:10px;margin-bottom:20px;}"
                ".btn{padding:10px 20px;border:none;border-radius:5px;cursor:pointer;font-weight:bold;transition:background 0.3s;}"
                ".start{background-color:#2ecc71;color:white;}"
                ".stop{background-color:#e74c3c;color:white;}"
                ".reset{background-color:#95a5a6;color:white;}"
                ".input-group{margin-bottom:15px;}"
                "input{padding:8px;width:50px;text-align:center;border:1px solid #ddd;border-radius:4px;}"
                "label{margin-right:5px;}"
                "</style>"
                "</head>"
                "<body>"
                "<div class='timer-container'>"
                "<h1>ESP8266 웹 타이머</h1>"
                "<div class='input-group'>"
                "<label for='hours'>시간:</label>"
                "<input type='number' id='hours' min='0' max='23' value='0'>"
                "<label for='minutes'>분:</label>"
                "<input type='number' id='minutes' min='0' max='59' value='5'>"
                "<label for='seconds'>초:</label>"
                "<input type='number' id='seconds' min='0' max='59' value='0'>"
                "</div>"
                "<div class='display' id='display'>00:05:00</div>"
                "<div class='controls'>"
                "<button class='btn start' onclick='startTimer()'>시작</button>"
                "<button class='btn stop' onclick='stopTimer()'>정지</button>"
                "<button class='btn reset' onclick='resetTimer()'>초기화</button>"
                "</div>"
                "</div>"
                "<script>"
                "let timer;"
                "let hours = 0, minutes = 5, seconds = 0;"
                "let isRunning = false;"
                
                "function updateDisplay() {"
                "  const h = String(hours).padStart(2, '0');"
                "  const m = String(minutes).padStart(2, '0');"
                "  const s = String(seconds).padStart(2, '0');"
                "  document.getElementById('display').textContent = `${h}:${m}:${s}`;"
                "}"
                
                "function startTimer() {"
                "  if (isRunning) return;"
                "  hours = parseInt(document.getElementById('hours').value) || 0;"
                "  minutes = parseInt(document.getElementById('minutes').value) || 0;"
                "  seconds = parseInt(document.getElementById('seconds').value) || 0;"
                "  if (hours === 0 && minutes === 0 && seconds === 0) return;"
                "  isRunning = true;"
                "  updateDisplay();"
                "  timer = setInterval(function() {"
                "    if (seconds > 0) {"
                "      seconds--;"
                "    } else if (minutes > 0) {"
                "      minutes--;"
                "      seconds = 59;"
                "    } else if (hours > 0) {"
                "      hours--;"
                "      minutes = 59;"
                "      seconds = 59;"
                "    } else {"
                "      clearInterval(timer);"
                "      isRunning = false;"
                "      alert('타이머 종료!');"
                "      fetch('/alarm?state=on');"
                "    }"
                "    updateDisplay();"
                "  }, 1000);"
                "  fetch('/timer?action=start&h='+hours+'&m='+minutes+'&s='+seconds);"
                "}"
                
                "function stopTimer() {"
                "  clearInterval(timer);"
                "  isRunning = false;"
                "  fetch('/timer?action=stop');"
                "}"
                
                "function resetTimer() {"
                "  clearInterval(timer);"
                "  isRunning = false;"
                "  hours = 0; minutes = 5; seconds = 0;"
                "  document.getElementById('hours').value = hours;"
                "  document.getElementById('minutes').value = minutes;"
                "  document.getElementById('seconds').value = seconds;"
                "  updateDisplay();"
                "  fetch('/timer?action=reset');"
                "}"
                
                "updateDisplay();"
                "</script>"
                "</body>"
                "</html>";
  
  server.send(200, "text/html", html);
}
    

위 코드는 웹 인터페이스를 생성하는 부분이야. 시간, 분, 초를 설정하고 타이머를 시작/정지/초기화할 수 있는 버튼이 있어. 이제 이 인터페이스와 ESP8266을 연결해보자!

ESP8266 웹 타이머 시간: 0 분: 5 초: 0 00:05:00 시작 정지 초기화 알람 상태: 대기 중 사용자 입력 웹 브라우저 ESP8266 HTTP 요청 웹 타이머 인터페이스 구조

⚙️ 타이머 백엔드 구현하기

이제 웹 인터페이스에서 보낸 요청을 처리할 백엔드 코드를 작성해보자. ESP8266에서 타이머를 실행하고 알람을 울리는 기능을 구현할 거야.


#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

// 와이파이 설정
const char* ssid = "너의_와이파이_이름";
const char* password = "너의_와이파이_비밀번호";

// 하드웨어 핀 설정
const int BUZZER_PIN = D1;  // 부저 연결 핀
const int LED_PIN = D2;     // LED 연결 핀

// 웹서버 객체 생성 (포트 80)
ESP8266WebServer server(80);

// 타이머 변수
unsigned long timerDuration = 0;
unsigned long timerStartTime = 0;
bool timerRunning = false;

void setup() {
  Serial.begin(115200);
  
  // 핀 모드 설정
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(LED_PIN, OUTPUT);
  
  // 초기 상태 설정
  digitalWrite(BUZZER_PIN, LOW);
  digitalWrite(LED_PIN, LOW);
  
  // 와이파이 연결
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  // 웹서버 라우트 설정
  server.on("/", handleRoot);
  server.on("/timer", handleTimer);
  server.on("/alarm", handleAlarm);
  
  // 서버 시작
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  // 클라이언트 요청 처리
  server.handleClient();
  
  // 타이머 체크
  if (timerRunning) {
    unsigned long currentTime = millis();
    unsigned long elapsedTime = currentTime - timerStartTime;
    
    // 타이머 종료 체크
    if (elapsedTime >= timerDuration) {
      timerRunning = false;
      triggerAlarm();
    }
  }
}

// 타이머 요청 처리
void handleTimer() {
  String action = server.arg("action");
  
  if (action == "start") {
    int hours = server.arg("h").toInt();
    int minutes = server.arg("m").toInt();
    int seconds = server.arg("s").toInt();
    
    // 밀리초로 변환
    timerDuration = (hours * 3600L + minutes * 60L + seconds) * 1000L;
    timerStartTime = millis();
    timerRunning = true;
    
    Serial.print("타이머 시작: ");
    Serial.print(hours); Serial.print("시간 ");
    Serial.print(minutes); Serial.print("분 ");
    Serial.print(seconds); Serial.println("초");
    
    server.send(200, "text/plain", "Timer started");
  } 
  else if (action == "stop") {
    timerRunning = false;
    Serial.println("타이머 정지");
    server.send(200, "text/plain", "Timer stopped");
  } 
  else if (action == "reset") {
    timerRunning = false;
    timerDuration = 0;
    Serial.println("타이머 초기화");
    server.send(200, "text/plain", "Timer reset");
    
    // 알람이 울리고 있다면 끄기
    digitalWrite(BUZZER_PIN, LOW);
    digitalWrite(LED_PIN, LOW);
  }
}

// 알람 요청 처리
void handleAlarm() {
  String state = server.arg("state");
  
  if (state == "on") {
    triggerAlarm();
    server.send(200, "text/plain", "Alarm triggered");
  } 
  else if (state == "off") {
    digitalWrite(BUZZER_PIN, LOW);
    digitalWrite(LED_PIN, LOW);
    server.send(200, "text/plain", "Alarm turned off");
  }
}

// 알람 트리거 함수
void triggerAlarm() {
  Serial.println("알람 울림!");
  
  // LED 켜기
  digitalWrite(LED_PIN, HIGH);
  
  // 부저 소리 내기 (간단한 멜로디)
  for (int i = 0; i < 3; i++) {
    tone(BUZZER_PIN, 1000); // 1kHz 소리
    delay(500);
    tone(BUZZER_PIN, 800);  // 800Hz 소리
    delay(500);
  }
  noTone(BUZZER_PIN);
}

// HTML 페이지 처리 (위에서 작성한 handleRoot 함수 사용)
    

이 코드는 웹 인터페이스에서 보낸 타이머 설정 요청을 처리하고, 타이머가 끝나면 알람을 울리는 기능을 구현했어. ESP8266은 실시간으로 타이머를 체크하고 시간이 다 되면 부저와 LED를 작동시켜!

⚠️ 주의: 부저와 LED를 연결할 때 적절한 저항을 사용해야 해. LED에는 220~330Ω 저항을 직렬로 연결하고, 부저는 사양에 맞게 연결하자.

하드웨어 연결 방법

ESP8266에 부저와 LED를 연결하는 방법은 다음과 같아:

  1. 부저: D1 핀과 GND 핀에 연결
  2. LED: D2 핀에 LED 양극(+), 저항을 통해 GND에 음극(-) 연결

이렇게 하면 타이머가 끝났을 때 시각적(LED)과 청각적(부저) 알림을 모두 받을 수 있어!

🚀 고급 기능 추가하기

기본적인 타이머와 알람 시스템이 완성됐어! 이제 몇 가지 고급 기능을 추가해서 더 멋진 프로젝트로 만들어보자.

1. 여러 개의 타이머 설정하기

한 번에 여러 개의 타이머를 설정할 수 있으면 더 유용하겠지? 다음 코드를 참고해서 구현해보자:


// 최대 타이머 개수
#define MAX_TIMERS 3

// 타이머 구조체
struct Timer {
  unsigned long duration;
  unsigned long startTime;
  bool running;
  String name;
};

// 타이머 배열
Timer timers[MAX_TIMERS];

// 타이머 초기화
void initTimers() {
  for (int i = 0; i < MAX_TIMERS; i++) {
    timers[i].duration = 0;
    timers[i].startTime = 0;
    timers[i].running = false;
    timers[i].name = "타이머 " + String(i + 1);
  }
}

// 타이머 시작
void startTimerById(int id, unsigned long duration, String name) {
  if (id >= 0 && id < MAX_TIMERS) {
    timers[id].duration = duration;
    timers[id].startTime = millis();
    timers[id].running = true;
    timers[id].name = name;
  }
}

// 타이머 체크 (loop 함수에서 호출)
void checkTimers() {
  for (int i = 0; i < MAX_TIMERS; i++) {
    if (timers[i].running) {
      unsigned long currentTime = millis();
      unsigned long elapsedTime = currentTime - timers[i].startTime;
      
      if (elapsedTime >= timers[i].duration) {
        timers[i].running = false;
        // 알람 울리기
        triggerAlarm();
        Serial.print(timers[i].name);
        Serial.println(" 종료!");
      }
    }
  }
}
    

이 코드를 사용하면 최대 3개의 타이머를 동시에 설정할 수 있어. 웹 인터페이스도 여러 타이머를 보여주도록 수정해야 하겠지?

2. 알람 소리 커스터마이징

단순한 알람 소리보다 멜로디가 있으면 더 재미있을 거야. 다음은 간단한 멜로디를 재생하는 코드야:


// 멜로디 노트 정의 (도레미파솔라시도)
int notes[] = {262, 294, 330, 349, 392, 440, 494, 523};

// 멜로디 재생
void playMelody() {
  for (int i = 0; i < 8; i++) {
    tone(BUZZER_PIN, notes[i]);
    digitalWrite(LED_PIN, HIGH);
    delay(200);
    digitalWrite(LED_PIN, LOW);
    delay(100);
  }
  
  // 마지막에 높은 도 소리
  tone(BUZZER_PIN, 523);
  digitalWrite(LED_PIN, HIGH);
  delay(500);
  noTone(BUZZER_PIN);
  digitalWrite(LED_PIN, LOW);
}
    

이 함수를 triggerAlarm() 함수 안에서 호출하면 타이머가 끝났을 때 "도레미파솔라시도" 멜로디가 재생돼!

3. 웹 인터페이스 개선하기

웹 인터페이스에 몇 가지 기능을 추가해보자:

  • ✅ 타이머 진행 상황을 보여주는 프로그레스 바
  • ✅ 타이머 이름 설정 기능
  • ✅ 다크 모드/라이트 모드 전환
  • ✅ 자주 사용하는 타이머 프리셋 저장

이런 기능들은 JavaScript와 CSS를 활용해서 구현할 수 있어. 재능넷에서 웹 디자인 관련 재능을 가진 분들에게 도움을 요청해도 좋을 것 같아!

고급 기능이 추가된 웹 타이머 아침 운동 타이머 00:30:00 50% 시작 정지 요리 타이머 00:15:30 66% 시작 정지 공부 타이머 01:30:00 20% 시작 정지 ⚙️ 다크 모드

🔔 알람 시스템 개선하기

지금까지 만든 알람 시스템은 부저와 LED만 사용했어. 하지만 더 다양한 알람 방식을 추가할 수 있어!

1. 푸시 알림 추가하기

웹 브라우저의 푸시 알림 기능을 사용하면 타이머가 끝났을 때 사용자에게 알림을 보낼 수 있어. JavaScript의 Notification API를 사용해보자:


// HTML 파일의 JavaScript 부분에 추가
function requestNotificationPermission() {
  if (!("Notification" in window)) {
    alert("이 브라우저는 알림을 지원하지 않습니다.");
  } else if (Notification.permission !== "denied") {
    Notification.requestPermission().then(function (permission) {
      if (permission === "granted") {
        console.log("알림 권한이 허용되었습니다.");
      }
    });
  }
}

function showNotification(title, message) {
  if (Notification.permission === "granted") {
    var notification = new Notification(title, {
      body: message,
      icon: 'https://example.com/icon.png'
    });
    
    notification.onclick = function() {
      window.focus();
      this.close();
    };
  }
}

// 페이지 로드 시 알림 권한 요청
document.addEventListener('DOMContentLoaded', requestNotificationPermission);

// 타이머 종료 시 알림 표시 (startTimer 함수 내 타이머 종료 부분에 추가)
if (hours === 0 && minutes === 0 && seconds === 0) {
  showNotification("타이머 종료", "설정한 타이머가 종료되었습니다!");
  fetch('/alarm?state=on');
}
    

이 코드를 추가하면 타이머가 끝났을 때 웹 브라우저에서 푸시 알림을 받을 수 있어! 물론 사용자가 알림 권한을 허용해야 해.

2. 이메일 알림 추가하기

ESP8266에서 이메일을 보내는 기능을 추가할 수도 있어. 다음 라이브러리를 사용해보자:


#include <ESP8266WiFi.h>
#include <ESP_Mail_Client.h>

// 이메일 설정
#define SMTP_HOST "smtp.gmail.com"
#define SMTP_PORT 465
#define AUTHOR_EMAIL "your-email@gmail.com"
#define AUTHOR_PASSWORD "your-app-password"
#define RECIPIENT_EMAIL "recipient@example.com"

// 이메일 세션 객체
SMTPSession smtp;

// 이메일 보내기 함수
void sendEmail(String subject, String message) {
  ESP_Mail_Session session;
  session.server.host_name = SMTP_HOST;
  session.server.port = SMTP_PORT;
  session.login.email = AUTHOR_EMAIL;
  session.login.password = AUTHOR_PASSWORD;
  session.login.user_domain = "";
  
  SMTP_Message email;
  email.sender.name = "ESP8266 타이머";
  email.sender.email = AUTHOR_EMAIL;
  email.subject = subject;
  email.addRecipient("User", RECIPIENT_EMAIL);
  email.text.content = message.c_str();
  
  if (!smtp.connect(&session))
    return;
    
  if (!MailClient.sendMail(&smtp, &email))
    Serial.println("이메일 전송 실패");
  else
    Serial.println("이메일 전송 성공");
}

// 타이머 종료 시 이메일 보내기
void triggerAlarm() {
  // 기존 알람 코드...
  
  // 이메일 알림 보내기
  sendEmail("타이머 알림", "설정한 타이머가 종료되었습니다!");
}
    

이 기능을 사용하려면 ESP_Mail_Client 라이브러리를 설치해야 해. 그리고 Gmail을 사용할 경우 앱 비밀번호를 생성해야 한다는 점을 기억해!

💡 참고: Gmail을 사용할 경우 보안 설정에서 '보안 수준이 낮은 앱'을 허용하거나, 더 좋은 방법으로 앱 비밀번호를 생성해서 사용해야 해. 자세한 내용은 Google 계정 설정을 참고하세요.

3. 텔레그램 봇 알림

텔레그램 메신저를 사용한다면, 봇을 통해 알림을 받을 수도 있어:


#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>

// 텔레그램 봇 설정
#define BOT_TOKEN "YOUR_BOT_TOKEN"
#define CHAT_ID "YOUR_CHAT_ID"

WiFiClientSecure client;
UniversalTelegramBot bot(BOT_TOKEN, client);

// 텔레그램 메시지 보내기
void sendTelegramMessage(String message) {
  client.setInsecure(); // SSL 인증서 검증 건너뛰기
  bot.sendMessage(CHAT_ID, message, "");
}

// 타이머 종료 시 텔레그램 메시지 보내기
void triggerAlarm() {
  // 기존 알람 코드...
  
  // 텔레그램 알림 보내기
  sendTelegramMessage("⏰ 타이머 알림: 설정한 타이머가 종료되었습니다!");
}
    

이 기능을 사용하려면 UniversalTelegramBot 라이브러리를 설치하고, 텔레그램 봇을 생성해야 해. BotFather를 통해 봇을 만들고 토큰을 받을 수 있어.

🔍 문제 해결 가이드

프로젝트를 진행하다 보면 여러 문제가 발생할 수 있어. 자주 발생하는 문제와 해결 방법을 알아보자!

  1. ESP8266이 와이파이에 연결되지 않아요

    - SSID와 비밀번호가 정확한지 확인해보세요.
    - 라우터가 2.4GHz 대역을 지원하는지 확인하세요. ESP8266은 5GHz를 지원하지 않아요.
    - ESP8266과 라우터 사이의 거리를 가깝게 해보세요.

  2. 웹페이지가 로드되지 않아요

    - 시리얼 모니터에서 ESP8266의 IP 주소를 확인하세요.
    - 브라우저에서 정확한 IP 주소를 입력했는지 확인하세요.
    - ESP8266과 같은 네트워크에 연결되어 있는지 확인하세요.

  3. 타이머가 정확하지 않아요

    - ESP8266의 millis() 함수는 약 50일 후에 오버플로우됩니다. 장기간 실행 시 이 점을 고려하세요.
    - 정확한 시간이 필요하다면 NTP 서버를 사용해 시간을 동기화하는 것이 좋아요.

  4. 부저가 소리를 내지 않아요

    - 부저의 극성이 올바른지 확인하세요.
    - 능동 부저와 수동 부저의 차이를 확인하세요. 수동 부저는 tone() 함수가 필요하지만, 능동 부저는 디지털 신호만으로 작동합니다.

  5. 메모리 부족 오류가 발생해요

    - HTML 코드를 최소화하세요.
    - SPIFFS를 사용해 HTML 파일을 저장하고 불러오는 방식으로 변경해보세요.
    - 불필요한 라이브러리나 변수를 제거하세요.

💪 힘내세요! 문제가 생겨도 포기하지 마세요! 모든 개발자는 이런 과정을 겪으며 성장합니다. 재능넷에서 IoT 전문가를 찾아 도움을 요청할 수도 있어요!

🔮 미래 개선 방향

이 프로젝트를 더 발전시킬 수 있는 방법들을 알아보자!

1. MQTT 프로토콜 통합

MQTT는 IoT 기기 간 통신에 널리 사용되는 경량 프로토콜이야. ESP8266에 MQTT 클라이언트를 추가하면 다른 스마트 기기와 통신할 수 있어:


#include <PubSubClient.h>

// MQTT 설정
const char* mqtt_server = "broker.mqtt-dashboard.com";
const int mqtt_port = 1883;
const char* mqtt_topic = "esp8266/timer";

WiFiClient espClient;
PubSubClient mqtt(espClient);

void setupMQTT() {
  mqtt.setServer(mqtt_server, mqtt_port);
  mqtt.setCallback(mqttCallback);
  
  // MQTT 브로커에 연결
  if (mqtt.connect("ESP8266TimerClient")) {
    mqtt.subscribe(mqtt_topic);
    Serial.println("MQTT 연결 성공");
  }
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
  // 메시지 처리
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  
  Serial.print("MQTT 메시지 수신: ");
  Serial.println(message);
  
  // 메시지에 따라 동작 수행
  if (message == "start") {
    // 타이머 시작
  } else if (message == "stop") {
    // 타이머 정지
  }
}

// 타이머 상태 발행
void publishTimerState(String state) {
  mqtt.publish(mqtt_topic, state.c_str());
}
    

MQTT를 사용하면 스마트폰 앱이나 다른 IoT 기기에서도 타이머를 제어할 수 있어!

2. 음성 제어 추가하기

Google Assistant나 Amazon Alexa와 연동하면 음성으로 타이머를 제어할 수 있어. 이를 위해서는 Dialogflow나 AWS Lambda 같은 서비스를 사용해야 해.

3. 데이터 로깅 및 분석

타이머 사용 패턴을 기록하고 분석하면 사용자의 습관을 파악할 수 있어. 예를 들어, 요리 타이머를 자주 사용한다면 요리 관련 프리셋을 추천할 수 있지.

4. 배터리 전원으로 작동하기

ESP8266을 배터리로 구동하면 휴대성이 좋아져. 다음과 같은 전력 절약 기법을 사용할 수 있어:


// 딥 슬립 모드 사용
void goToSleep(uint64_t sleepTime) {
  ESP.deepSleep(sleepTime * 1000000); // 마이크로초 단위
}

// 타이머가 오래 남았을 때 슬립 모드로 전환
if (remainingTime > 60000) { // 1분 이상 남았을 때
  // 남은 시간에서 약간 빼고 슬립 모드로 전환
  goToSleep(remainingTime / 1000 - 10);
}
    

이런 기법을 사용하면 배터리 수명을 크게 늘릴 수 있어!

ESP8266 타이머 시스템 확장 가능성 ESP8266 웹 타이머 MQTT 스마트홈 연동 음성 제어 Alexa/Google 데이터 분석 사용 패턴 모바일 앱 원격 제어 배터리 전원 휴대성 다중 알람 여러 장치 연동

🎉 마무리

축하해! 이제 ESP8266을 사용한 웹 기반 타이머 및 알람 시스템을 만드는 방법을 배웠어. 이 프로젝트를 통해 다음과 같은 기술을 익혔지:

  1. ESP8266 기본 설정 및 프로그래밍
  2. 와이파이 연결 및 웹서버 구축
  3. HTML, CSS, JavaScript로 웹 인터페이스 만들기
  4. 타이머 및 알람 기능 구현
  5. 고급 기능 추가 방법

이 프로젝트는 IoT의 기본 개념을 이해하는 데 아주 좋은 시작점이야. 여기서 배운 지식을 바탕으로 더 복잡한 IoT 프로젝트도 도전해볼 수 있을 거야!

혹시 더 많은 IoT 프로젝트나 프로그래밍 관련 정보가 필요하다면, 재능넷에서 관련 전문가들의 재능을 찾아보는 것도 좋은 방법이야. 다양한 분야의 전문가들이 당신의 프로젝트를 도와줄 준비가 되어 있어!

🚀 다음 프로젝트도 기대해주세요! 🚀

ESP8266으로 만드는 스마트홈 시스템, 날씨 스테이션, 식물 자동 급수 시스템 등
더 많은 IoT 프로젝트를 소개할 예정이에요!

📚 참고 자료

더 공부하고 싶다면 다음 자료들을 참고해보세요:

  1. ESP8266 Arduino Core 공식 문서
  2. Random Nerd Tutorials - ESP8266 프로젝트
  3. Instructables - Arduino 프로젝트
  4. ESP8266 Arduino GitHub 저장소
  5. W3Schools - JavaScript 튜토리얼

이 글이 도움이 되었길 바라! 질문이나 피드백이 있다면 언제든지 댓글로 남겨주세요. 즐거운 DIY 프로젝트 되세요! 😊

댓글 작성

이 글에 대한 여러분의 생각을 들려주세요

댓글 0
댓글을 불러오는 중입니다.

아직 댓글이 없습니다.