DCF77 라디오 시계 및 분석기 v2.0: 아두이노 메가/우노 기반 정밀 시계
프로젝트 개요
독일 프랑크푸르트에서 송출되는 DCF77 장파(77.5kHz) 표준 전파를 수신하여 시각을 동기화하는 고정밀 라디오 시계입니다. 단순한 시계 표시를 넘어 DCF77 신호의 펄스 폭, 주기, 패리티 비트 등을 실시간 분석·표시하는 '분석기' 기능을 탑재했습니다. 버전 2.0에서는 우도 클라인(Udo Klein)의 슈퍼필터(Superfilter)를 별도 아두이노 우노로 구현하여 수신 감도를 대폭 향상시켰습니다.
버전 2.0 주요 개선사항
- 코드 완전 재작성 및 상세 주석 추가 (가독성·유지보수성 확보)
- DCF77 슈퍼필터 전용 아두이노 우노 보드 추가 (노이즈 환경에서 신호 복원)
- PIR 모션 센서 연동으로 디스플레이 절전 모드 구현
- 보조 디스플레이 추가 (온도, 일출/일몰 시각 등)
- 맥심 MAX7219 대신 아두이노 메가 GPIO 직접 구동으로 다전압/다전류 LED 제어 문제 해결
하드웨어 구성
메인 보드: 아두이노 메가 2560
| 기능 |
핀 |
비고 |
| DCF77 신호 입력 (슈퍼필터 출력) |
D2 (인터럽트 0) |
라이징/폴링 에지 모두 감지 |
| PIR 모션 센서 |
D3 |
절전 모드 제어용 |
| 부저 스위치 |
D4 |
DCF 펄스 음성 모니터링 |
| 차임 스위치 |
D5 |
정시 알림음 제어 |
| 절전 스위치 |
D6 |
디스플레이 상시 ON/OFF |
| DS18B20 온도 센서 |
D8 |
1-Wire 버스 |
| 온도 Min/Max 리셋 버튼 |
D9 |
누르면 리셋 |
| MAX7219 CS/CLK/DATA |
D10/D11/D12 |
7세그 디스플레이 3개 제어 (공통 캐소드) |
| 요일 LED (일~토) |
D22~D28 |
7개 LED |
| CEST/CET/윤년/에러/동기 등 상태 LED |
D29~D50 |
총 22개 상태 표시 LED |
| 압전 부저 |
A7 |
DCF 펄스 비프음 |
| 사운드 보드 볼륨 |
A6 |
차임 볼륨 제어 |
| 차임 트리거 |
A5 |
LOW 액티브 |
| I2C (RTC DS1307) |
SDA/SCL |
하드웨어 I2C |
슈퍼필터 보드: 아두이노 우노 (별도)
우도 클라인의 DCF77 라이브러리 기반. 입력된 노이즈 섞인 DCF 신호를 필터링하여 클린한 펄스 스트림을 출력.
| 출력 |
핀 |
설명 |
| 필터링된 DCF 출력 |
D12 |
메인 보드 D2로 연결 |
| 반합성 신호 |
A2 (D16) |
디버깅용 |
| 완전 합성 신호 |
D6 |
이상적 DCF 신호 재생성 |
| 모니터 LED |
A4 (D18) |
입력 신호 표시 |
| 1Hz 펄스/락 LED |
D10 |
필터 락 상태 |
| 신호 품질 LED |
D13 |
좋음/나쁨 표시 |
DCF77 프로토콜 핵심
- 매 초마다 펄스 전송 (시작 마커: 2초간 무신호 = 분 마커)
- 펄스 폭: 100ms = 비트 0, 200ms = 비트 1
- 분당 59비트 전송 (비트 0~58), 59번째 초는 무신호
- 패리티 비트 3개 포함: 분(P1, 비트 28), 시(P2, 비트 35), 날짜(P3, 비트 58) - 짝수 패리티
- 데이터: 분(6비트), 시(6비트), 일(6비트), 요일(3비트), 월(5비트), 년(8비트), 서머타임/윤년 플래그
소프트웨어 아키텍처 (메인 스케치)
인터럽트 기반 펄스 측정
volatile unsigned int DCFSignalState = 0;
unsigned long leadingEdge, trailingEdge, previousLeadingEdge;
void int0handler() {
DCFSignalState = digitalRead(DCF77PIN); // CHANGE 인터럽트
}
void scanSignal() {
if (DCFSignalState == 1) { // 라이징 에지
leadingEdge = millis();
} else { // 폴링 에지
trailingEdge = millis();
// 주기(Period) = leadingEdge - previousLeadingEdge → 1000ms 기대
// 펄스 폭(Pulse Width) = trailingEdge - leadingEdge → 100/200ms 기대
// 오차 범위 초과 시 에러 플래그 설정
// 패리티 검사 수행 (비트 28, 35, 58에서)
// 분 마커(약 2000ms 갭) 감지 시 finalizeBuffer() 호출
}
}
버퍼 처리 및 디코딩
DCFbitBuffer[59]에 비트 순차 저장
- 내부 LED 링(MAX7219 #0)에 실시간 비트 표시
- 분 마커 감지 시 패리티 3개 모두 통과하면 외부 LED 링(#1)에 복사, RTC 동기화
- 패리티 실패 시 외부 링 클리어, 에러 카운터 증가, 시각 유지
주기적 태스크
void loop() {
if (DCFSignalState != previousSignalState) scanSignal();
checkSwitches(); // 스위치 상태 변화 감지
checkPIR(); // PIR 모션 감지 → 절전 타이머 리셋
tasksEverySecond(); // 초단위: 온도 요청, 부저, 차임 등
tasksEveryMinute(); // 분단위: 디스플레이 업데이트, 패리티 LED 리셋
tasksEveryHour(); // 시단위: 에러 카운터 리셋, 차임 울림
}
디스플레이 구성 (MAX7219 7세그먼트 × 7개)
| 디바이스 # |
표시 내용 |
밝기 |
| 0 |
내부 LED 링 (수신 중인 비트) |
1 |
| 1 |
외부 LED 링 (최종 디코딩된 비트) |
1 |
| 2 |
버퍼 비트/에러 카운터 |
15 |
| 3 |
펄스 폭/주기 (L/R 분할 표시) |
2 |
| 4 |
온도/주번호 |
15 |
| 5 |
날짜 (DD.MM) |
7 |
| 6 |
시각 (HH:MM:SS) |
1 |
절전 모드 (파워 세이빙)
- 야간 자동 소등:
POWERSAVINGONTIME (기본 22시) ~ POWERSAVINGOFFTIME (기본 9시)
- PIR 모드:
POWERSAVE_BY_PIR=1 시, PIR_DELAY_TIME분(기본 30분) 무동작 시 디스플레이 소등
- 절전 중에도 시계/RTC/수신 로직은 정상 동작
- 절전 대상 디스플레이 선택 가능 (함수
turnDisplaysOff() 수정)
온도 측정 (DS18B20)
- 1-Wire 버스, 분해능 12비트 (0.0625°C) 설정 가능
- 30초 마크마다 변환 요청, 1분마다 표시 갱신
- 최고/최저 온도 기록, 자정 또는 버튼으로 리셋
차임(정시 알림) 기능
- Adafruit 사운드 보드 FX 연동 (A5 핀 LOW 펄스로 트리거)
- 주간(절전 시간 외)에만 동작
- 볼륨은 부팅 시 A6 핀 펄스로 단계적 감소 설정
프론트 패널 제작 노하우
- Inkscape로 벡터 디자인 (1:1 스케일 필수)
- 온라인 포토 서비스(Dibond 패널 인쇄) 이용 시 반드시 1:1 출력 확인 후 주문
- 레이저 커팅 아크릴 코팅 방식은 공차 문제로 비추천
- 드릴링/라우팅으로 LED/스위치 홀 가공 후 패널 부착
교육/연구 활용 가치
- 장파 수신 및 신호 처리 실습 (노이즈 필터링, 패리티 검사, 클락 복원)
- 임베디드 실시간 시스템 설계 (인터럽트, 상태 머신, 태스크 스케줄링)
- 하드웨어/소프트웨어 협업 디자인 (슈퍼필터 별도 보드 분리)
- 오픈 소스 하드웨어 문서화 사례 (회로도, PCB 거버, 3D 케이스, 펌웨어 모두 공개)
참고 자료