Birthday Reminder Device That Will Run for 50 Years on A Single Coin Cell

arduino birthday reminder device

Arduino based Birthday Reminder Device

Yes, you read the title correct. Have you ever forgot your birthday, that you needed someone else to remind you about it? Or what if you could gift someone you love, a device that will wish them on their birthday for 50 times? I kid you not, this simple Arduino powered Birthday Reminder Device that runs on a single CR2450 coin cell can wish your loved ones or yourself a happy birthday for 50 years, before the battery run out of juice.

I think this is the first time somebody makes a birthday reminder/alarm of this kind, because I tried searching for similar projects but found nothing. This project is also available at and Hackaday.

I built this as part of the Hackaday Coin Cell Challenge and it won runner-up prize of $100 Tindie credits. This birthday alarm thing simply popped into my mind and I started researching about the feasibility of the idea. I have never used the sleep modes of any microcontrollers before. So I had to learn everything about making MCUs run at insanely low currents and save every bit of energy from the power source. It was a challenge really! I used Atmel ATmega168P as the microcontroller (actually I modified an Arduino Nano clone that has ATmega168P on it by removing all the unwanted components such as the voltage regulator, USB bridge etc.) and used Arduino IDE to develop the firmware.

The time and birthday date can be programmed via any serial monitor over USB. Once the time and alarm are set, the MCU goes to sleep mode. When the current RTC time matches your birthday every year, the LED will flash for a minute and will print a happy birthday message to the serial monitor if connected to a computer that time. The average current consumption is around 1.2uAh (including self-discharge of the cell) which makes it possible to run it for more than 50 years on a CR2450 (540mAh) Lithium coin cell.


  • Around 1.22uAh average current consumption including cell self-discharge (608 nA is the actual device current consumption on sleep without considering self-discharge, as measured by ammeter, on cell CR2450N)
  • Actual operating times on different types of Lithium coin cells are : >29 years on CR2023 (225 mAh), >50 years on CR2450N (540 mAh), and >64 years on CR2477N (950 mAh). [actual operating time depends on the battery's physical and chemical health over the period]
  • Birthday can be set and updated via any serial monitor software over USB with simple commands.
  • Dedicated time setting switch allows to set, see and update time anytime you want.
  • Software setting of time means, it can be set pretty accurately with an app running on a computer (a time setting/syncing software based on Processing is under development)
  • Open source - all design files and software codes are available to download with detailed documentation and high resolution images.
Now I'll walk you through the instructions to build this and show you can do the actual current consumption test.

Modifying the Arduino Nano

For this project, you can use a bare microcontroller or use an Arduino Nano or Mini boards. All that required is we must run it with internal oscillator which is 1MHz and at full 1.8 - 5V operating voltage range. The CR2450 or similar Lithium cells have a nominal voltage of 3V, and so we can run the MCU without using a voltage regulator. Chinese clones of Nano and Mini are extremely cheap that you can buy them for the chip's price! I used such a Nano clone that has CH340G as the USB to serial bridge. Below is the one I used. You can download the schematic of this Arduino clone at the end.

arduino birthday reminder nano ch340g clone

Arduino Nano clone with CH340G - top

arduino birthday reminder nano ch340g clone

Arduino Nano clone with CH340G - bottom

I had both ATmega168 and 328 versions. I bought the 168 versions by mistake a few years ago (now I found a use for it). In this particular board you need to remove,

  • The USB to Serial bridge IC which here is the CH340G.
  • The Shchottky diode that is connected to the USB 5V.
  • Two 1K resistors connected to the TX and RX pins of the CH340G.
  • RX, TX and PWR LEDs (SMD)
  • The AMS1117 5V voltage regulator.
I used the LED on digital pin 13 for debugging and as the main flasher, and so I didn't remove it. The capacitors need not to be removed as they'll help attenuate noise. Once the regulator is removed, you need to short the pads of the voltage regulator as shown in the image. This is due to the routing used in the PCB design. Do not remove the crystal oscillator of the MCU yet because we'll need it to change the fuse bits. The MCUs will be having the default Arduino boot-loader and fuse settings that makes it run at external 16MHz crystal. If we remove the crystal before setting the fuse to use internal OSC, we simply can't program the chip with a USBasp ISP programmer. Below is the modified version of the Arduino Nano.

arduino nano clone with ch340g modified

I haven't removed the RX and TX LEDs here yet but you need to.

arduino nano clone with ch340g modified

See how I've shorted the pads of the voltage regulator

Changing the Fuse Bits of ATmega168P

Normally, the chips on the Arduino boards will be coming with the Arduino bootloader and fuse bits. We need to change this in order to run the MCU at a lower power mode. In order to achieve this, we need to,

  • Make the MCU run at 1MHz. We can enable the internal oscillator and also the "divide by 8" bit to produce 1MHz clock from the 8MHz. Less the clock speed, lesser will be the power consumption. We won't be crunching any numbers here, so 1MHz is more than enough.
  • Disable the brown-out detection (BOD) module.
  • Disable all the internal modules such as ADC, Timers etc. We'll do this in software.
  • Disable watchdog timer (WDT).
  • Make all the IO pins inputs and LOW except digital pins 13, 2 and 3.

atmega168p fuse bit configuration

Required fuse bit configuration for ATmega168P

Above is the fuse settings for ATmega168P. Note that you need the "P" versions of the ATmega chips because they have the pico-power (a low power mode) feature. The normal versions (non P) don't support these extra power saving modes. So make sure you get the P versions. You might now wonder why I'm using 168 instead of 328. That's because when I was testing the circuit, 328 seemed consuming around 30uA for the same code and setting I used for 168 which only consumed around 2uA. I don't know why this is. Like I said before, this is the first time I'm fiddling around with power saving modes such as deep sleep. So I must've been missing something. If you know anything about it, please let me know in the comments.

To change the fuse bits, we need an ISP programmer. There are many ISP programmers and compatible softwares. I used the USBasp as programmer and ProgISP (Download) as programming software. The chip ID or signature of the ATmega168P-AU I used was 1E940B. This might change depending on the version you have. To change the fuse bits:

  • Connect the USBasp to Nano. Normally, USBasp will have a 10-pin connector but Nano has 6-pin ISP header. So I made a simple 10-pin to 6-pin adapter. You might need to make something similar or find a cable.
  • Select the MCU model from the list and verify the signature with the RD button.
  • Set the checkboxes and fuse bits as shown in the image above and use the Auto button or the Write button on the fuse setting window to update the fuse bits.

progisp window

ProgISP window

If successful, a message will be printed to the console. From now on, you'll need the ISP to flash the MCU. Below is the USBasp I used.

usbasp avr isp programmer

USBasp AVR Programmer - top

usbasp avr isp programmer

USBasp AVR Programmer - bottom

Compiling and Uploading Firmware

Now that we have changed the fuse bits of our microcontroller, we also need to tell the Arduino software and the compiler about the changes we made so that we can compile the code properly inside the Arduino IDE. How we do this is by adding a custom board definition in the boards.txt file that resides in the Arduino installation directory that is normally at <installed location>/Arduino/hardware/arduino/avr/boards.txt on Windows systems. This might be different for you depending on which OS you have, or version of the IDE you have. I'm using the IDE version 1.8.5

Once we locate the boards.txt file, you need to add a custom definition of a new Arduino Pro Mini board. Around line 655 will be the starting of the existing Pro Mini board definitions. There'll be many versions of the boards. We need to add a new variant. Add the following definition (copy-paste to the text file) to it and save.

## Arduino Pro or Pro Mini (3.3V, 1 MHz) w/ ATmega168 
## -------------------------------------------------- (3.3V, 1 MHz)
adding new arduino board definition

The highlighted part is the newly added board definition

You need to edit the boards.txt while the Arduino IDE is not running. Once you save the new boards.txt file and restart Arduino IDE, you'll see the new board we just added in the list. Take a look at the screenshots below.

adding new arduino board variant

Choose Arduino Pro or Pro Mini from the list

adding new arduino board variant

New variant is now available

Now we're ready to compile Arduino codes for our new board. As we're not using the Arduino Bootloader (BL), we need to create a hex file of the program and use USBasp and ProgISP to flash the microcontroller. We can do this using the "Export compiled binary" option from Sketch menu of the IDE or hit Ctrl + Alt + S. When we do that, two hex files (intel format) will be created in the same directory our sketch resides. One hex file is with BL, and the other is without BL.

arduino ide export compiled binary

Use the Export compiled binary option

arduino ide hex files

Newly created binary HEX files

Once we have the hex file, in the ProgISP choose the Load Flash option to load the hex file we want to flash the MCU with, then hit Auto button. If uploading is success, it'll be printed to the ProgISP's console.

Intersil ISL1208 I2C RTC

intersil isl1208 rtc ic

Intersil ISL1208 RTC IC

The Intersil ISL1208 is a low power RTC IC with I2C interface. It uses an external 32.768 KHz crystal to keep track of the time and has month-date-hour-min-sec alarm registers. It only consumes around 400nA in battery opearation (VBAT) operation and a maximum of 1.2 uA at VDD. The operating voltage is from 1.8V to 5.5V. What make this a good candidate are the low power consumption and the month-date alarm feature. Normal RTCs such as DS1307 doesn't have a month setting in alarm register without which we can't generate a birthday alarm every year. It has an interrupt output pin which will generate a 250mS active LOW signal when the current time matches the alarm date and time. We'll use this to wake the MCU up from sleep mode which I'll explain further below. To learn more about ISL1208 and interfacing it with Arduino with a library, go to my tutorial - Interfacing ISL1208 RTC with Arduino.

As I had an SMD version of the ISL1208 I had to make a little breakout board in order to be plugged onto my main board. Below is what I made.

intersil isl1208 rtc ic breakout board

Intersil ISL1208 RTC breakout board - top

intersil isl1208 rtc ic breakout board

Intersil ISL1208 RTC breakout board - bottom

CR2450N 3V Lithium Coin Cell

This will be the main power source of this project. Specifications for a Renata CR2450 are as follows,

  • Chemical System : Li / MnO2 (According to IEC 60086)
  • Nominal Voltage : 3V
  • Rated Capacity : 540mAh
  • Standard Discharge Current : 0.8mA
  • Max. Cont. Discharge Current : 3.0mA
  • Average Weight : 5.9 g
  • Operating Temperature* : -40 to +85°C
  • Self Discharge at 23°C : < 1%/year
  • Shelf life : up to 10 years

renata 3v lithium coin cell

Renata CR2450 Lithium coin cell - top

renata 3v lithium coin cell

Renata CR2450 Lithium coin cell - bottom


arduino birthday reminder eagle schematic

Arduino Birthday Reminder Eagle schematic - View PDF or Download Eagle file

Use the above schematic to solder the modules on a perfboard. The two 4.7K resistors are the I2C pull-ups. The values can range from 3.3K to above 5.6K. The R2 and R3 are pull-ups for the interrupt pins. Arduino Nano has two hardware interrupt pins - digital pin 3 and 2. Digital pin 2 will be used for the alarm wake up interrupt from the RTC and digital pin 3 will be used to wake the MCU when you need to set the time. Below is the CP2102 USB-to-Serial module I used. You can use any such USB bridge controllers such as FT232R.

cp2102 usb serial breakout board rhydolabz

Silabs CP2102 USB-UART breakout board from rhydolabz

The USB-to-Serial module will be used to communicate over the serial monitor. The RX and TX pins of CP2102 are connected to RX and TX pins of Nano respectively. Note that you shouldn't connect the +5V from the USB to the main VCC voltage. A full tutorial on CP2102 USB-UART bridge controller can be found here - CP2102 USB to Serial Converter.

How Does It Work?

The working of the device actually quiet simple. Let's see how the main algorithm works,

  • Set the current time on the RTC via serial monitor.
  • Set the alarm time and date on the RTC.
  • The MCU goes to sleep mode after setting the time and alarm by disabling the internal peripherals including timers and ADC.
  • When the current time matches the alarm date and time (MM, DD, hh, mm, ss, p) the RTC will generate and interrupt and wake the MCU from sleep.
  • Up on waking up, the MCU will enable the required internal peripherals and print a happy birthday message to the serial monitor. It also flashes the LED inside the dome in a certain pattern.
  • After wishing you a happy birthday, the MCU will go to sleep mode again and will only wake up on your birthday next year.
  • But you can see the time and update it whenever needed by turning the time update switch ON.

When powered up for the first time, all RTC registers will be zero and it doesn't increment until we first write to any of them. To set the time on the RTC,

  • Turn the time update switch ON (connects the digital pin 3 to GND). We can not set time without pulling the pin 3 LOW.
  • First connect the device to your computer with a USB cable. A COM port will be established on your PC to communicate.
  • Find the COM port of the device from device manager.
  • Open any serial monitor software or Arduino serial monitor with the COM port of the device.
Serial Established.
Ready to update time.
  • Sending t command will print the current time, a will print the alarm date and time, and c will cancel the time setting operation and put the MCU into sleep mode after 6 seconds.
  • You need to send the current time in the format shown below,


  • T = indicates time information
  • YY = least significant digits of a year (eg. 18 for 2018, range is from 00 to 99)
  • MM = month (eg. 01 for January, range is 01 to 12)
  • DD = date (eg. 24, range is 01 to 31)
  • hh = hours (eg. 06, range is 01 to 12 for 12 hour format)
  • mm = minutes (eg. 55, range is 00 to 59)
  • ss = seconds (eg. 30, range is 00 to 59)
  • p = period of the day for 12 hour format (0 = AM, 1 = PM)
  • # = delimiter

For example, to set the time and date 08:35:12 AM, 05-01-2018, we should send:



  • T = indicates time information
  • 18 = the year 2018
  • 01 = month January
  • 05 = date
  • 08 = hours
  • 35 = minutes
  • 12 = seconds
  • 0 = AM
  • # = delimiter

If the operation is successful, the MCU will print the received time to the console as:

Time update received = T1801050835120
Date and Time is 8:35:12 AM, 5-1-18

If the time string you entered is invalid, the below message will be printed:

Invalid time input - <original string>, <length of original string>

Once you successfully set the time, the RTC will keep track of it as long as there's power available to it. You can verify the time you just set by sending the t command. Setting the alarm is similar to this except the data format is different. To set the alarm you need to send it as:



  • A = indicates alarm information
  • MM = month
  • DD = date
  • hh = hours
  • mm = minutes
  • ss = seconds
  • p = time period (0 = AM, 1 = PM)
  • # = delimiter

Note that there's no year information with the alarm string because obviously we don't need it. For example to set my birthday 08:00:00 AM, 28-08, I need to send:


You can check the alarm time anytime with the command a. Once the alarm time and date are set it's time to put the MCU into sleep. Then the device will print the following message:

Everything's set. Please disable the time set pin now.

Now you need to turn the time setting switch OFF ie, pull the digital pin 3 HIGH (the 10K pull-up will do that). The system won't sleep until you do this. When the time setting switch is turned OFF, the device will enter into sleep mode in 6 seconds and print the below message before it.

Well done! Sleeping in 6 seconds..

So that's how you set the time and alarm. Now, whenever you need to check the time or update it, you can turn on the timer setting switch and the system will wake up, establish serial communication and prompt you to send the time. It will print the following message up on waking up,

Serial Established.
Time update wake up.
Ready to update time.

If you're just checking if time is correct and don't want to change anything, send c command to cancel the operation and put the system into sleep again. You need to also disable the time setting switch at this point.

When the current time matches the alarm time ie. your birthday, the RTC will generate a 250mS interrupt signal to the digital pin 2 of the Nano board. This signal will wake up the system. Up on waking up, the device will know that it's your birthday and will establish serial communication (only if you have the USB connected) and print the following message,

Tada! It's your birthday! Happy B'Day <your name> :)
See you on your next birthday! TC. Bye!
Sleeping in 6 seconds..

And it'll also flash the LED connected to digital pin 13. Here's a screenshot of the Arduino serial monitor while I was testing the system.

arduino serial monitor window

Arduino Serial monitor window

So that's how you operate this device. To understand this in the code level, read the next section.


This project is completely open source and therefore I've published the source code for the firmware on my GitHub at under MIT License. You're free to adapt, modify and redistribute without any restrictions. If you would add a backlink to this project from your modified one, that'd be appreciated. I've thoroughly commented the code and made it straight forward wherever possible.

We have total 13 functions/procedures in the code. They are:

1. void setup()

This is the Arduino's setup function that will initialize everything and set the configuration registers of the ISL1208 RTC.

2. void loop()

The main loop function.

3. void sleepNow()

This function terminates all communications, disables the MCU's internal peripherals, attaches the interrupts to digital pins 3 and 2, and puts the system into deep sleep mode. Up on any interrupt, the program execution continues from the line after sleep_mode(). Note that before this normal program execution resumes, the MCU would've completed the interrupt service routines (ISRs) associated with the interrupt pins which are alarmInterrupt() and timeUpdateInterrupt().

4. void alarmInterrupt()

The ISR associated with the INT0 interrupt on digital pin 2.

5. void timeUpdateInterrupt()

The ISR associated with the INT1 interrupt on digital pin 3.

6. void fetchTime()

fetchTime() reads the time registers of the RTC and will print the current time to the console.

7. void blinkLED()

Blinks the LEDs obviously.

8. bool establishSerial()

Establishes serial communication with the help of USB-to-Serial module.

9. bool endSerial()

Ends serial communication.

10. byte bcdToDec(byte)

Accepts a BCD (Binary Coded Digits) value and translate it into corresponding decimal value. We need this because the RTC registers only stores and accepts BCD values. Therefore we need to convert to and from BCD occasionally.

11. byte decToBcd(byte)

Accepts a decimal value and translates it into corresponding BCD value.

12. void printTime()

Reads the RTC time registers and prints the current time to the console when t command is received.

13. void printAlarmTime()

Reads the RTC alarm registers and prints the alarm time and date to the console when the a command is received.


arduino birthday reminder breadboard prototype

Prototype on breadboard

This would be the most interesting part of this project where you'll know how I ended up making a device that run for 50 years on a coin cell! I first prototyped the entire circuit on a breadboard and finalized the design. A Li-Ion battery (3.6V) was used for testing purpose so as to save my brand new coin cells. I used my Fluke 87 True RMS multimeter for the current measurements. It has a 0.1uA precision for the micro ampere range.

arduino birthday reminder breadboard prototype testing

My table - all basic stuff!

Let's see how we can put the Atmega168P into deep sleep mode and reduce the current consumption drastically.

noInterrupts (); //temporarily disable interrupts
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Choose our preferred sleep mode:
sleep_enable(); // Set sleep enable (SE) bit:
ADCSRA = 0; //disable ADC
power_all_disable(); //disables all modules
digitalWrite(LED_PIN, LOW); //turn LED off to indicate sleep
interrupts(); //re-enable interrupts
sleep_mode(); //goes to sleep

As I've said before, this is the first time I;m using sleep modes in a microcontroller (MCU) because I've never needed it before. Most of the information related to AVR sleep modes was found from this forum thread and the AVR library documentation.

ATmega168P has five sleep modes.

  • SLEEP_MODE_IDLE – least power savings
  • SLEEP_MODE_PWR_DOWN – most power savings

More info on the sleep modes can be found here and in this video. We're using the SLEEP_MODE_PWR_DOWN mode as you can see there. At this mode, the current consumption at 3.6V is only around 0.2 uA. See the below graph from the ATmega168PA datasheet that shows the relation between active current vs supply voltage and power down current vs supply voltage.

atmega168 active current graph

Around 0.5uA at 3.6V (we're using internal oscillator)

atmega168 power down current graph

Between 0.1 and 0.2uA at 3.6V and 25°C

Here's the actual reading of the current consumed by sleeping ATmega168P @1MHz.

arduino birthday reminder multimeter test

The (-) sign is because I had connected the probes in reverse

The value hops between 0.1uA and 0.2uA due to the lack of enough precision. Such a precise measurement isn't necessary but would've been interesting to see.

The power consumption of ISL1208 RTC at max is 1.2uA. So if we add this with the power down mode current consumption of the MCU we get 1.2 + 0.2 = 1.4uA. My meter measured between 1.4uA and 1.6uA which justifies the calculations. The variations is only due to the lack of precision and our approximation or rounding of numbers.

arduino birthday reminder multimeter test

Screenshot taken from video below

Here's an unlisted video from my YouTube channel where I show the testing.

Now let's do the simple math to find how long we can the system on a coin cell. The CR2450N from Reneta has a nominal capacity of 540mAh. I have two red SMD LEDs on the system which consume about 6mA (even with two LEDs) with when turned ON. So that is the peak current consumption of the device at worst. How long these LEDs light up can be summarized as,

  1. As long as the time setting switch is activated while you're setting the time (but you don't have to do this every year)
  2. The 6 second delay before sleep.
  3. LED flashes on your birthday and stays ON for about 19 seconds.

Let's not be accurate here but just make an approximation. Let's assume the time setting requires 2 minutes (LEDs will be ON for 2 mins) and and additional 1 minute ON time for other things including the birthday flashing. So it's total 3 minutes or 180 seconds for which the system consumes 3mA current. Let's take the sleep or idle current as 1.6uA, though it's lower actually. There is 31557600 seconds in a year of 365.25 days. If LEDs stay ON for 180 seconds in a year and OFF for (31557600 - 180) seconds, then the average current consumption will be,

Average Current = [((6 x 10^-3) x 180) + ((1.6 x 10^-6) x 31557420))] / 31557600
                = (1.08 + 50.491872) / 31557600
                = 51.571872 / 31557600
                = 1.634 x 10^-6 = 1.634 uAh

If the average current consumption is 1.634uAh, then the 540 mAh cell can run the device for:

Time Span (approx) = (540 x 10^-3) / (1.634 x 10^-6) = 330477.3562 hours
                   = 13769.88 days
                   = 37.699 years

Note that this is an approximation and does not consider self-discharge of the battery. It'll be taken into account later. You can also use the ElectroDroid app to calculate battery life. Here's a screenshot of the calculations we just did.

arduino birthday reminder electrodroid calculation

But wait... Can we reduce the current consumption further ? YES WE CAN! I made further optimizations to the design to limit the average current consumption to 0.6uA. Now let's see what optimizations I did,

  1. To remove the extra red SMD LED to reduce the current when the system is active/running. Before it was 6mA at max with two LEDs. So with one LED, it'll be reduced to half, ie 3mA.
  2. To reduce the current consumption of RTC, we need to disconnect the VDD pin of the ISL1208 RTC from the VBAT pin. Previously the VDD pin was connected to the VBAT pin where I supplied the 3V from the cell (you can see this in the schematic). In that configuration, I also had the LOW_POWER mode bit (LPMOD) of the RTC set to 1, activating the low power mode. So now you might think if the low power mode is set, then the chip should be consuming the lowest current. But that's not the case when we have the VDD tied to VBAT. Because low power mode bit is only useful if we have VDD > VBAT all the time. At such situations, the RTC's internal power switch will select VBAT as power source reducing the current further by 600nA when VDD >= VBAT (from typical 1.2uA which I've mentioned before). But if we can run the RTC in VBAT only with VDD = 0, the current consumption can be reduced to the minimum ie, 400nA as per the datasheet. So what I did was, first I disabled the low power mode by setting LPMOD to 0. Then added a jumper to the RTC breakout board to disconnect the VDD pin from VBAT when we don't need it. Why need the jumper is because, the VDD pin must be greater than or equal to VBAT in order for the I2C to work. So we can connect the jumpers when we need I2C while we're setting the time, and can disconnect it after. This will let the RTC to consume the targeted 400nA current. Tada! We did it. Read more about this on the ISL1208 RTC Tutorial.

Now that we have reduced the current consumption of the RTC from 1.2uA to 0.4uA (400nA), we can do the math again!

System Active Current = 3mAh max
System Sleep Mode Current = 0.4uA (RTC) + 0.2uA (MCU) = 0.6uAh
System ON time = 60s (time setting) + 19s (birthday flashing) + 6s (before sleep) = 85 seconds
System Sleeping Time = 31557600s - 85s = 31557515 seconds
Total time in a year = 31557600 seconds
Battery capacity = 540mAh

If we put those new values to the ElectroDroid's battery life calculator, we get, 101 years and 136 days. A theoretical operating time of more than a century! The average current consumption is now only 608 nA. Here's the screenshot.

arduino birthday reminder electrodroid calculation

arduino birthday reminder current consumption test

The sleep mode current measured by Fluke 87

Here's the current consumption test video after the optimizations and mods.

Okay, What's the actual operating time ?

Batteries aren't perfect, nor anything we design. So let's also consider the 1% self discharge of the cell into account.

1% of initial capacity of 540mAh CR2450N = 5.4mAh

Self-discharge current = 5.4mA per year or 616.4nAh (5.4mA / hours in a year)

Adding this 616.4nAh with the 600nAh sleep current = 1.216uAh

Expected operating time with average current of 1.224uAh = 50 years, and 131 days

That's the actual operating time if the cell will be fine. Below is a table of actual operating times of different types of coin cells with the 1% self-discharge of initial capacity every year.

Cell Capacity Self-discharge Current Isd *Average Current Consumption Expected operating time
225mAh (CR2032) 256nAh 864nAh 29 years, 264 days
540mAh (CR2450N) 616.4 nAh 1224nAh (1.22uAh) 50 years, 131 days
950mAh (CR2477N) 1084 nAh (1.084uAh) 1692nAh (1.692uAh) 64 years, 33 days

*Average current is calculated with 3mA active current and (Isd + 600 nA) sleeping current and doing the same math we previously did.

The main practical concerns associated with running the device for such long periods are,

  1. Will the battery retain the charge and voltage for that long ?
  2. The effects of environmental variations on the circuit and battery performance.
  3. And you screwing up things! XD (don't drop it, chew it, sit on it, run your car through it or launch it into space!)

Coin cells are usually made to last for 10 years, which is their shelf life, and some even last longer than that. But that doesn't mean they'll start to disintegrate to a useless state after that. If the cell is physically fine, it can still power things up. As per Renata datasheet, the self-discharge rate of CR2450N is less than 1% of the capacity every year. As per this datasheet from Energizer, that 1% figure is of the fresh capacity. Below is a chart that shows the standard discharge time in years (this doesn't consider the self-discharge or other exceptions). It clearly shows the theoretical expected operating time is way too longer than 10 years.

coin cell discharge time graph

Source : Renata

coin cell discharge performance graph

Discharge performance of CR2450N. Source : Renata

Self-discharging not only reduces the capacity but also reduces the voltage. Both ATmega168P and ISL1208 are designed to be operated fine at voltages as low as 1.8V. So the reduction in voltage might not be a problem. You can learn more about running systems with coin cells here.

To ensure long operating span, we must make sure the device is properly concealed against much of the environmental changes such as temperature, humidity, corrosion etc. These are some things you can do to protect your circuits,

  1. Coat the PCB with long lasting conformal coating.
  2. Place a pack of silica gel inside the enclosure.
  3. Seal the enclosure with less temperature conductive materials and make it air tight.
  4. Place it somewhere safe from naughty hands!


I used a perfboard to solder everything as per the schematic. Used berg connectors for the battery, switch and LED so that it'll be easy to remove them if needed. Below are some images of the PCB.

arduino birthday reminder pcb

arduino birthday reminder pcb

One jumper was needed

To build the enclosure I used a 4" x 4" switch box which I bought from an electrical shop. I made two rectangular holes for the switch and USB. You can 3D print an enclosure if you want; sadly I don't have one. The dome was snatched from a cheap LED light and used super glue to fix it on the box. I painted it with silver spray paint.

arduino birthday reminder pcb box

arduino birthday reminder pcb box

arduino birthday reminder box

arduino birthday reminder led

Use your ingenuity to build it.

arduino birthday reminder led

arduino birthday reminder coin cell

arduino birthday reminder dome

What missing is some decorations. I'm not good at decorating things. If you are going to gift this to someone, you know what to do.

arduino birthday reminder usb

USB port

arduino birthday reminder time switch

Time setting switch (SPST)

arduino birthday reminder completed

The final output is satisfying to the extend of my hard work. I might find someone else to decorate it.


There's always room for improvement. Some of my suggestions are,

  1. Using a Nokia 5110 LCD with or instead of the LED bulb. The LCD controller only consumes a couple of 100uA at normal operating modes without the LED backlighting of course. Monochrome LCDs only consume extremely low currents. So using it would be better than a flashing LED, where you can actually print the happy birthday message on the screen itself. I might do this in future because I have couple of them lying around here.
  2. A software that runs on the computer that'll set/sync the time accurately and automatically. I'm thinking of developing a simple one using Processing.
  3. Flashing the LEDs to indicate your age - for example if it's your 5th birthday (Wow are you're reading this?!), it'll flash a sequence for 5 times. Currently you can not set the age in the system. You may add this.
  4. Designing a dedicated PCB in eagle (planned).
  5. If blinking LED isn't your thing you can actually make this more exciting with for example using an opto-coupler you can turn on an AC alarm, music player, lights or anything you want to blink, move and scream on the birthday of the one you wish. You can even exclude the microcontroller and only use the interrupt from the RTC. Everything is possible.

So what are you waiting for? Make one, decorate it with stickers, color papers, glitter or anything and gift to your loved ones or even yourself! And tell them to wait for this magical device to wish them happy birthday. What you see here is actually a prototype of a device that I'll refine and release in future. So stay tuned. Please feel free to share if you have found any errors with this documentation or have any improvement suggestions. Happy making.



Date published : 4:07 PM, 05-02-2019, Tuesday
Last updated : 9:28 PM, 05-02-2019, Tuesday


Made with for Open Source
Copyright © 2014 - 2021  Vishnu M Aiea
Site last updated : IST 11:38 PM 20-01-2020, Monday
Page rendered in 0.0313 seconds. Version 1.2.7