Home IoT Hub Series · 04
[4편] 문 닫았나 계속 신경 쓰일 때 - 현관문 열림을 IoT 허브로 확인하기
![[4편] 문 닫았나 계속 신경 쓰일 때 - 현관문 열림을 IoT 허브로 확인하기 대표 이미지](/iot-lab/assets/front-door-reed-switch-hero.png)
이 글은 2편: 두뇌 만들기에서 구축한 중앙 NodeMCU 서버에 연결되는 우리집 IoT 허브 구성 문서입니다. MC-38 리드스위치가 문 열림 상태를 감지해 침입 경고 판단의 입력값을 만듭니다. 수집된 데이터는 로컬 무선망
IoT_Hub_Net을 통해 중앙 서버의 9번 정문 열림 슬롯(/set?no9=값)을 갱신하며, 20채널 스마트홈 통합 컨트롤러의 판단 근거로 사용됩니다.[3편] 집 안 온습도, 감으로 보지 말고 숫자로 보자. 이번에는 현관문이다. 문이 열리면 두뇌 OLED가 반전되고 부저가 울리는, 진짜 경고 시스템을 처음으로 맛볼 수 있는 편이다.
센서 구조는 3편보다 더 간단합니다. 리드스위치는 자석 하나와 센서 하나로 구성되고, 데이터 핀 한 개만 연결하면 됩니다. 복잡한 라이브러리도 필요하지 않습니다.
준비물과 가격
| 부품 | 수량 | 개당 가격 | 비고 |
|---|---|---|---|
| Wemos D1 Mini (ESP8266) | 1개 | 2,000원 | 센서 노드 본체 |
| MC-38 리드스위치 | 1개 | 800원 | 자석 도어 센서. 배선 나사 포함 |
| 점퍼 와이어 (암-암) | 2개 | — | 앞서 산 묶음에서 쓴다 |
| Micro USB 케이블 + 충전기 | 1세트 | — | 구형 충전기 재활용 |
| 합계 | 2,800원 | (충전기·케이블 제외) |
MC-38 리드스위치 원리
겉보기엔 플라스틱 조각 두 개지만, 원리는 간단하다.
- 센서 본체 안에 리드스위치(Reed Switch)라는 작은 유리관이 들어 있다. 자석이 가까이 오면 두 금속 접점이 붙으면서 회로가 닫히고, 자석이 멀어지면 접점이 떨어지면서 회로가 열린다.
- 자석 조각을 문에 붙이고, 센서 본체를 문틀에 붙인다. 문이 닫혀 있으면 자석이 센서 가까이 있어서 회로가 닫히고(LOW 신호), 문이 열리면 자석이 떨어져서 회로가 열린다(HIGH 신호).
센서에서 나오는 전선은 두 가닥입니다. 극성이 없어서 어느 쪽을 GND에, 어느 쪽을 GPIO에 연결해도 동작합니다. 다만 코드에서 INPUT_PULLUP을 사용해야 합니다.
문 닫힘 → 자석 가까이 → 회로 닫힘 → GND 연결 → GPIO = LOW → "0" 문 열림 → 자석 멀어짐 → 회로 열림 → 풀업만 남음 → GPIO = HIGH → "1"
핀 연결
| 센서/모듈 | 보드 연결 |
|---|---|
| 전선 1 | GND |
| 전선 2 | D1 (GPIO5) |
pinMode(5, INPUT_PULLUP)으로 내부 풀업 저항을 켜서, 자석이 떨어졌을 때 HIGH가 확실히 잡히도록 구성합니다.문에 붙일 땐 이렇게:
┌─ 문틀 ─┐ ┌────── 문 ──────┐ │ │ │ │ │ [센서] │ ◄─── │ [자석] │ │ 본체 │ 가까이 │ 작은 조각 │ │ │ │ │ └─────────┘ └─────────────────┘
센서 본체와 자석 조각 사이 간격은 1cm 이내로 붙여야 한다. 1.5cm만 벌어져도 인식이 안 될 수 있다. 양면테이프로 붙이면 깔끔하다.
선행 작업
이번 편은 추가 라이브러리가 필요하지 않습니다. ESP8266 기본 기능(GPIO 읽기, Wi-Fi, HTTP)만으로 동작합니다. Arduino IDE에서 보드만 LOLIN(WEMOS) D1 R2 & mini로 맞추면 됩니다.
🚨 코드 넣기 전에 반드시!!
3편과 같은 구조입니다. Wi-Fi 정보는 이미 IoT_Hub_Net / iothub1234로 코드에 들어 있습니다. 두뇌가 먼저 켜져 있어야 합니다. 센서 노드를 먼저 켜면 Wi-Fi를 찾지 못해 Connecting... 상태에서 멈출 수 있습니다.
이 편에서 데이터는 9번 슬롯(Front Door)으로 들어갑니다. 문이 열리면 1, 닫히면 0을 보냅니다. 9번은 경고 대상 슬롯이기 때문에 1이 전송되는 순간 부저가 울리기 시작합니다. 처음 테스트할 때 부저가 울리면 정상 동작입니다.
전체 코드
#include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> // ============================================= // 1. Wi-Fi 설정 (두뇌의 AP에 접속) // ============================================= const char* ssid = "IoT_Hub_Net"; const char* password = "iothub1234"; const char* hubURL = "http://192.168.1.1"; // ============================================= // 2. 센서 설정 // ============================================= #define DOOR_PIN 5 // D1 (GPIO5) #define SLOT_NO 9 // 두뇌 9번 슬롯 = Front Door // ============================================= // 3. 전송 간격 & 디바운스 // ============================================= #define INTERVAL 1000 // 1초마다 체크 #define DEBOUNCE 300 // 300ms 이내 재전송 방지 int lastState = -1; // 직전 문 상태 (-1=초기) unsigned long lastSend = 0; // ============================================= // setup // ============================================= void setup() { Serial.begin(115200); pinMode(DOOR_PIN, INPUT_PULLUP); // 내부 풀업 사용 WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.print("Connecting to IoT_Hub_Net"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.print("Connected! IP: "); Serial.println(WiFi.localIP()); Serial.println("Waiting for door state change..."); Serial.println("---"); } // ============================================= // loop // ============================================= void loop() { // 현재 문 상태 읽기 // LOW = 문 닫힘 (자석 붙음) // HIGH = 문 열림 (자석 떨어짐) int currentState = digitalRead(DOOR_PIN); // 상태가 바뀌었을 때만 전송 (불필요한 트래픽 방지) if (currentState != lastState) { // 디바운스: 마지막 전송 후 일정 시간 안 지났으면 무시 unsigned long now = millis(); if (now - lastSend > DEBOUNCE) { lastState = currentState; lastSend = now; // 문이 열렸으면 1, 닫혔으면 0 String val = (currentState == HIGH) ? "1" : "0"; Serial.print("Door "); Serial.print(currentState == HIGH ? "OPEN " : "CLOSED"); Serial.print(" -> sending "); Serial.print(val); Serial.print(" to slot "); Serial.println(SLOT_NO); // 두뇌로 전송 WiFiClient client; HTTPClient http; String url = String(hubURL) + "/set?no" + String(SLOT_NO) + "=" + val; http.begin(client, url); int code = http.GET(); http.end(); Serial.print("HTTP "); Serial.print(code); Serial.print(" -> "); Serial.println(url); Serial.println(); } } delay(INTERVAL); }
업로드
1. Wemos D1 Mini를 USB로 PC에 연결. 2. 툴 → 보드 → LOLIN(WEMOS) D1 R2 & mini 선택. 3. 포트 선택 후 업로드. 4. 시리얼 모니터 열고 보드레이트 115200 확인.
확인할 것
시리얼 모니터
업로드가 끝나면 Arduino IDE의 툴 → 시리얼 모니터를 열고 보드레이트를 115200으로 맞춥니다. 다음은 정상 동작을 확인하기 위한 시리얼 모니터 출력 예시입니다. 이 로그는 실제 캡처가 아니라, MC-38 리드스위치 배선과 문 열림/닫힘 판단을 점검하기 위한 시리얼 모니터 출력 예시입니다.
[BOOT] Home IoT Node #04 - Front door reed switch [WIFI] connected to IoT_Hub_Net, ip=192.168.1.49 [GPIO] reed raw=LOW, debounce=stable [SENSOR] door_state=CLOSED [HTTP] GET /set?no9=0 [HUB] 200 OK - slot no9=CLOSED [EVENT] door opened -> no9=1
Connected또는connected가 보이면 Wi-Fi 연결 단계는 통과한 것입니다.HTTP 200또는200 OK가 보이면 두뇌 서버에 값이 전달된 것입니다.- 값이 갱신되지 않으면 먼저 URL의 슬롯 번호와 센서 배선을 함께 확인합니다.
두뇌에서 경고 확인 (이게 핵심이다)
문을 열었을 때:
- 두뇌 OLED의 9번
Front Door라벨이 반전 표시됩니다. - 부저가 0.5초 간격으로 삐-삐- 울리기 시작합니다.
- HTML 대시보드에서 9번 카드가 빨간색으로 강조됩니다.
문을 닫았을 때:
- OLED 반전이 풀리고 부저가 꺼집니다.
- 카드가 원래 색으로 돌아옵니다.
이게 바로 2편에서 checkWarning() 함수에 넣어둔 i == 8 조건이 실제로 동작하는 순간이다.
안 될 때 체크포인트
문을 열어도 반응이 없다
| 증상 | 원인 | 해결 |
|---|---|---|
| 시리얼 모니터에 아무것도 안 찍힘 | Wi-Fi 연결 실패 | IoT_Hub_Net이 살아 있는지 확인. 센서 노드가 두뇌와 같은 방에 있는지 확인 |
Door OPEN은 찍히는데 HTTP -1 | 두뇌 주소 오류 | 두뇌가 192.168.1.1로 AP를 열었는지 확인. 2편 코드에서 WiFi.softAP()가 정상 호출됐는지 체크 |
| 시리얼 모니터는 잘 되는데 두뇌 OLED 변화 없음 | 슬롯 번호 불일치 | SLOT_NO 9가 맞는지 확인. 두뇌 코드 label[8]이 "Front Door"인지 확인 |
문이 열려 있는데도 닫혔다고 나온다
| 증상 | 원인 | 해결 |
|---|---|---|
Door CLOSED만 계속 찍힘 | 풀업 설정 누락 | pinMode(DOOR_PIN, INPUT_PULLUP)이 코드에 있는지 확인합니다. 이 설정이 없으면 핀이 불안정해져 LOW로 읽힐 수 있습니다. |
| 자석을 붙여도 계속 OPEN | 자석이 너무 멀다 | 자석과 센서 간격을 1cm 이내로 좁힙니다. 1.5cm 이상 벌어지면 인식되지 않을 수 있습니다. |
| 문이 완전히 닫혔는데도 OPEN | 센서/자석 위치가 틀어짐 | 문을 닫은 상태에서 자석이 센서 본체 정면에 오도록 위치를 조정합니다. 양면테이프로 고정하기 전에 손으로 위치를 바꿔 가며 테스트합니다. |
문을 열 때마다 여러 번 전송된다
| 증상 | 원인 | 해결 |
|---|---|---|
Door OPEN이 여러 줄 연속으로 찍힘 | 접점 떨림 (bouncing) | 정상 동작입니다. 코드에서 DEBOUNCE 300으로 300ms 이내 재전송을 막고 있습니다. 그래도 여러 번 표시되면 DEBOUNCE 값을 500으로 늘립니다. |
현장 추가 체크포인트
이 노드는 코드만 보면 짧아 보일 수 있지만, 실제 집에 붙이면 센서 위치·전원·무선망·노이즈 때문에 값이 쉽게 흔들립니다. 아래 항목은 두뇌 서버에 잘못된 판단 근거가 들어가지 않도록 현장에서 먼저 점검할 내용입니다.
| 증상 | 가능한 원인 | 현장 해결 방법 |
|---|---|---|
| 문을 열어도 닫힘으로 표시됨 | 철문 자체의 자력이나 자석 위치 불량으로 리드스위치가 계속 붙어 있음 | 센서와 자석 사이 간격을 5~10mm로 맞추고, 철문에는 포맥스·나무 블록 스페이서를 끼워 자력 간섭을 줄입니다. |
| 문을 닫을 때 값이 여러 번 튐 | 문 충격으로 접점이 빠르게 붙었다 떨어지는 채터링 발생 | 코드에서 200~500ms 디바운스 시간을 두고 같은 상태가 유지될 때만 서버로 전송합니다. |
| 가끔 침입 경고가 늦게 뜸 | 문 근처 Wi-Fi 음영이나 센서 노드 재접속 지연 | 현관 근처 수신 세기를 확인하고, HTTP 실패 시 3회 재시도 후 다음 주기에 다시 보내도록 합니다. |
| 양면테이프가 떨어짐 | 문틀의 먼지·습기·온도 변화로 접착력이 약해짐 | 설치 전 알코올로 닦고, 케이블 장력은 별도 고정 클립으로 빼서 센서 본체에 힘이 가지 않게 합니다. |
집에 붙일 때 팁
- 양면테이프로 부착하면 문에 구멍을 뚫지 않아도 됩니다. 3M 양면테이프 정도면 장기간 고정에 충분합니다.
- 센서 본체는 문틀에, 자석은 문에 붙입니다. 반대로 부착해도 동작 원리는 같습니다.
- 전원은 현관 근처 콘센트에 USB 충전기를 꽂아 공급합니다. Micro USB 케이블이 짧으면 2m 연장 케이블을 사용할 수 있습니다.
- D1 Mini는 크기가 작아 문틀 위쪽 구석에 숨기기 좋습니다. 흰색 케이블 타이로 정리하면 눈에 잘 띄지 않습니다.
지금까지 구성한 흐름
- MC-38 리드스위치 + Wemos D1 Mini로 두 번째 센서 노드를 만들었다.
- 문이 열리면 두뇌에
1, 닫히면0을 보냅니다. - 두뇌의 경고 시스템이 실제로 작동하는 것을 처음 확인합니다: OLED 반전 + 부저 경고음.
- 이제 현관문이 열릴 때마다 두뇌가 부저로 알려줍니다.
다음 글 예고
다음 편에서는 냉장고 온도를 붙인다. DS18B20 방수형 센서를 냉장실 안에 넣고, 문 밖으로 케이블만 빼서 D1 Mini에 연결하는 구조다. DHT22보다 더 정밀하고, 방수라서 습기 걱정도 없다.
이 글은 2편의 중앙 두뇌 서버와 3~19편의 분산 엣지 노드가 함께 구성하는 20채널 홈 IoT 시스템의 일부입니다. 필요한 편으로 이동해 슬롯과 센서 흐름을 함께 확인합니다.
[1편] 우리집 IoT 허브 전체 그림[2편] 중앙 두뇌 서버 만들기 · 슬롯 1~20[3편] 집 안 온습도, 감으로 보지 말고 숫자로 보자 · 슬롯 1·2[4편] 문 닫았나 계속 신경 쓰일 때 · 슬롯 9[5편] 냉장고가 제대로 돌고 있는지 눈으로 확인하자 · 슬롯 12[6편] 창문 열어도 될까? · 슬롯 3[7편] 욕실 곰팡이 생기기 전에 습도부터 잡자 · 슬롯 19[8편] 보일러가 실제로 도는지 배관 온도로 확인하자 · 슬롯 5·17[9편] 외출했는데 가스레인지가 켜져 있지 않을까? · 슬롯 6[10편] 가스 냄새가 나기 전에 먼저 경고받자 · 슬롯 7[11편] 집을 비웠을 때 불꽃 징후를 먼저 잡자 · 슬롯 8[12편] 머리가 멍한 이유가 공기 때문인지 확인하자 · 슬롯 13·14[13편] 전기세 무지 나오네, 이번 기회에 눈으로 보자 · 슬롯 15[14편] 물 새는지, 얼마나 쓰는지 숫자로 보자 · 슬롯 16[15편] 비 오는 줄 모르고 창문 열어두지 않게 · 슬롯 18[16편] 불 껐나, 문 잠갔나 한 번에 확인하자 · 슬롯 11·10[17편] 리모컨 없이 에어컨을 IoT 허브에서 제어하자 · 슬롯 4[18편] 강아지 밥그릇이 비었는지 눈으로 보자 · 슬롯 20[19편] 사람 있을 때만 시원하게, 없을 땐 아끼자 · 슬롯 1·4[20편] 집 안 상태가 한 화면에 보이기 시작했다 · 슬롯 전체