How to Build Your Own DIY Programmable Arduino Countdown Timer with 16×2 LCD Display

https://ogbugbu-technologies.com.ng

Whether you’re building a kitchen timer, a darkroom exposure controller, or a timed charging station, a programmable relay timer is a classic “must-have” project. This guide breaks down the code and hardware for a professional-grade countdown timer with an LCD interface and EEPROM memory—which means it remembers your last set time even if you unplug it!


The Components: What’s Under the Hood?

To build this project, you need a few specific parts. Here is why each one is vital:

ComponentPurpose
Arduino Uno / NanoThe “brain” that processes the logic and counts the seconds.
I2C LCD (16×2)Displays the countdown and the setup menu. The I2C module on the back saves you from wiring 12+ pins, reducing it to just 4.
Relay Module (5V)Acts as a smart switch. It allows the low-power Arduino to turn high-power devices (like a lamp or motor) ON and OFF.
Active BuzzerProvides an audible alert once the timer reaches zero.
Push ButtonsUsed for user input (Set, Up, Down, and Start/Reset).

The Wiring Guide

Connecting the components is straightforward if you follow the I2C and Analog pin assignments.

  • LCD Display: Connect SDA to A4 and SCL to A5. Power it via the 5V and GND pins.
  • Input Buttons: Use pins A0, A1, A2, and A3. These are configured as INPUT_PULLUP, so you only need to wire the button between the pin and GND.
  • Relay & Buzzer: Connect the Relay signal to Pin 5 and the Buzzer to Pin 6.

How the Code Works

The code uses three main libraries to keep things running smoothly:

  1. LiquidCrystal_I2C.h: Manages the screen via the I2C protocol.
  2. Countimer.h: A specialized library that handles the “ticking” logic in the background so the screen doesn’t flicker.
  3. EEPROM.h: This is built into Arduino. It saves your HH:MM:SS settings to the chip’s permanent memory.

Key Features of the Script:

  • Setting the Time: By tapping the Set button, you cycle through Seconds, Minutes, and Hours. Use Up/Down to adjust the values.
  • Memory Save: Every time you adjust the time, the code calls eeprom_write(). This ensures that if you lose power, your timer doesn’t reset to zero.
  • The Relay Trigger: When the timer is active (flag2 == 1), the relay is closed. When the timer hits $00:00:00$, the relay opens and the buzzer triggers a “beep-beep-beep” sequence.
  • The “Long Press” Reset: We added a custom logic that monitors how long you hold the Set button. If held for more than 1.5 seconds, it wipes the timer back to zero.

Arduino Code

#include <Wire.h> 
#include <LiquidCrystal_I2C.h> 
#include "Countimer.h"
#include <EEPROM.h>

// Try 0x27 if 0x3F didn't work
LiquidCrystal_I2C lcd(0x27, 16, 2); 

Countimer tdown;

#define bt_set    A3
#define bt_up     A2
#define bt_down   A1
#define bt_start  A0

int time_s = 0;
int time_m = 0;
int time_h = 0;

int set = 0;
int flag1=0, flag2=0;

int relay = 5;
int buzzer = 6;

// For Reset Logic
unsigned long buttonPressTime = 0;
bool isPressing = false;

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

  pinMode(bt_set,   INPUT_PULLUP);
  pinMode(bt_up,    INPUT_PULLUP);
  pinMode(bt_down,  INPUT_PULLUP);
  pinMode(bt_start, INPUT_PULLUP);

  pinMode(relay, OUTPUT);
  pinMode(buzzer, OUTPUT);
  
  digitalWrite(relay, LOW);
  digitalWrite(buzzer, LOW);

  lcd.init();        
  lcd.backlight();   

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("   Timer Ready  ");
  
  tdown.setInterval(print_time, 999);
  eeprom_read();
  delay(1000);
  lcd.clear();
}

void print_time(){
  if(time_s > 0 || time_m > 0 || time_h > 0){
    time_s--;
    if(time_s < 0) { time_s = 59; time_m--; }
    if(time_m < 0) { time_m = 59; time_h--; }
  }
}

void loop() {
  tdown.run();

  // --- RESET LOGIC ---
  if(digitalRead(bt_set) == LOW) {
    if(!isPressing) {
      buttonPressTime = millis();
      isPressing = true;
    }
    // If held for 1.5 seconds, Reset to Zero
    if(millis() - buttonPressTime > 1500) {
      time_s = 0; time_m = 0; time_h = 0;
      set = 0;
      flag2 = 0;
      tdown.stop();
      digitalWrite(relay, LOW);
      eeprom_write();
      lcd.clear();
      lcd.print("  Timer Reset!  ");
      delay(1000);
    }
  } else {
    // Normal Mode Switching on short release
    if(isPressing && (millis() - buttonPressTime < 1500)) {
       set++;
       if(set > 3) set = 0;
       delay(100);
    }
    isPressing = false;
  }

  // Up Button
  if(digitalRead(bt_up) == 0) {
    if(set == 0) { tdown.start(); flag2 = 1; }
    if(set == 1) { time_s++; if(time_s > 59) time_s = 0; }
    if(set == 2) { time_m++; if(time_m > 59) time_m = 0; }
    if(set == 3) { time_h++; if(time_h > 99) time_h = 0; }
    if(set > 0) eeprom_write();
    delay(200); 
  }

  // Down Button
  if(digitalRead(bt_down) == 0) {
    if(set == 0) { tdown.stop(); flag2 = 0; }
    if(set == 1) { time_s--; if(time_s < 0) time_s = 59; }
    if(set == 2) { time_m--; if(time_m < 0) time_m = 59; }
    if(set == 3) { time_h--; if(time_h < 0) time_h = 99; }
    if(set > 0) eeprom_write();
    delay(200); 
  }

  // Start Button
  if(digitalRead(bt_start) == 0) { 
    flag2 = 1; 
    digitalWrite(relay, HIGH); 
    tdown.restart(); 
    tdown.start();
  }

  // Display logic
  lcd.setCursor(0,0);
  if(set == 0) lcd.print("      Timer     ");
  else if(set == 1) lcd.print("  Set Timer SS  ");
  else if(set == 2) lcd.print("  Set Timer MM  ");
  else if(set == 3) lcd.print("  Set Timer HH  ");

  lcd.setCursor(4,1);
  if(time_h <= 9) lcd.print("0"); lcd.print(time_h); lcd.print(":");
  if(time_m <= 9) lcd.print("0"); lcd.print(time_m); lcd.print(":");
  if(time_s <= 9) lcd.print("0"); lcd.print(time_s); lcd.print("   ");

  // End of Timer
  if(time_s == 0 && time_m == 0 && time_h == 0 && flag2 == 1) {
    flag2 = 0;
    tdown.stop(); 
    digitalWrite(relay, LOW);
    for(int i=0; i<3; i++) {
      digitalWrite(buzzer, HIGH); delay(300);
      digitalWrite(buzzer, LOW);  delay(200);
    }
  }

  if(flag2 == 1) digitalWrite(relay, HIGH);
  else digitalWrite(relay, LOW);

  delay(1);
}

void eeprom_write() {
  EEPROM.write(1, time_s);  
  EEPROM.write(2, time_m);  
  EEPROM.write(3, time_h);  
}

void eeprom_read() {
  time_s = EEPROM.read(1);
  time_m = EEPROM.read(2);
  time_h = EEPROM.read(3);
  // Prevent EEPROM garbage values (255) from breaking the timer
  if(time_s > 59) time_s = 0;
  if(time_m > 59) time_m = 0;
  if(time_h > 99) time_h = 0;
}

Troubleshooting Tips

  1. Blank Screen: If the backlight is on but no text appears, turn the blue potentiometer on the back of the I2C module to adjust the contrast.
  2. Buttons Unresponsive: Ensure the buttons are connected to GND. Since we use INPUT_PULLUP, the pin needs to be pulled to ground to register a press.
  3. Relay Not Clicking: Make sure your power source provides enough current (mA). If the Arduino is powered by a weak laptop USB port, the relay might not have enough juice to flip the internal switch.

About ogbugbu-technologies.com.ng

View all posts by ogbugbu-technologies.com.ng →

Leave a Reply

Your email address will not be published. Required fields are marked *