[아두이노] 슈퍼커패시터 UPS + Raspberry Pi + Arduino 자동 복구 시스템 아이디어
시스템 개요
이 시스템의 목적은 다음 두 가지입니다.
정전 시 Raspberry Pi를 안전하게 종료하여 데이터 손상을 방지
전원 복구 후 Raspberry Pi가 자동으로 다시 부팅되지 않는 경우 Arduino가 강제로 깨워서 자동 복구
즉, 단순 UPS가 아니라 안전 종료(Safe Shutdown) + 자동 복구(Self-Healing) 기능을 구현하는 구조입니다.
각 장치 역할
Raspberry Pi (데이터 보호 담당)
UPS 전원 상태 감시
정전 발생 감지
디스크 캐시 저장(sync)
안전 종료 수행
종료 직전 Arduino에게 종료 사실 전달
Arduino (전원 관리자 담당)
전원 복구 시 가장 먼저 동작
Raspberry Pi의 생존 여부 확인
Raspberry Pi가 응답하지 않으면 RUN 핀 리셋
무인 자동 복구 수행
하드웨어 연결
Raspberry Pi
| GPIO | 용도 |
|---|---|
| GPIO18 | UPS 전원 감지 입력 |
| GPIO20 | Heartbeat 출력 |
Arduino
| 핀 | 용도 |
|---|---|
| D2 | Raspberry Pi Heartbeat 입력 |
| D3 | Raspberry Pi RUN 리셋 제어 |
동작 시나리오
정상 상태
외부 전원이 정상 공급 중
외부 전원 ON
↓
UPS 정상
↓
Raspberry Pi 실행
↓
GPIO20 = HIGH
↓
Arduino 대기
정전 발생
UPS 감지 핀이 LOW로 떨어짐
정전 발생
↓
GPIO18 FALLING 감지
↓
sync 실행
↓
3초 대기
↓
sync 재실행
↓
Heartbeat LOW
↓
Shutdown 수행
전원 복구
전원 복구
↓
Arduino 부팅
↓
5초 대기
↓
Heartbeat 확인
Raspberry Pi 정상 부팅
Heartbeat = HIGH
↓
정상 상태
↓
아무 작업 안 함
Raspberry Pi 식물인간 상태
Heartbeat = LOW
↓
RUN 핀 리셋
↓
Raspberry Pi 강제 재부팅
Raspberry Pi 파이썬 코드
#!/usr/bin/env python3
import RPi.GPIO as GPIO
import time
import os
POWER_SENSE_PIN = 18
HEARTBEAT_PIN = 20
GPIO.setmode(GPIO.BCM)
GPIO.setup(
POWER_SENSE_PIN,
GPIO.IN,
pull_up_down=GPIO.PUD_DOWN
)
GPIO.setup(
HEARTBEAT_PIN,
GPIO.OUT
)
# 살아있음을 알림
GPIO.output(
HEARTBEAT_PIN,
GPIO.HIGH
)
# 전원 차단 감지
GPIO.add_event_detect(
POWER_SENSE_PIN,
GPIO.FALLING,
bouncetime=500
)
print("UPS Monitor Started")
try:
while True:
if GPIO.event_detected(
POWER_SENSE_PIN
):
print("Power Failure Detected")
# 데이터 저장
os.system("sync")
print("Saving Data 1/2")
time.sleep(3)
os.system("sync")
print("Saving Data 2/2")
print("Shutdown in 5 seconds")
for sec in range(5, 0, -1):
print(sec)
time.sleep(1)
# 종료 직전 Heartbeat 제거
GPIO.output(
HEARTBEAT_PIN,
GPIO.LOW
)
time.sleep(0.5)
os.system(
"sudo shutdown -h now"
)
break
time.sleep(0.5)
except KeyboardInterrupt:
GPIO.cleanup()
Arduino 코드
const int RPI_HEARTBEAT_PIN = 2;
const int RPI_RESET_PIN = 3;
void setup()
{
Serial.begin(115200);
pinMode(
RPI_HEARTBEAT_PIN,
INPUT_PULLDOWN
);
// 평상시 High-Z 상태 유지
pinMode(
RPI_RESET_PIN,
INPUT
);
Serial.println(
"Arduino Power Manager Start"
);
// Raspberry Pi 부팅 시간 확보
delay(5000);
if (
digitalRead(
RPI_HEARTBEAT_PIN
) == LOW
)
{
Serial.println(
"Raspberry Pi Not Responding"
);
// RUN 핀 리셋
pinMode(
RPI_RESET_PIN,
OUTPUT
);
digitalWrite(
RPI_RESET_PIN,
LOW
);
delay(500);
// 선 떼기
pinMode(
RPI_RESET_PIN,
INPUT
);
Serial.println(
"Reset Complete"
);
}
else
{
Serial.println(
"Raspberry Pi Alive"
);
}
}
void loop()
{
// 센서 수집
// 환경 제어
// 데이터 처리
delay(1000);
}
Raspberry Pi 서비스 등록
서비스 파일 생성
파일:
/etc/systemd/system/ups-monitor.service
내용:
[Unit]
Description=UPS Power Monitor
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/pi/ups_monitor.py
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
서비스 등록
sudo systemctl daemon-reload
sudo systemctl enable ups-monitor.service
sudo systemctl start ups-monitor.service
상태 확인
sudo systemctl status ups-monitor.service
권장 하드웨어 구성
RUN 핀 직접 연결 금지
Arduino 출력 핀을 Raspberry Pi RUN 핀에 직접 연결하는 것보다 아래 방식이 안전합니다.
Arduino D3
│
▼
NPN 트랜지스터
│
▼
Raspberry Pi RUN
또는
Arduino D3
│
▼
옵토커플러
│
▼
Raspberry Pi RUN
Heartbeat 개선 버전 (권장)
현재 구조
HIGH = 살아있음
LOW = 죽음
개선 구조
1초마다 GPIO20 토글
HIGH
LOW
HIGH
LOW
HIGH
LOW
...
Arduino는 5초 동안 변화가 있는지 확인
변화 있음
→ 정상
변화 없음
→ 이상 상태
→ RUN 리셋
이 방식은 GPIO가 우연히 HIGH에 고착되는 경우까지 검출할 수 있어 더 신뢰성이 높습니다.
최종 동작 흐름
정상 운전
↓
정전 발생
↓
UPS 감지
↓
Raspberry Pi
↓
sync
↓
3초 대기
↓
sync
↓
Heartbeat OFF
↓
Shutdown
=========================
전원 복구
↓
Arduino 기동
↓
5초 대기
↓
Heartbeat 확인
HIGH
└─ 정상
LOW
└─ RUN 리셋
↓
Raspberry Pi 재부팅
이 구조는 스마트팜 제어기, 환경 모니터링 장치, PLC 게이트웨이, 데이터 로거처럼 무인으로 장기간 운영되는 시스템에서 사용할 수 있는 비교적 견고한 안전 종료 및 자동 복구 아키텍처입니다.
댓글
댓글 쓰기