고급⏱ 예상 시간: 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단계회로 연결하기
- PIR 센서의 OUT을 GPIO13에 연결합니다.
- PIR의 VCC를 5V(VIN), GND를 GND에 연결합니다.
- 부저를 GPIO12에 연결합니다.
- LED를 GPIO14에 220Ω 저항과 함께 연결합니다.
- 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단계업로드 및 테스트
- 필요한 라이브러리들을 설치합니다.
- Wi-Fi 정보를 입력하고 코드를 업로드합니다.
- 30초간 PIR 안정화를 기다립니다.
- 센서 앞에서 움직이면 멜로디가 울리고 OLED에 'VISITOR!' 표시됩니다.
- 스마트폰 브라우저에서 IP 주소로 접속하면 방문 기록을 확인할 수 있습니다!
💡 팁: 문 앞에 설치하면 실제 스마트 초인종으로 활용할 수 있어요.