Countdown until Christmas

Hi All,

I'm having trouble getting this code to work...can anyone shed some light?

/*
* Christmas.ino
* countdown the days, hours and minutes till christmas.
*/

#include <Time.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;

//Libraries for Dot Matrix
#include <SPI.h>
#include <DMD.h>
#include <TimerOne.h>
DMD dmd(1, 1);

#define SPEAKERPIN 4


byte handx[]={12,13,14,15,16,17,18,19,20,21,21,22,
  22,23,23,23,23,23,22,22,21,21,20,19,
  18,17,16,15,14,13,12,10,9,8,7,6,
  5,4,3,2,2,1,1,0,0,0,0,0,
  1,1,2,2,3,4,5,6,7,8,9,10};

byte handy[]={0,0,0,0,1,1,1,2,2,3,4,4,
  5,6,7,8,8,9,10,11,11,12,13,13,
  14,14,14,15,15,15,15,15,15,15,14,14,
  14,13,13,12,11,11,10,9,8,8,7,6,
  5,4,4,3,2,2,1,1,1,0,0,0};

int dmode=0;    //display mode
int brightness=2;   //display brightness
int bcount=0;   //variable used to keep track of pwm phase
#define BSTEPS 7

void ScanDMD(){       //also implements a basic pwm brightness control
  dmd.scanDisplayBySPI();
  bcount=bcount+brightness;
  if(bcount<BSTEPS){digitalWrite(9,LOW);}
  bcount=bcount%BSTEPS;
}

void setup () {
  Wire.begin();
     Serial.begin(9600);

  Timer1.initialize( 500 );           //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
  Timer1.attachInterrupt( ScanDMD );   //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()
  dmd.clearScreen( true );     //clear/init the DMD pixels held in RAM
  digitalWrite(SPEAKERPIN,LOW);    //speaker off
  rtc.begin();
}
  


void loop () {
  
  setSyncProvider(RTC.get);
  time_t daysleft,christmasdate; // setup the fields needed.
       christmasdate = 1482670799; // December 25, 2016
       daysleft = christmasdate - now(); // subtract todays date from the christmas date to get the days left.


  // Display the days left before christmas.
  dmd.selectFont( SystemFont5x7 );
  dmd.drawString( 0,0, "Days,", 4, GRAPHICS_NORMAL );
  dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY);, 3, GRAPHICS_NORMAL );

The idea is for the Dot Matrix Display...

(32x16 Red Dot Matrix Display | Freetronics)
(Using Your Freetronics DMD | Freetronics)

To countdown the days until Christmas. I'd like it to eventually display the days, hours, minutes, seconds. But should be able to figure that out when this piece of code works.

My current error messages are:

#warning CHANGE THESE TO SEMI-ADJUSTABLE PIN DEFS!

  ^

 In function 'void loop()':

Countdown:59: error: 'RTC' was not declared in this scope

   setSyncProvider(RTC.get);

                   ^

Countdown:59: error: 'setSyncProvider' was not declared in this scope

   setSyncProvider(RTC.get);

                          ^

Countdown:62: error: 'now' was not declared in this scope

        daysleft = christmasdate - now(); // subtract todays date from the christmas date to get the days left.

                                       ^

Countdown:66: error: 'SystemFont5x7' was not declared in this scope

   dmd.selectFont( SystemFont5x7 );

                   ^

Countdown:68: error: 'SECS_PER_DAY' was not declared in this scope

   dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY);, 3, GRAPHICS_NORMAL );

                                                     ^

Countdown:68: error: 'displayDaysDigits' was not declared in this scope

   dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY);, 3, GRAPHICS_NORMAL );

                                                                 ^

Countdown:68: error: expected primary-expression before ',' token

   dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY);, 3, GRAPHICS_NORMAL );

                                                                   ^

Countdown:68: error: expected '}' at end of input

   dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY);, 3, GRAPHICS_NORMAL );

                                                                                         ^

exit status 1
'RTC' was not declared in this scope

I'm using all of the following components
Nano Board

XC4621 Red LED Matrix

XC4450 Real Time Clock Module
https://www.jaycar.com.au/arduino-compatible-real-time-clock-module/p/XC4450

Assistance is greatly appreciated

Any reason why you don't use the loop and update the display when 60sec (or 1 sec) have elapsed rather than update all the time as fast as you can?

dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY)[b];[/b], 3, GRAPHICS_NORMAL );

There is a wrong semicolon in there

change

RTC_DS1307 rtc;

to

RTC_DS1307 RTC;

change:

  dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY);, 3, GRAPHICS_NORMAL );

to:

  dmd.drawString( 2,9, displayDaysDigits(daysleft / SECS_PER_DAY), 3, GRAPHICS_NORMAL );

Depending on which IDE version/Arduino AVR Boards version/operating system you're using you may also need to change:

#include <Time.h>

to:

#include <TimeLib.h>

There may still be some other errors after that. You should always post links to where you downloaded all libraries used in your sketch from, or if you installed them using Library Manager. Otherwise there's no way for us to test your code.

Thaks Guys, the libraries are:

Time: Time Library, Timekeeping and Time/Date Manipulation on Teensy

And in the code section here:
https://www.jaycar.com.au/diy-arduino-clock

Thanks!

Change line 52 from:

rtc.begin();

to

RTC.begin();

change line 59 from

setSyncProvider(RTC.get);

to:

setSyncProvider(RTC.now);

(I'm actually not sure that's correct but it does compile)

Add:

#include <SystemFont5x7.h>

near the top of your sketch

That's as far as I can go because you didn't post your entire sketch. You are really going about this project in the wrong way. The right way is to get each part of your project working individually with small test sketches, the display, the RTC, etc. Only then do you start putting it all together. Instead you just mashed together a bunch of code without with lots of bugs which you would have already identified and solved in the test sketches.

MITLRpro:
Thaks Guys, the libraries are:

Time: Time Library, Timekeeping and Time/Date Manipulation on Teensy

And in the code section here:
Arduino Matrix Multi Clock | Jaycar Electronics

Thanks!

I suggest to stick to basics.
Here is a small code I put together that should help out.

it looks long because I tried to comment it as much as possible so that it's straightforward to grasp what are the 3 classes being used and their capabilities.

I've been using the RTClib library as modified by Adafruit which will work with your set up. this library does not have the alarm or register management but you don't really need it.

The only thing you'll need to work out depending on where you live is how to handle Daylight Saving Time. RTCs don't know about those things. so I use a boolean that I set manually in my code (here to true because it's still summer time here). Because the clock does not know about DST it will get the difference between 2 dates wrong by 1 hour if the you are not yet with Christmas wintertime. hence the line in the code

TimeSpan timeToChristmas = (DST ? christmas - now + oneHour : christmas - now);

DST is maintained in my function call adjustForWesternEuropeDST(); that needs to be called at least once per hour to not miss the time to change clock.

if you are not in western Europe, you'll need to code that for your region as dates are not the same around the world.

On some of my physical gadgets I usually add a Dip switch so that I can read that dynamically when I reset the board instead of hardcoding it like I did here. if you plan to have your countdown clock in use every year I'd suggest you plan the same.

// import adafruit RTCLib library
#include "RTClib.h" // https://github.com/adafruit/RTClib

// the library defines the DateTime and TimeSpan class for time representation
// and RTC_DS1307, RTC_DS3231 or RTC_PCF8523 for the hardware

// ------------------------------------------------------
// RTC_DS1307 or  RTC_DS3231 RTC_PCF8523 objects
// ------------------------------------------------------
// There's pretty much only one way to get the time using the RTClib, which is to call now() on an instance
// now() returns a DateTime object that describes the current year, month, day, hour, minute and second

// This line sets the RTC with an explicit date & time, for example to set
// October,16 2016 at 17h40:25 you would call:
// rtc.adjust(DateTime(2016, 10, 16, 17, 40, 25));

// The following line sets the RTC to the date & time this sketch was compiled
// compile, upload and execute to setup your RTC Module, then comment out
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// if you are fast your clock still ends up about 5 seconds late... you might want to adjust that manually after

// ---------------------
// DateTime object : no TimeZone / DST / leap second handling
// ---------------------
// you can create a DateTime object by passing
// DateTime(uint16_t year, uint8_t month, uint8_t day,uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
// a DateTime object offers time information methods
//    uint16_t year()
//    uint8_t month()
//    uint8_t day()
//    uint8_t hour()
//    uint8_t minute()
//    uint8_t second()
//    uint8_t dayOfTheWeek()
// days are represented as such
// const char *daysOfTheWeek[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// a DateTime object can present a timestamp as a 32-bit uint32_t
// either time as seconds since 1/1/2000
// long secondstime();
// or time as seconds since midnight, January 1st 1970 not counting leapseconds
// uint32_t unixtime(void);

// ---------------------
// TimeSpan object
// ---------------------
// you can create a TimeSpan object with
// TimeSpan (int32_t seconds); or
// TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds);
// or by subtracting a DateTime object from another
// a TimeSpan object offers time information methods
//  int16_t days()
//  int8_t  hours()
//  int8_t  minutes()
//  int8_t  seconds()
//  int32_t totalseconds()

RTC_DS3231 rtc;
DateTime christmas;

const unsigned long updatePeriod = 1000UL; // UL for unsigned long. update display every updatePeriod ms


// --------------------------------------------------------------------------------------------------------------
// Daylight saving time (DST) or summer time is the practice of advancing clocks during summer
// months by one hour so that evening daylight lasts an hour longer, while sacrificing normal sunrise times.
// The EU has a guideline that determines the daylight saving time to start on the last Sunday of March
// and to end on the last Sunday of October. In the EU the hour to switch is at 01:00 UTC.
// --------------------------------------------------------------------------------------------------------------
boolean DST ; // true when DST starts and that false at the end of DST
const TimeSpan oneHour = TimeSpan((int32_t) 3600); // one hour that we use for DST caclulations

void  adjustForWesternEuropeDST() // switch times are 2 and 3 am (that is 1:00 UTC)
{
  DateTime now = rtc.now();
  if (now.dayOfTheWeek() == 1 && now.month() == 10 && now.day() >= 25 && now.day() <= 31 && now.hour() == 3 && DST == true)
  {
    // need to set the clock to 2 am;
    rtc.adjust(DateTime(now.year(), 10, now.day(), 2, now.minute(), now.second()));
    DST = false;
  }

  if (now.dayOfTheWeek() == 1 && now.month() == 3 && now.day() >= 25 && now.day()  <= 31 && now.hour() == 2 && DST == false)
  {
    // need to set the clock to 3 am;
    rtc.adjust(DateTime(now.year(), 3, now.day(), 3, now.minute(), now.second()));
    DST = true;
  }
}


// --------------------------------------------------------------------------------------------------------------
//
// --------------------------------------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1); // can't go further
  }
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // only if your clock is not set up
  DST = true; // when you launch the program you need to set this correctly because the clock can't know

  christmas = DateTime(rtc.now().year(), 12, 25, 0, 0, 0); // would be even better to check if we are after the 25th of december, then pick next year's one.
}


// --------------------------------------------------------------------------------------------------------------
//
// --------------------------------------------------------------------------------------------------------------
void loop() {
  static unsigned long previousMillis = 0;
  static DateTime now;

  if (millis() - previousMillis >= updatePeriod) {
    adjustForWesternEuropeDST();
    now = rtc.now();
    TimeSpan timeToChristmas = (DST ? christmas - now + oneHour : christmas - now);

    // not really necessary to get them into variables, just a convenience
    // in case you want to use them many times
    uint8_t nbDays = timeToChristmas.days();
    uint8_t nbHours = timeToChristmas.hours();
    uint8_t nbMinutes = timeToChristmas.minutes();
    uint8_t nbSeconds = timeToChristmas.seconds();

    Serial.print("Time remaning before Christmas = ");
    Serial.print(nbDays); Serial.print(nbDays > 1 ? F(" days ") : F(" day "));
    Serial.print(nbHours); Serial.print(F(":"));
    Serial.print(nbMinutes); Serial.print(F(":"));
    Serial.println(nbSeconds);
    previousMillis += updatePeriod;
  }
}

I've not tested this much - quickly hacked together - so use with caution

hope this helps

curious to know if you solved your issue with the above?

J-M-L:
I suggest to stick to basics.
Here is a small code I put together that should help out.

I found this post in my search for a Christmas clock. I've used 2 nights to understand it and add my own little parts. I'll have to say:

Briliant little Piece of code. I Borrowed it. Added my own bits, and a few of the bits you (J-M-L) suggested. Result: I have a Christmas Clock. Thanks to J-M-L.

I have testet my formatting for different date ranges, and think my only major issue is going to be new years eve, time will tell. If it is buggy there, a power cycle will solve it.

Here is my current version:

 // I have Borrowed, maybe even stolen a little (https://forum.arduino.cc/index.php?topic=429746.msg2964008#msg2964008). 
 // But I have also added my own "improvements". 
 // This is my take on a christmas countdown. 
 
 #include <LiquidCrystal.h>
 #include <Wire.h>
 #include "RTClib.h"

 #define FIRST_LINE 0 //text position for first line
 #define SECOND_LINE 1 //text position for second line

DateTime christmas;
boolean DST ; // true when DST starts and that false at the end of DST
const TimeSpan oneHour = TimeSpan((int32_t) 3600); // one hour that we use for DST caclulations
const unsigned long updatePeriod = 1000UL; // UL for unsigned long. update display every updatePeriod ms

// initialize the library with the numbers of the interface pins
//    LiquidCrystal lcd(RS, enable, d4, d5, d6, d7); //
//
// The parameters to this initialisation function are the pins on 
// the Arduino board that are connected to the pins on the LCD Module, 
// i.e., the pins on the right column in the table above.
//
// The first parameter is the “RS” — which, literally, means 
//      “Register Select”, and which is used to tell the
//       module if “that which comes over the bus (the set of data pins)
//       corresponds to “data to print” or “control instructions”
//
// The second parameter is “Enable Signal"
//       the remaining parameters are the 4 digital pins forming the bus.
//

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
RTC_DS3231 rtc;
int i = 0;

// --------------------------------------------------------------------------------------------------------------
// Daylight saving time (DST) or summer time is the practice of advancing clocks during summer
// months by one hour so that evening daylight lasts an hour longer, while sacrificing normal sunrise times.
// The EU has a guideline that determines the daylight saving time to start on the last Sunday of March
// and to end on the last Sunday of October. In the EU the hour to switch is at 01:00 UTC.
// --------------------------------------------------------------------------------------------------------------
//boolean DST;  // true when DST starts and that false at the end of DST
//const TimeSpan oneHour = TimeSpan((int32_t) 3600); // one hour that we use for DST caclulations

void  adjustForWesternEuropeDST() // switch times are 2 and 3 am (that is 1:00 UTC)
{
  DateTime now = rtc.now();
  if (now.dayOfTheWeek() == 1 && now.month() == 10 && now.day() >= 25 && now.day() <= 31 && now.hour() == 3 && DST == true)
  {
    // need to set the clock to 2 am;
    rtc.adjust(DateTime(now.year(), 10, now.day(), 2, now.minute(), now.second()));
    DST = false;
  }

  if (now.dayOfTheWeek() == 1 && now.month() == 3 && now.day() >= 25 && now.day()  <= 31 && now.hour() == 2 && DST == false)
  {
    // need to set the clock to 3 am;
    rtc.adjust(DateTime(now.year(), 3, now.day(), 3, now.minute(), now.second()));
    DST = true;
  }
}


void setup() {
      // set up the LCD's number of columns and rows:
      lcd.begin(16, 2);

      // Setup i2c to RTC
      Wire.begin();
      Serial.begin(9600); // or whatever baud rate you wish to use

      // Checks if it's to late to be checking the list for this year (24/12 6pm)
      DateTime now = rtc.now();
      christmas = DateTime(now.year(), 12, 24, 18, 0, 0); 
}

void loop() {
  
  static unsigned long previousMillis = 0;
  static DateTime now;

  if (now.month() == 12 && now.day() >= 24 && now.hour() >= 18)
      {
      // After 24/12 at 6 PM (18) we need to prepare for next years christmas.
          christmas = DateTime(now.year()+1, 12, 24, 18, 0, 0); 
      }
  
  if (millis() - previousMillis >= updatePeriod) {
    adjustForWesternEuropeDST();
    now = rtc.now();
    TimeSpan timeToChristmas = (DST ? christmas - now + oneHour : christmas - now);

    // not really necessary to get them into variables, just a convenience
    // in case you want to use them many times
    int nbDays = timeToChristmas.days();
    int nbHours = timeToChristmas.hours();
    int nbMinutes = timeToChristmas.minutes();
    int nbSeconds = timeToChristmas.seconds();

    // Print to serial port for testing/debugging
    // Serial.print("Time remaning before Christmas = ");
    // Serial.print(nbDays); Serial.print(nbDays > 1 ? F(" days ") : F(" day "));
    // Serial.print(nbHours); Serial.print(F(":"));
    // Serial.print(nbMinutes); Serial.print(F(":"));
    // Serial.println(nbSeconds);

    // Print to LCD display
    // Setup and Print First line
    lcd.setCursor(2, FIRST_LINE);
    lcd.print("Tid til JUL:");

    // Setup and Print Second line
    // |0123456789ABCDEF|
    // | 360 DAGE 05:16 | CASE 365
    // |99 DAGE 05:16:27| CASE 99
    // | 9 DAGE 05:16:27| CASE 9
    // | 1 DAG 05:16:27 | CASE 2
    // |    05:16:27    | CASE 1

    // Change nbDays for debugging and testing
    // nbDays = 360;

    if (nbDays > 99){
        i=365;
    } else if (nbDays > 9){
        i=99;
    } else if (nbDays > 1){
        i=9;
    } else if (nbDays == 1){
        i=2;
    } else if (nbDays == 0){
        i=1;
    }
    
    lcd.setCursor(0, SECOND_LINE);

    // I just wanted to play with a case switch. 
    
    switch (i) {
    case 1:
      lcd.print("    ");
      lcd.print(nbHours > 9 ? F("") : F("0"));lcd.print(nbHours, DEC); lcd.print(F(":"));
      lcd.print(nbMinutes > 9 ? F("") : F("0"));lcd.print(nbMinutes, DEC); lcd.print(F(":"));
      lcd.print(nbSeconds > 9 ? F("") : F("0")); lcd.print(nbSeconds, DEC);
      lcd.print("    ");
      break;
    case 2:
      lcd.print(" ");
      lcd.print(nbDays, DEC); lcd.print(" dag ");
      lcd.print(nbHours > 9 ? F("") : F("0"));lcd.print(nbHours, DEC); lcd.print(F(":"));
      lcd.print(nbMinutes > 9 ? F("") : F("0"));lcd.print(nbMinutes, DEC); lcd.print(F(":"));
      lcd.print(nbSeconds > 9 ? F("") : F("0")); lcd.print(nbSeconds, DEC);
      lcd.print(" ");  
      break;
    case 9:
      lcd.print(" ");
      lcd.print(nbDays, DEC); lcd.print(" dage ");
      lcd.print(nbHours > 9 ? F("") : F("0"));lcd.print(nbHours, DEC); lcd.print(F(":"));
      lcd.print(nbMinutes > 9 ? F("") : F("0"));lcd.print(nbMinutes, DEC); lcd.print(F(":"));
      lcd.print(nbSeconds > 9 ? F("") : F("0")); lcd.print(nbSeconds, DEC);
      lcd.print("");
      break;
    case 99:
      lcd.print(nbDays, DEC); lcd.print(" dage ");
      lcd.print(nbHours > 9 ? F("") : F("0"));lcd.print(nbHours, DEC); lcd.print(F(":"));
      lcd.print(nbMinutes > 9 ? F("") : F("0"));lcd.print(nbMinutes, DEC); lcd.print(F(":"));
      lcd.print(nbSeconds > 9 ? F("") : F("0")); lcd.print(nbSeconds, DEC);
      break;
    case 365:
      lcd.print(" ");
      lcd.print(nbDays, DEC); lcd.print(" dage ");
      lcd.print(nbHours > 9 ? F("") : F("0"));lcd.print(nbHours, DEC); lcd.print(F(":"));
      lcd.print(nbMinutes > 9 ? F("") : F("0"));lcd.print(nbMinutes, DEC);
      lcd.print(" ");
      break;
    default:
      lcd.print("   FAIL--fail   ");  // Debugging....
      break;
    }
    
    previousMillis += updatePeriod;

  }
}

@thusgaard

DO NOT HIJACK !

Could you take a few moments to Learn How To Use The Forum.
It will help you get the best out of the forum.

In this instance I am letting it ride as a "value added" post.

Bob.