고급⏱ 예상 시간: 55분📝 4단계

ESP32 스마트 초인종

ESP32와 PIR 센서로 방문자를 감지하고, 부저로 알림을 울리면서 Wi-Fi를 통해 스마트폰으로 알림을 보내는 IoT 초인종입니다.

🧩 필요한 모듈

브레드보드
피에조 부저
ESP32
점퍼 와이어
LED
OLED 디스플레이 (0.96인치 I2C)
PIR 모션 센서
저항 (220Ω / 10kΩ)

📖 단계별 설명서

📝

1단계준비물 확인

다음 부품들을 준비해주세요:

  • ESP32 보드 1개
  • 브레드보드 1개
  • 점퍼 와이어 8개
  • PIR 모션 센서 1개
  • 피에조 부저 1개
  • LED 1개 (빨강)
  • 220Ω 저항 1개
  • OLED 디스플레이 (0.96인치) 1개
📝

2단계회로 연결하기

  1. PIR 센서의 OUT을 GPIO13에 연결합니다.
  2. PIR의 VCC를 5V(VIN), GND를 GND에 연결합니다.
  3. 부저를 GPIO12에 연결합니다.
  4. LED를 GPIO14에 220Ω 저항과 함께 연결합니다.
  5. OLED의 SDA를 GPIO21, SCL을 GPIO22에 연결합니다.

📐 회로도

회로도 이미지

/images/projects/esp32-smart-doorbell-circuit.png

💡 팁: PIR 센서는 5V가 필요하므로 ESP32의 VIN 핀(USB 5V)에서 전원을 공급합니다.

📝

3단계코드 작성하기

PIR 센서 감지 시 부저와 LED를 작동시키고, 웹 대시보드에서 방문 기록을 확인할 수 있습니다.

code.ino
#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define PIR_PIN 13
#define BUZZER_PIN 12
#define LED_PIN 14
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
WebServer server(80);

int visitCount = 0;
String lastVisit = "없음";
bool motionDetected = false;

void playDoorbell() {
  int melody[] = {523, 659, 784, 659};
  int durations[] = {200, 200, 300, 200};
  for (int i = 0; i < 4; i++) {
    tone(BUZZER_PIN, melody[i], durations[i]);
    delay(durations[i] + 50);
  }
  noTone(BUZZER_PIN);
}

void handleRoot() {
  String html = "<!DOCTYPE html><html><head>";
  html += "<meta charset='UTF-8'>";
  html += "<meta http-equiv='refresh' content='3'>";
  html += "<style>body{font-family:sans-serif;text-align:center;padding:40px;background:#f0f4f8;}";
  html += ".card{background:white;border-radius:16px;padding:30px;max-width:400px;margin:auto;box-shadow:0 4px 12px rgba(0,0,0,0.1);}";
  html += ".alert{color:#e74c3c;font-size:24px;font-weight:bold;}</style>";
  html += "</head><body><div class='card'>";
  html += "<h1>Smart Doorbell</h1>";
  html += "<p>Total visits: <strong>" + String(visitCount) + "</strong></p>";
  html += "<p>Last: " + lastVisit + "</p>";
  if (motionDetected) html += "<p class='alert'>Someone is here!</p>";
  html += "</div></body></html>";
  server.send(200, "text/html", html);
}

void setup() {
  Serial.begin(115200);
  pinMode(PIR_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println("Connecting WiFi...");
  display.display();
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());
  
  server.on("/", handleRoot);
  server.begin();
  
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Smart Doorbell");
  display.print("IP: ");
  display.println(WiFi.localIP());
  display.println("\nReady!");
  display.display();
  delay(30000); // PIR 안정화
}

void loop() {
  server.handleClient();
  
  if (digitalRead(PIR_PIN) == HIGH) {
    if (!motionDetected) {
      motionDetected = true;
      visitCount++;
      unsigned long sec = millis() / 1000;
      lastVisit = String(sec / 60) + "m " + String(sec % 60) + "s";
      
      Serial.println("Motion detected! Visit #" + String(visitCount));
      
      digitalWrite(LED_PIN, HIGH);
      playDoorbell();
      
      display.clearDisplay();
      display.setTextSize(2);
      display.setCursor(0, 0);
      display.println("VISITOR!");
      display.setTextSize(1);
      display.print("Count: ");
      display.println(visitCount);
      display.display();
    }
  } else {
    if (motionDetected) {
      motionDetected = false;
      digitalWrite(LED_PIN, LOW);
      
      display.clearDisplay();
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("Smart Doorbell");
      display.print("Visits: ");
      display.println(visitCount);
      display.println("\nWaiting...");
      display.display();
    }
  }
  delay(100);
}
+103 줄 더 보기

💡 팁: Wi-Fi 자격 증명을 반드시 본인의 네트워크 정보로 변경하세요.

📝

4단계업로드 및 테스트

  1. 필요한 라이브러리들을 설치합니다.
  2. Wi-Fi 정보를 입력하고 코드를 업로드합니다.
  3. 30초간 PIR 안정화를 기다립니다.
  4. 센서 앞에서 움직이면 멜로디가 울리고 OLED에 'VISITOR!' 표시됩니다.
  5. 스마트폰 브라우저에서 IP 주소로 접속하면 방문 기록을 확인할 수 있습니다!

💡 팁: 문 앞에 설치하면 실제 스마트 초인종으로 활용할 수 있어요.

🎉

축하합니다!

"ESP32 스마트 초인종" 프로젝트를 완성했습니다!