My smart display will have a number of time-based functions, so I knew that time management needed to be a key part of the solution. The best way for me to manage time, with minimal calls/updates from an NTP server, was to integrate a Real Time Clock (RTC).
RTCs are integrated circuits that - very simply - keep time. Hackaday did a write up last year on choosing the right RTC (https://hackaday.com/2020/09/30/choosing-the-right-rtc-for-your-project/). I used this guide as a starting point for my research.
I had four requirements for the RTC:
- Must operate at low power
- Must be able to set and trigger alarms
- Must be able to set and trigger timers
- Must have a clock out feature (needed for the Sharp Memory Display)
I pretty quickly zeroed in on MicroCrystal's RV-3028 and RV-8803. Both operate at low power, are extremely accurate, and come in small packages.
I was able to get samples of both from MicroCyrstal (huzzah for samples!!) and I got to work.
After a week of testing, I landed on the RV-3028, for the following reasons.
- Insanely low power - 45nA!!!
- Ability to set a periodic timer (interrupt every minute or second), countdown timer (e.g. countdown from 5 minutes), and alarms - AT THE SAME TIME
- Separate clock out and interrupt pins
- Separate Unix and "Local" time tracking
The last two points are the post important, so I'll go into more detail.
Clock Out and Interrupt Pins
The Sharp Memory display requires an "refresh" command every second or so. This can be done with hardware or software - and a HW refresh command was going be better from a battery perspective. I toyed with using the ESP32s ultra low processor as a refresh "engine", but decided against it because (a) I would lose a valuable GPIO and (b) programming the ULP is difficult to do with Arduino or MicroPython.
So, with the RV-3028, I can use one pin to control my alarm/timer/countdown interrupts (each with separate registers, so that I can have all three running at the same time) and I can have a separate line for the a 1HZ pulse on the clockout pin. This ultimately means that my microcontroller can spend more time in deep sleep.
Separate UNIX and and "Local" time tracking
Unix time, or epoch time, is typically calculated as the number of seconds (or milli/micro seconds) that have passed since January 1, 1970 (UTC). The RTC allows you to store UNIX time (separate from local time). This allows me to have a "time" value that can be used for local representation (stored in a separate register). In short, I can store a UTC time and a local time. This is extremely important when it comes to Daylight Savings Time; twice a year (usually), at 2AM (usually), the local time needs "spring forward" or "fall back".
In the past, I've hardcoded very specific daylight savings offset rules for my projects. This works for an individual maker, but doesn't work for a potential commercial product (that could sit in any number of time zones with arbitrary rules). Fortunately, having the epoch, and using the "setenv" functionality in the ESP32, gives me the ability to dynamically change the local time (based on DST or timezone) without complex logic or repeated calls to an NTP server.
Running BOM (@250 units)
|Component||Function||Deep Sleep (uA)||Costs (USD)|
|Sharp Memory Display (LS027B7DH01A)||Display||10-35||$20.00|