#include #define DCF77PIN 2 // Input for the DCF receiver #define BLINKPIN 13 // LED indicator output #define DCF_split_millis 140 // Number of milliseconds before we assume a logic 1 #define DCF_sync_millis 1200 // No signal at second 59 // Definitions for the timer interrupt 2 handler // The Arduino runs at 16 Mhz, we use a prescaler of 64 -> We need to // initialize the counter with 6. This way, we have 1000 interrupts per second. // We use tick_counter to count the interrupts. LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 8); #define INIT_TIMER_COUNT 6 #define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT int tick_counter = 0; // DCF time format struct struct DCF77Buffer { unsigned long long prefix :21; unsigned long long Min :7; // minutes unsigned long long P1 :1; // parity minutes unsigned long long Hour :6; // hours unsigned long long P2 :1; // parity hours unsigned long long Day :6; // day unsigned long long Weekday :3; // day of week unsigned long long Month :5; // month unsigned long long Year :8; // year (5 -> 2005) unsigned long long P3 :1; // parity }; // Parity struct struct { unsigned char parity_flag :1; unsigned char parity_min :1; unsigned char parity_hour :1; unsigned char parity_date :1; } flags; // Clock variables volatile unsigned char DCFSignalState = 0; unsigned char previousSignalState; int previousFlankTime; int bufferPosition; unsigned long long dcf_rx_buffer; // Time variables volatile unsigned char ss; volatile unsigned char mm; volatile unsigned char hh; volatile unsigned char day; volatile unsigned char mon; volatile unsigned int year; unsigned char previousSecond; // Initialize the DCF77 routines: initialize the variables, // configure the interrupt behaviour. void DCF77Init() { previousSignalState=0; previousFlankTime=0; bufferPosition=0; dcf_rx_buffer=0; ss=mm=hh=day=mon=year=0; pinMode(DCF77PIN, INPUT); //Timer2 Settings: Timer Prescaler /64, TCCR2B |= (1< 59, // a new minute begins -> time to call finalizeBuffer(). void appendSignal(unsigned char signal) { dcf_rx_buffer = dcf_rx_buffer | ((unsigned long long) signal << bufferPosition); // Update the parity bits. First: Reset when minute, hour or date starts. if (bufferPosition == 21 || bufferPosition == 29 || bufferPosition == 36) { flags.parity_flag = 0; } // save the parity when the corresponding segment ends if (bufferPosition == 28) {flags.parity_min = flags.parity_flag;}; if (bufferPosition == 35) {flags.parity_hour = flags.parity_flag;}; if (bufferPosition == 58) {flags.parity_date = flags.parity_flag;}; // When we received a 1, toggle the parity flag if (signal == 1) { flags.parity_flag = flags.parity_flag ^ 1; } bufferPosition++; if (bufferPosition > 59) { finalizeBuffer(); } } // Evaluates the information stored in the buffer. This is where the DCF77 // signal is decoded and the internal clock is updated. void finalizeBuffer(void) { if (bufferPosition == 59) { struct DCF77Buffer *rx_buffer; rx_buffer = (struct DCF77Buffer *)(unsigned long long)&dcf_rx_buffer; if (flags.parity_min == rx_buffer->P1 && flags.parity_hour == rx_buffer->P2 && flags.parity_date == rx_buffer->P3) { //convert the received bits from BCD mm = rx_buffer->Min-((rx_buffer->Min/16)*6); hh = rx_buffer->Hour-((rx_buffer->Hour/16)*6); day= rx_buffer->Day-((rx_buffer->Day/16)*6); mon= rx_buffer->Month-((rx_buffer->Month/16)*6); year= 2000 + rx_buffer->Year-((rx_buffer->Year/16)*6); } } // reset stuff ss = 0; bufferPosition = 0; dcf_rx_buffer=0; } // Evaluates the signal as it is received. Decides whether we received // a "1" or a "0" based on the void scanSignal(void){ if (DCFSignalState == 1) { int thisFlankTime=millis(); if (thisFlankTime - previousFlankTime > DCF_sync_millis) { finalizeBuffer(); } previousFlankTime=thisFlankTime; } else { /* or a falling flank */ int difference=millis() - previousFlankTime; if (difference < DCF_split_millis) { appendSignal(0); } else { appendSignal(1); } } } // The interrupt routine for counting seconds - increment hh:mm:ss. ISR(TIMER2_OVF_vect) { RESET_TIMER2; tick_counter += 1; if (tick_counter == 1000) { ss++; if (ss==60) { ss=0; mm++; if (mm==60) { mm=0; hh++; if (hh==24) hh=0; } } tick_counter = 0; } }; // Interrupthandler for INT0 - called when the signal on Pin 2 changes. void int0handler() { // check the value again - since it takes some time to // activate the interrupt routine, we get a clear signal. DCFSignalState = digitalRead(DCF77PIN); } //LCD routines void clearLCD() { lcd.print(12, BYTE); } void startBigChars() { lcd.print(2, BYTE); } // Dump the time to the serial LCD void DumpTime(void){ /* if (year == 0) { lcd.print(bufferPosition); lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor( 0, 0); } else { lcd.print(" "); lcd.setCursor( 0, 0); if (day < 10) { lcd.print(" "); lcd.setCursor( 0,0); } }*/ // de dagen wegschijven naar het display if (day == 0) { lcd.setCursor( 0,1); lcd.print("00"); // tussen streepje plaatsen op display lcd.setCursor(2,1); lcd.print("-"); }else{ if (day <= 9){ lcd.setCursor( 0,1); lcd.print("0"); lcd.setCursor( 1,1); lcd.print(day, DEC); }else{ lcd.setCursor( 0,1); lcd.print(day, DEC); } // tussen streepje plaatsen op display lcd.setCursor(2,1); lcd.print("-"); } // de maanden wegschijven naar het display if (mon == 0) { lcd.setCursor(3,1); lcd.print("00"); // tussen streepje plaatsen op display lcd.setCursor(5,1); lcd.print("-"); }else{ if (mon <= 9){ lcd.setCursor( 3,1); lcd.print("0"); lcd.setCursor( 4,1); lcd.print(mon, DEC); }else{ lcd.setCursor( 3,1); lcd.print(mon, DEC); } // tussen streepje plaatsen op display lcd.setCursor(5,1); lcd.print("-"); } // de jaren wegschijven naar het display if (year == 0) { lcd.setCursor(6,1); lcd.print("0000"); }else{ lcd.setCursor(6,1); lcd.print(year, DEC); } // de uren weergeven op het display if (hh == 0) { lcd.setCursor( 12, 1); lcd.print("00"); } lcd.setCursor( 12, 1); if (hh <= 9) { lcd.print("0"); lcd.setCursor( 13, 1); lcd.print(hh, DEC); }else{ lcd.setCursor( 12, 1); lcd.print(hh, DEC); } // per seconde de : laten knipperen if ((ss % 2) == 0) { lcd.setCursor( 14, 1); lcd.print(":"); } else { lcd.print(" "); } // de minuten weergeven op het display if (mm == 0) { lcd.setCursor( 15, 1); lcd.print("00"); } lcd.setCursor( 15, 1); if (mm <= 9) { lcd.print("0"); lcd.setCursor( 16, 1); lcd.print(mm, DEC); }else{ lcd.setCursor( 15, 1); lcd.print(mm, DEC); } // per seconde de : laten knipperen if ((ss % 2) == 0) { lcd.setCursor( 17, 1); lcd.print(":"); } else { lcd.print(" "); } // secondes weergeven op display if (ss == 0) { lcd.setCursor( 18, 1); lcd.print("00"); } lcd.setCursor( 18, 1); if (ss <= 9) { lcd.print("0"); lcd.setCursor( 19, 1); lcd.print(ss, DEC); }else{ lcd.setCursor( 18, 1); lcd.print(ss, DEC); } // alles weergeven in arduino programma op pc Serial.print(day,DEC); Serial.print("-"); Serial.print(mon,DEC); Serial.print("-"); Serial.print(year,DEC); Serial.print(" "); Serial.print(hh,DEC); Serial.print(":"); Serial.print(mm,DEC); Serial.print(":"); Serial.print(ss,DEC); Serial.print(" "); Serial.println(digitalRead(DCF77PIN)); } // Standard Arduino methods below. void setup(void) { // We need to start serial here again, // for Arduino 007 (new serial code) Serial.begin(9600); clearLCD(); DCF77Init(); lcd.setCursor(0,0); lcd.print("Atoomtijd:"); } void loop(void) { if (ss != previousSecond) { DumpTime(); previousSecond = ss; } if (DCFSignalState != previousSignalState) { scanSignal(); if (DCFSignalState) { digitalWrite(BLINKPIN, HIGH); } else { digitalWrite(BLINKPIN, LOW); } previousSignalState = DCFSignalState; } }