아두이노 기반 스마트 누수 감지 및 밸브 제어 시스템
프로젝트 개요
물이 새는 사고는 가정에서 큰 피해를 초래할 수 있습니다. 이 프로젝트는 아두이노를 기반으로 누수를 실시간 감지하고, 메인 수도 밸브를 자동으로 차단하여 피해를 최소화하는 시스템을 구현합니다. 라즈베리 파이 같은 고성능 플랫폼 대신 아두이노와 같은 단순 마이크로컨트롤러에 핵심 책임을 위임하여, 네트워크 장애 시에도 기본 기능(누수 감지 및 밸브 차단)이 독립적으로 동작하도록 설계했습니다.
주요 기능
- 로컬 누수 감지: 바닥에 설치된 수분 센서가 물 접촉을 감지하면 즉시 메인 밸브를 차단
- 원격 누수 알림 수신: MQTT 브로커를 통해 집안 다른 구역의 누수 감지 장비로부터 알림을 수신하여 연동 차단
- 모터라이즈드 밸브 제어: 12V DC 모터 구동 밸브를 듀얼 릴레이로 정/역 회전 제어하여 개폐
- 상태 표시 LED: 3색 LED로 시스템 상태(누수 여부, 밸브 상태, MQTT 연결 상태) 직관적 표시
- 수동 리셋 버튼: 이상 상황 해제 후 시스템 재시작용 푸시 버튼
- MQTT 연동: 장비 상태 및 장애 정보를 홈 오토메이션 시스템과 공유
하드웨어 구성
| 부품 |
수량 |
비고 |
| 아두이노 우노 (Arduino UNO) | 1 | 메인 컨트롤러 |
| 아두이노 이더넷 실드 2 | 1 | 유선 네트워크 및 MQTT 통신용 |
| 모터라이즈드 볼 밸브 (12V DC) | 1 | 메인 수도관 차단용, 리미트 스위치 내장 |
| 수분 감지 센서 | 1 | 누수 예상 지점 다수 병렬 연결 가능 |
| 듀얼 릴레이 모듈 (5V, 12V 각 1개) | 2 | 밸브 모터 정/역 회전 제어 및 리미트 스위치 감지용 |
| 알루미늄 인클로저 | 1 | 방수/방진 하우징 |
| AC/DC 파워 서플라이 (5V/12V 듀얼 출력) | 1 | 아두이노(5V) 및 밸브 모터(12V) 전원 공급 |
| AC 하우징, JST 커넥터, LED 키트 등 | 각 1 | 배선 및 표시부 구성용 |
시스템 동작 원리
밸브 제어 로직
밸브 내부에는 정/역 회전에 따라 개폐되는 DC 모터와, 완전 개방/폐쇄 위치를 감지하는 리미트 스위치가 있습니다. 아두이노는 듀얼 릴레이를 통해 모터 극성을 전환하며, 리미트 스위치 신호(풀업 입력)로 현재 위치를 확인합니다. 리미트 스위치 신뢰성 확보를 위해 개폐 동작 전 반대쪽 리미트 스위치를 한 번 더 터치하여 위치를 재확인하는 안전 로직을 포함합니다.
LED 상태 표시
- 빨강 LED (Alarm): 점등 = 로컬 누수 감지, 깜빡임 = 원격 누수 알림 수신, 소등 = 정상
- 노랑 LED (Fault): 점등 = 밸브 제어 불가, 깜빡임 = MQTT 브로커 연결 실패, 소등 = 정상
- 파랑 LED (System): 점등 = 밸브 열림/감시 중, 깜빡임 = 밸브 닫힘, 소등 = 시스템 다운 또는 전원 차단
MQTT 통신 구조
클라이언트 ID: GLX_BASEMENT_001 형식 사용. 다음 토픽으로 상태/장애 발행 및 타 장비 장애 구독:
- 상태 발행:
GLX/BASEMENT/001/Status (JSON: 리셋 여부, 누수 감지, 밸브 상태, 밸브 연결 여부)
- 장애 발행/구독:
GLX/BASEMENT/001/Fault (JSON: 누수 감지 여부, 위치)
- 전체 장애 구독:
GLX/+/+/Fault (와일드카드로 타 장비 알림 수신)
소스 코드 핵심 부분
전체 코드는 아두이노 IDE에서 컴파일 가능하며, 주요 라이브러리(PubSubClient, Ethernet, Timer 등) 필요. 핵심 기능은 다음과 같습니다.
메인 루프 (loop)
void loop() {
// LED 초기 상태 설정
configureLedsWithInitialStates();
// 리셋 버튼 인터럽트 처리
if (isResetRequested) { ... watchdog 리셋 ... }
// 로컬 수분 센서 읽기 (디바운싱 적용)
readLocalWaterSensor();
// 누수 감지 시(로컬 또는 원격) 밸브가 열려 있으면 닫기
if (isWaterDetected || isWaterDetectedRemotely) {
if (isValveClosed == 0) closeValve();
}
// 주기적 MQTT 상태/장애 발행
if (mqttIntervalCnt == 0) {
if (isWaterDetected) publishFault();
publishStatus();
mqttIntervalCnt = mqttInterval;
} else {
mqttIntervalCnt--;
}
// MQTT 네트워크 루프 처리
client.loop();
// LED 최종 상태 업데이트
configureLedsWithFinalStates();
delay(mainLoopDelay);
}
밸브 개폐 제어 함수
int openValve() {
// 1. 닫힘 리미트 스위치 재확인 (릴레이 시나리오 1: 닫힘 방향)
setupRelays(1);
if (waitForEndOfCycle(ValveClosedPin) != 0) return -1;
// 2. 열림 방향으로 구동 (릴레이 시나리오 2: 열림 방향)
setupRelays(2);
if (waitForEndOfCycle(ValveOpenedPin) != 0) return -1;
isValveClosed = 0; isConnectedToValve = 1;
setupRelays(0); // 릴레이 OFF
return 0;
}
int closeValve() {
// 1. 열림 리미트 스위치 재확인
setupRelays(2);
if (waitForEndOfCycle(ValveOpenedPin) != 0) return -1;
// 2. 닫힘 방향으로 구동
setupRelays(1);
if (waitForEndOfCycle(ValveClosedPin) != 0) return -1;
isValveClosed = 1; isConnectedToValve = 1;
setupRelays(0);
return 0;
}
디바운싱 및 안정성 확보
센서 오작동 방지를 위해 getDebouncedValue() 함수로 일정 간격(기본 100ms) 다중 확인 후 상태 확정. 리미트 스위치 역시 동일 로직 적용.
안전 주의사항 (필독)
AC/DC 파워 서플라이는 5V와 12V 듀얼 출력입니다. 아두이노는 5V 핀에 직접 공급하므로(Vin은 6V 이상 필요), AC 전원 연결 상태에서 절대 아두이노 DC 잭이나 USB 케이블을 연결하지 마십시오. 디버깅용 USB 연결 시 전원선(VCC)을 제거한 데이터선만 연결된 커스텀 케이블을 사용하세요. AC 하우징과 파워 서플라이 사이는 110V/220V 고압이므로 감전 위험이 있습니다.
회로도

확장 아이디어
- 여러 구역에 추가 수분 센서 설치 후 병렬 연결로 감지 범위 확대
- Home Assistant, OpenHAB 등 홈 오토메이션 허브와 MQTT로 연동하여 알림 자동화(푸시, 문자, 음성 등)
- 밸브 수동 바이패스 배관 구성으로 정전/고장 시 수동 개방 가능하도록 설계(본문 참고)
- 배터리 백업(UPS) 추가로 정전 시에도 일정 시간 동작 보장