How to control timed servo with RTC? (DS1302)

Hello, I want to make a system that will work 3 times a day at the hours I set with the DS1302 RTC clock module, and I also want to write an article showing how much time is left on the 2IC LCD screen, etc. How can I code this? Since I would only control the servo, I did not want to use a timed relay. I've been dealing with the ridiculous codes given by chatgpt since the morning, please someone help me with this.

Welcome to the forum

To make your project work you need to know 4 times, ie the 3 times that the servo should be triggered and the current time

The clumsy but easy way to do this is to read the time from the RTC to get the current hour and minute every time that the minute changes and then to compare the current hour and minute with the target hours and minutes.

When the current hour matches one of the 3 trigger hours and the current minute matches the second of the same target time then activate the servo

  • Do you know how to read the current hour and minute from the RTC and put them in variables ?
  • Do you know how to compare the current values with the target values ?

NOTE : There is a much neater way to do this that does not involve comparing hours and minutes, but I suspect that you are not ready to use it

As you have the current time and know the target time then subtracting one from the other and displaying it is not that difficult

There is no one on the internet who does what I want. There are systems made with relays everywhere. Building the circuit is easy, but the hardest part is coding. I want to finish the project before it even starts.

may be instead of asking chatGPT for half a day you could have invested the same amount of time reading about C++ and practicing with RTC examples... a bit of knowledge goes a long way...


PS you also need an extra time : the duration of the servo trigger

Since there is no ready code with which I can do this right now, I think I need to code it entirely myself. I can start by learning C++ :slight_smile:

The beauty of coding is that you make the program and associated hardware do what you want

You will certainly find examples on the Internet, indeed even in the IDE, that show you how the elements of what you want to do can be coded

Think of these elements, such as reading the time from the RTC, as ingredients in a recipe that you put together to give a result that meets your needs

How many of these ingredients have you got working ?

can you clarify what the servo needs to do "3 times a day" ?

Now the project is actually an automatic feeding machine. I'll put a round cap on it. For example, it will work at 13.00, 15.00 and 17.00 a day. At 13:00, it will rotate 180 degrees, that is, it will turn the lid. After stopping like this for about 5 seconds, it will turn 180 degrees and return to its previous position. I will repeat this 3 times at different times of the day.

ok - so do you know how to write a code that reads the current time ?

Even better. No minutes to worry about !

ie, when hour becomes equal to 13, 15 or 17, move the servo through 180 degrees then about 5 seconds later move it back

I think I can write there are so many examples

there is a library

I've been working on something that seems very simple for two days :slight_smile:

Have you been trying to write the whole sketch at once or just parts of it ?

From the questions that we are asking I think that you can see which direction @J-M-L and I are taking you. ie, get sections of your requirements working then combine them

At first, to understand the logic, I made something that transferred the current time to the serial monitor using RTC, then I tried to do the whole project but of course I couldn't do it.

may be something like this (typed here)

#include <Ds1302.h> // https://www.arduino.cc/reference/en/libraries/ds1302/
#include <Servo.h>

Ds1302 rtc(PIN_ENA, PIN_CLK, PIN_DAT);

Servo servo;
const byte servoPin = 9;

const uint8_t targetHour[]  = {13, 15, 17};
const uint8_t targetHourCount = sizeof targetHour / sizeof * targetHour; // number of targets
uint8_t targetHourIndex = 0;

void action() {
  servo.write(180);
  delay(5000); // wait 5s there
  servo.write(0);
}

void setup() {
  Serial.begin(115200);
  servo.write(0);
  servo.attach(servoPin);   // attaches the servo on pin 9 to the Servo object
  rtc.init();               // assumes the RTC is working
}


void loop() {
  Ds1302::DateTime now;
  rtc.getDateTime(&now);

  if (now.hour == targetHour[targetHourIndex]) {
    Serial.println("it's "); Serial.print(targetHour[targetHourIndex]); Serial.println("h. We do something");
    action(); // do what's needed
    targetHourIndex = (targetHourIndex + 1) % targetHourCount; // get ready for next one so that we don't repeat the action
  }
}

(hope you'll study this hard and understand what it does)

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <virtuabotixRTC.h>
#include <Servo.h>

#define DS1302_CLK   10
#define DS1302_DAT   11
#define DS1302_RST   12

#define SERVO_PIN 8 // Servo sinyal pini

LiquidCrystal_I2C lcd(0x27, 16, 2);
virtuabotixRTC myRTC(DS1302_CLK, DS1302_DAT, DS1302_RST);
Servo servoMotor;

int baslatSaat = 14;
int baslatDakika = 35;
int baslatSaniye = 15;

int durdurSaat = 14;
int durdurDakika = 35;
int durdurSaniye = 25;

void setup() {
  Serial.begin(9600);
  
  lcd.init();
  lcd.backlight();

  servoMotor.attach(SERVO_PIN);
  
  myRTC.updateTime(); // RTC modülünden zaman bilgisini güncelle

  myRTC.setDS1302Time(0, 35, 14, 0, 18, 10, 2020); // Başlangıç zamanı
}

void loop() {
  myRTC.updateTime();

  int saat = myRTC.hours;
  int dakika = myRTC.minutes;
  int saniye = myRTC.seconds;

  String zaman = String(saat) + String(dakika) + String(saniye);
  String baslatZaman = String(baslatSaat) + String(baslatDakika) + String(baslatSaniye);
  String durdurZaman = String(durdurSaat) + String(durdurDakika) + String(durdurSaniye);

  lcd.setCursor(0, 0);
  lcd.print("  SAAT> ");
  lcd.print(saat < 10 ? "0" + String(saat) : String(saat));
  lcd.print(":");
  lcd.print(dakika < 10 ? "0" + String(dakika) : String(dakika));
  lcd.print(":");
  lcd.print(saniye < 10 ? "0" + String(saniye) : String(saniye));

  lcd.setCursor(0, 1);
  if (zaman.toInt() >= baslatZaman.toInt() && zaman.toInt() < durdurZaman.toInt()) {
    lcd.print("Servo Calisiyor");
    servoMotor.write(180); // Servo motoru 90 dereceye döndür
  } else {
    lcd.print("Servo Calismiyor");
    servoMotor.write(0); // Servo motorunu sıfır konumuna getir
  }

  delay(1000);
}

I was able to make a code like this and finally a code that shows the remaining hours and minutes on the LCD screen, but after a power cut, the RTC module does not function and the set time starts again. Is there something in the codes that prevents the RTC from working properly?

that's because you have

if your RTC has a builtin battery, then you need to run that command only once to set then right time and then don't have that command in your code any more - otherwise, and as you found out - when you reboot the line of code is executed and you set the time again...


concatenating time as you do into string and extracting the int again is not a good idea for example say it's 11:03:00 then zaman is "1130" because that's how you built it

now say it's 1:13:00 then you get again "1130" ...
➜ it's not a good way to build and compare times

it's better to count the number of seconds since midnight

unsigned int saat = myRTC.hours;
unsigned int dakika = myRTC.minutes;
unsigned int saniye = myRTC.seconds;
unsigned long  zaman = 3600ul * saat + 60ul * dakika + saniye; // number of seconds since midnight

and define your target time this way too

Thank you, I corrected the codes as you said, but now I suspect that the RTC module is broken, because when the battery is inserted, the time appears on the LCD screen as 00:00:00, but in fact the time continues, when I remove the battery, the time appears again, but when the battery is inserted, the LCD screen shows the time as 00:00:00. I don't think there is a problem with the codes because the same problem occurs in the codes I have tried before. I think it would be better for me to use DS3231 instead of DC1302.

Show your new code otherwise we can’t help

Sure a DS3231 is more frequent and you’ll find tons of examples for it