Introduction: Nearly-Autonomous Retirement Countdown Display
A friend at work (Martha Edburg*) writes on her whiteboard the number of days until she can retire. A manager asked if I could make a sign or some kind of display that would automatically count down the time for her. At first I thought, eh, too much work. But the more I thought about it, the more I thought it would be a cool project. MERC was born! Well, the idea was born.
This Instructables is titled "Nearly-Autonomous Retirement Countdown Display", but I have actually been referring to it as MERC. Martha Edburg Retirement Countdown. I also use the term MER; for example, the MER date. I just thought "Nearly-Autonomous" makes a better title for this Instructables.
Why "nearly" autonomous? Firstly, it needs power from an outside source to operate. Secondly, the RTC (Real-Time Clock) has a backup battery that needs to be replaced every year or two or so. Other than those exceptions, MERC will always calculate and display time until retirement without outside intervention. The RTC keeps the current date/time and the MER date is hard-coded. No external input is needed. If power is removed, the RTC continues to keep time. When power is applied, it will continually display the remaining time to retirement.
*This name may or may not have been changed to protect order in the universe and is totally fictitious. Any similarity to a real person (living, dead, or living dead) is entirely coincidental.
Step 1: Preliminaries
I was originally thinking to count down the days. Eh, changes too slowly, too boring. Hours, Minutes? Better. Nay, let's go for seconds! It's going to be lots of seconds. Seconds from when? Well, seconds from the current date to the MER date. If the MER date changes, things could get complicated. So, I picked a point in time and called that time zero. That point is the beginning of 2020. Yeah, I know 2020 wasn't a great year, but I wanted a multiple of 4 (for leap year calculations) and it had to be before now and before the MER date. So, the first second of 2020 it is! Well, I guess it would be the 0th second? Whatever. So the time to retirement (to be displayed) will be the MER date (in seconds from 2020) minus the current date (in seconds from 2020). Seems pretty simple. Ha!
Need to calculate the number of seconds from the beginning of 2020 to the MER date. This will be a constant.
Let's use a MER date of August 31, 2024*.
First, calculate the number of seconds in the full years:
2020: 31,622,400 secs (leap) +
2021: 31,536,000 +
2022: 31,536,000 +
2023: 31,536,000 = 126,230,400 secs
And for the partial year 2024:
January through August, except for the last day in August because that is a partial day.
(31 + 29 + 31 + 30 + 31 + 30 + 31 + 30) = 243 full days * 86,400 = 20,995,200 + 126,230,400 = 147,225,600 secs.
Aug 31 at 5 PM, +17 hours * 3600 = 61,200 seconds.
Add all that up and we get 147,286,800 seconds total from beginning of 2020 to the MER date. This is going to have to be a long integer.
This was fairly easy to calculate one-time with a fixed date. It gets more complicated when calculating the current seconds from 2020 because of leap years and different number of days in different months.
Do I really need to be this accurate? No, not really. But I want to. And, I am not adjusting for daylight saving time (DST). MERC just stays with PST. So, it can be 3600 seconds off. But an accurate 3600 seconds! Good enough for retirement-planning purposes.
*This date may or may not have been changed to protect Martha's privacy.
Step 2: Ground Rules
Just some guidelines (for me).
- No cheating.
- Do not go searching the webiverse for anything like, "retirement countdown timer display".
- Do not ask friends/coworkers for any advice or opinions.
- OK to use existing Arduino libraries.
- As much as possible, use parts that I already have.
- Do not make a science project out of this. Hmmm, I guess it is a science project. Well, do not make it a career. Get it done.
- This is a prototype. It does not have to be pretty. The diamond-encrusted platinum enclosure can come later.
Step 3: Parts List
- Optrex DMC-20434 LCD (or similar), ~$10
- Arduino (I used an Uno, only because that is what I had), $22.95
- RTC (Real-Time Clock), $22.50
- 10 KΩ pot (I used a 10-turn I had, but any trim pot is fine), $1.25
- Pushbutton, $1.50
- 100 nF caps, <$1
- Enclosure, $5.35
- Wall wart, 9 V, $12.00
- Miscellaneous nuts, bolts, wire, etc.
And, of course, the usual electronics tools.
The only thing I had to buy was the power supply (wall wart). I had an enclosure. There was already a slot in it and other cutouts, but I was able to work with it.
My go-to electronics parts store is All Electronics. It is fairly close; I make a stop there when we are in the area. I have been going to All Electronics for years. Many years. Many, many years. OK, decades. Both of us have been around for a long time. :) For online buying I use Mouser or Digi-Key. I also like SparkFun.
Random comments on a couple of the parts:
LCD
I used a very old LCD. It has a standard 4-bit or 8-bit parallel interface. There is a very good Arduino library that works well with it. So for this prototype, that worked fine for me. There are newer/better LCDs. Some have a backlight and some use a simpler 2-wire interface (I2C aka IIC).
Real-Time Clock (DS3234)
This little part is amazing. Well, the datasheet is amazing. It claims to be accurate to ±2 PPM. That is awesome! In a (average) year, that means it would be off by only about ±63 seconds! Oh, but the datasheet also says it is ±5 PPM over 10 years. Another 5 PPM? So, let's use a total of 7 PPM, absolute worst case. That would give an average error of about 221 seconds, or 3 minutes and 41 seconds in a year. Not bad! And this is with no adjustments. Plenty good enough for MERC.
Step 4: The Schematic
Nothing super complicated here.
4 wires between the RTC and the Arduino for SPI. (Plus another 2 wires for power, of course.)
The LCD uses 4 data bits, an Enable, a Register Select, and the Vo input. The Read/Write line is connected to ground so all we can (and need to) do is write to the LCD. The Enable line clocks in the data. The voltage at Vo sets the contrast; this is controlled by the 10 kΩ trim pot.
The input power to the Arduino is not shown in this schematic, but it is provided by the 9 V wall wart which plugs directly into the Arduino barrel connector. The 5 V shown in this schematic is an output from the Arduino and is used to power the RTC and LCD.
I added the reset switch only because I wanted to fill a hole on the top of the enclosure. But since the pushbutton is now there, I will have to occasionally push it to justify its existence. Resetting will run through the splash screens, which includes displaying the current date/time. This is good to verify that MERC has not lost track of time.
Step 5: Building It
Above images: assembly complete, back with mounting screws installed, boards mounted in the enclosure, and then after most of the wiring was done.
General steps:
- Cut a slot in the front of the enclosure for the LCD. The enclosure I used already had a slot in it. I had to widen it a bit. It was too tall, but good enough for this prototype. Mount the LCD using 4 screws and nuts.
- Mount the Arduino to the back of the enclosure. I used a nylon screw, a nut to hold the screw to the enclosure, and another another nut to hold the board in place.
- Use a small perf board to mount the RTC, the pot for LCD contrast, and a couple of header pins to connect power. See the schematic in the previous Step for the wiring.
- Mount the perf board to the enclosure back, same way as the Arduino.
- Make holes in the enclosure for the trim pot on the perf board, and the USB connector and power input on the Arduino.
- Uninstall the LCD, Arduino, and perf board.
- Connect all those wires. I used header jumper wires on the breadboard, but soldering wires is better for something more permanent, even though this is only a prototype.
- Reinstall the LCD, Arduino, and the perf board. And install the reset pushbutton.
- Carefully fold all the wires so they fit in the enclosure without getting crushed/pinched as the enclosure is closed. Use the screws provided with the enclosure to install the back.
There was one casualty during the build. I used all the parts from the breadboard for the final build, so it had to work after I was done with the wiring and putting it all in the enclosure. Well, it didn't work. :( The LCD did not come on. Go in to troubleshooter mode . . . power is getting to everything, nothing was smoking, lights were blinking on the Arduino, signals were getting to the LCD. Problem turned out to be the trim pot. It was stuck at a setting that was very low contrast, too low to see anything. So all was running OK, but nothing showed on the display. Replaced the trim pot and all was well.
Step 6: Software (Firmware)
OK, the build is done! Plug it in and...nothing happens. Oh yes, need to write some software and then pour it into the Arduino. :)
I used an Arduino Uno, so the software was written in the Arduino IDE. Not going to talk about that; there are tons of Arduino info available here and elsewhere.
The image above is the breadboard I used for early software development.
Top-level flow:
- Initialize everything.
- Read the current time/date from the RTC.
- Calculate the seconds from 2020 to the current date/time.
- Subtract current seconds from MER seconds and we have the number of seconds to display.
- If the number of seconds <= 0, done! Clear the display and show congratulatory messages. If not:
- Convert the seconds-to-display to a string, properly formatted for the LCD being used.
- Write the seconds to the LCD.
- goto 2.
Seems pretty simple, but it turned out more challenging than I thought it would be (isn't it always?!?). Mostly because of leap years and different numbers of days in the months. And getting the seconds to display properly, along with adding commas to make it more readable.
More detailed flow:
- The only libraries I used were LiquidCrystal for the LCD and SPI for talking to the RTC. Init both of those, clear the LCD, and define and zero all variables. Define the MER seconds constant. Display the splash screen (MERC, software version, current date/time) and then clear it.
- Pretty easy. Just send the RTC the starting register and then read everything in.
- To calculate seconds:
- calc the number of full years: current year - 20 (The RTC returns 00–99 for the year)
- * 31,536,000 seconds for each regular year, or * 31,622,400 seconds for each leap year
- calc the number of days, so far, in the current year and * 86,400 to convert to seconds.
- I used an array to look up the total number of days for the completed months and then added the days in the current month.
- For example, on April 15, the array would return 90, the total days from January to March. Then add the current days in April (15), subtract one because the current day is not complete (14). If it is a leap year and the current month is March or later, add one day.
- convert current hours to seconds, * 3600
- convert current minutes to seconds, * 60
- add the current seconds to all of the above, and we have the total numbers of seconds from 2020 to the current date/time.
- Simple subtraction, pretty easy.
- Also easy.
- This took some time to get working properly. At first, I was using an array of characters because it uses less memory. But then I found it was much easier/simpler to just use a String object. Also, I wanted to insert commas in the displayed number to make it more readable. I did this during the output string-building loop. Check the attached sketch for details.
- Easy. I used the LiquidCrystal library. Just set the cursor position and then write the string.
- Delay 318 ms before going back to 2. Not really sure why I put this delay here. I guess I just do not want it running wide-open.
Yes, I could just read the RTC once and keep track of the seconds, but the RTC does that nicely for me. No, I really do not have to go through the calculation process (3.) every time, but it works like this and just seems to be more robust. And, see Step 2, line 3.
The display needs to update at least every second, so all of the above must be completed in much less than 1 second. I used the Arduino "micros()" function to measure the time it takes to execute the entire loop (without the 318 ms delay, of course). Using "millis()" would have been good enough, but "micros()" has more resolution.
Full-Loop time = 25.9 ms, average. (400 loops, std dev = 3 µs)
Wow, runs pretty fast and consistent! OK, so no problem keeping the display updated.
The LCD has 4 lines. It takes only one line to display the remaining seconds. What to do with the other 3 lines? I thought about displaying random, cute messages such as "seconds until you plan to retire", "seconds until you might retire", "seconds until you want to retire", etc. That would get repetitious after a while, unless I could come up with hundreds of messages. OK, forget that. How about displaying the current date/time? No real need. Well, we know the numbers of seconds to retirement. From the seconds, easy to calculate the number of minutes (÷60). And hours (÷3,600). And days (÷86,400). Yeah, why not display all that. I left everything as integers so there will be truncation errors in doing the calculations, but good enough for MERC.
The software, attached to this step, is a single .ino file.
"Sketch uses 6616 bytes (20%) of program storage space. Maximum is 32256 bytes. Global variables use 460 bytes (22%) of dynamic memory, leaving 1588 bytes for local variables. Maximum is 2048 bytes."
Step 7: The End
MERC is done and I'm also about done writing this Instructables. I'm reading through all these Steps and it seems so much easier than it actually was to get this whole thing together and working. That is usually the case. Many problems challenges arise throughout development.
Lessons Learned
- It takes almost 2 ms to clear the LCD. That seems pretty quick, but not for a 16 MHz processor! I had to add a delay after each lcd.clear() to prevent total LCD catastrophe (the display goes wacky!). It took way more than 2 ms to figure out this
problemchallenge. - Make sure the top of LCD will be at the top of the enclosure before doing any wiring. :)
- I had to add an "L" after long constants to get the correct result after an addition. I though it would auto-convert to a long because it was being added to a long variable, but apparently not.
- Use a vise to hold my cell phone when taking pictures, and especially when taking a video. For taking a picture, I set a 10-second timer to give some time for any shaking to settle.
Future Improvements
- Battery operation would be a cool feature. Would prolly need to use a different (low power) processor.
- Newfangled LCD with a backlight.
- A very large LCD or other type of large of display. I think this is what the manager (mentioned in the Introduction) was asking for.
- Software updates*, such as scrolling text or animation for the splash screens. And maybe even animation for the main screen?
- Adjust for DST.
Testing
Testing was done by using a small amount of thiotimoline to move MERC into the future for verifying correct operation. . . . OK, fine, so maybe I didn't really use thiotimoline. :) I did test it by overriding what the RTC returns by adding a line(s) right after the RTC read. For example: "curYr = 24L;" to set the current year to 2024. Or, for some testing, I would write a new date/time into the RTC and then let it run. Testing was very important here. Do not want Martha to miss her retirement date!
Schedule
There was no schedule. (Well, I did have to finish it way before the MER date, but that was not a problem.) This was supposed to be a fun project. No schedules, deadlines, or status reports. I spent a leisurely 2 months, calendar time, working on MERC. Sometimes I would work on it for a few days straight (after work and weekends); other times I would not touch it for a week. It would not have been as much fun if I had to rush through it.
Version
This first version of software is v0.0.5, but I have been referring to it as just version 5. So, MERC 5, as attached in Step 6. Why is this version 5 and not version 1? Well, you see, the MERC units 1 through 4 were not entirely successful.
The End
All in all, I had a lot of fun developing and building MERC. And I learned a few things, which is always good. You have read this far?!? Really? :) If so, I always welcome suggestions/criticisms/comments. And someone please check my math! :)Thanks for reading!!!
*software is never done! :)