Components and supplies
Arduino UNO
LCD 4x20 display
Project description
Code
"Atomic" Longcase Clock Arduino Code v16
arduino
Arduino Code v16 Requires the following libraries dcf77.h Note this clock uses Udo Kleins Release 3 library download here DCF77 Release 3 LiquidCrystal_I2C.h Wire.h
1[code] 2/* 3v16 coded to use Udo Klein's v3 library https://github.com/udoklein/dcf77/releases/tag/v3.0.0 4v15 remove moonphase advance fast add mooncountSec advance by 1465 (1/60th phase) 5 6 Longcase Clock 7 http://www.brettoliver.org.uk 8 9 Copyright 2014 Brett Oliver 10 11 This program is free software: you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation, either version 3 of the License, or 14 (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program. If not, see http://www.gnu.org/licenses/ 23 24 25 Based on the DCF77 library by Udo Klein 26 http://blog.blinkenlight.net/experiments/dcf77/dcf77-library/ 27 http://blog.blinkenlight.net/experiments/dcf77/simple-clock/ 28 29*/ 30 31 32#include <dcf77.h> 33#include <LiquidCrystal_I2C.h> 34#include <Wire.h> 35using namespace Internal; //v3 36 37 38/* we always wait a bit between updates of the display */ 39unsigned long delaytime=250; 40//********************** 41// set the LCD address to 0x27 for a 20 chars 4 line display 42// Set the pins on the I2C chip used for LCD connections: 43// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol 44LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address 45 46 47//********************** 48 49const uint8_t dcf77_analog_sample_pin = 5; 50const uint8_t dcf77_sample_pin = A1; // A5 == d19 (DFC77 signal)changed from A5 51const uint8_t dcf77_inverted_samples = 0; 52const uint8_t dcf77_analog_samples = 0; 53const uint8_t dcf77_monitor_led = A0; // v3 54//const uint8_t dcf77_monitor_pin = A0; // A4 == d18 changed from A4 removed v3 55uint8_t ledpin(const uint8_t led){ //v3 56 return led; //v3 57} //v3 58 59const int8_t timezone_offset = -1; // GB is one hour behind CET/CEST 60 61//********************* 62 63 64int retardOn = 0; 65 66//int infraredSwval = 0; // infrared value 67//int infraredSw = A3; // set A3 to input ( pin 13) 68int retardcount = 0; 69int pulsecount = 0; // pulse counts upto required number to step forward 1 hour 70int retardSw = 13; // winter retard switch pin 9 71int retardSwval = 0; // value of retardSw 72int advanceSw = 9; // summer advance switch pin 13 73int advanceSwval = 0; // value of advanceSw 74int pulseOn = 0; // 0 pulse off 1 pulse on (summer winter pulsing 75int summertest = 0; // equals 1 for summertime and 0 for wintertime 76int summerwinter = 0; // summer winter toggle 77int extracount = 0; // where quartz seconds needs to miss a pulse 78int hourextra = 00; // hour last miss pulse variable 79int dayextra = 00; // day last miss pulse variable 80int monthextra = 00; // month last miss pulse variable 81int minuteextra = 00; // minute last miss pulse variable 82int secondextra = 00; // second last miss pulse variable 83int yearextra = 00; 84 85 86 87int secondsnow = 0; // previous second 88int yearmiss = 00; 89int daymiss = 00; // day last extra pulse variable 90int monthmiss = 00; // month last extra pulse variable 91int secsmiss = 0; // works out is seconds need to an extra pulse or miss a pulse 92int misscount = 0; // 1 ok 0 needs to miss a pulse 1 needs an extra pulse 93int hourmiss = 00; // hour last extra pulse variable 94int minutemiss = 00; // minute last extra pulse variable 95int secondmiss = 00; // second last extra pulse variable 96int signalQual = 0; // computed once per minute and indicates how well 97// the received signal matches the locally synthesized reference signal max 50 98int monthval = 0; 99int dayval = 0; 100//int zero = 0; 101int years = 0; 102int months = 0; 103int days = 0; 104 105int hours = 0; 106 107int minutes = 0; 108 109int seconds = 0; 110int secsval = 0; 111int minsval = 0; 112int hourval = 0; 113int led15 = 2; //15 second pulse 114 115int quartzmotor1 = HIGH; // ledState used to set the quartz motor pin 7 initial state 116int quartzmotor2 = LOW; // ledState used to set the quartz motor pin 8 initial state 117int quartz01 =7; // Quartz clock motor pulse 01 118int quartz02 =8; // Quartz clock motor pulse 02 119int stepSecs =11; // when high seconds are advanced 120 121int hrminmotor1 = HIGH; // ledState used to set the quartz motor pin 1 initial state 122int hrminmotor2 = LOW; // ledState used to set the quartz motor pin 2 initial state 123int hrmin01 =12; // Quartz clock motor pulse 01 124int hrmin02 =2; // Quartz clock motor pulse 02 125 126 127//Moon Display 128unsigned long mooncountSec = 1; // counts every sec until 43245 then moonphase is advanced by 1 129unsigned long moontime = 1; 130int moonphase = 0; // advances 1 every 43245 secs and 86490 secs until 60 when it is reset to 2 (moon dial advanced to 1) 131int moonphasedisp = 1; // advances 1 every 86490 secs until moonphase 60 when it is reset to 1 (moon dial advanced to 1) 132int moondisAdv = 3; // advances moon phase display once per second 133int moonphaseAdv = 4; //advances moon phase count once per second 134//int moonphaseAdvfast = 11; //advances moon phase count 5 once per second 135int mooncountSecAdv = 11; //advances mooncountSec 1465 once per second 136int moonReset = A3; // resets moon phase and count to 1 new moon 137int moonmotor1 = HIGH; // ledState used to set the quartz motor pin 5 initial state 138int moonmotor2 = LOW; // ledState used to set the quartz motor pin 6 initial state 139int moon01 =5; // Moon clock motor pulse 01 140int moon02 =6; // Moon clock motor pulse 02 141 142float h, m; 143int s = 0; 144unsigned long over = 0; 145 146// End Moon Display 147int LCDdispCtrl = A2; 148int step15 = 10; //step hour mins forward by 15 seconds 149 150//******************** 151 152namespace Timezone { 153 uint8_t days_per_month(const Clock::time_t &now) { //v3 mod 154 switch (now.month.val) { 155 case 0x02: 156 // valid till 31.12.2399 157 // notice year mod 4 == year & 0x03 158 return 28 + ((now.year.val != 0) && ((bcd_to_int(now.year) & 0x03) == 0)? 1: 0); 159 case 0x01: case 0x03: case 0x05: case 0x07: case 0x08: case 0x10: case 0x12: return 31; 160 case 0x04: case 0x06: case 0x09: case 0x11: return 30; 161 default: return 0; 162 163 } 164 } 165 166 void adjust(Clock::time_t &time, const int8_t offset) { //v3 mod 167 // attention: maximum supported offset is +/- 23h 168 169 int8_t hour = BCD::bcd_to_int(time.hour) + offset; 170 171 if (hour > 23) { 172 hour -= 24; 173 uint8_t day = BCD::bcd_to_int(time.day) + 1; 174 uint8_t weekday = BCD::bcd_to_int(time.weekday) + 1; //v3 175 if (day > days_per_month(time)) { 176 day = 1; 177 uint8_t month = BCD::bcd_to_int(time.month); 178 ++month; 179 if (month > 12) { 180 month = 1; 181 uint8_t year = BCD::bcd_to_int(time.year); 182 ++year; 183 if (year > 99) { 184 year = 0; 185 } 186 time.year = BCD::int_to_bcd(year); 187 } 188 time.month = BCD::int_to_bcd(month); 189 } 190 time.day = BCD::int_to_bcd(day); 191 time.weekday = BCD::int_to_bcd(weekday); //v3 192 } 193 194 if (hour < 0) { 195 hour += 24; 196 uint8_t day = BCD::bcd_to_int(time.day) - 1; 197 uint8_t weekday = BCD::bcd_to_int(time.weekday) - 1; //v3 198 if (day < 1) { 199 uint8_t month = BCD::bcd_to_int(time.month); 200 --month; 201 if (month < 1) { 202 month = 12; 203 int8_t year = BCD::bcd_to_int(time.year); 204 --year; 205 if (year < 0) { 206 year = 99; 207 } 208 time.year = BCD::int_to_bcd(year); 209 } 210 time.month = BCD::int_to_bcd(month); 211 day = days_per_month(time); 212 } 213 time.day = BCD::int_to_bcd(day); 214 time.weekday = BCD::int_to_bcd(weekday); //v3 215 } 216 217 time.hour = BCD::int_to_bcd(hour); 218 } 219} 220 221uint8_t sample_input_pin() { 222 const uint8_t sampled_data = 223 dcf77_inverted_samples ^ (dcf77_analog_samples? (analogRead(dcf77_analog_sample_pin) > 200) 224 : digitalRead(dcf77_sample_pin)); 225 226 //digitalWrite(dcf77_monitor_pin, sampled_data); // removed v3 227 digitalWrite(ledpin(dcf77_monitor_led), sampled_data); // v3 228 return sampled_data; 229} 230 231void setup() { 232 digitalWrite(led15, HIGH); // turn 15 sec clocks off at start 233 234 235 lcd.begin(20,4); // initialize the lcd for 20 chars 4 lines, turn on backlight 236 // using namespace Internal; // v3 Removed 237 //************* 238 // lcd.backlight(); // backlight on not needed as controlled by 7 MAX2719 239 lcd.setCursor(0,0); //Start at character 0 on line 0 240 lcd.print("DCF77 Longcase Clock"); 241 242 243 244 245 246 //*************** 247 Serial.begin(9600); 248 /* Serial.println(); 249 Serial.println(F(" DCF77 Longcase Clock ")); 250 Serial.println(F("(c) Brett Oliver 2014")); 251 Serial.println(F("http://www.brettoliver.org.uk")); 252 Serial.println(F("Based on the DCF77 library by Udo Klein")); 253 Serial.println(F("www.blinkenlight.net")); 254 Serial.println(); 255 Serial.print(F("Sample Pin: ")); 256 Serial.println(dcf77_sample_pin); 257 Serial.print(F("Inverted Mode: ")); 258 Serial.println(dcf77_inverted_samples); 259 Serial.print(F("Analog Mode: ")); 260 Serial.println(dcf77_analog_samples); 261 Serial.print(F("Monitor Pin: ")); 262 Serial.println(dcf77_monitor_pin); 263 Serial.print(F("Timezone Offset:")); 264 Serial.println(timezone_offset); 265 Serial.println(); 266 Serial.println(); 267 Serial.println(F("Initializing...")); 268 */ 269 // pinMode(dcf77_monitor_pin, OUTPUT); // removed v3 270 271 pinMode(dcf77_sample_pin, INPUT); 272 digitalWrite(dcf77_sample_pin, HIGH); 273 274 275 //******************* 276 277 //pinMode(led15, OUTPUT); 278 pinMode(quartz01, OUTPUT); 279 pinMode(quartz02, OUTPUT); 280 pinMode(moon01, OUTPUT); 281 pinMode(moon02, OUTPUT); 282 pinMode(hrmin01, OUTPUT); 283 pinMode(hrmin02, OUTPUT); 284 pinMode(ledpin(dcf77_monitor_led), OUTPUT); // v3 285 286 287 //pinMode(17, INPUT); // infrared switch 288 pinMode(advanceSw,INPUT); 289 pinMode(retardSw,INPUT); 290 pinMode(moonphaseAdv,INPUT); 291 //pinMode(moonphaseAdvfast,INPUT); 292 pinMode(mooncountSecAdv,INPUT); 293 pinMode(moondisAdv,INPUT); 294 pinMode(moonReset,INPUT); 295 pinMode(LCDdispCtrl,INPUT); 296 pinMode(step15,INPUT); // 15 second (hour min) man advance 297 // pinMode(stepSecs,INPUT); // secs man advance 298 299 300 //******************* 301 302 DCF77_Clock::setup(); 303 DCF77_Clock::set_input_provider(sample_input_pin); 304 305 306 // Wait till clock is synced, depending on the signal quality this may take 307 // rather long. About 5 minutes with a good signal, 30 minutes or longer 308 // with a bad signal 309 310 311 312 313 for (uint8_t state = Clock::useless; //v3 Mod 314 state == Clock::useless || state == Clock::dirty; //v3 Mod 315 state = DCF77_Clock::get_clock_state()) { 316 317 // wait for next sec 318 Clock::time_t now; //v3 mod 319 DCF77_Clock::get_current_time(now); 320 321 // render one dot per second while initializing 322 static uint8_t count = 0; 323 Serial.print('.'); 324 ++count; 325 if (count == 60) { 326 count = 0; 327 Serial.println(); 328 } 329 } 330} 331 332void paddedPrint(BCD::bcd_t n) { 333 Serial.print(n.digit.hi); 334 Serial.print(n.digit.lo); 335} 336void LCDpaddedPrint(BCD::bcd_t n) { 337 lcd.print(n.digit.hi); 338 lcd.print(n.digit.lo); 339} 340 341void loop() { 342 343 Clock::time_t now; //v3 mod 344 345 DCF77_Clock::get_current_time(now); 346 Timezone::adjust(now, timezone_offset); 347 348 349 if (now.month.val > 0) { 350 351 352 //*********** 353 // get month & day values 354 dayval = now.day.val, DEC; 355 monthval = now.month.val, DEC; 356 // Serial.print(" day "); 357 // Serial.print(now.day.val, DEC); 358 // Serial.print(" month "); 359 // Serial.print(now.month.val, DEC); 360 // Serial.print(' '); 361 // get month & day values 362 // Quartz clock driver 363 // toggle Quartz drive 7 & 8 evey second 364 secsmiss = seconds - secondsnow; 365 366 if (secsmiss ==-59 || secsmiss ==-60 && seconds ==0) // takes account of seconds rollover -59 or leap second -60 367 { 368 secsmiss = 1; 369 } 370 371 372 373 374 375 // If not andvancing seconds then use this (normal) 376 if (secsmiss >=1 && seconds !=60) // if zero or less seconds pulse need to be missed. Leap second missed if seconds = 60 377 { 378 secondsmotor (); // function steps quartz motor 379 } 380 381 382 383 384 if (secsmiss < 1 || seconds == 60) //records time of extra sec second (quart motor needs to loose a second) 385 386 { 387 extracount = extracount + 1; //increment extra count total (1sec needs to miss pulse) 388 hourextra = hours; 389 minuteextra = minutes; 390 secondextra = seconds; 391 yearextra = years; 392 monthextra = months; 393 dayextra = days; 394 395 } 396 397 398 if (secsmiss > 1) //records time of miss second (quart motor needs to add a second) 399 { 400 misscount = misscount + 1; //increment Miss count total (1sec has missed extra pulse) 401 hourmiss = hours; 402 minutemiss = minutes; 403 secondmiss = seconds; 404 yearmiss = years; 405 monthmiss = months; 406 daymiss = days; 407 408 } 409 410 411 412 secondsnow = seconds; 413 414 415 416 if (hours== 6 && minutes == 10 && seconds == 01) // resets miss second counter to 0 at 6:10:01 417 { 418 misscount = 0; 419 extracount = 0; 420 } 421 422 423 // } 424 // Enable below to analize missed pulses on serial monitor 425 //Serial.print(" "); 426 // Serial.print("secsmiss "); 427 // Serial.println(secsmiss); 428/* 429 430 Serial.print("Slow Seconds "); 431 Serial.print(misscount); 432 Serial.print(" "); 433 Serial.print(hourmiss); 434 Serial.print(":"); 435 Serial.print(minutemiss); 436 Serial.print(":"); 437 Serial.print(secondmiss); 438 Serial.print(" "); 439 Serial.print(daymiss); 440 Serial.print("/"); 441 Serial.print(monthmiss); 442 Serial.print("/"); 443 Serial.println(yearmiss); 444 445 446 Serial.print("Fast Seconds "); 447 Serial.print(extracount); 448 Serial.print(" "); 449 Serial.print(hourextra); 450 Serial.print(":"); 451 Serial.print(minuteextra); 452 Serial.print(":"); 453 Serial.print(secondextra); 454 Serial.print(" "); 455 Serial.print(dayextra); 456 Serial.print("/"); 457 Serial.print(monthextra); 458 Serial.print("/"); 459 Serial.println(yearextra); 460 461 462*/ 463 464 465 466 467 // end missing second pulse 468 469 // ################################################################################ 470 471 472 473 474 /* 475 Serial.println(F("confirmed_precision [Hz], target_precision v,total_adjust [Hz], frequency [Hz]")); 476 Serial.print(DCF77_Frequency_Control::get_confirmed_precision()); 477 Serial.print(F(", ")); 478 Serial.print(DCF77_Frequency_Control::get_target_precision()); 479 Serial.print(F(", ")); 480 Serial.print(DCF77_1_Khz_Generator::read_adjustment()); 481 Serial.print(F(", ")); 482 Serial.print(16000000L - DCF77_1_Khz_Generator::read_adjustment()); 483 Serial.print(F(" Hz, ")); 484 485 */ 486 487 //*************** 488 // signal quality 489 490 // signalQual = DCF77_Clock::get_prediction_match(); 491 // if(signalQual == 255 || signalQual == 0 ) 492 // { 493 // signalQual = 00; 494 // } 495 // else 496 //{ 497 // signalQual = (signalQual * 2) -1; 498 //} 499 // Serial.print (" Signal Match "); 500 // Serial.print (signalQual); 501 // Serial.print ("% "); 502 503 // display 7 segment intensity value on LCD 504 // lcd.setCursor(0,2); 505 //lcd.print("7 Seg Int "); 506 // lcd.print("Brightness "); 507 // segIntensity(intensity); // adds leading zero to 7 segment intensity 508 509 510 // end display 7 segment intensity value on LCD 511 512 513 // ################################# 514 //LDR start 515 516 // ldrValue = analogRead(ldr); 517 518 // Serial.print (" LDR Value "); 519 // Serial.print (ldrValue, DEC); 520 // Serial.print (" "); 521 // intensityValue(); 522 // Serial.print ("Intensity "); 523 // Serial.print (intensity); 524 // Serial.print (" "); 525 526 //LDR finish 527 //################################# 528 //Serial.print (now.second.val); 529 // Serial.print (" "); 530 lcd.setCursor(17,2); 531 //lcd.print(" Wait "); 532 switch (DCF77_Clock::get_clock_state()) { 533 // case DCF77::useless: Serial.print(F("useless ")); break; 534 case Clock::useless: //v3 mod 535 lcd.print(F(" Fail ")); 536 break; 537 // case DCF77::dirty: Serial.print(F("dirty: ")); break; 538 // case DCF77::synced: Serial.print(F("synced: ")); break; 539 // case DCF77::locked: Serial.print(F("locked: ")); break; 540 case Clock::dirty: //v3 mod 541 lcd.print(F("Dty")); 542 break; 543 case Clock::synced: //v3 Mod 544 lcd.print(F("Syn")); 545 break; 546 case Clock::locked: //v3 mod 547 lcd.print(F("Lck")); 548 break; 549 } 550 551 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 552 // Get hours minutes and seconds variables 553 hours = BCD::bcd_to_int(now.hour); 554 555 556 minutes = BCD::bcd_to_int(now.minute); 557 558 559 seconds = BCD::bcd_to_int(now.second); 560 561 years = BCD::bcd_to_int(now.year); 562 563 months = BCD::bcd_to_int(now.month); 564 565 days = BCD::bcd_to_int(now.day); 566 567 568 569 570 /* Serial.print (" H,M,S "); 571 Serial.print (hours2); 572 573 Serial.print (hours1); 574 Serial.print (":"); 575 576 577 Serial.print (minutes2); 578 579 Serial.print (minutes1); 580 Serial.print (":"); 581 582 583 Serial.print (seconds2); 584 585 Serial.print (seconds1); 586 Serial.print (":"); 587 588 */ 589 lcd.setCursor(6,3); 590 591 592 593 // 7 segment 594 595 596 //**************** 597 598 lcd.setCursor(0,0); 599 600 LCDpaddedPrint(now.hour); 601 lcd.print(":"); 602 LCDpaddedPrint(now.minute); 603 lcd.print(":"); 604 LCDpaddedPrint(now.second); 605 lcd.print(" "); 606 607 LCDpaddedPrint(now.day); 608 lcd.print("/"); 609 LCDpaddedPrint(now.month); 610 lcd.print("/"); 611 lcd.print("20"); 612 LCDpaddedPrint(now.year); 613 614 615 616 617 618 //**************** 619 /* 620 621 paddedPrint(now.hour); 622 Serial.print(':'); 623 paddedPrint(now.minute); 624 Serial.print(':'); 625 paddedPrint(now.second); 626 Serial.print(' '); 627 628 paddedPrint(now.day); 629 Serial.print('/'); 630 paddedPrint(now.month); 631 Serial.print('/'); 632 Serial.print(F("20")); 633 paddedPrint(now.year); 634 635 636 */ 637 638 639 640 // const int8_t offset_to_utc = timezone_offset + now.uses_summertime? 2: 1; 641 const int8_t offset_to_utc = timezone_offset + (now.uses_summertime? 2: 1); 642 643 // Serial.print(F(" GMT")); 644 645 summertest = (abs(offset_to_utc)); // equals 1 if summertime and 2 if wintertime 646 647 if (summertest ==2) // if wintertime make summertest =0 648 { 649 summertest = 0; 650 } 651 652 //************** 653 lcd.setCursor(15,3); 654 lcd.print("GMT+"); 655 // UTCcheck= offset_to_utc; 656 // lcd.print(UTCcheck); 657 lcd.print(summertest); 658 659 } 660 661 662 // Quality display on LCD 663 if (seconds >= 0 && seconds <= 10) 664 { 665 signalmatch(); // Quality factor 666 } 667 668 else if (seconds == 11) 669 { 670 blankrow3(); //Blanks row 3 671 } 672 673else if (seconds == 12) 674 { 675 lcd.setCursor(0,3); 676 lcd.print("Quartz "); 677 } 678 else if (seconds >= 13 && seconds <= 23) 679 { 680 precision(); //quartz confirmed and target precision 681 } 682 683 else if (seconds == 24) 684 { 685 blankrow3(); //Blanks row 3 686 } 687 688 else if (seconds >=25 && seconds <= 35 ) 689 { 690 lcd.setCursor(0,3); 691 692 signalmatch(); // Quality factor 693 } 694 695 else if (seconds == 36) 696 { 697 blankrow3(); //Blanks row 3 698 } 699 700 else if (seconds == 37) 701 { 702 lcd.setCursor(0,3); 703 lcd.print("Quartz "); 704 } 705 else if (seconds >= 38 && seconds <= 48) 706 { 707 precision(); //quartz confirmed and target precision 708 } 709 710 else if (seconds == 49) 711 { 712 blankrow3(); //Blanks row 3 713 } 714 715 else if (seconds >=50 && seconds <= 59 ) 716 { 717 lcd.setCursor(0,3); 718 719 signalmatch(); // Quality factor 720 } 721 722 723 // End of Quality display on LCD 724 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 725 726 727 728 // winter to summer change // clocks go forward################################# 729 advanceSwval = digitalRead(advanceSw); // read advanceSw switch 730 // 240 x 15 sec pulses need to be added to normal 15 second pulses to advance by 1 hour 731 if (pulsecount < 240 && (seconds == 0 || seconds == 15 || seconds == 30 || seconds == 45) && (advanceSwval == 1 || pulseOn == 1)) 732 // summertest is 1 in summertime and 0 in wintertime advance on 00 ,15,30 &45 secs does not advance pulse count 733 734 { 735 // sumwinSwval = 1; 736 pulseOn = 1; 737 //Serial.println(" 15 second test "); 738 739 hrminmotor(); // function steps hr min motor 740 741 } 742 743 else if (pulsecount < 240 && (advanceSwval == 1 || pulseOn == 1)) // summertest is 1 in summertime and 0 in wintertime 744 745 { 746 // sumwinSwval = 1; 747 pulseOn = 1; 748 pulsecount = pulsecount + 1; 749 750 hrminmotor(); // function steps hr min motor 751 } 752 753 else 754 { 755 digitalWrite(hrmin01, LOW); // set the hr min motor drive 1 pin LOW 756 digitalWrite(hrmin02, LOW); // set the hr min motor drive 2 pin LOW 757 pulseOn = 0; // 758 // sumwinSwval = 0; 759 pulsecount = 0; 760 } 761 762 // end winter to summer chaange advance ############################## 763 764 765 766 // summer to winter change clocks go back################################# 767 retardSwval = digitalRead(retardSw); // read retardSw switch 768 769 if (retardcount < 240 && retardSwval == 1) // 240 x 15 sec pulses need to be ignored to retard by 1 hour 770 { 771 retardOn = 1; 772 } 773 774 else if (retardcount < 240 && (seconds == 0 || seconds == 15 || seconds == 30 || seconds == 45) && (retardSwval == 1 || retardOn == 1)) 775 { 776 retardOn = 1; 777 retardcount = retardcount + 1; 778 } 779 780 else if (retardcount < 240 && (retardSwval == 1 || retardOn == 1)) 781 { 782 retardOn = 1; 783 784 } 785 786 else 787 { 788 retardOn = 0; 789 // sumwinSwval = 0; 790 retardcount = 0; 791 } 792 793 794 795 // end summer to winter change clocks go back################################# 796 797 798 799 800 801 // Display of Title and 30 second pulse correction on row 01 ############################## 802 803 if (retardcount > 0 || retardcount == 119 ) //Prints correction pulse number 804 { 805 lcd.setCursor(0,1); 806 lcd.print("Winter Retard "); 807 lcd.setCursor(15,1); 808 809 810 811 retard(retardcount); // add leading 0 <99 812 retardtens(retardcount); // add another leading 0 less than 10 813 lcd.print(retardcount); 814 } 815 else if (retardcount == 240 ) //Prints blank when correction pulse is on last number 816 { 817 lcd.setCursor(0,1); 818 lcd.print(" "); 819 // lcd.print(retardcount); 820 } 821 822 823 else if (seconds >= 0 && seconds <= 5 && pulsecount == 0) // Ignored while clock is correcting forward or retarding 824 { 825 826 lcd.setCursor(0,1); //Start at character 0 on line 0 827 lcd.print("DCF77 Longcase Clock"); 828 829 } 830 else if(seconds > 05 && seconds <= 10 && pulsecount == 0) // Ignored while clock is correcting forward or retarding 831 { 832 lcd.setCursor(0,1); //Start at character 0 on line 0 833 //lcd.print(" DCF77 Master Clock "); 834 lcd.print(" Brett Oliver v16.0 "); 835 } 836 837 else if(seconds == 11 && pulsecount == 0) // Ignored while clock is correcting forward or retarding 838 { 839 lcd.setCursor(0,1); //Start at character 0 on line 0 840 841 lcd.print(" "); 842 } 843 844 else if(seconds > 11 && seconds <= 13 && pulsecount == 0) // Ignored while clock is correcting forward or retarding 845 { 846 lcd.setCursor(0,1); //Start at character 0 on line 0 847 848 // lcd.print(" Pulses "); 849 lcd.print(" 1 Second Clocks "); 850 851 } 852 853 854 855 else if(seconds > 13 && seconds <=59 && pulsecount == 0) // Ignored while clock is correcting forward or retarding 856 { 857 lcd.setCursor(0,1); //Start at character 0 on line 0 858 lcd.print(" Slow "); // miss pulse detected so extra 1 second motor pulse added 859 lcd.print(misscount); 860 861 lcd.print(" "); 862 lcd.print(" Fast "); 863 lcd.print(extracount); 864 } 865 866 else if (pulsecount > 0 || pulsecount == 239 ) //Prints correction pulse number 867 { 868 lcd.setCursor(0,1); 869 lcd.print("Summer Advance "); 870 lcd.setCursor(15,1); 871 //lcd.print(pulsecount); 872 873 advance(pulsecount); // add leading 0 <99 874 advancetens(pulsecount); // add another leading 0 less than 10 875 lcd.print(pulsecount); 876 } 877 else if (pulsecount == 240 ) //Prints blank when correction pulse is on last number 878 { 879 lcd.setCursor(0,1); 880 lcd.print(" "); 881 //lcd.print(pulsecount); 882 } 883 884 885 // sum win test print 886 //sumwinSwval = digitalRead(sumwinSw); // read sumwinSw switch 887 /* Serial.print(" Sum Win Pulse No "); 888 Serial.print(pulsecount); 889 Serial.print(" "); 890 891 Serial.print("Sum Win SW "); 892 Serial.print(sumwinSwval); 893 Serial.print(" "); 894 Serial.print("Pulse On "); 895 Serial.print(pulseOn); 896 Serial.print(" "); 897 Serial.print("Retard On "); 898 Serial.print(retardOn); 899 Serial.print(" "); 900 Serial.print("Retard Count "); 901 Serial.print(retardcount); 902 Serial.print(" "); 903 Serial.print("Summer Test "); 904 Serial.print(summertest); 905 Serial.print(" "); 906 */ 907 908 // end sum win test print 909 // 910 911 // winter to summer change // clocks go forward################################# 912 913 // End Display of Title and 30 second pulse correction on row 01 ############################## 914 //----------------------------------------------------------------------- 915 // Moon Phase Dial Display 916 mooncountSec = mooncountSec + 1; 917 // moontime = 86490 - mooncountSec; //counts down to next phase change 918 moontime = mooncountSec; // counts up to next phase change 919 // calc/display hour min sec to next moon phase 920 h = int (moontime/3600); 921 over = moontime % 3600; 922 m = int (over/60); 923 over = over % 60; 924 s = int (over); 925 /* 926 Serial.print ("Sec Pulses: "); 927 Serial.println (mooncountSec); 928 Serial.print ("Sec Pulses: "); 929 Serial.println (moontime); 930 931 Serial.print ("Next Phase: "); 932 Serial.print (h, 0); 933 Serial.print ("h "); 934 Serial.print (m, 0); 935 Serial.print ("m "); 936 Serial.print (s, 0); 937 Serial.print ("s "); 938 939 Serial.println (); 940*/ 941 942 943 // 944 945 946 947 // set in this order so Moon motor steps each second until 60 (0) 948 /* 949 if ( moonphase == 60 ) // was 61 950 { 951 // delay(100); // add delay so seconds mtor can operate again in the same second 952 moonmotor (); // function steps moon motor 953 // moonphase = moonphase + 1; 954 lcd.setCursor(5,2); //Start at character on line 2 955 lcd.print(" "); // Blank old moon phase 956 moonphase = 0; //resets moonphase count so it displays day 1 (2/60th)on the dial 957 moonphasedisp = 0; //resets moonphase LCD count so it displays day 1 (2/60th)on the dial 958 // mooncountSec = 1; 959 960 } 961 */ 962 /* 963 if ( moonphase == 60 ) 964 { 965 // delay(100); // add delay so seconds mtor can operate again in the same second 966 moonmotor (); // function steps moon motor 967 moonphase = moonphase + 1; 968 } 969 970 */ 971 972 973 // steps moon phase display to 0 and resets mooncountSec when moonphase is 59 and a half 974 975 976 // if ( mooncountSec == 43245 && moonphase == 59 ) 977 if ( moonphase == 59 ) 978 { 979 moonmotor (); // function steps moon motor 980 lcd.setCursor(5,2); //Start at character on line 2 981 lcd.print(" "); // Blank old moon phase 982 983 // moonphase = moonphase + 1; 984 // moonphasedisp = moonphasedisp + 1; 985 986 moonphase = 0; //resets moonphase count so it displays day 1 (2/60th)on the dial 987 moonphasedisp = 0; //resets moonphase LCD count so it displays day 1 (2/60th)on the dial 988 mooncountSec = 1; 989 } 990 991 992 if ( mooncountSec == 43245 ) 993 994 { 995 moonmotor (); // function steps moon motor 996 moonphase = moonphase + 1; 997 } 998 999 1000 // steps moon phase display and resets mooncountSec after 86490 1 sec pulses (1 day 1min 25sec) 1001 else if ( mooncountSec >= 86490 ) 1002 1003 { 1004 moonmotor (); // function steps moon motor 1005 moonphase = moonphase + 1; 1006 moonphasedisp = moonphasedisp + 1; 1007 1008 mooncountSec = 1; 1009 } 1010 1011 1012 1013 1014 //if ( mooncountSec == 5 ) 1015 // turn off Moon motor unless stepping 1016 if ( ( mooncountSec > 5 && mooncountSec < 43240 ) || ( mooncountSec > 43250 && mooncountSec < 86485 ) && digitalRead (moonphaseAdv) == LOW && digitalRead (mooncountSecAdv) == LOW ) 1017 { 1018 Serial.println("Moon Motor Off "); 1019 1020 1021 digitalWrite(moon01, LOW); // set the quartz motor drive 7 pin LOW 1022 digitalWrite(moon02, LOW); // set the quartz motor drive 8 pin LOW 1023 } 1024 else 1025 { 1026 Serial.println("Moon Motor On "); 1027 } 1028 1029 1030 lcd.setCursor(0,2); //Start at character 0 on line 2 1031 lcd.print("Moon "); 1032 lcd.print(moonphasedisp); 1033 1034 lcd.setCursor(7,2); //Start at character on line 2 1035 lcd.print(" "); 1036 //lcd.print(mooncountSec); 1037 moonh(h); // add leading 0 if less than 10 1038 lcd.print (h); 1039 lcd.setCursor(10,2); //Start at character on line 2 1040 lcd.print (":"); 1041 moonm(m); // add leading 0 if less than 10 1042 lcd.print (m); 1043 lcd.setCursor(13,2); //Start at character on line 2 1044 lcd.print (":"); 1045 moons(s); // add leading 0 if less than 10 1046 lcd.print (s); 1047 1048 1049 1050 Serial.print("Moon Count "); 1051 Serial.println(mooncountSec); 1052 1053 Serial.print("Moon Phase "); 1054 Serial.println(moonphase); 1055 1056 Serial.print("Moon Phase Disp "); 1057 Serial.println(moonphasedisp); 1058 1059 // End Moon Phase Dial Display 1060 //------------------------------------------------------------------------------------------- 1061 1062 // Moon control switches 1063 1064 // New Moon reset 1065 if ( digitalRead (moonReset) == HIGH ) 1066 { 1067 //clear LCD first 1068 lcd.setCursor(5,2); //Start at character on line 2 1069 lcd.print(" "); // Blank old moon phase 1070 lcd.setCursor(8,2); //Start at character 5 on line 2 1071 1072 lcd.print(" "); // blanks mooncountSec 1073 //mooncountSec = 1; //resets mooncountSec for new Moon 1074 mooncountSec = 1; //resets mooncountSec for new Moon test 1075 moonphase = 0; // resets moonphase for new Moon 1076 moonphasedisp = 0; // resets moonphase for new Moon 1077 } 1078 1079 // Moon dialdisplay manual advance 1080 if ( digitalRead (moondisAdv) == HIGH ) 1081 { 1082 moonmotor (); // function steps moon motor 1083 } 1084 1085 // Moon phase LCD display manual advance 1086 if ( digitalRead (moonphaseAdv) == HIGH && moonphase > 59 ) // reset moonphase and moonphasedisp when moonphasedisp goes over 59 1087 { 1088 lcd.setCursor(5,2); //Start at character on line 2 1089 lcd.print(" "); // Blank old moon phase 1090 moonphase = 0; //resets moonphase for new Moon 1091 moonphasedisp = 0; //resets moonphase for new Moon 1092 mooncountSec = 1; // resets moonphase for new Moon 1093 } 1094 1095 else if ( digitalRead (moonphaseAdv) == HIGH ) 1096 { 1097 moonphase = moonphase + 2; 1098 moonphasedisp = moonphasedisp + 1; 1099 mooncountSec = 1; 1100 } 1101 1102 //------------------------------Test 1103 1104 // Moon count LCD display of H M S 1105 if ( digitalRead (mooncountSecAdv) == HIGH && mooncountSec > 43244 && mooncountSec <= 44709 ) 1106 { 1107 //add 1 to moonphase 1108 moonphase = moonphase + 1; 1109 mooncountSec = mooncountSec + 1465; 1110 1111 } 1112 1113 else if ( digitalRead (mooncountSecAdv) == HIGH && mooncountSec >= 86490 ) // resets mooncount sec 1114 { 1115 // resets mooncount sec adds 1 to moonphse and moonphsedisp to keep them in sync 1116 mooncountSec = 1; 1117 moonphase = moonphase + 1; 1118 moonphasedisp = moonphasedisp + 1; 1119 1120 } 1121 1122 else if ( digitalRead (mooncountSecAdv) == HIGH ) 1123 { 1124 mooncountSec = mooncountSec + 1465; 1125 1126 } 1127 1128 /* 1129 1130 //------------------------------------End test 1131 1132 // Moon count LCD display of H M S 1133 1134 if ( digitalRead (mooncountSecAdv) == HIGH ) 1135 { 1136 mooncountSec = mooncountSec + 1465; 1137 1138 } 1139 1140 */ 1141 1142 1143 // End Moon control switches 1144 //------------------------------------------------ 1145 // LCD Display Switch 1146 if ( digitalRead (LCDdispCtrl) == LOW ) 1147 { 1148 lcd.noDisplay(); //LCD display off 1149 lcd.noBacklight(); // LCD backlight off 1150 } 1151 else 1152 { 1153 lcd.display(); //display on 1154 lcd.backlight(); // LCD backlight on 1155 } 1156 // LCD Display Switch 1157//--------------------------------------------------- 1158 1159 1160 // 15 second clock pulses 1161 if ((retardOn == 0 && pulseOn ==0) && (seconds == 0 || seconds == 15 || seconds == 30 || seconds == 45 )) // will only pulse if retardOn = 0 ( not in winter retard mode) 1162 { 1163 hrminmotor(); // function steps hr min motor 1164 1165 } 1166// Step hr min motor every second 1167 else if ( digitalRead (step15) == HIGH ) 1168 { 1169 hrminmotor(); // function steps hr min motor 1170 } 1171 1172 1173 else if ((retardOn == 0 && pulseOn ==0) && (seconds != 0 || seconds != 15 || seconds !=30 || seconds != 45)) // will only pulse if retardOn = 0 ( not in winter retard mode 1174 { 1175 digitalWrite(hrmin01, LOW); // set the hr min motor drive 1 pin LOW 1176 digitalWrite(hrmin02, LOW); // set the hr min motor drive 2 pin LOW 1177 } 1178 1179 1180 1181 1182 // end 15 second clock pulses 1183 1184} 1185 1186 1187 1188 1189 1190 1191void secondsmotor (){ 1192 1193 if (quartzmotor1 == LOW) 1194 { 1195 quartzmotor1 = HIGH; 1196 } 1197 else 1198 quartzmotor1 = LOW; 1199 { 1200 digitalWrite(quartz01, quartzmotor1); // set the quartz motor drive 7 pin 1201 1202 } 1203 1204 if (quartzmotor2 == HIGH) 1205 { 1206 quartzmotor2 = LOW; 1207 } 1208 else 1209 quartzmotor2 = HIGH; 1210 { 1211 digitalWrite(quartz02, quartzmotor2); // set the quartz motor drive 8 pin 1212 1213 } 1214 1215} 1216 1217 1218void secondsmotorAdvance (){ 1219 1220 1221 digitalWrite(quartz01, HIGH); // set the quartz motor drive 7 pin 1222 1223 digitalWrite(quartz02, LOW); // set the quartz motor drive 8 pin 1224 1225 1226 Serial.print("quartzmotor1 "); 1227 Serial.println(quartzmotor1); 1228 Serial.print("quartzmotor2 "); 1229 Serial.println(quartzmotor2); 1230delay(200); // add delay so seconds mtor can operate again in the same second 1231 1232 digitalWrite(quartz01, LOW); // set the quartz motor drive 7 pin 1233 1234 digitalWrite(quartz02, HIGH); // set the quartz motor drive 8 pin 1235 1236 1237 1238 Serial.print("quartzmotor1 "); 1239 Serial.println(quartzmotor1); 1240 Serial.print("quartzmotor2 "); 1241 Serial.println(quartzmotor2); 1242delay(100); // add delay so seconds mtor can operate again in the same second 1243 1244 } 1245//step Moon motor 1246void moonmotor (){ 1247 1248 if (moonmotor1 == LOW) 1249 { 1250 moonmotor1 = HIGH; 1251 } 1252 else 1253 moonmotor1 = LOW; 1254 { 1255 digitalWrite(moon01, moonmotor1); // set the quartz motor drive 7 pin 1256 1257 } 1258 1259 if (moonmotor2 == HIGH) 1260 { 1261 moonmotor2 = LOW; 1262 } 1263 else 1264 moonmotor2 = HIGH; 1265 { 1266 digitalWrite(moon02, moonmotor2); // set the quartz motor drive 8 pin 1267 1268 } 1269 1270} 1271 1272//step hour min 15 second motor 1273void hrminmotor (){ 1274 1275 if (hrminmotor1 == LOW) 1276 { 1277 hrminmotor1 = HIGH; 1278 } 1279 else 1280 hrminmotor1 = LOW; 1281 { 1282 digitalWrite(hrmin01, hrminmotor1); // set the quartz motor drive 7 pin 1283 1284 } 1285 1286 if (hrminmotor2 == HIGH) 1287 { 1288 hrminmotor2 = LOW; 1289 } 1290 else 1291 hrminmotor2 = HIGH; 1292 { 1293 digitalWrite(hrmin02, hrminmotor2); // set the quartz motor drive 8 pin 1294 1295 } 1296 1297} 1298 1299 1300 1301// ################################################################################ 1302/* 1303void segIntensity(int intensity){ 1304 1305 if(intensity < 10) 1306 lcd.print("0"); // Print hour on first line 1307 lcd.print(intensity); 1308} 1309*/ 1310// end 1311 1312void advance(int pulsecount){ // leading 0 on pulse count 1313 if (pulsecount < 100) 1314 1315 lcd.print("0"); 1316 1317} 1318 1319void advancetens(int pulsecount){ // leading 0 on pulse count 1320 if (pulsecount <10) 1321 1322 lcd.print("0"); 1323 1324} 1325//****************************** 1326 1327void retard(int retardcount){ // leading 0 on pulse count 1328 if (retardcount < 100) 1329 1330 lcd.print("0"); 1331 1332} 1333 1334void retardtens(int retardcount){ // leading 0 on pulse count 1335 if (retardcount <10) 1336 1337 lcd.print("0"); 1338 1339} 1340 1341 1342 1343 1344void monthzero(int monthval) { // leading zero on month value 1345 if (monthval < 10) 1346 1347 lcd.print("0"); // Print hour on first line 1348 lcd.print(monthval); 1349} 1350 1351 1352void dayzero(int dayval) { // leading zero on day value 1353 if (dayval < 10) 1354 1355 lcd.print("0"); // Print hour on first line 1356 lcd.print(dayval); 1357} 1358 1359 1360 1361 1362void blankrow3() { 1363 lcd.setCursor(0,3); 1364 lcd.print(" "); 1365} 1366 1367 1368 1369 1370 1371void signalmatch() { 1372 1373 signalQual = DCF77_Clock::get_prediction_match(); 1374 if(signalQual == 255 || signalQual == 0 ) 1375 { 1376 signalQual = 00; 1377 } 1378 else 1379 { 1380 signalQual = signalQual * 2; 1381 } 1382 lcd.setCursor(0,3); 1383 lcd.print("Sig Match "); 1384 lcd.print(signalQual); 1385 lcd.print("%"); 1386} 1387 1388 1389 1390void precision() { 1391 lcd.setCursor(0,3); 1392 lcd.print("Accuracy "); 1393 lcd.print(DCF77_Frequency_Control::get_confirmed_precision()); 1394 lcd.print("Hz "); 1395} 1396/* 1397void freqadj() { 1398 lcd.setCursor(0,3); 1399 // lcd.print("Qtz "); 1400 lcd.print(16000000L - DCF77_1_Khz_Generator::read_adjustment()); 1401 lcd.print("Hz"); 1402} 1403*/ 1404 1405// add leading zero on moon h 1406void moonh(int h){ // leading 0 on pulse count 1407 if (h <10) 1408 1409 lcd.print("0"); 1410 1411} 1412 1413// add leading zero on moon m 1414void moonm(int m){ // leading 0 on pulse count 1415 if (m <10) 1416 1417 lcd.print("0"); 1418 1419} 1420 1421// add leading zero on moon s 1422void moons(int s){ // leading 0 on pulse count 1423 if (s <10) 1424 1425 lcd.print("0"); 1426 1427} 1428[/code]
"Atomic" Longcase Clock Arduino Code v16
arduino
Arduino Code v16 Requires the following libraries dcf77.h Note this clock uses Udo Kleins Release 3 library download here DCF77 Release 3 LiquidCrystal_I2C.h Wire.h
1[code] 2/* 3v16 coded to use Udo Klein's v3 library https://github.com/udoklein/dcf77/releases/tag/v3.0.0 4v15 5 remove moonphase advance fast add mooncountSec advance by 1465 (1/60th phase) 6 7 8 Longcase Clock 9 http://www.brettoliver.org.uk 10 11 Copyright 2014 Brett 12 Oliver 13 14 This program is free software: you can redistribute it and/or modify 15 16 it under the terms of the GNU General Public License as published by 17 the 18 Free Software Foundation, either version 3 of the License, or 19 (at your option) 20 any later version. 21 22 This program is distributed in the hope that it will 23 be useful, 24 but WITHOUT ANY WARRANTY; without even the implied warranty of 25 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 GNU General 28 Public License for more details. 29 30 You should have received a copy of the 31 GNU General Public License 32 along with this program. If not, see http://www.gnu.org/licenses/ 33 34 35 36 Based on the DCF77 library by Udo Klein 37 http://blog.blinkenlight.net/experiments/dcf77/dcf77-library/ 38 39 http://blog.blinkenlight.net/experiments/dcf77/simple-clock/ 40 41*/ 42 43 44#include 45 <dcf77.h> 46#include <LiquidCrystal_I2C.h> 47#include <Wire.h> 48using namespace 49 Internal; //v3 50 51 52/* we always wait a bit between updates of the display 53 */ 54unsigned long delaytime=250; 55//********************** 56// set the LCD 57 address to 0x27 for a 20 chars 4 line display 58// Set the pins on the I2C chip 59 used for LCD connections: 60// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol 61LiquidCrystal_I2C 62 lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address 63 64 65//********************** 66 67const 68 uint8_t dcf77_analog_sample_pin = 5; 69const uint8_t dcf77_sample_pin = A1; // 70 A5 == d19 (DFC77 signal)changed from A5 71const uint8_t dcf77_inverted_samples 72 = 0; 73const uint8_t dcf77_analog_samples = 0; 74const uint8_t dcf77_monitor_led 75 = A0; // v3 76//const uint8_t dcf77_monitor_pin = A0; // A4 == d18 changed 77 from A4 removed v3 78uint8_t ledpin(const uint8_t led){ //v3 79 return led; //v3 80} 81 //v3 82 83const int8_t timezone_offset = -1; // GB is one hour behind CET/CEST 84 85//********************* 86 87 88int 89 retardOn = 0; 90 91//int infraredSwval = 0; // infrared value 92//int infraredSw 93 = A3; // set A3 to input ( pin 13) 94int retardcount = 0; 95int pulsecount = 0; 96 // pulse counts upto required number to step forward 1 hour 97int retardSw = 13; 98 // winter retard switch pin 9 99int retardSwval = 0; // value of retardSw 100int 101 advanceSw = 9; // summer advance switch pin 13 102int advanceSwval = 0; // value 103 of advanceSw 104int pulseOn = 0; // 0 pulse off 1 pulse on (summer winter pulsing 105int 106 summertest = 0; // equals 1 for summertime and 0 for wintertime 107int summerwinter 108 = 0; // summer winter toggle 109int extracount = 0; // where quartz seconds needs 110 to miss a pulse 111int hourextra = 00; // hour last miss pulse variable 112int dayextra 113 = 00; // day last miss pulse variable 114int monthextra = 00; // month last miss 115 pulse variable 116int minuteextra = 00; // minute last miss pulse variable 117int 118 secondextra = 00; // second last miss pulse variable 119int yearextra = 00; 120 121 122 123int 124 secondsnow = 0; // previous second 125int yearmiss = 00; 126int daymiss = 00; // 127 day last extra pulse variable 128int monthmiss = 00; // month last extra pulse variable 129int 130 secsmiss = 0; // works out is seconds need to an extra pulse or miss a pulse 131int 132 misscount = 0; // 1 ok 0 needs to miss a pulse 1 needs an extra pulse 133int hourmiss 134 = 00; // hour last extra pulse variable 135int minutemiss = 00; // minute last extra 136 pulse variable 137int secondmiss = 00; // second last extra pulse variable 138int 139 signalQual = 0; // computed once per minute and indicates how well 140// the received 141 signal matches the locally synthesized reference signal max 50 142int monthval = 143 0; 144int dayval = 0; 145//int zero = 0; 146int years = 0; 147int months = 0; 148int 149 days = 0; 150 151int hours = 0; 152 153int minutes = 0; 154 155int seconds = 0; 156int 157 secsval = 0; 158int minsval = 0; 159int hourval = 0; 160int led15 = 2; //15 second 161 pulse 162 163int quartzmotor1 = HIGH; // ledState used to set the quartz motor 164 pin 7 initial state 165int quartzmotor2 = LOW; // ledState used to set the quartz 166 motor pin 8 initial state 167int quartz01 =7; // Quartz clock motor pulse 01 168int 169 quartz02 =8; // Quartz clock motor pulse 02 170int stepSecs =11; // when high 171 seconds are advanced 172 173int hrminmotor1 = HIGH; // ledState used 174 to set the quartz motor pin 1 initial state 175int hrminmotor2 = LOW; // 176 ledState used to set the quartz motor pin 2 initial state 177int hrmin01 =12; 178 // Quartz clock motor pulse 01 179int hrmin02 =2; // Quartz clock motor pulse 180 02 181 182 183//Moon Display 184unsigned long mooncountSec = 1; // counts every 185 sec until 43245 then moonphase is advanced by 1 186unsigned long moontime = 1; 187int 188 moonphase = 0; // advances 1 every 43245 secs and 86490 secs until 60 when it is 189 reset to 2 (moon dial advanced to 1) 190int moonphasedisp = 1; // advances 1 every 191 86490 secs until moonphase 60 when it is reset to 1 (moon dial advanced to 1) 192int 193 moondisAdv = 3; // advances moon phase display once per second 194int moonphaseAdv 195 = 4; //advances moon phase count once per second 196//int moonphaseAdvfast = 11; 197 //advances moon phase count 5 once per second 198int mooncountSecAdv = 11; //advances 199 mooncountSec 1465 once per second 200int moonReset = A3; // resets moon phase and 201 count to 1 new moon 202int moonmotor1 = HIGH; // ledState used to set 203 the quartz motor pin 5 initial state 204int moonmotor2 = LOW; // ledState 205 used to set the quartz motor pin 6 initial state 206int moon01 =5; // Moon clock 207 motor pulse 01 208int moon02 =6; // Moon clock motor pulse 02 209 210float h, 211 m; 212int s = 0; 213unsigned long over = 0; 214 215// End Moon Display 216int LCDdispCtrl 217 = A2; 218int step15 = 10; //step hour mins forward by 15 seconds 219 220//******************** 221 222namespace 223 Timezone { 224 uint8_t days_per_month(const Clock::time_t &now) { //v3 mod 225 226 switch (now.month.val) { 227 case 0x02: 228 // valid till 31.12.2399 229 230 // notice year mod 4 == year & 0x03 231 return 28 + ((now.year.val != 232 0) && ((bcd_to_int(now.year) & 0x03) == 0)? 1: 0); 233 case 0x01: case 234 0x03: case 0x05: case 0x07: case 0x08: case 0x10: case 0x12: return 31; 235 case 236 0x04: case 0x06: case 0x09: case 0x11: return 30; 237 238 default: return 0; 239 240 } 241 } 242 243 void adjust(Clock::time_t 244 &time, const int8_t offset) { //v3 mod 245 // attention: maximum supported offset 246 is +/- 23h 247 248 int8_t hour = BCD::bcd_to_int(time.hour) + offset; 249 250 251 if (hour > 23) { 252 hour -= 24; 253 uint8_t day = BCD::bcd_to_int(time.day) 254 + 1; 255 uint8_t weekday = BCD::bcd_to_int(time.weekday) + 1; //v3 256 if 257 (day > days_per_month(time)) { 258 day = 1; 259 uint8_t month = BCD::bcd_to_int(time.month); 260 261 ++month; 262 if (month > 12) { 263 month = 1; 264 uint8_t 265 year = BCD::bcd_to_int(time.year); 266 ++year; 267 if 268 (year > 99) { 269 year = 0; 270 } 271 time.year = BCD::int_to_bcd(year); 272 273 } 274 time.month = BCD::int_to_bcd(month); 275 } 276 277 time.day = BCD::int_to_bcd(day); 278 time.weekday = BCD::int_to_bcd(weekday); 279 //v3 280 } 281 282 if (hour < 0) { 283 hour += 24; 284 uint8_t day 285 = BCD::bcd_to_int(time.day) - 1; 286 uint8_t weekday = BCD::bcd_to_int(time.weekday) 287 - 1; //v3 288 if (day < 1) { 289 uint8_t month = BCD::bcd_to_int(time.month); 290 291 --month; 292 if (month < 1) { 293 month = 12; 294 int8_t 295 year = BCD::bcd_to_int(time.year); 296 --year; 297 if 298 (year < 0) { 299 year = 99; 300 } 301 time.year = BCD::int_to_bcd(year); 302 303 } 304 time.month = BCD::int_to_bcd(month); 305 day 306 = days_per_month(time); 307 } 308 time.day = BCD::int_to_bcd(day); 309 310 time.weekday = BCD::int_to_bcd(weekday); //v3 311 } 312 313 time.hour 314 = BCD::int_to_bcd(hour); 315 } 316} 317 318uint8_t sample_input_pin() { 319 const 320 uint8_t sampled_data = 321 dcf77_inverted_samples ^ (dcf77_analog_samples? (analogRead(dcf77_analog_sample_pin) 322 > 200) 323 : digitalRead(dcf77_sample_pin)); 324 325 //digitalWrite(dcf77_monitor_pin, 326 sampled_data); // removed v3 327 digitalWrite(ledpin(dcf77_monitor_led), sampled_data); 328 // v3 329 return sampled_data; 330} 331 332void setup() { 333 digitalWrite(led15, 334 HIGH); // turn 15 sec clocks off at start 335 336 337 lcd.begin(20,4); // initialize 338 the lcd for 20 chars 4 lines, turn on backlight 339 // using namespace Internal; 340 // v3 Removed 341 //************* 342 // lcd.backlight(); // backlight on not needed 343 as controlled by 7 MAX2719 344 lcd.setCursor(0,0); //Start at character 0 on line 345 0 346 lcd.print("DCF77 Longcase Clock"); 347 348 349 350 351 352 //*************** 353 354 Serial.begin(9600); 355 /* Serial.println(); 356 Serial.println(F(" DCF77 357 Longcase Clock ")); 358 Serial.println(F("(c) Brett Oliver 2014")); 359 360 Serial.println(F("http://www.brettoliver.org.uk")); 361 Serial.println(F("Based 362 on the DCF77 library by Udo Klein")); 363 Serial.println(F("www.blinkenlight.net")); 364 365 Serial.println(); 366 Serial.print(F("Sample Pin: ")); 367 Serial.println(dcf77_sample_pin); 368 369 Serial.print(F("Inverted Mode: ")); 370 Serial.println(dcf77_inverted_samples); 371 372 Serial.print(F("Analog Mode: ")); 373 Serial.println(dcf77_analog_samples); 374 375 Serial.print(F("Monitor Pin: ")); 376 Serial.println(dcf77_monitor_pin); 377 378 Serial.print(F("Timezone Offset:")); 379 Serial.println(timezone_offset); 380 381 Serial.println(); 382 Serial.println(); 383 Serial.println(F("Initializing...")); 384 385 */ 386 // pinMode(dcf77_monitor_pin, OUTPUT); // removed v3 387 388 pinMode(dcf77_sample_pin, 389 INPUT); 390 digitalWrite(dcf77_sample_pin, HIGH); 391 392 393 //******************* 394 395 396 //pinMode(led15, OUTPUT); 397 pinMode(quartz01, OUTPUT); 398 pinMode(quartz02, 399 OUTPUT); 400 pinMode(moon01, OUTPUT); 401 pinMode(moon02, OUTPUT); 402 pinMode(hrmin01, 403 OUTPUT); 404 pinMode(hrmin02, OUTPUT); 405 pinMode(ledpin(dcf77_monitor_led), 406 OUTPUT); // v3 407 408 409 //pinMode(17, INPUT); // infrared switch 410 pinMode(advanceSw,INPUT); 411 412 pinMode(retardSw,INPUT); 413 pinMode(moonphaseAdv,INPUT); 414 //pinMode(moonphaseAdvfast,INPUT); 415 416 pinMode(mooncountSecAdv,INPUT); 417 pinMode(moondisAdv,INPUT); 418 pinMode(moonReset,INPUT); 419 420 pinMode(LCDdispCtrl,INPUT); 421 pinMode(step15,INPUT); // 15 second (hour min) 422 man advance 423 // pinMode(stepSecs,INPUT); // secs man advance 424 425 426 //******************* 427 428 429 DCF77_Clock::setup(); 430 DCF77_Clock::set_input_provider(sample_input_pin); 431 432 433 434 // Wait till clock is synced, depending on the signal quality this may take 435 436 // rather long. About 5 minutes with a good signal, 30 minutes or longer 437 // 438 with a bad signal 439 440 441 442 443 for (uint8_t state = Clock::useless; 444 //v3 Mod 445 state == Clock::useless || state == Clock::dirty; //v3 Mod 446 447 state = DCF77_Clock::get_clock_state()) { 448 449 // wait for next sec 450 451 Clock::time_t now; //v3 mod 452 DCF77_Clock::get_current_time(now); 453 454 455 // render one dot per second while initializing 456 static uint8_t count 457 = 0; 458 Serial.print('.'); 459 ++count; 460 if (count == 60) { 461 count 462 = 0; 463 Serial.println(); 464 } 465 } 466} 467 468void paddedPrint(BCD::bcd_t 469 n) { 470 Serial.print(n.digit.hi); 471 Serial.print(n.digit.lo); 472} 473void 474 LCDpaddedPrint(BCD::bcd_t n) { 475 lcd.print(n.digit.hi); 476 lcd.print(n.digit.lo); 477 478} 479 480void loop() { 481 482 Clock::time_t now; //v3 mod 483 484 DCF77_Clock::get_current_time(now); 485 486 Timezone::adjust(now, timezone_offset); 487 488 489 if (now.month.val > 0) 490 { 491 492 493 //*********** 494 // get month & day values 495 dayval = 496 now.day.val, DEC; 497 monthval = now.month.val, DEC; 498 // Serial.print(" 499 day "); 500 // Serial.print(now.day.val, DEC); 501 // Serial.print(" month 502 "); 503 // Serial.print(now.month.val, DEC); 504 // Serial.print(' '); 505 506 // get month & day values 507 // Quartz clock driver 508 // toggle Quartz 509 drive 7 & 8 evey second 510 secsmiss = seconds - secondsnow; 511 512 if (secsmiss 513 ==-59 || secsmiss ==-60 && seconds ==0) // takes account of seconds rollover -59 514 or leap second -60 515 { 516 secsmiss = 1; 517 } 518 519 520 521 522 523 524 // If not andvancing seconds then use this (normal) 525 if (secsmiss >=1 && seconds 526 !=60) // if zero or less seconds pulse need to be missed. Leap second missed if 527 seconds = 60 528 { 529 secondsmotor (); // function steps quartz motor 530 531 } 532 533 534 535 536 if (secsmiss < 1 || seconds == 60) //records time of 537 extra sec second (quart motor needs to loose a second) 538 539 { 540 extracount 541 = extracount + 1; //increment extra count total (1sec needs to miss pulse) 542 hourextra 543 = hours; 544 minuteextra = minutes; 545 secondextra = seconds; 546 yearextra 547 = years; 548 monthextra = months; 549 dayextra = days; 550 551 } 552 553 554 555 if (secsmiss > 1) //records time of miss second (quart motor needs to add a 556 second) 557 { 558 misscount = misscount + 1; //increment Miss count total 559 (1sec has missed extra pulse) 560 hourmiss = hours; 561 minutemiss = minutes; 562 563 secondmiss = seconds; 564 yearmiss = years; 565 monthmiss = months; 566 567 daymiss = days; 568 569 } 570 571 572 573 secondsnow = seconds; 574 575 576 577 578 if (hours== 6 && minutes == 10 && seconds == 01) // resets miss second counter 579 to 0 at 6:10:01 580 { 581 misscount = 0; 582 extracount = 0; 583 } 584 585 586 587 // } 588 // Enable below to analize missed pulses on serial monitor 589 //Serial.print(" 590 "); 591 // Serial.print("secsmiss "); 592 // Serial.println(secsmiss); 593/* 594 595 596 Serial.print("Slow Seconds "); 597 Serial.print(misscount); 598 Serial.print(" 599 "); 600 Serial.print(hourmiss); 601 Serial.print(":"); 602 Serial.print(minutemiss); 603 604 Serial.print(":"); 605 Serial.print(secondmiss); 606 Serial.print(" 607 "); 608 Serial.print(daymiss); 609 Serial.print("/"); 610 Serial.print(monthmiss); 611 612 Serial.print("/"); 613 Serial.println(yearmiss); 614 615 616 Serial.print("Fast 617 Seconds "); 618 Serial.print(extracount); 619 Serial.print(" "); 620 Serial.print(hourextra); 621 622 Serial.print(":"); 623 Serial.print(minuteextra); 624 Serial.print(":"); 625 626 Serial.print(secondextra); 627 Serial.print(" "); 628 Serial.print(dayextra); 629 630 Serial.print("/"); 631 Serial.print(monthextra); 632 Serial.print("/"); 633 634 Serial.println(yearextra); 635 636 637*/ 638 639 640 641 642 // end missing 643 second pulse 644 645 // ################################################################################ 646 647 648 649 650 651 /* 652 Serial.println(F("confirmed_precision 653 [Hz], target_precision v,total_adjust [Hz], frequency [Hz]")); 654 Serial.print(DCF77_Frequency_Control::get_confirmed_precision()); 655 656 Serial.print(F(", ")); 657 Serial.print(DCF77_Frequency_Control::get_target_precision()); 658 659 Serial.print(F(", ")); 660 Serial.print(DCF77_1_Khz_Generator::read_adjustment()); 661 662 Serial.print(F(", ")); 663 Serial.print(16000000L - DCF77_1_Khz_Generator::read_adjustment()); 664 665 Serial.print(F(" Hz, ")); 666 667 */ 668 669 //*************** 670 671 // signal quality 672 673 // signalQual = DCF77_Clock::get_prediction_match(); 674 675 // if(signalQual == 255 || signalQual == 0 ) 676 // { 677 // signalQual 678 = 00; 679 // } 680 // else 681 //{ 682 // signalQual = (signalQual 683 * 2) -1; 684 //} 685 // Serial.print (" Signal Match "); 686 // Serial.print 687 (signalQual); 688 // Serial.print ("% "); 689 690 // display 7 segment intensity 691 value on LCD 692 // lcd.setCursor(0,2); 693 //lcd.print("7 Seg Int "); 694 695 // lcd.print("Brightness "); 696 // segIntensity(intensity); // adds leading 697 zero to 7 segment intensity 698 699 700 // end display 7 segment intensity 701 value on LCD 702 703 704 // ################################# 705 //LDR 706 start 707 708 // ldrValue = analogRead(ldr); 709 710 // Serial.print (" 711 LDR Value "); 712 // Serial.print (ldrValue, DEC); 713 // Serial.print (" 714 "); 715 // intensityValue(); 716 // Serial.print ("Intensity "); 717 // 718 Serial.print (intensity); 719 // Serial.print (" "); 720 721 //LDR 722 finish 723 //################################# 724 //Serial.print (now.second.val); 725 726 // Serial.print (" "); 727 lcd.setCursor(17,2); 728 //lcd.print(" Wait 729 "); 730 switch (DCF77_Clock::get_clock_state()) { 731 // case DCF77::useless: 732 Serial.print(F("useless ")); break; 733 case Clock::useless: //v3 mod 734 735 lcd.print(F(" Fail ")); 736 break; 737 // case DCF77::dirty: 738 Serial.print(F("dirty: ")); break; 739 // case DCF77::synced: Serial.print(F("synced: 740 ")); break; 741 // case DCF77::locked: Serial.print(F("locked: ")); break; 742 743 case Clock::dirty: //v3 mod 744 lcd.print(F("Dty")); 745 break; 746 747 case Clock::synced: //v3 Mod 748 lcd.print(F("Syn")); 749 break; 750 751 case Clock::locked: //v3 mod 752 lcd.print(F("Lck")); 753 break; 754 755 } 756 757 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 758 759 // Get hours minutes and seconds variables 760 hours = BCD::bcd_to_int(now.hour); 761 762 763 764 minutes = BCD::bcd_to_int(now.minute); 765 766 767 seconds = BCD::bcd_to_int(now.second); 768 769 770 years = BCD::bcd_to_int(now.year); 771 772 months = BCD::bcd_to_int(now.month); 773 774 775 days = BCD::bcd_to_int(now.day); 776 777 778 779 780 /* Serial.print (" 781 H,M,S "); 782 Serial.print (hours2); 783 784 Serial.print (hours1); 785 786 Serial.print (":"); 787 788 789 Serial.print (minutes2); 790 791 792 Serial.print (minutes1); 793 Serial.print (":"); 794 795 796 797 Serial.print (seconds2); 798 799 Serial.print (seconds1); 800 801 Serial.print (":"); 802 803 */ 804 lcd.setCursor(6,3); 805 806 807 808 809 // 7 segment 810 811 812 //**************** 813 814 lcd.setCursor(0,0); 815 816 817 LCDpaddedPrint(now.hour); 818 lcd.print(":"); 819 LCDpaddedPrint(now.minute); 820 821 lcd.print(":"); 822 LCDpaddedPrint(now.second); 823 lcd.print(" "); 824 825 826 LCDpaddedPrint(now.day); 827 lcd.print("/"); 828 LCDpaddedPrint(now.month); 829 830 lcd.print("/"); 831 lcd.print("20"); 832 LCDpaddedPrint(now.year); 833 834 835 836 837 838 839 //**************** 840 /* 841 842 paddedPrint(now.hour); 843 Serial.print(':'); 844 845 paddedPrint(now.minute); 846 Serial.print(':'); 847 paddedPrint(now.second); 848 849 Serial.print(' '); 850 851 paddedPrint(now.day); 852 Serial.print('/'); 853 854 paddedPrint(now.month); 855 Serial.print('/'); 856 Serial.print(F("20")); 857 858 paddedPrint(now.year); 859 860 861 */ 862 863 864 865 // const 866 int8_t offset_to_utc = timezone_offset + now.uses_summertime? 2: 1; 867 const 868 int8_t offset_to_utc = timezone_offset + (now.uses_summertime? 2: 1); 869 870 // 871 Serial.print(F(" GMT")); 872 873 summertest = (abs(offset_to_utc)); // equals 874 1 if summertime and 2 if wintertime 875 876 if (summertest ==2) // if wintertime 877 make summertest =0 878 { 879 summertest = 0; 880 } 881 882 //************** 883 884 lcd.setCursor(15,3); 885 lcd.print("GMT+"); 886 // UTCcheck= offset_to_utc; 887 888 // lcd.print(UTCcheck); 889 lcd.print(summertest); 890 891 } 892 893 894 895 // Quality display on LCD 896 if (seconds >= 0 && seconds <= 10) 897 { 898 899 signalmatch(); // Quality factor 900 } 901 902 else if (seconds == 11) 903 904 { 905 blankrow3(); //Blanks row 3 906 } 907 908else if (seconds == 12) 909 910 { 911 lcd.setCursor(0,3); 912 lcd.print("Quartz "); 913 } 914 else 915 if (seconds >= 13 && seconds <= 23) 916 { 917 precision(); //quartz confirmed 918 and target precision 919 } 920 921 else if (seconds == 24) 922 { 923 blankrow3(); 924 //Blanks row 3 925 } 926 927 else if (seconds >=25 && seconds <= 35 ) 928 { 929 930 lcd.setCursor(0,3); 931 932 signalmatch(); // Quality factor 933 } 934 935 936 else if (seconds == 36) 937 { 938 blankrow3(); //Blanks row 3 939 } 940 941 942 else if (seconds == 37) 943 { 944 lcd.setCursor(0,3); 945 lcd.print("Quartz 946 "); 947 } 948 else if (seconds >= 38 && seconds <= 48) 949 { 950 precision(); 951 //quartz confirmed and target precision 952 } 953 954 else if (seconds == 49) 955 956 { 957 blankrow3(); //Blanks row 3 958 } 959 960 else if (seconds >=50 && seconds 961 <= 59 ) 962 { 963 lcd.setCursor(0,3); 964 965 signalmatch(); // Quality 966 factor 967 } 968 969 970 // End of Quality display on LCD 971 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ 972 973 974 975 976 // winter to summer change // clocks go forward################################# 977 978 advanceSwval = digitalRead(advanceSw); // read advanceSw switch 979 // 240 980 x 15 sec pulses need to be added to normal 15 second pulses to advance by 1 hour 981 982 if (pulsecount < 240 && (seconds == 0 || seconds == 15 || seconds == 30 || seconds 983 == 45) && (advanceSwval == 1 || pulseOn == 1)) 984 // summertest is 1 in summertime 985 and 0 in wintertime advance on 00 ,15,30 &45 secs does not advance pulse count 986 987 988 { 989 // sumwinSwval = 1; 990 pulseOn = 1; 991 //Serial.println(" 15 992 second test "); 993 994 hrminmotor(); // function steps hr min motor 995 996 997 } 998 999 else if (pulsecount < 240 && (advanceSwval == 1 || pulseOn == 1)) // 1000 summertest is 1 in summertime and 0 in wintertime 1001 1002 { 1003 // sumwinSwval 1004 = 1; 1005 pulseOn = 1; 1006 pulsecount = pulsecount + 1; 1007 1008 hrminmotor(); 1009 // function steps hr min motor 1010 } 1011 1012 else 1013 { 1014 digitalWrite(hrmin01, 1015 LOW); // set the hr min motor drive 1 pin LOW 1016 digitalWrite(hrmin02, LOW); // 1017 set the hr min motor drive 2 pin LOW 1018 pulseOn = 0; // 1019 // sumwinSwval 1020 = 0; 1021 pulsecount = 0; 1022 } 1023 1024 // end winter to summer chaange advance 1025 ############################## 1026 1027 1028 1029 // summer to winter change clocks 1030 go back################################# 1031 retardSwval = digitalRead(retardSw); 1032 // read retardSw switch 1033 1034 if (retardcount < 240 && retardSwval == 1) // 1035 240 x 15 sec pulses need to be ignored to retard by 1 hour 1036 { 1037 retardOn 1038 = 1; 1039 } 1040 1041 else if (retardcount < 240 && (seconds == 0 || seconds == 15 1042 || seconds == 30 || seconds == 45) && (retardSwval == 1 || retardOn == 1)) 1043 { 1044 1045 retardOn = 1; 1046 retardcount = retardcount + 1; 1047 } 1048 1049 else if 1050 (retardcount < 240 && (retardSwval == 1 || retardOn == 1)) 1051 { 1052 retardOn 1053 = 1; 1054 1055 } 1056 1057 else 1058 { 1059 retardOn = 0; 1060 // sumwinSwval 1061 = 0; 1062 retardcount = 0; 1063 } 1064 1065 1066 1067 // end summer to winter change 1068 clocks go back################################# 1069 1070 1071 1072 1073 1074 // Display 1075 of Title and 30 second pulse correction on row 01 ############################## 1076 1077 1078 if (retardcount > 0 || retardcount == 119 ) //Prints correction pulse number 1079 1080 { 1081 lcd.setCursor(0,1); 1082 lcd.print("Winter Retard "); 1083 lcd.setCursor(15,1); 1084 1085 1086 1087 1088 retard(retardcount); // add leading 0 <99 1089 retardtens(retardcount); // 1090 add another leading 0 less than 10 1091 lcd.print(retardcount); 1092 } 1093 else 1094 if (retardcount == 240 ) //Prints blank when correction pulse is on last number 1095 1096 { 1097 lcd.setCursor(0,1); 1098 lcd.print(" "); 1099 1100 // lcd.print(retardcount); 1101 } 1102 1103 1104 else if (seconds >= 0 && seconds 1105 <= 5 && pulsecount == 0) // Ignored while clock is correcting forward or retarding 1106 1107 { 1108 1109 lcd.setCursor(0,1); //Start at character 0 on line 0 1110 lcd.print("DCF77 1111 Longcase Clock"); 1112 1113 } 1114 else if(seconds > 05 && seconds <= 10 && 1115 pulsecount == 0) // Ignored while clock is correcting forward or retarding 1116 { 1117 1118 lcd.setCursor(0,1); //Start at character 0 on line 0 1119 //lcd.print(" DCF77 1120 Master Clock "); 1121 lcd.print(" Brett Oliver v16.0 "); 1122 } 1123 1124 else 1125 if(seconds == 11 && pulsecount == 0) // Ignored while clock is correcting forward 1126 or retarding 1127 { 1128 lcd.setCursor(0,1); //Start at character 0 on line 0 1129 1130 1131 lcd.print(" "); 1132 } 1133 1134 else if(seconds > 11 && 1135 seconds <= 13 && pulsecount == 0) // Ignored while clock is correcting forward or 1136 retarding 1137 { 1138 lcd.setCursor(0,1); //Start at character 0 on line 0 1139 1140 1141 // lcd.print(" Pulses "); 1142 lcd.print(" 1 Second Clocks 1143 "); 1144 1145 } 1146 1147 1148 1149 else if(seconds > 13 && seconds <=59 && pulsecount 1150 == 0) // Ignored while clock is correcting forward or retarding 1151 { 1152 lcd.setCursor(0,1); 1153 //Start at character 0 on line 0 1154 lcd.print(" Slow "); // miss pulse detected 1155 so extra 1 second motor pulse added 1156 lcd.print(misscount); 1157 1158 lcd.print(" 1159 "); 1160 lcd.print(" Fast "); 1161 lcd.print(extracount); 1162 } 1163 1164 1165 else if (pulsecount > 0 || pulsecount == 239 ) //Prints correction pulse number 1166 1167 { 1168 lcd.setCursor(0,1); 1169 lcd.print("Summer Advance "); 1170 lcd.setCursor(15,1); 1171 1172 //lcd.print(pulsecount); 1173 1174 advance(pulsecount); // add leading 0 <99 1175 1176 advancetens(pulsecount); // add another leading 0 less than 10 1177 lcd.print(pulsecount); 1178 1179 } 1180 else if (pulsecount == 240 ) //Prints blank when correction pulse is on 1181 last number 1182 { 1183 lcd.setCursor(0,1); 1184 lcd.print(" "); 1185 1186 //lcd.print(pulsecount); 1187 } 1188 1189 1190 // sum win test print 1191 //sumwinSwval 1192 = digitalRead(sumwinSw); // read sumwinSw switch 1193 /* Serial.print(" Sum Win 1194 Pulse No "); 1195 Serial.print(pulsecount); 1196 Serial.print(" "); 1197 1198 1199 Serial.print("Sum Win SW "); 1200 Serial.print(sumwinSwval); 1201 Serial.print(" 1202 "); 1203 Serial.print("Pulse On "); 1204 Serial.print(pulseOn); 1205 Serial.print(" 1206 "); 1207 Serial.print("Retard On "); 1208 Serial.print(retardOn); 1209 Serial.print(" 1210 "); 1211 Serial.print("Retard Count "); 1212 Serial.print(retardcount); 1213 1214 Serial.print(" "); 1215 Serial.print("Summer Test "); 1216 Serial.print(summertest); 1217 1218 Serial.print(" "); 1219 */ 1220 1221 // end sum win test print 1222 // 1223 1224 1225 // winter to summer change // clocks go forward################################# 1226 1227 1228 // End Display of Title and 30 second pulse correction on row 01 ############################## 1229 1230 //----------------------------------------------------------------------- 1231 1232 // Moon Phase Dial Display 1233 mooncountSec = mooncountSec + 1; 1234 // moontime 1235 = 86490 - mooncountSec; //counts down to next phase change 1236 moontime = mooncountSec; 1237 // counts up to next phase change 1238 // calc/display hour min sec to next moon 1239 phase 1240 h = int (moontime/3600); 1241 over = moontime % 3600; 1242 m = int (over/60); 1243 1244 over = over % 60; 1245 s = int (over); 1246 /* 1247 Serial.print ("Sec Pulses: 1248 "); 1249 Serial.println (mooncountSec); 1250 Serial.print ("Sec Pulses: "); 1251 1252 Serial.println (moontime); 1253 1254 Serial.print ("Next Phase: "); 1255 Serial.print 1256 (h, 0); 1257 Serial.print ("h "); 1258 Serial.print (m, 0); 1259 Serial.print 1260 ("m "); 1261 Serial.print (s, 0); 1262 Serial.print ("s "); 1263 1264 Serial.println 1265 (); 1266*/ 1267 1268 1269 // 1270 1271 1272 1273 // set in this order so Moon 1274 motor steps each second until 60 (0) 1275 /* 1276 if ( moonphase == 60 ) // was 1277 61 1278 { 1279 // delay(100); // add delay so seconds mtor can operate again in 1280 the same second 1281 moonmotor (); // function steps moon motor 1282 // moonphase 1283 = moonphase + 1; 1284 lcd.setCursor(5,2); //Start at character on line 2 1285 lcd.print(" 1286 "); // Blank old moon phase 1287 moonphase = 0; //resets moonphase count so 1288 it displays day 1 (2/60th)on the dial 1289 moonphasedisp = 0; //resets moonphase 1290 LCD count so it displays day 1 (2/60th)on the dial 1291 // mooncountSec = 1; 1292 1293 1294 } 1295 */ 1296 /* 1297 if ( moonphase == 60 ) 1298 { 1299 // delay(100); 1300 // add delay so seconds mtor can operate again in the same second 1301 moonmotor 1302 (); // function steps moon motor 1303 moonphase = moonphase + 1; 1304 } 1305 1306 1307 */ 1308 1309 1310 // steps moon phase display to 0 and resets mooncountSec when 1311 moonphase is 59 and a half 1312 1313 1314 // if ( mooncountSec == 43245 && moonphase 1315 == 59 ) 1316 if ( moonphase == 59 ) 1317 { 1318 moonmotor (); // function steps 1319 moon motor 1320 lcd.setCursor(5,2); //Start at character on line 2 1321 lcd.print(" 1322 "); // Blank old moon phase 1323 1324 // moonphase = moonphase + 1; 1325 1326 // moonphasedisp = moonphasedisp + 1; 1327 1328 moonphase = 0; //resets moonphase 1329 count so it displays day 1 (2/60th)on the dial 1330 moonphasedisp = 0; //resets 1331 moonphase LCD count so it displays day 1 (2/60th)on the dial 1332 mooncountSec = 1333 1; 1334 } 1335 1336 1337 if ( mooncountSec == 43245 ) 1338 1339 { 1340 moonmotor 1341 (); // function steps moon motor 1342 moonphase = moonphase + 1; 1343 } 1344 1345 1346 1347 // steps moon phase display and resets mooncountSec after 86490 1 sec pulses 1348 (1 day 1min 25sec) 1349 else if ( mooncountSec >= 86490 ) 1350 1351 { 1352 moonmotor 1353 (); // function steps moon motor 1354 moonphase = moonphase + 1; 1355 moonphasedisp 1356 = moonphasedisp + 1; 1357 1358 mooncountSec = 1; 1359 } 1360 1361 1362 1363 1364 1365 //if ( mooncountSec == 5 ) 1366 // turn off Moon motor unless stepping 1367 if 1368 ( ( mooncountSec > 5 && mooncountSec < 43240 ) || ( mooncountSec > 43250 && mooncountSec 1369 < 86485 ) && digitalRead (moonphaseAdv) == LOW && digitalRead (mooncountSecAdv) 1370 == LOW ) 1371 { 1372 Serial.println("Moon Motor Off "); 1373 1374 1375 digitalWrite(moon01, 1376 LOW); // set the quartz motor drive 7 pin LOW 1377 digitalWrite(moon02, LOW); // 1378 set the quartz motor drive 8 pin LOW 1379 } 1380 else 1381 { 1382 Serial.println("Moon 1383 Motor On "); 1384 } 1385 1386 1387 lcd.setCursor(0,2); //Start at character 1388 0 on line 2 1389 lcd.print("Moon "); 1390 lcd.print(moonphasedisp); 1391 1392 1393 lcd.setCursor(7,2); //Start at character on line 2 1394 lcd.print(" "); 1395 1396 //lcd.print(mooncountSec); 1397 moonh(h); // add leading 0 if less than 10 1398 1399 lcd.print (h); 1400 lcd.setCursor(10,2); //Start at character on line 2 1401 1402 lcd.print (":"); 1403 moonm(m); // add leading 0 if less than 10 1404 lcd.print 1405 (m); 1406 lcd.setCursor(13,2); //Start at character on line 2 1407 lcd.print (":"); 1408 1409 moons(s); // add leading 0 if less than 10 1410 lcd.print (s); 1411 1412 1413 1414 1415 Serial.print("Moon Count "); 1416 Serial.println(mooncountSec); 1417 1418 1419 Serial.print("Moon Phase "); 1420 Serial.println(moonphase); 1421 1422 1423 Serial.print("Moon Phase Disp "); 1424 Serial.println(moonphasedisp); 1425 1426 1427 // End Moon Phase Dial Display 1428 //------------------------------------------------------------------------------------------- 1429 1430 1431 // Moon control switches 1432 1433 // New Moon reset 1434 if ( digitalRead (moonReset) 1435 == HIGH ) 1436 { 1437 //clear LCD first 1438 lcd.setCursor(5,2); //Start at character 1439 on line 2 1440 lcd.print(" "); // Blank old moon phase 1441 lcd.setCursor(8,2); 1442 //Start at character 5 on line 2 1443 1444 lcd.print(" "); // blanks 1445 mooncountSec 1446 //mooncountSec = 1; //resets mooncountSec for new Moon 1447 mooncountSec 1448 = 1; //resets mooncountSec for new Moon test 1449 moonphase = 0; // resets moonphase 1450 for new Moon 1451 moonphasedisp = 0; // resets moonphase for new Moon 1452 } 1453 1454 1455 // Moon dialdisplay manual advance 1456 if ( digitalRead (moondisAdv) == HIGH 1457 ) 1458 { 1459 moonmotor (); // function steps moon motor 1460 } 1461 1462 // Moon 1463 phase LCD display manual advance 1464 if ( digitalRead (moonphaseAdv) == HIGH && 1465 moonphase > 59 ) // reset moonphase and moonphasedisp when moonphasedisp goes over 1466 59 1467 { 1468 lcd.setCursor(5,2); //Start at character on line 2 1469 lcd.print(" 1470 "); // Blank old moon phase 1471 moonphase = 0; //resets moonphase for new 1472 Moon 1473 moonphasedisp = 0; //resets moonphase for new Moon 1474 mooncountSec = 1; 1475 // resets moonphase for new Moon 1476 } 1477 1478 else if ( digitalRead (moonphaseAdv) 1479 == HIGH ) 1480 { 1481 moonphase = moonphase + 2; 1482 moonphasedisp = moonphasedisp 1483 + 1; 1484 mooncountSec = 1; 1485 } 1486 1487 //------------------------------Test 1488 1489 1490 // Moon count LCD display of H M S 1491 if ( digitalRead (mooncountSecAdv) 1492 == HIGH && mooncountSec > 43244 && mooncountSec <= 44709 ) 1493 { 1494 //add 1 1495 to moonphase 1496 moonphase = moonphase + 1; 1497 mooncountSec = mooncountSec + 1465; 1498 1499 1500 } 1501 1502 else if ( digitalRead (mooncountSecAdv) == HIGH && mooncountSec 1503 >= 86490 ) // resets mooncount sec 1504 { 1505 // resets mooncount sec adds 1 to 1506 moonphse and moonphsedisp to keep them in sync 1507 mooncountSec = 1; 1508 moonphase 1509 = moonphase + 1; 1510 moonphasedisp = moonphasedisp + 1; 1511 1512 } 1513 1514 else 1515 if ( digitalRead (mooncountSecAdv) == HIGH ) 1516 { 1517 mooncountSec = mooncountSec 1518 + 1465; 1519 1520 } 1521 1522 /* 1523 1524 //------------------------------------End 1525 test 1526 1527 // Moon count LCD display of H M S 1528 1529 if ( digitalRead (mooncountSecAdv) 1530 == HIGH ) 1531 { 1532 mooncountSec = mooncountSec + 1465; 1533 1534 } 1535 1536 1537 */ 1538 1539 1540 // End Moon control switches 1541 //------------------------------------------------ 1542 1543 // LCD Display Switch 1544 if ( digitalRead (LCDdispCtrl) == LOW ) 1545 { 1546 lcd.noDisplay(); 1547 //LCD display off 1548 lcd.noBacklight(); // LCD backlight off 1549 } 1550 else 1551 1552 { 1553 lcd.display(); //display on 1554 lcd.backlight(); // LCD backlight 1555 on 1556 } 1557 // LCD Display Switch 1558//--------------------------------------------------- 1559 1560 1561 1562 // 15 second clock pulses 1563 if ((retardOn == 0 && pulseOn ==0) && (seconds 1564 == 0 || seconds == 15 || seconds == 30 || seconds == 45 )) // will only pulse if 1565 retardOn = 0 ( not in winter retard mode) 1566 { 1567 hrminmotor(); // function 1568 steps hr min motor 1569 1570 } 1571// Step hr min motor every second 1572 else if 1573 ( digitalRead (step15) == HIGH ) 1574 { 1575 hrminmotor(); // function steps hr 1576 min motor 1577 } 1578 1579 1580 else if ((retardOn == 0 && pulseOn ==0) && (seconds 1581 != 0 || seconds != 15 || seconds !=30 || seconds != 45)) // will only pulse if 1582 retardOn = 0 ( not in winter retard mode 1583 { 1584 digitalWrite(hrmin01, LOW); 1585 // set the hr min motor drive 1 pin LOW 1586 digitalWrite(hrmin02, LOW); // set 1587 the hr min motor drive 2 pin LOW 1588 } 1589 1590 1591 1592 1593 // end 15 second 1594 clock pulses 1595 1596} 1597 1598 1599 1600 1601 1602 1603void secondsmotor (){ 1604 1605 1606 if (quartzmotor1 == LOW) 1607 { 1608 quartzmotor1 = HIGH; 1609 } 1610 else 1611 1612 quartzmotor1 = LOW; 1613 { 1614 digitalWrite(quartz01, quartzmotor1); // set 1615 the quartz motor drive 7 pin 1616 1617 } 1618 1619 if (quartzmotor2 == HIGH) 1620 1621 { 1622 quartzmotor2 = LOW; 1623 } 1624 else 1625 quartzmotor2 = HIGH; 1626 1627 { 1628 digitalWrite(quartz02, quartzmotor2); // set the quartz motor drive 8 1629 pin 1630 1631 } 1632 1633} 1634 1635 1636void secondsmotorAdvance (){ 1637 1638 1639 1640 digitalWrite(quartz01, HIGH); // set the quartz motor drive 7 pin 1641 1642 digitalWrite(quartz02, 1643 LOW); // set the quartz motor drive 8 pin 1644 1645 1646 Serial.print("quartzmotor1 1647 "); 1648 Serial.println(quartzmotor1); 1649 Serial.print("quartzmotor2 "); 1650 1651 Serial.println(quartzmotor2); 1652delay(200); // add delay so seconds mtor can 1653 operate again in the same second 1654 1655 digitalWrite(quartz01, LOW); // set the 1656 quartz motor drive 7 pin 1657 1658 digitalWrite(quartz02, HIGH); // set the quartz 1659 motor drive 8 pin 1660 1661 1662 1663 Serial.print("quartzmotor1 "); 1664 Serial.println(quartzmotor1); 1665 1666 Serial.print("quartzmotor2 "); 1667 Serial.println(quartzmotor2); 1668delay(100); 1669 // add delay so seconds mtor can operate again in the same second 1670 1671 } 1672//step 1673 Moon motor 1674void moonmotor (){ 1675 1676 if (moonmotor1 == LOW) 1677 { 1678 moonmotor1 1679 = HIGH; 1680 } 1681 else 1682 moonmotor1 = LOW; 1683 { 1684 digitalWrite(moon01, 1685 moonmotor1); // set the quartz motor drive 7 pin 1686 1687 } 1688 1689 if (moonmotor2 1690 == HIGH) 1691 { 1692 moonmotor2 = LOW; 1693 } 1694 else 1695 moonmotor2 = HIGH; 1696 1697 { 1698 digitalWrite(moon02, moonmotor2); // set the quartz motor drive 8 pin 1699 1700 1701 } 1702 1703} 1704 1705//step hour min 15 second motor 1706void hrminmotor (){ 1707 1708 1709 if (hrminmotor1 == LOW) 1710 { 1711 hrminmotor1 = HIGH; 1712 } 1713 else 1714 1715 hrminmotor1 = LOW; 1716 { 1717 digitalWrite(hrmin01, hrminmotor1); // set 1718 the quartz motor drive 7 pin 1719 1720 } 1721 1722 if (hrminmotor2 == HIGH) 1723 1724 { 1725 hrminmotor2 = LOW; 1726 } 1727 else 1728 hrminmotor2 = HIGH; 1729 { 1730 1731 digitalWrite(hrmin02, hrminmotor2); // set the quartz motor drive 8 pin 1732 1733 1734 } 1735 1736} 1737 1738 1739 1740// ################################################################################ 1741/* 1742void 1743 segIntensity(int intensity){ 1744 1745 if(intensity < 10) 1746 lcd.print("0"); 1747 // Print hour on first line 1748 lcd.print(intensity); 1749} 1750*/ 1751// end 1752 1753void 1754 advance(int pulsecount){ // leading 0 on pulse count 1755 if (pulsecount < 100) 1756 1757 1758 lcd.print("0"); 1759 1760} 1761 1762void advancetens(int pulsecount){ // leading 1763 0 on pulse count 1764 if (pulsecount <10) 1765 1766 lcd.print("0"); 1767 1768} 1769//****************************** 1770 1771void 1772 retard(int retardcount){ // leading 0 on pulse count 1773 if (retardcount < 100) 1774 1775 1776 lcd.print("0"); 1777 1778} 1779 1780void retardtens(int retardcount){ // leading 1781 0 on pulse count 1782 if (retardcount <10) 1783 1784 lcd.print("0"); 1785 1786} 1787 1788 1789 1790 1791void 1792 monthzero(int monthval) { // leading zero on month value 1793 if (monthval < 10) 1794 1795 1796 lcd.print("0"); // Print hour on first line 1797 lcd.print(monthval); 1798} 1799 1800 1801void 1802 dayzero(int dayval) { // leading zero on day value 1803 if (dayval < 10) 1804 1805 1806 lcd.print("0"); // Print hour on first line 1807 lcd.print(dayval); 1808} 1809 1810 1811 1812 1813void 1814 blankrow3() { 1815 lcd.setCursor(0,3); 1816 lcd.print(" "); 1817} 1818 1819 1820 1821 1822 1823void 1824 signalmatch() { 1825 1826 signalQual = DCF77_Clock::get_prediction_match(); 1827 if(signalQual 1828 == 255 || signalQual == 0 ) 1829 { 1830 signalQual = 00; 1831 } 1832 else 1833 1834 { 1835 signalQual = signalQual * 2; 1836 } 1837 lcd.setCursor(0,3); 1838 lcd.print("Sig 1839 Match "); 1840 lcd.print(signalQual); 1841 lcd.print("%"); 1842} 1843 1844 1845 1846void 1847 precision() { 1848 lcd.setCursor(0,3); 1849 lcd.print("Accuracy "); 1850 lcd.print(DCF77_Frequency_Control::get_confirmed_precision()); 1851 1852 lcd.print("Hz "); 1853} 1854/* 1855void freqadj() { 1856 lcd.setCursor(0,3); 1857 1858 // lcd.print("Qtz "); 1859 lcd.print(16000000L - DCF77_1_Khz_Generator::read_adjustment()); 1860 1861 lcd.print("Hz"); 1862} 1863*/ 1864 1865// add leading zero on moon h 1866void moonh(int 1867 h){ // leading 0 on pulse count 1868 if (h <10) 1869 1870 lcd.print("0"); 1871 1872} 1873 1874// 1875 add leading zero on moon m 1876void moonm(int m){ // leading 0 on pulse count 1877 1878 if (m <10) 1879 1880 lcd.print("0"); 1881 1882} 1883 1884// add leading zero on 1885 moon s 1886void moons(int s){ // leading 0 on pulse count 1887 if (s <10) 1888 1889 1890 lcd.print("0"); 1891 1892} 1893[/code]
Downloadable files
Schematic
Schematic
Vero 01
Vero 01
Schematic
Schematic
Vero 01
Vero 01
Vero01 back
Vero01 back
Documentation
"Atomic" Longcase Clock Schematic
"Atomic" Longcase Clock Schematic
"Atomic" Longcase Clock Schematic
"Atomic" Longcase Clock Schematic
Comments
Only logged in users can leave comments
brettoliver
0 Followers
•0 Projects
+1
Work attribution
Table of contents
Intro
5
0