Hi All,
New to the forum, first post. I am trying to create a countdown clock for a friend who is retiring. I have a Arduino uno, Adafruit data logger, Adafruit rgb shield with a 2x16 - rgb lcd. I've been able to get the date and time to display but don't have any idea how to compare the retirement date with the datetime now. The retirement date is april 30 2014 at 10pm and I want to display days, hours,
and minutes left. Sounds simple.
thanks
here is what I have so far.
// RetirementClock.ino
#include <Wire.h>
#include "RTClib.h"
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
// #defines the backlight color
#define BLUE 0x4
RTC_DS1307 RTC;
void setup () {
Wire.begin();
RTC.begin();
Serial.begin(9600);
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
lcd.setBacklight(BLUE);
lcd.setCursor(0, 0);
}
void loop () {
String temp;
String thischar;
DateTime now = RTC.now();
lcd.setCursor(0, 0);
//make sure to display two digits wide
if (now.month() <10) {
temp.concat("0");
temp.concat(now.month());
lcd.print(temp);
}
else{
lcd.print(now.month(), DEC);
}
lcd.print('/');
temp = "";
//make sure to display two digits wide
if (now.day() <10) {
temp.concat("0");
temp.concat(now.day());
lcd.print(temp);
}
else{
lcd.print(now.day(), DEC);
}
lcd.print('/');
temp = "";
//make sure to display two digits wide
thischar.concat(now.year());
temp.concat(thischar.charAt(2));
temp.concat(thischar.charAt(3));
lcd.print(temp);
lcd.setCursor(0, 1);
temp = "";
//make sure to display two digits wide
if (now.hour() <10) {
temp.concat("0");
temp.concat(now.hour());
lcd.print(temp);
}
else{
lcd.print(now.hour(), DEC);
}
lcd.print(":");
temp = "";
//make sure to display two digits wide
if (now.minute() <10) {
temp.concat("0");
temp.concat(now.minute());
lcd.print(temp);
}
else{
lcd.print(now.minute(), DEC);
}
lcd.print(":");
temp = "";
//make sure to display two digits wide
if (now.second() <10) {
temp.concat("0");
temp.concat(now.second());
lcd.print(temp);
}
else{
lcd.print(now.second(), DEC);
}
delay(1000);
}
There is a Time library that allows you to create time objects with arbitrary dates and time. Use that to create a retirementDate object. It has functions to compute the minutes, hours, days, etc. to another time (now.minutesToTime_t(retirementDate), for example).
Once you download the library, and install it in the libraries folder in your sketchbook (create it if it does not exist), and restart the IDE, all you need is:
Time retirementDate(/* the date and time info goes here */);
time_t now(); // return the current time as seconds since Jan 1 1970
void setTime(time_t t);
void setTime(int hr,int min,int sec,int day, int month, int yr);
void adjustTime(long adjustment);
So the format is (hr,min,sec,day,month,yr).
/* Useful Macros for converting elapsed time to a time_t */
#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN)
#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR)
#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011
#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK)
Now the macros that I think I should use are the daysToTime_t, hoursToTime_t and minutesToTime_t. But I am still a little confused as to what this macro is doing and how. Objects are the hardest thing to learn in C++.
The first D in daysToTime_t would be now() and the second retiremenDate() this doesn't look right the second D looks like it's asking for the number of days * sec per day but that is not what I want. I want to give it the date and it return the days left. What am I missing here.
But I am still a little confused as to what this macro is doing and how. Objects are the hardest thing to learn in C++.
Objects and macros are completely unrelated.
If you think objects are hard, you've obviously never learned about pointers.
It is not necessary to know how code works in order to be able to use it.
The macros are not determining the difference between two days/hours/mins/weeks. They are converting a number of days to a time_t format, or the number of minutes to a time_t format.
There is a makeTime() method, at the bottom of the class. Create an instance of the TimeElements structure. Set the date and time members. Then, pass that instance to makeTime() to get a time_t variable.
The difference between two time_t variables (which is also what now() returns) is a matter of subtraction, giving a difference in seconds.
The numberOfHours, numberOfMinutes, and numberOfSeconds macros are then useful for converting the time_t difference to hours, minutes, and seconds.
It is not necessary to know how code works in order to be able to use it.
That's me I am the greatest copy and paste artist ever. I try to learn from guys like yourself that know what their doing by trying snip-its of code and seeing what it does. Thanks for the help. I'll keep trying.
/*
* RetirementClock.ino
* countdown the days, hours and minutes till retirement.
*/
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
// #defines the backlight color
#define BLUE 0x4
void setup () {
Wire.begin();
Serial.begin(9600);
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
lcd.setBacklight(BLUE);
lcd.setCursor(0, 0);
setSyncProvider(RTC.get);
}
void loop () {
time_t daysleft,retirementdate;
retirementdate = 1398895200L; // April 30, 2014 @ 22:00:00 hrs.
daysleft = retirementdate - now();
long nineoclock = 75600;
long tenoclock = 79200;
long elevenoclock = 82800;
long twelveoclock = 86399;
lcd.setCursor(0, 0);
lcd.print("Days ");
lcd.print(daysleft / SECS_PER_DAY);
if (elapsedSecsToday(now()) < nineoclock)
{
lcd.setCursor(10, 0);
lcd.print("Hrs ");
printDigits((nineoclock - elapsedSecsToday(now()))/ SECS_PER_HOUR);
}
else if ((elapsedSecsToday(now()) > nineoclock) && (elapsedSecsToday(now()) < tenoclock ))
{
lcd.setCursor(10, 0);
lcd.print("Hrs ");
lcd.print("0");
}
else if ((elapsedSecsToday(now()) > tenoclock) && (elapsedSecsToday(now()) < elevenoclock))
{
lcd.setCursor(10, 0);
lcd.print("Hrs ");
lcd.print("23");
}
else
{
lcd.setCursor(10, 0);
lcd.print("Hrs ");
lcd.print("22");
}
lcd.setCursor(0, 1);
lcd.print("Min ");
printDigits(59 - minute());
lcd.setCursor(7, 1);
lcd.print("Sec ");
printDigits(59 - second());
delay(1000);
}
void printDigits(int digits){
// utility function for digital clock display: prints leading 0
if(digits < 10)
lcd.print('0');
lcd.print(digits);
}
Well it took a few days but it's working so far. It was not easy trying out some of the macros and functions in the time library.
There are two other macros that I'd like to try but I don't understand there syntax, daysToTime_t, makeTime and I haven't found any examples of there use.
Just cleaned up the code a little bit. Next I think I'll add the capability to input the retirement date. So that means I have to add a menu(to select from input or display), date converter(to convert the date from string to time_t).
/*
* RetirementClock.ino
* countdown the days, hours and minutes till retirement.
*/
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
// #defines the backlight color
#define BLUE 0x4
void setup () {
Wire.begin();
Serial.begin(9600);
// set up the LCD's number of rows and columns:
lcd.begin(16, 2);
lcd.setBacklight(BLUE);
lcd.setCursor(0, 0);
lcd.clear();
}
void loop () {
setSyncProvider(RTC.get);
time_t daysleft,retirementdate; // setup the fields needed.
retirementdate = 2280614400L; // January 01, 2042
daysleft = retirementdate - now(); // subtract todays date from the retirement date to get the days left.
// Display the days left before retirement.
lcd.setCursor(0, 0);
lcd.print("Days ");
displayDaysDigits(daysleft / SECS_PER_DAY);
// Display the hours left before midnight.
lcd.setCursor(10, 0);
lcd.print("Hrs ");
displayTimeDigits(23 - hour());
// Display the minutes left in a hour.
lcd.setCursor(0, 1);
lcd.print("Min ");
displayTimeDigits(59 - minute());
// Display the seconds left in a minute.
lcd.setCursor(7, 1);
lcd.print("Sec ");
displayTimeDigits(59 - second());
delay(1000);
}
void displayTimeDigits(int digits){
// utility function for time display: displays leading 0.
if(digits < 10)
lcd.print('0');
lcd.print(digits);
}
void displayDaysDigits(int digits){
// utility function for days display: displays leading spaces.
if(digits <= 9)
{
lcd.print(" ");
lcd.print(digits);
}
else if(digits <= 99)
{
lcd.print(" ");
lcd.print(digits);
}
else if(digits <= 999)
{
lcd.print(" ");
lcd.print(digits);
}
else if(digits <= 99)
{
lcd.print(" ");
lcd.print(digits);
}
else
{
lcd.print(digits);
}
}