산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

DCF77 분석기/시계 v2.0

구성품 및 소모품

Arduino Mega 2560
× 1
Arduino UNO
× 1

이 프로젝트 정보

Arduino 플랫폼을 발견한 후 나는 놀랐고 언젠가는 내 자신의 전자 제품을 개발하고 싶다는 꿈이 이루어졌습니다.

누구나 그렇듯이 저는 기본 스케치부터 시작했지만 곧 유용한 것을 만들고 싶었습니다. 라디오 시계(내 경우에는 독일의 DCF77 신호와 동기화)를 항상 좋아했기 때문에 시간뿐만 아니라 현재 상황을 알려주는 시계를 만들기로 결정했습니다.

수백 시간 동안 만지작거리고 셀 수 없는 실수를 저지른 끝에 마침내 내 고유의 코드와 인쇄 회로 기판 디자인으로 작동하는 시계를 갖게 되었습니다.

DCF77 Analyzer/Clock v1.0의 사진 및 동영상:

하지만 나중에 Udo Klein의 DCF77 슈퍼필터를 발견했는데 무선 신호가 좋지 않을 때 깨끗한 신호를 제공합니다.

이것은 DCF77 안테나와 내 스케치를 실행하는 Arduino Mega 사이에 연결된 Superfilter 소프트웨어(독립형 '블랙 박스'로 볼 수 있으며 신호를 필터링함)가 있는 별도의 Arduino Uno 보드입니다.

그래서 첫 번째 시계의 2.0 버전을 만들었습니다.

<울>
  • 완전히 재작성된 코드
  • 모든 사람이 상황을 이해할 수 있도록 광범위하게 댓글을 달았습니다.
  • 전력 소모를 줄이기 위해 PIR 움직임 센서 추가
  • DCF77 슈퍼필터 추가
  • 온도 또는 기타 용도를 위한 추가 디스플레이(예:일출/일몰 시간)
  • 새로운 DCF77 Analyzer/Clock v2.0의 사진 및 비디오:

    데모

    동영상을 보려면 여기를 클릭하세요.

    '할아버지 시계'에서 빌드

    동영상을 보려면 여기를 클릭하세요.

    디자인

    전면 패널 및 케이스:

    전면 패널의 디자인은 Inkscape라는 프리웨어 프로그램에서 만들었습니다(이 페이지 시작 부분의 다운로드 URL 참조).

    실제로 전면 패널을 제작하는 것이 가장 어려운 부분으로 판명되었습니다. 나는 레이저 커터와 알루미늄과 같은 코팅이 된 특별한 종류의 아크릴을 사용하여 지역 FabLab에서 그것을 만들기 위해 많은 돈을 썼습니다. 아이디어는 레이저로 구멍을 자르고 아래의 검은 아크릴을 노출시키는 매우 얇은 코팅을 태워 텍스트와 선을 새기는 것이었습니다. 그러나 레이저 커터가 많은 사용자의 '남용'과 과도하게 사용되어 내가 원하는 허용 오차 내에서 생산할 수 없었기 때문에 이것은 악몽이었습니다.

    그러던 중 온라인 사진 서비스를 알게 되었습니다. 그들은 모든 종류의 재료에 인쇄하며 그 중 하나가 DiBond 패널이었습니다. 가격은 매우 좋았고 우송료를 포함하여 28유로였습니다. 그러나 결과물은 내 디자인을 1:1로 인쇄하지 않고 약간 확대했기 때문에 처음에는 실망스러웠습니다. 따라서 이 방법을 사용하기로 결정했다면 주의하십시오. 먼저 전화를 걸어 1:1 인쇄가 가능한지 물어보세요.

    전화 통화 후 그들은 나에게 올바른 치수의 다른 패널을 보냈습니다. 기대 이상으로 훌륭했습니다!

    그런 다음 많은 드릴링과 라우팅이 필요했습니다.

    <섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

    코드

    <울>
  • DCF 분석기 / 클록 v2.1
  • 수퍼필터 스케치
  • DCF 분석기 / 클록 v2.1Arduino
    2020-01-18 버그 릴리스:절전 스위치 수정<사전>/* ===================================================================================DCF77 분석기 / 시계 버전 2 =================================================================================이 스케치는 무료 소프트웨어입니다. 자유 소프트웨어 재단(Free Software Foundation)에서 발행한 GNU 약소 일반 공중 라이선스(GNU Lesser General Public License) 조건에 따라 이를 재배포 및/또는 수정할 수 있습니다. 라이선스 버전 2.1 또는 (귀하의 선택에 따라) 이후 버전. 이 스케치는 유용할 것이라는 희망으로 배포되지만 어떠한 보증도 하지 않습니다. 상품성 또는 특정 목적에의 적합성에 대한 묵시적 보증도 없이. 자세한 내용은 GNU 약소 일반 공중 사용 허가서를 참조하십시오. 이 라이브러리와 함께 GNU Lesser General Public License 사본을 받았어야 합니다. 그렇지 않은 경우 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ==============================================================================================================이 C++ 코드는 나 자신이 Arduino와 C++ 초보자이기 때문에 최적화된 것과는 거리가 멀다. 하지만 지금은 조금 더 배운 후에도 코드를 단순하고 읽기 쉽게 유지하고 싶습니다. 이것이 무슨 일이 일어나고 있는지 이해하는 데 도움이 되도록 코드를 지나치게 문서화한 이유입니다. Erik de Ruiter 2014-2020년 5월 2014년 5월 첫 번째 버전 2016년 3월 - 대대적인 점검... 2016년 7월 - 2.0 시계 구축 및 스케치 적용으로 시작 버전 2.1 날짜 2020-01-18 - Powersafe 기능이 수정되었습니다. 버전 2.0 - 이 스케치는 DCF/Analyzer Clock의 2.0 버전에 맞게 조정되었습니다. 기본적으로 Arduino MEGA와 DCF Superfilter를 사용했으며 많은 별도의 LED를 구동하기 위해 이제 Maxim 7219 칩 대신 Arduino Mega의 포트를 사용합니다. 이는 다양한 전압/전류 사양으로 LED를 구동하는 것이 Maxim 칩에서 문제가 되기 때문입니다. 예를 들어 추가 LED를 켜면 이미 켜져 있는 LED에 영향을 줍니다(어두움). 저는 전자 엔지니어가 아니기 때문에 유일한 해결책은 Arduino Mega의 추가 포트를 사용하는 것이었습니다. 물론 트랜지스터나 추가 칩을 사용하여 LED를 구동할 수 있지만 저에게는 이것이 명백한 솔루션이었습니다. - 모든 Maxim Common Anode 디스플레이 코드 버전 1.72 제거 - 옵션:활동이 감지되지 않을 때 선택 가능한 디스플레이를 차단하려면 저렴한 Ebay PIR 감지기를 사용하십시오. 스위치 끄기 지연은 사람이 움직이지 않지만 디스플레이는 켜져 있어야 하는 경우 디스플레이가 꺼지는 것을 방지하기 위해 사용자가 설정할 수 있습니다. - 이제 'POWERSAVINGOFFTIME' 및 ​​'POWERSAVINGONTIME' 값을 모두 0으로 설정하여 야간 종료 표시를 비활성화할 수 있습니다. - 절전 모드에서 온도 표시가 꺼지지 않는 문제를 수정했습니다. - errorCounter 디스플레이가 매시간 재설정되지 않음 - 수정된 버전 1.71 - 자정에 온도 최소/최대 메모리 재설정을 위한 사용자 옵션 버전 1.7:- 온도 디스플레이의 해상도가 개선됨:섭씨 0.5도에서 0.1도 DS18B20 센서 시간 때문에 온도를 변환하고 코드를 깨끗하게 유지하기 위해 온도 디스플레이는 분당 한 번 업데이트됩니다. - 패리티 검사 루틴이 최적화되었습니다. - 잘못된 DCF 데이터를 보다 안정적으로 검사하여 잘못된 데이터로 RTC 업데이트를 방지합니다. - EoB 오류는 이제 내부 LED 링을 원래대로 지웁니다. - 이제 DCF OK LED가 DCF 신호의 상태를 보다 안정적으로 표시합니다. 오류가 발생하면 즉시 꺼지고 3개의 패리티 비트가 모두 정상일 때만 켜집니다. 버전 1.6:- 온도 기능이 분당 한 번만 계산되도록 변경되었습니다. 100ms의 지연을 사용하여 DS18B20 센서에 온도를 계산할 시간을 주기 때문에 변경 전에 이상한 오류가 발생했습니다. 그러나 지연 기능은 대부분의 C++ 코드에서 매우 나쁜 생각이므로 마침내 제거했습니다. 버전 1.5:- scanSignal 기능과 나머지 코드의 전체 점검! 첫 번째 시도는 효과가 있었지만 개선될 수 있었습니다... - rPW 및 rPT LED가 의도한 대로 작동하지 않아 지금 수정되었습니다. - 버퍼 끝 오류 검사 루틴이 이제 정상적으로 작동합니다. - 들어오는 DCF 신호의 패리티 검사를 통합했습니다. 신호에서 3개의 패리티 비트가 전송되므로 이제 이 비트가 확인되고 3개가 모두 정상인 경우에만 수신된 시간 정보가 승인되고 디스플레이가 업데이트되고 RTC가 동기화됩니다. 원하는 경우 3개의 추가 이중 색상 LED(공통 음극)를 부착하여 3개의 패리티 비트 각각이 정상인지 또는 실패인지 확인할 수 있습니다. - 모든 PIN 구성을 읽기 쉬운 테이블에 넣어 배선(또는 배선 변경)을 훨씬 쉽게 만들었습니다. - 1 DS18B20 temp를 사용하는 한. 센서, I2C 장치의 주소를 더 이상 알아낼 필요가 없도록 코드를 편집했습니다. - 코드의 큰 정리... - 디스플레이를 끄면 절전(시계는 정상적으로 작동함)은 이제 POWERSAVINGONTIME 및 POWERSAVINGOFFTIME 두 변수를 편집하여 좀 더 쉽게 구성할 수 있습니다. - 일부 변수 이름 변경:- Maxim 인스턴스 'lc' 및 'lc1'이 이제 MaximCC 및 MaximCA임 - 디스플레이 설명 MaximDcfTime이 이제 DisplayTempWeek임 - DCF77SOUNDPIN이 이제 BUZZERSWITCHPIN임 - 전원 공급 후 LED/디스플레이 테스트가 이제 내장됨 간단한 설명:전원 켜기:전원을 켜면 먼저 LED 테스트가 수행됩니다. LED와 디스플레이는 전력 소비를 낮게 유지하기 위해 순차적으로 켜집니다. 그런 다음 시계는 DCF 펄스를 수신하기 시작하고 분 표시(2초 간격)가 감지되면 분 표시 LED가 켜지고 버퍼 카운터가 재설정됩니다. 내부 LED 링은 이제 버퍼에도 저장되어 있는 들어오는 DCF 펄스를 표시합니다. 데이터 수신 중 3분에 패리티 DCF 비트를 검사하여 데이터가 유효한지 확인합니다. 유효한 데이터 수신:분 끝에 Minute Mark가 감지된 후(BF(Buffer Full) LED 켜짐), 3개의 패리티 비트 모두 OK('DCF OK' LED 켜짐), 버퍼 정보는 다음과 같습니다. 시간 및 날짜 정보를 추출하는 데 사용됩니다. 그런 다음 RTC 시계가 업데이트되고('RTC 동기화됨' LED가 켜짐) 내부 LED 링 정보가 외부 LED 링으로 복사됩니다. 시간, 날짜 및 주 표시, 요일 LED, 여름/겨울 및 윤년 LED 정보가 새로운 시간 정보로 업데이트됩니다. 유효한 데이터 없음:잡음이 있는 신호로 인해 하나 이상의 패리티 비트가 정상이 아닌 경우 DCF 정보 수신은 계속되지만 RTC, 디스플레이 및 LED를 업데이트하는 데 사용되지 않습니다. 외부 LED 링, 'RTC synced' 및 'DCF OK' LED가 재설정됩니다. 시간, 날짜, 주, 요일 LED, 여름/겨울 LED 및 윤년 LED는 영향을 받지 않으며 마지막으로 수신된 유효한 값을 계속 표시합니다. 'Period Time' 및/또는 'Period With' 오류 LED가 오류를 나타내고 오류 카운터 디스플레이가 업데이트됩니다. 매시간 오류 표시가 0으로 설정됩니다. EoB, End of Buffer LED는 노이즈 신호로 인해 Minute Mark가 감지되기 ​​전에 더 많은 DCF 펄스가 수신되면 켜집니다. (분 표시가 감지되면 58비트/펄스 이하이어야 합니다.) 분 표시가 감지되면 새 주기가 시작됩니다. 온도:30초 표시에서 온도 디스플레이는 마지막 재설정 후 과거 기간의 높음 및 낮음 값을 표시합니다. 차임:차임 스위치가 ON/HIGH이면 매 시간이 시작될 때 차임(연결된 경우)이 울릴 것입니다. 야간에는 사용자가 코드 자체에서 설정한 시간인 차임이 비활성화됩니다. 절전 - 디스플레이 꺼짐 절전 스위치가 HIGH인 경우에만 작동합니다. 1. NIGHT SHUT OFF 사용자가 설정한 시간에 디스플레이가 밤에 꺼지고 아침에 켜집니다. POWERSAVINGOFFTIME 및 POWERSAVINGONTIME 변수를 살펴보십시오. 기능을 확인하여 야간에 끄고 싶은 디스플레이를 선택하십시오. 2. PIR SENSOR PIR 센서를 연결하고 PIR 옵션 POWERSAVE_BY_PIR과 PIR_DELAY_TIME의 지연을 활성화합니다. PIR 감지기가 움직임을 감지할 때마다 분 카운터가 재설정되지만 PIR_DELAY_TIME보다 오랫동안 움직임이 감지되지 않으면 디스플레이가 꺼집니다. 움직임이 발생하면 디스플레이가 즉시 켜집니다. 참고:앞에서 말했듯이 시계는 디스플레이가 꺼져 있는 동안 정상적으로 작동합니다. DCF 신호음:BUZZERSWITCHPIN 핀에 연결된 스위치를 사용하면 수신된 DCF 비트가 들어오는 것을 들을 수 있습니다. 톤 지속 시간은 DCF 비트의 펄스 폭과 동일하므로 100ms 또는 200ms입니다. 기타:RTC 배터리가 비어 있거나 연결 오류가 감지되면 RTC 오류 LED가 켜집니다. 크레딧:저는 자체 DCF77 디코더를 만든 Matthias Dalheimer와 Thijs Elenbaas의 작업에서 많은 것을 배웠습니다. 그들의 작업이 없었다면 어디서부터 시작해야 할지 몰랐을 것입니다. 나는 무슨 일이 일어나고 있는지 이해할 수 있도록 내 자신의 코드를 작성하게 되었습니다. 흥미로운 웹사이트:- Brett Oliver:http://home.btconnect.com/brettoliver1/ - Joop Tap:http://www.jooptap.nl - Thijs Ellenbaas:http://thijs.elenbaas.net/2012/04/ arduino-dcf77-radio-clock-receiver-hardware-2/ - 마티아스 달하이머 :https://github.com/roddi/DCF77-Arduino/blob/master/DCF77Servoclock/DCF77.h - DCF77 위키피디아 :https://en .wikipedia.org/wiki/DCF77 - 더 많은 DCF77 정보:http://www.picbasic.nl/indexes_uk.htm - 내 Flickr 웹사이트:https://www.flickr.com/photos/edr1924/albums - 내 Github 홈페이지 :https://github.com/deruiter *///------------------------------------------------ -------------------------------------------------- ----------------------// 라이브러리//------------------------ -------------------------------------------------- --------------------------------// 아두이노(신규) 시간 라이브러리 ........... ........................... http://www.pjrc.com/teensy/td_libs_Time.html#include <시간.h>// Arduino Uno, Mega 등을 사용하는 경우 이 라인을 활성화합니다.#include // 기본 DS1307 라이브러리 시간을 time_t로 반환하는 y ........... http://www.pjrc.com/teensy/td_libs_DS1307RTC.html#include // Maxim 7219 디스플레이 라이브러리 ..... ........................... http://playground.arduino.cc/Main/LEDMatrix// !!! 참고:일반 양극 지원을 받으려면 Ledcontrol.h 라이브러리의 특수 버전을 사용해야 합니다. // Maxim 칩은 일반적으로 일반 음극 디스플레이에만 적합하기 때문입니다!#include //SPI 인터페이스 라이브러리 .... ........................................... http://arduino.cc/en/Reference/ SPI#include // OneWire를 사용하면 DS18S20, DS18B20, DS1822와 같은// Maxim/Dallas에서 만든 1선 장치에 액세스할 수 있습니다............. .............. http://www.pjrc.com/teensy/td_libs_OneWire.html// DallasTemperature 라이브러리는 이 모든 작업을 수행할 수 있습니다! ... http://milesburton.com/Dallas_Temperature_Control_Library#include //----------------------------- -------------------------------------------------- ---------------------------// 읽기 쉬운 테이블의 Arduino UNO 핀 연결//// 입력 - Rx - 프로그래밍에 사용 /PC와의 통신// 출력 - Tx - 프로그래밍/PC와의 통신에 사용#define DCF77PIN 2 // 입력 - 안테나 PCB의 DCF 신호. 핀은 인터럽트 입력이어야 합니다!#define PIRDETECTORPIN 3 // 입력 - PIR 감지기:디스플레이를 활성화하기 위해 방에서 활동 확인#define BUZZERSWITCHPIN 4 // 입력 - SWITCH - DCF77 '삐' 피에조 부저 켜기/끄기 / ON =HIGH , OFF =LOW#define CHIMESWITCHPIN 5 // 입력 - SWITCH - 시간별 차임 소리 켜기/끄기 / ON =HIGH, OFF =LOW#define POWERSAVESWITCHPIN 6 // 입력 - SWITCH - 절전 기능 켜기/끄기 표시하므로 is always on / ON =HIGH, OFF =LOW#define TEMPSENSORPIN 8 // 입력 - Dallas One Wire DS18B20 온도 센서#define TEMPRESETPIN 9 // 입력 - PUSH BUTTON - 온도 재설정 최소/최대 메모리 / HIGH =reset#define MAXIMCCLD 10 // 출력 - CS/LOAD - Maxim 7219 칩에 의사 SPI 연결 - 7 세그먼트 디스플레이#define MAXIMCCCLK 11 // 출력 - CLOCK - Maxim 7219 칩에 의사 SPI 연결 - 7 세그먼트 디스플레이#define MAXIMCCDATA 12 // 출력 - DATA - Maxim 7219 칩에 대한 유사 SPI 연결 - 7 세그먼트 디스플레이// !! 핀 22~53은 LED의#define LED_SUNDAY 22 // 출력 - LED - Sunday#define LED_MONDAY 23 // 출력 - LED - Monday#define LED_TUESDAY 24 // 출력 - LED - 화요일#define LED_WEDNESDAY 25 // 출력 - LED - 수요일#define LED_THURSDAY 26 // 출력 - LED - 목요일#define LED_FRIDAY 27 // 출력 - LED - Friday#define LED_SATURDAY 28 // 출력 - LED - Saturday#define LED_CEST 29 // 출력 - LED - Summertime CEST #define LED_CET 30 // 출력 - LED - Wintertime CET#define LED_LEAPYEAR 31 // 출력 - LED - 윤년#define LED_RTCERROR 32 // 출력 - LED - RTC 데이터 읽기 문제(빈 배터리/연결)#define LED_RTCSYNC 33 // 출력 - LED - RTC가 DCF 시간과 성공적으로 동기화되면 켜짐#define LED_TEMP 34 // 출력 - LED - 온도 표시#define LED_OPTION1 35 // 출력 - LED - 선택적 1 데이터 표시#define LED_OPTION2 36 // 출력 - LED - 선택적 2 데이터 표시#define LED_ERRORPT 37 // 출력 - LED - DCF 주기 시간 오류#define LED_ ERRORPW 38 // 출력 - LED - DCF 기간 폭 error#define LED_BUFFERFULL 39 // 출력 - LED - 버퍼 가득 참 표시자, 다음 데이터가 분석됨#define LED_MINUTEMARKER 40 // 출력 - LED - 버퍼 전에 감지된 DCF 데이터 스트림의 끝 가 채워지면 데이터가 손상됨#define LED_BUFFEROVERFLOW 41 // 출력 - LED - 잘못된 신호로 인해 예상보다 많은 데이터가 1분 동안 수신됨#define LED_DCFSTATUS 42 // 출력 - LED - DCF 데이터가 양호하면 켜짐#define LED_POWERSAVE 43 / / 출력 - LED - 절전 모드 활성화, 일부 디스플레이 꺼짐#define LED_PARITY1PASS 44 // 출력 - LED - 패리티 1비트 정상#define LED_PARITY1FAIL 45 // 출력 - LED - 패리티 1비트 FAILED#define LED_PARITY2PASS 46 // output - LED - Parity 2 bit is OK#define LED_PARITY2FAIL 47 // output - LED - Parity 2 bit FAILED#define LED_PARITY3PASS 48 // output - LED - Parity 3 bit is OK#define LED_PARITY3FAIL 49 // output - LED - Parity 3 bit FAILED#define LED_PIRMOTION 50 // 출력 - LED - PIR이 움직임을 감지할 때 켜짐/ / 아날로그 핀#define BUZZER A7 // 출력 - DCF77용 피에조 부저 '삐'(부저의 '+'로)#define SPEAKERVOLPIN A6 // 출력 - 사운드 보드 볼륨 - LOW =볼륨 한 단계 낮음. SPEAKERVOLUME은 전원을 켠 후 이 출력이 활성화되는 횟수를 결정합니다.#define CHIMEPIN A5 // 출력 - 차임 활성화 - OUTPUT LOW =Adafruit Soundboard FX// DS1307용으로 사용됨 RTC // I2C DATA - 실시간 클록 pcb/에 연결에서 차임 활성화 / DS1307 RTC에 사용 // I2C CLOCK - 실시간 클럭 pcb에 연결//-------------------------------- -------------------------------------------------- ------------------------// DS18B20 초기화//-------------------- -------------------------------------------------- ------------------------------------OneWire ds(TEMPSENSORPIN); // Onewire 인스턴스 정의 DS//------------------------------------------ -------------------------------------------------- --------------// Maxim 7219 매트릭스 디스플레이 초기화//----------------------------------------- -------------------------------------------------- -----------------------------/* clearDisplay(int addr) ........... ........................... 선택된 디스플레이 지우기 MaximCC.shutdown(int addr, boolean) ....... ........................... MAX72XX를 절전 모드에서 깨우다(true =sleep, false =awake) MaximCC.setIntensity(int addr , 값) .............. Led의 중간 밝기 설정(0=최소 - 15=최대) MaximCC .setLed(int addr, int row, int col, boolean state) ........... 행, 열의 led를 켭니다. 인덱스가 0에서 시작한다는 것을 기억하십시오! MaximCC.setRow(int addr, int row, byte value) ........... 이 함수는 3개의 인수를 취합니다. 예:MaximCC.setRow(0,2,B10110000); MaximCC.setColumn(int addr, int col, byte value) .... 이 함수는 3개의 인자를 받습니다. 예:MaximCC.setColumn(0,5,B00001111); MaximCC.setDigit(int addr, int digit, byte value, boolean dp) ...... 이 함수는 byte 유형의 인수를 취하고 지정된 열에 해당 숫자를 인쇄합니다. 유효한 값의 범위는 0..15부터입니다. 0..9 사이의 모든 값은 숫자로 인쇄되고 10..15 사이의 값은 16진수로 인쇄됩니다. MaximCC.setChar(int addr, int digit, char value, boolean dp) ....... 표시:0 1 2 3 4 5 6 7 8 9 ABCDEFHLP; - . , _ (공백 또는 공백 문자) POWERSAVESWITCHPIN ***** 가지고 있는 장치의 수를 설정하십시오. ***** 그러나 최대 기본값인 8 MAX72XX도 작동합니다. LedConrol(DATAIN, CLOCK, CS/LOAD, NUMBER OF MAXIM CHIPS) */// lc는 Maxim 디스플레이용입니다.LedControl MaximCC =LedControl(MAXIMCCDATA, MAXIMCCCLK, MAXIMCCLD, 7, false); // Maxim 72xx에 대한 핀과 우리가 사용하는 72xx의 수를 정의합니다//-------------------------------------------------- -------------------------------------------------- ----------------------// 사용자 설정, 변수 및 배열 정의//------------------ -------------------------------------------------- --------------------------------------// 아래 값은 PIN 번호가 아니라 사운드 보드의 '볼륨 낮추기' 입력이 활성화되는 횟수를 설정하는 값 // 원하는 경우 전원을 켠 후 사운드 보드의 볼륨을 낮출 수 있도록 합니다.#define SPEAKERVOLUME 12// 원하는 경우 선택 시작 후 모든 LED 및 디스플레이 테스트// '1' =예, '0' =아니요#define PERFORM_LED_TEST 1// ms의 각 7 세그먼트 디스플레이 간의 지연#define LEDTEST_DELAY_DISPLAYS 600// LED 링의 각 LED 간 지연 ms#define LEDTEST_DELAY_LED_RING 20// DS18B20 온도 센서를 최고 분해능으로 한 번 구성하려는 경우 선택합니다.// 이것은 전나무용 센서를 사용한 후에 필요합니다. 성 시간. 소프트웨어를 실행한 후// 이 설정을 ON으로 한 후 종료 밤 시간. 이것은 절전 디스플레이 ON 및 OFF 시간에 사용됩니다.// 차임벨이 활성화되는지 여부를 결정합니다(낮 동안).//// 절전 시간에만 디스플레이가 꺼지고 시계는 완전히 활성 상태로 유지됩니다./ / 언제든지 디스플레이 전원 끄기를 비활성화하려면 절전 스위치를 OFF로 설정하기만 하면 됩니다.//// 절전 스위치 ON:설정된 야간 시간에 디스플레이가 꺼집니다. // 그리고 POWERSAVE_BY_PIR 기능이 활성화되고 거기에 있으면 is no // 설정된 PIR_DELAY_TIME에 대한 이동입니다.// 절전 스위치 OFF:항상 켜져 있고 낮에만 차임벨이 표시됩니다.//// 값은 '시' 형식이므로 8PM은 20:00이 아닌 '20'이 됩니다. or 8PM...#define POWERSAVINGOFFTIME 9 // 디스플레이가 활성화됨#define POWERSAVINGONTIME 22 // 디스플레이가 꺼짐// 사용자 옵션:방에 활동이 있을 때만 디스플레이 활성화// '1' =ON, '0 ' =OFF#define POWERSAVE_BY_PIR 1// 감지되지 않은 후 디스플레이를 끄기 전에 대기하는 MINUTES의 지연#define PIR_DELAY_TIME 30// 최소 온도 재설정을 위한 사용자 옵션 /자정에 최대 메모리// '1' =자정에 재설정, '0' =수동 재설정만 가능#define TEMPRESET_MIDNIGHT 1//---------------------- -------------------------------------------------- -------// 기타 매개변수 정의#define DS1307_I2C_ADDRESS 0x68 // RTC I2C 주소 정의#define DCF_INTERRUPT 0 // 핀과 관련된 인터럽트 번호// Maxim 7219 디스플레이 번호 배선 시퀀스의 정의// 첫 번째 Maxim 7219 in 배선 'daisychain'은 '0', 다음 '1' 등이어야 합니다.// COMMON CATHODE DISPLAYS#define LedRingInner 0#define LedRingOuter 1#define DisplayBufferBitError 2#define DisplayPeriodPulse 3#define DisplayTempWeek 4#define DisplayDate 5#define Display / 디스플레이 밝기 레벨의 정의#define BrightnessLedRingOuter 1#define BrightnessLedRingInner 1#define BrightnessDisplayTime 1#define BrightnessDisplayDate 7#define BrightnessDisplayTempWeek 15#define BrightnessDisplayPeriodPulse 2#define BrightnessDisplayBufferBitError 15//Edge long tatic unsigned long trailingEdge =0; unsigned long previousLeadingEdge =0; // 에 사용됨 휘발성 unsigned int DCFSignalState =0; // 인터럽트 변수에는 항상 휘발성 한정자가 필요합니다!!// 에서 사용됨 previousSecond =0;unsigned int previousSignalState =0;// DCF 버퍼 및 표시기static int DCFbitBuffer[59]; // 여기서 수신된 DCF비트는 저장됩니다.const int bitValue[] ={1, 2, 4, 8, 10, 20, 40, 80}; // 이들은 수신된 DCFbits의 10진수 값입니다. // 새로운 분에 시작된 후에만 수신된 비트를 내부 LED에 표시 ringboolean MinuteMarkerFlag =false;int bufferPosition =0;int previousMinute =0;int previousHour =0;// 변수 DCF 비트가 valdbool인지 확인하기 위해 dcfValidSignal =false;int dcfP1counter =0;int dcfP2counter =0;int dcfP3counter =0;int dcfParityCheckP1 =0;int dcfParityCheckP2 =0;int dcfParityCheckP2 =0을 저장할 DCF time/dcfParityCheckP3 =디코딩 inint dcfMinute =0;int dcfHour =0;int dcfDay =0;int dcfWeekDay =0;int dcfMonth =0;int dcfYear =0;int dcfDST =0;int jumpYear =0;//주 및 일수 값을 저장하는 데 사용되는 변수int dayNumber;int weekNumber;// 오류 카운터 변수 int errorCounter =0; 부울 errorCondition =false;// 기타 변수 부울 daytimeChange =true; 부울 dayTime =false;int dcf77SoundSwitch =0;// 온도 변수 바이트 존재 =0 바이트 DS18B20Data[12];int maxTemp =0;int minTemp =0;int lowByte =0;int hi ghByte =0;float tempReading =0;int tempCelsius =0;boolean tempResetButton =false;// PIR 감지기 변수int pirActivity =0;int pirDisplaysState =1;unsigned int pirTimer =0;unsigned long previousTimePIR =0;//==================================================================================/ 설정//=================================================================================void setup(){ // 시리얼 통신 초기화 Serial.begin(9600); // PIN 연결 초기화 pinMode(DCF77PIN, INPUT); 핀모드(TEMPRESETPIN, 입력); 핀모드(BUZZERSWITCHPIN, INPUT); 핀모드(CHIMESWITCHPIN, INPUT); 핀모드(POWERSAVESWITCHPIN, 입력); 핀모드(PIRDETECTORPIN, 입력); 핀모드(CHIMEPIN, 출력); 핀모드(스피커볼핀, 출력); // LED 핀 22 - 50 초기화 for (int i1 =22; i1 <=50; i1++) { pinMode(i1, OUTPUT); } // 변수, LED 디스플레이 및 LED의 initialize() 초기화; // 신호의 변화를 찾아 핀 DCF_INTERRUPT에서 DCF77 펄스 인터럽트를 초기화하여 // 상승 또는 하강 에지 펄스가 인터럽트 핸들러를 트리거하고 // int0handler 기능을 실행합니다. attachInterrupt(DCF_INTERRUPT, int0handler, CHANGE); // RTC를 초기화하고 SyncProvider로 설정합니다. // 나중에 RTC는 DCF 시간과 동기화됩니다. setSyncProvider(RTC.get); // RTC에서 시간을 가져오는 함수 // RTC가 시스템 시간을 설정했는지 확인 if (timeStatus() !=timeSet) { // RTC와 동기화할 수 없음 - RTCError 활성화 LED digitalWrite(LED_RTCERROR, HIGH); } else { // RTC가 시스템 시간을 설정했습니다. - dim RTCError LED digitalWrite(LED_RTCERROR, LOW); } // 전원을 켠 후 Adafruit 오디오 보드의 스피커 볼륨을 설정합니다. // 두 핀을 기본 출력 상태인 LOW로 초기화합니다. digitalWrite(SPEAKERVOLPIN, LOW); digitalWrite(CHIMPIN, LOW); // 'SPEAKERVOLUME' 단계로 사운드보드 기본 볼륨 낮추기 for (int i =0; i <=SPEAKERVOLUME; i++) { digitalWrite(SPEAKERVOLPIN, HIGH); 지연(100); digitalWrite(스피커볼핀, LOW); 지연(100); } // 다음 함수는 한 번만 실행되어야 합니다. // DS18B20 센서의 온도 분해능을 구성하는 데 사용됩니다. if (CONFIGURE_DS18B20 ==1) { configureDS18B20(); } // 테스트 목적으로 사용하거나 RTC 시간을 수동으로 설정합니다. // setTime(23, 59, 40, 31, 12, 13); // RTC.set(now()); // 온도 변환 요청 computeTemp(); // LED 테스트가 필요한지 확인 if (PERFORM_LED_TEST ==1) { // LED 테스트 수행 ledTest(); } else { // LED 테스트를 수행하지 않는 경우 DS18B20 센서가 준비될 때까지 약간 기다려야 합니다. delay(750); } // 이제 센서에서 온도를 가져와서 표시합니다. displayTemp(); // LED 테스트 후 errorCounter 디스플레이 활성화 ledDisplay(DisplayBufferBitError, "R", 0);}//===============================================================================// 루프//================================================================================void loop(){ // 펄스 방향이 변경되었는지 먼저 확인(상승 또는 Falling) // 그렇지 않으면 동일한 펄스를 계속 평가할 것입니다. if (DCFSignalState !=previousSignalState) { // 변수의 '재설정' 상태 previousSignalState =DCFSignalState; // 들어오는 펄스를 평가합니다. scanSignal(); } // 스위치가 변경되었는지 확인하고 그에 따라 작동합니다. checkSwitches(); // PIR 이동 확인 checkPIR(); // 1초, 1분 또는 1시간에 한 번만 발생해야 하는 작업을 실행 //---------------------------------- ------------------------------------------- taskEverySecond(); taskEveryMinute(); taskEveryHour();}//===================================================================================================================//// 함수명 :processDcfBit// 에서 호출됨 ://// 목적 :신호가 수신되는 대로 평가합니다. "1" 또는 "0"을 수신했는지 여부를 결정하고// 펄스 타이밍이 제한 내에 있는지 확인하기 위해 검사를 수행합니다.// 매개변수:없음// 반환 값:없음////====================================================================================================================/* 펄스 펄스 폭 폭 |- -| |-- --| |----- END OF MINUTE 마커:2000ms -----| ___ ___ ___ ___ ___ | 0 | | 1 | | 0 | | 0 | | 1 | | | | | | | | | | | | | | | | | | | | | ______| |_______________| |___________| |___________________________________| |_______________| |__ _ _ _ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 1000 2100 2000 2200 3000 3100 NO PULSE 5000 5100 6000 6200 < REJECTED error(LED_ERRORPW); errorCondition =true; } //-------------------------------------------------------------------------------- // CHECK PULSE TIME //-------------------------------------------------------------------------------- // If the detected pulse is too short it will be an incorrect pulse that we shall reject // should be 100 and 200 ms ideally if (((trailingEdge - leadingEdge) <70) || ((trailingEdge - leadingEdge)> 230)) { //rPT - ERROR:Pulse Width too short or too long -> REJECTED error(LED_ERRORPT); errorCondition =true; } // if we had an error return and start over if (errorCondition ==true) { errorCondition =false; // although we have an error, store current rising edge time to compare at the next Rising-Edge. previousLeadingEdge =leadingEdge; 반품; } //-------------------------------------------------------------------- // no errors found so now we can continue //-------------------------------------------------------------------- // first we turn any error Led's OFF digitalWrite(LED_ERRORPW, LOW); digitalWrite(LED_ERRORPT, LOW); digitalWrite(LED_BUFFERFULL, LOW); // previous BF digitalWrite(LED_BUFFEROVERFLOW, LOW); // previous EoB digitalWrite(LED_MINUTEMARKER, LOW); // previous EoM // END OF MINUTE check, looking for a gap of approx. 2000ms if (leadingEdge - previousLeadingEdge> 1900 &&leadingEdge - previousLeadingEdge <2100) { // end of minute detected:finalizeBuffer(); } // refresh previousLeadingEdge time with the new leading edge time previousLeadingEdge =leadingEdge; //-------------------------------------------------------------------------------- // process DCF bits //-------------------------------------------------------------------------------- // distinguish between long and short pulses if (trailingEdge - leadingEdge <170) { // call processDcfBit function and sent it the value '0' processDcfBit(0); // if switch is HIGH, the DCF pulses are audible if (dcf77SoundSwitch ==1) buzzer(100); } else { // call processDcfBit function and sent it the value '1' processDcfBit(1); // if switch is HIGH, the DCF pulses are audible if (dcf77SoundSwitch ==1) buzzer(200); } } // if (DCFSignalState ==0)} // void scanSignal();//================================================================================================================//// Function name :processDcfBit// called from ://// Purpose :after reception of one good DCF bit, do some checks and save it in the DCFbitBuffer array// Parameters :none// Return value :none////================================================================================================================void processDcfBit(int dcfBit){ //-------------------------------------------------------------------- // display values on the 7 segment displays //-------------------------------------------------------------------- // display bufferPosition, digits 7,6 MaximCC.setChar(DisplayBufferBitError, 7, bufferPosition / 10, false); MaximCC.setChar(DisplayBufferBitError, 6, bufferPosition % 10, false); // display received DCFbit, digit 4 MaximCC.setChar(DisplayBufferBitError, 4, dcfBit, false); //-------------------------------------------------------------------- // display incoming DCF bits on inner LED ring //-------------------------------------------------------------------- // only if we have valid DCF data or after an Minute Mark (EoM) signal // activate the inner LED ring and diplay incoming data if (dcfValidSignal ==true || MinuteMarkerFlag ==true) { // display received bits on inner LED ring MaximCC.setLed(LedRingInner, bufferPosition / 8, bufferPosition % 8, dcfBit); } //-------------------------------------------------------------------- // // Fill DCFbitBuffer array with DCFbit //-------------------------------------------------------------------- DCFbitBuffer[bufferPosition] =dcfBit; //-------------------------------------------------------------------- // Parity check //-------------------------------------------------------------------- // DURING reception of the DCF bits, calculate and display the results of the DCF parity check. // // There is a Parity bit for the minutes, the hours and for the date. // DCF77 works with EVEN parity, this works as follows:// The hours for example have 6 bits plus a paritybit. The bits with value 1 are add up including the paritybit, // the result must be an even number. If there is a bit wrong received, a 0 is as 1, or a 1 is as 0 received, // then the result is uneven. source:http://www.picbasic.nl/frameload_uk.htm?http://www.picbasic.nl/info_dcf77_uk.htm if (bufferPosition ==0) { // reset the parity LED's digitalWrite(LED_PARITY1PASS, LOW); digitalWrite(LED_PARITY1FAIL, LOW); digitalWrite(LED_PARITY2PASS, LOW); digitalWrite(LED_PARITY2FAIL, LOW); digitalWrite(LED_PARITY3PASS, LOW); digitalWrite(LED_PARITY3FAIL, LOW); // reset variables dcfP1counter =0; dcfP2counter =0; dcfP3counter =0; dcfParityCheckP1 =0; dcfParityCheckP2 =0; dcfParityCheckP3 =0; } // ---------------------------------------- // First parity check:minute bits // ---------------------------------------- if (bufferPosition ==28) { for (int i =21; i <=27; i++) { // count the number of bits with the value '1' dcfP1counter +=DCFbitBuffer[i]; } // perform P1 parity check. Parity is OK if the sum is an EVEN value if ((DCFbitBuffer[28] + dcfP1counter) % 2 ==0) { // Parity1 PASS LED ON digitalWrite(LED_PARITY1PASS, HIGH); // Parity P1 PASS dcfParityCheckP1 =1; } else { // Parity1 FAIL LED ON digitalWrite(LED_PARITY1FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } } // ---------------------------------------- // Second parity check:hour bits // ---------------------------------------- if (bufferPosition ==35) { for (int i =29; i <=34; i++) { dcfP2counter +=DCFbitBuffer[i]; } // perform P2 parity check. Parity is OK if the sum is an EVEN value if ((DCFbitBuffer[35] + dcfP2counter) % 2 ==0) { // Parity2 PASS LED ON digitalWrite(LED_PARITY2PASS, HIGH); // Parity P2 PASS dcfParityCheckP2 =1; } else { // Parity2 FAIL LED ON digitalWrite(LED_PARITY2FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } } // ---------------------------------------- // Third parity check:date bits // ---------------------------------------- if (bufferPosition ==58) { for (int i =36; i <=57; i++) { dcfP3counter +=DCFbitBuffer[i]; } // perform P3 parity check. Parity is OK if the sum is an EVEN value (DCFbitBuffer[58] + dcfP3counter) % 2 ==0 ? dcfParityCheckP3 =1 :dcfParityCheckP3 =0; // Turn Parity2 'PASS' or 'FAIL' LED ON if (dcfParityCheckP3 ==1) { // Parity2 PASS LED ON digitalWrite(LED_PARITY3PASS, HIGH); // Parity P3 PASS dcfParityCheckP3 =1; } else { // Parity2 FAIL LED ON digitalWrite(LED_PARITY3FAIL, HIGH); // we have no valid data! dcfValidSignal =false; // Turn DCF OK LED OFF digitalWrite(LED_DCFSTATUS, LOW); } // ---------------------------------------- // finally, check all Parity bits // ---------------------------------------- dcfParityCheckP1 + dcfParityCheckP2 + dcfParityCheckP3 ==3 ? dcfValidSignal =true :dcfValidSignal =false; } //-------------------------------------------------------------------- // before continuing with the next bit, increment counter //-------------------------------------------------------------------- bufferPosition++; //-------------------------------------------------------------------- // check if we have not received too many pulses? //-------------------------------------------------------------------- if (bufferPosition> 59) { // Buffer Overflow ERROR - we have received more pulses before reaching // the 2 second 'gap' signalling the end of the minute. //This error may be due to a noisy signal giving addition peaks/dcfBits // So clear both DCFbit displays and start again. // Reset buffer counter bufferPosition =0; // clear inner LED ring MaximCC.clearDisplay(LedRingInner); // turn Buffer Overflow Error LED ON error(LED_BUFFEROVERFLOW); // exit return; } //-------------------------------------------------------------------- // everything OK so we wait for next incoming DCFbit //--------------------------------------------------------------------}//================================================================================================================//// Function name :finalizeBuffer// called from ://// Purpose :Process the succesfully received DCF data of one minute// Parameters :none// Return value :none////================================================================================================================void finalizeBuffer(void){ //-------------------------------------------------------------------- // We are here because of the detected 2 second 'gap'. // Now check if it correspondends with the buffer counter // 'bufferPosition' which should be value 59 //-------------------------------------------------------------------- if (bufferPosition ==59 &&dcfValidSignal ==true) { // bufferPosition ==59 so turn Buffer Full LED ON digitalWrite(LED_BUFFERFULL, HIGH); // Turn DCF OK LED ON digitalWrite(LED_DCFSTATUS, HIGH); // Reset inner LED ring (incoming time information) MaximCC.clearDisplay(LedRingInner); // copy 'contents' of inner LED ring to the outer LED ring (current time information) for (int i =0; i <59; i++) { MaximCC.setLed(LedRingOuter, i / 8, i % 8, DCFbitBuffer[i]); } // process buffer and extract data sync the time with the RTC decodeBufferContents(); // set Arduino time and after that set RTC time setTime(dcfHour, dcfMinute, 0, dcfDay, dcfMonth, dcfYear); RTC.set(now()); // activate Synced LED digitalWrite(LED_RTCSYNC, HIGH); // Reset running buffer bufferPosition =0; // Reset DCFbitBuffer array, positions 0-58 (=59 bits) for (int i =0; i <59; i++) { DCFbitBuffer[i] =0; } // reset flag MinuteMarkerFlag =false; } // if (bufferPosition ==59) //-------------------------------------------------------------------- // The buffer is not yet filled although the 2 second 'gap' was detected. // Can be result of a noisy signal, starting in middle of receiving data etc. // Turn 'Minute Mark' LED ON //-------------------------------------------------------------------- else { digitalWrite(LED_MINUTEMARKER, HIGH); // Clear displays MaximCC.clearDisplay(LedRingInner); MaximCC.clearDisplay(LedRingOuter); // Reset running buffer and start afresh. Now we are in sync with the incoming data bufferPosition =0; // Reset DCFbitBuffer array, positions 0-58 (=59 bits) for (int i =0; i <59; i++) { DCFbitBuffer[i] =0; } // set flag so we can display incoming pulsed on the inner LED ring. MinuteMarkerFlag =true; }}//================================================================================================================//// Function name :decodeBufferContents// called from ://// Purpose :Evaluates the information stored in the buffer.// This is where the DCF77 signal is decoded to time and date information// Parameters :none// Return value :none////================================================================================================================void decodeBufferContents(void){ // Buffer is full and ready to be decoded dcfMinute =bitDecode(21, 27); dcfHour =bitDecode(29, 34); dcfDay =bitDecode(36, 41); dcfWeekDay =bitDecode(42, 44); dcfMonth =bitDecode(45, 49); dcfYear =bitDecode(50, 57); //call function to calculate day of year and weeknumber dayWeekNumber(dcfYear, dcfMonth, dcfDay, dcfWeekDay); // Get value of Summertime DCFbit. '1' =Summertime, '0' =wintertime dcfDST =bitDecode(17, 17); // determine Leap Year leapYear =calculateLeapYear(dcfYear);}//================================================================================================================//// bitDecode//// called from //================================================================================================================int bitDecode(int bitStart, int bitEnd){ // reset 'bitValue-array' counter int i =0; int value =0;...This file has been truncated, please download it to see its full contents.
    Superfilter sketchArduino
    //// This is the Superfilter sketch I use with the DCF Analyzer/Clock 2.0 // Udo Klein did an amazing job with this filter//// Erik de Ruiter/* Arduino Uno pin connections I used for the DCF Analyzer Clock DCF input ................. A5 (19) =dcf77_sample_pin Output DCF Filtered ....... 12 =dcf77_filtered_pin Output DCF Semi Synthesized A2 (16) =dcf77_semi_synthesized_pin Output DCF Synthesized .... 6 =dcf77_synthesized_pin LED DCF output filtered ... A4 (18) =dcf77_monitor_pin =DCF Monitor LED LED 1 Hz pulse ............ 10 =dcf77_second_pulse_pin =Filter Locked LED LED DCF OK ................ 13 =dcf77_signal_good_indicator_pin =Signal Quality LED LED Difference Filtered ... 7 =dcf77_filter_diff_pin \ LED Difference Semi Synth.. A0 =dcf77_semi_synthesized_diff_pin -> =Signal Difference LED LED Difference Synthesized 4 =dcf77_synthesized_diff_pin /*/ //// www.blinkenlight.net//// Copyright 2014, 2015 Udo Klein//// This program is free software:you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see http://www.gnu.org/licenses/#include /*const uint8_t pon_pin =51; // connect pon to ground !!!const uint8_t data_pin =19;const uint8_t gnd_pin =51;const uint8_t vcc_pin =49;*/const uint8_t dcf77_analog_samples =false;const uint8_t dcf77_analog_sample_pin =5;const uint8_t dcf77_sample_pin =19; // A5const uint8_t dcf77_inverted_samples =0;#if defined(__AVR__)#define ledpin(led) (led)#else#define ledpin(led) (led<14? led:led+(54-14))#endifconst uint8_t dcf77_monitor_pin =ledpin(18); // A4const bool provide_filtered_output =true;const uint8_t dcf77_filtered_pin =ledpin(12);const uint8_t dcf77_inverted_filtered_pin =ledpin(11);const uint8_t dcf77_filter_diff_pin =ledpin(7);const bool provide_semi_synthesized_output =true;const uint8_t dcf77_semi_synthesized_pin =ledpin(16);const uint8_t dcf77_inverted_semi_synthesized_pin =ledpin(15);const uint8_t dcf77_semi_synthesized_diff_pin =ledpin(14);const bool provide_synthesized_output =true;const uint8_t dcf77_synthesized_pin =ledpin(6);const uint8_t dcf77_inverted_synthesized_pin =ledpin(5);const uint8_t dcf77_synthesized_diff_pin =ledpin(4);const uint8_t dcf77_second_pulse_pin =ledpin(10);const uint8_t dcf77_signal_good_indicator_pin =ledpin(13);volatile uint16_t ms_counter =0;volatile Internal::DCF77::tick_t tick =Internal::DCF77::undefined;template void set_output(uint8_t clock_state, uint8_t sampled_d ata, uint8_t synthesized_signal){ if (enable) { const uint8_t filtered_output =clock_state  200) :digitalRead(dcf77_sample_pin)); #else dcf77_inverted_samples ^ digitalRead(dcf77_sample_pin); #endif digitalWrite(dcf77_monitor_pin, sampled_data); digitalWrite(dcf77_second_pulse_pin, ms_counter <500 &&clock_state>=Clock::locked); const uint8_t synthesized_signal =tick ==Internal::DCF77::long_tick ? ms_counter <200:tick ==Internal::DCF77::short_tick ? ms_counter <100:tick ==Internal::DCF77::sync_mark ? 0:// tick ==DCF77::undefined --> default handling // allow signal to pass for the first 200ms of each second (ms_counter <=200 &&sampled_data) || // if the clock has valid time data then undefined ticks // are data bits --> first 100ms of signal must be high ms_counter <100; set_output (clock_state, sampled_data, synthesized_signal); set_output (clock_state, sampled_data, synthesized_signal); set_output (clock_state, sampled_data, synthesized_signal); ms_counter+=(ms_counter <1000); scope_1.process_one_sample(sampled_data); scope_2.process_one_sample(digitalRead(dcf77_synthesized_pin)); return sampled_data;}void output_handler(const Clock::time_t &decoded_time) { // reset ms_counter for 1 Hz ticks ms_counter =0; // status indicator --> always on if signal is good // blink 3s on 1s off if signal is poor // blink 1s on 3s off if signal is very poor // always off if signal is bad const uint8_t clock_state =DCF77_Clock::get_clock_state(); digitalWrite(dcf77_signal_good_indicator_pin, clock_state>=Clock::locked ? 1:clock_state ==Clock::unlocked? (decoded_time.second.digit.lo &0x03) !=0:clock_state ==Clock::free ? (decoded_time.second.digit.lo &0x03) ==0:0); // compute output for signal synthesis Internal::DCF77_Encoder now; now.second =BCD::bcd_to_int(decoded_time.second); now.minute =decoded_time.minute; now.hour =decoded_time.hour; now.weekday =decoded_time.weekday; now.day =decoded_time.day; now.month =decoded_time.month; now.year =decoded_time.year; now.uses_summertime =decoded_time.uses_summertime; now.leap_second_scheduled =decoded_time.leap_second_scheduled; now.timezone_change_scheduled =decoded_time.timezone_change_scheduled; now.undefined_minute_output =false; now.undefined_uses_summertime_output =false; now.undefined_abnormal_transmitter_operation_output =false; now.undefined_timezone_change_scheduled_output =false; now.advance_minute(); tick =now.get_current_signal();}void setup_serial() { Serial.begin(115200);}void output_splash_screen() { Serial.println(); Serial.println(F("DCF77 Superfilter 3.0")); Serial.println(F("(c) 2015 Udo Klein")); Serial.println(F("www.blinkenlight.net")); Serial.println(); Serial.print(F("Sample Pin:")); Serial.println(dcf77_sample_pin); Serial.print(F("Inverted Mode:")); Serial.println(dcf77_inverted_samples); #if defined(__AVR__) Serial.print(F("Analog Mode:")); Serial.println(dcf77_analog_samples); #endif Serial.print(F("Monitor Pin:")); Serial.println(dcf77_monitor_pin); Serial.println(); if (provide_filtered_output) { Serial.println(F("Filtered Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_filtered_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_filter_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_filtered_pin); Serial.println(); } if (provide_semi_synthesized_output) { Serial.println(F("Semi Synthesized Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_semi_synthesized_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_semi_synthesized_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_semi_synthesized_pin); Serial.println(); } if (provide_synthesized_output) { Serial.println(F("Synthesized Output")); Serial.print(F(" Filtered Pin:")); Serial.println(dcf77_synthesized_pin); Serial.print(F(" Diff Pin:")); Serial.println(dcf77_synthesized_diff_pin); Serial.print(F(" Inverse Filtered Pin:")); Serial.println(dcf77_inverted_synthesized_pin); Serial.println(); } Serial.print(F("Second Pulse Pin:")); Serial.println(dcf77_second_pulse_pin); Serial.print(F("Signal Good Pin:")); Serial.println(dcf77_signal_good_indicator_pin); Serial.println(); Serial.println(); Serial.println(F("Initializing...")); Serial.println();};void setup_pins() { if (provide_filtered_output) { pinMode(dcf77_filtered_pin, OUTPUT); pinMode(dcf77_filter_diff_pin, OUTPUT); pinMode(dcf77_inverted_filtered_pin, OUTPUT); } if (provide_semi_synthesized_output) { pinMode(dcf77_semi_synthesized_pin, OUTPUT); pinMode(dcf77_semi_synthesized_diff_pin, OUTPUT); pinMode(dcf77_inverted_semi_synthesized_pin, OUTPUT); } if (provide_synthesized_output) { pinMode(dcf77_synthesized_pin, OUTPUT); pinMode(dcf77_synthesized_diff_pin, OUTPUT); pinMode(dcf77_inverted_synthesized_pin, OUTPUT); } pinMode(dcf77_monitor_pin, OUTPUT); pinMode(dcf77_signal_good_indicator_pin, OUTPUT); pinMode(dcf77_second_pulse_pin, OUTPUT); pinMode(dcf77_sample_pin, INPUT); digitalWrite(dcf77_sample_pin, HIGH);}void setup_clock() { DCF77_Clock::setup(); DCF77_Clock::set_input_provider(sample_input_pin); DCF77_Clock::set_output_handler(output_handler);}void setup() { setup_serial(); output_splash_screen(); setup_pins(); setup_clock();/* pinMode(gnd_pin, OUTPUT); digitalWrite(gnd_pin, LOW); pinMode(pon_pin, OUTPUT); digitalWrite(pon_pin, LOW); pinMode(vcc_pin, OUTPUT); digitalWrite(vcc_pin, HIGH); */}void loop() { Clock::time_t now; DCF77_Clock::get_current_time(now); if (now.month.val> 0) { Serial.println(); Serial.print(F("Decoded time:")); DCF77_Clock::print(now); Serial.println(); } Serial.print(DCF77_Clock::get_clock_state()); Serial.print(' '); DCF77_Clock::debug(); scope_1.print(); scope_2.print();}

    맞춤형 부품 및 인클로저

    This is a PCB I made for the Time and Date displays Maxim_7219_LED_display_unit_for_Adafruit_0_56inch_7_segment_v1_1.zipThis is my PCB design for the very compact smaller 7 segment displays Maxim_7219_LED_display_unit_for_KingBright_7_segment_SC39_11SRWAv1_1.zipTicking sound and Chime sound, see text for explanation Grandfather_Clock_Sound_files.zip

    회로도

    DOWNLOAD to view details! dcf77-analyzer-clock-v2_1_jVZT5sqIwn.zip

    제조공정

    1. 뻐꾸기 시계
    2. Arduino 관점 시계
    3. Arduino로 DIY 가장 간단한 IV9 Numitron 시계
    4. Adafruit 1/4 60 Ring Neopixel을 사용한 간단한 벽시계
    5. 단순 워드 클럭(Arduino)
    6. 이슬람 기도 시간이 있는 Arduino 시계
    7. Arduino 스파이봇
    8. FlickMote
    9. 마스터 시계
    10. DS1302 RTC가 있는 간단한 알람 시계