Help Needed: 12-Hour RTC Countdown TFT Display and servo

I'm working on an Arduino project and I'd really appreciate your help in reviewing or improving my code. Here's what I'm trying to achieve:

  • Arduino Mega 2560

  • DS3231 RTC module

  • 1.8" SPI TFT LCD (ST7735 driver, 128x160, using Adafruit_ST7735 library)

  • Tower Pro SG-5010 servo motor

  • External 5V power supply for the servo

  • I want to create a 12-hour countdown timer based on the real-time clock (DS3231).

  • The countdown is displayed on the TFT screen.

  • Once the 12 hours are over:

  • The servo motor rotates from 0° to 180°, waits, and returns back to 0°.

  • A new 12-hour countdown begins.

can someone help me to this project?

You forgot to post your code.
Also, have you already tested separately all your components?

You need to install the following libraries.
RTClib (by Adafruit)
Adafruit GFX Library
Adafruit ST7735 and ST7789 Library
Servo

Please take some time and read the following:

Are you working with this person (Mertgulec)

#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <Servo.h>

// TFT ekran pinler
#define TFT_CS     53
#define TFT_RST    49
#define TFT_DC     48

Adafruit_ST7735 ekran(TFT_CS, TFT_DC, TFT_RST);
RTC_DS3231 rtc;
Servo motor;  

const int MOTOR_PIN = 6;  // servo motor sinyal pini
DateTime sonTetiklemeZamani; // en son servo motorun çalıştığı zaman
bool sayacAktifMi = true;     // sayaç şu anda çalışıyor mu sorgusu

void setup() {
  Serial.begin(9600);
  Wire.begin(); // I2C haberleşmesi

  // TFT ekran başlatma
  ekran.initR(INITR_BLACKTAB);
  ekran.setRotation(1);
  ekran.fillScreen(ST77XX_BLACK);
  ekran.setTextSize(2);
  ekran.setTextColor(ST77XX_WHITE);

  // RTC modülü başlatma
  if (!rtc.begin()) {
    ekran.setCursor(0, 0);
    ekran.println("RTC bulunamadi!");
    while (1); // RTC yoksa kod kesilir
  }

  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // servo motor 0 dereceye ayarlama
  motor.attach(MOTOR_PIN);
  motor.write(0);

  // başlangıç zamanı çalıştığı saat
  sonTetiklemeZamani = rtc.now();
}

void loop() {
  DateTime simdi = rtc.now();  // Şu anki zamanı oku

  //yeni gün sorgusu
  TimeSpan kalanSure = TimeSpan(0, 12, 0, 0) - (simdi - sonTetiklemeZamani);

  // TFT ekran temizle yazdır
  ekran.fillScreen(ST77XX_BLACK);
  ekran.setCursor(10, 10);

  if (kalanSure.totalseconds() > 0) {
    // sayaç hala devam ediyorsa geri sayımı yazdır

    int saat = kalanSure.hours();
    int dakika = kalanSure.minutes();
    int saniye = kalanSure.seconds();

    ekran.print("Geri Sayim:");
    ekran.setCursor(10, 40);
    yazSaatiYaz(saat, dakika, saniye);
  } else {
    // motor çalıştır ve sayaç sıfırla

    if (sayacAktifMi) {
      ekran.setTextColor(ST77XX_GREEN);
      ekran.setCursor(10, 20);
      ekran.println("MAMA VAKTİ!!");
      ekran.setCursor(10, 50);
      ekran.println("MAMA DÖKÜLÜYOR!");

      delay(1000);

      // servo motoru 0 - 180
      motor.write(180);
      delay(2000);
      motor.write(0);
      delay(2000);

     
      sonTetiklemeZamani = simdi;

      sayacAktifMi = false;
    }
  }

  // sayaç kapalıysa ve tetiklemeden 10 saniye geçerse baştan başlat
  if ((simdi - sonTetiklemeZamani).totalseconds() > 10 && !sayacAktifMi) {
    sayacAktifMi = true;
  }

  delay(1000); //ekranı her saniye güncelle
}

// saat biçimi saat dakika saniye örnek 10:27:54
void yazSaatiYaz(int saat, int dakika, int saniye) {
  if (saat < 10) ekran.print("0");
  ekran.print(saat); ekran.print(":");

  if (dakika < 10) ekran.print("0");
  ekran.print(dakika); ekran.print(":");

  if (saniye < 10) ekran.print("0");
  ekran.print(saniye);
}

here its my code

yes he is my brother why?

Because some people will create two accounts which is against forum rules.

I didn't know my brother created an account, Im sorry for that.

You could do a 12 hour countdown timer just using millis() with no real-time clock. Does your countdown have to happen from a particular time of day?

no, the countdown will start as soon as the arduino board is powered. how do I do what you say?

Something like this. It compiles, but I haven't tested it. There may be mistakes in it. I haven't provided code to convert the time remaining calculation to hh:mm:ss. You should understand how to do that.

void setup() {
}

void loop() {
  const unsigned long period = 43200000UL; // 1000 x 60 x 60 x 12
  static unsigned long previousActivationTime = 0;
  unsigned long timeNow = millis();
  if (timeNow - previousActivationTime > period) {
    // Add your code for the servo here
    previousActivationTime = timeNow;
  }
  // For displaying count down time, once a second?
  static unsigned long previousClockUpdateTime = 0;
  timeNow = millis();
  if (timeNow - previousClockUpdateTime >= 1000) {
    previousClockUpdateTime = timeNow;
    // Convert period-(timeNow - previousActivationTime) to hh:mm:ss for display
  }
}

Try it, and if you have problems then come back and ask more questions. I suggest you reduce the value of period for testing and add some Serial.println()s to print when servo will be activated and print when count down updates. I.E. just use the above code with Serial.println()s added until you are happy it's working and you understand how it works

so i can use millis() and eeprom am i right?

#include <EEPROM.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <Servo.h>

// TFT display pin configuration
#define TFT_CS     53
#define TFT_RST    49
#define TFT_DC     48

#define MOTOR_PIN 6
#define EEPROM_ADRESI 0
#define BEKLEME_SURESI 43200000UL  // 12 hours in milliseconds (12*60*60*1000)

Adafruit_ST7735 ekran(TFT_CS, TFT_DC, TFT_RST);
Servo motor;

unsigned long sonTetiklemeZamani = 0;  // Last time the servo was activated
bool sayacAktifMi = true;              // Is the countdown currently active?

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

  // Initialize TFT screen
  ekran.initR(INITR_BLACKTAB);
  ekran.setRotation(1);
  ekran.fillScreen(ST77XX_BLACK);
  ekran.setTextSize(2);
  ekran.setTextColor(ST77XX_WHITE);

  // Initialize servo motor
  motor.attach(MOTOR_PIN);
  motor.write(0);  // Set initial position to 0 degrees

  // Read last activation time from EEPROM
  EEPROM.get(EEPROM_ADRESI, sonTetiklemeZamani);

  // If EEPROM is empty or contains invalid data, use current millis
  if (sonTetiklemeZamani == 0 || sonTetiklemeZamani > millis()) {
    sonTetiklemeZamani = millis();
  }
}

void loop() {
  unsigned long simdi = millis();
  unsigned long gecenSure = simdi - sonTetiklemeZamani;

  // Clear TFT and write updated countdown
  ekran.fillScreen(ST77XX_BLACK);
  ekran.setCursor(10, 10);

  if (gecenSure < BEKLEME_SURESI) {
    // Countdown is ongoing, display remaining time

    unsigned long kalanMs = BEKLEME_SURESI - gecenSure;

    int saat = kalanMs / 3600000UL;
    int dakika = (kalanMs % 3600000UL) / 60000UL;
    int saniye = (kalanMs % 60000UL) / 1000UL;

    ekran.print("Countdown:");
    ekran.setCursor(10, 40);
    yazSaatiYaz(saat, dakika, saniye);
  } else {
    // Countdown finished, activate the servo motor

    if (sayacAktifMi) {
      ekran.setTextColor(ST77XX_GREEN);
      ekran.setCursor(10, 20);
      ekran.println("FEEDING TIME!!");
      ekran.setCursor(10, 50);
      ekran.println("DISPENSING FOOD");

      delay(1000);

      // Move servo to 180 degrees and back to 0
      motor.write(180);
      delay(2000);
      motor.write(0);
      delay(2000);

      // Save new activation time to EEPROM
      sonTetiklemeZamani = millis();
      EEPROM.put(EEPROM_ADRESI, sonTetiklemeZamani);
      sayacAktifMi = false;
    }
  }

  // Reactivate the countdown 10 seconds after the servo triggers
  if ((millis() - sonTetiklemeZamani) > 10000 && !sayacAktifMi) {
    sayacAktifMi = true;
  }

  delay(1000);  // Update the display every second
}

// Display time in hh:mm:ss format
void yazSaatiYaz(int saat, int dakika, int saniye) {
  if (saat < 10) ekran.print("0");
  ekran.print(saat); ekran.print(":");

  if (dakika < 10) ekran.print("0");
  ekran.print(dakika); ekran.print(":");

  if (saniye < 10) ekran.print("0");
  ekran.print(saniye);
}

is there any place where you see an error sir?

If you want the 12 hour countdown to work across periods when there is no power to your Arduino, then you are back to using a real time clock, because the Arduino has no way of knowing how long the power was off. EEPROM won't help you.

When you said that, it made me think you didn't want to take into account power off periods.

I don't have time to check your code for you. Why don't you do what I said:

Or run your own code and see whether it works or not.
I strongly suggest you work with small parts of your code first, get them working, then add more parts to your code, check it works again, etc.

Thank you for your help, I will try, should I contact you if I have problems?

Post back here if you have problems then I, or someone else, will help you.

1 Like