Hello, I want to write code with Nodemcu that will turn the relay on and off at a certain time every 2 days. Can you help me? I am using ds1302 rtc module.
Welcome to the forum
How accurate must the timing be ?
Will the NodeMCU be able to access WiFi where it is located ?
Since I will be using it in the village, I am not a fan of using Wi-Fi. There are disconnection problems etc. I bought DS1302 rtc module for this
If you don’t have any code already, give it a shot.
first, try turning the relay on and off with a button via code using digitalRead() and digitalWrite().
Write a second test to set & read the RTC, and finally, ignore the button, and see if you can trigger the relay using the time of day from the RTC.
Show us your code in tags
I want to use this code to turn the relay on and off every 2 days.
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <virtuabotixRTC.h>
// DS1302 pinleri
#define CLK_PIN D4
#define DATE_PIN D3
#define RESET_PIN D5
// Röle pini
#define RELAY_PIN D0
// RTC
virtuabotixRTC myRTC(CLK_PIN, DATE_PIN, RESET_PIN);
// LCD ekranın adresi
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(9600);
digitalWrite(RELAY_PIN, HIGH);
pinMode(RELAY_PIN, OUTPUT);
// Saat ayarı - saniye, dakika, saat, gün, ay, yıl
//myRTC.setDS1302Time(00, 15, 18, 14, 6, 2024, 3);
}
void loop() {
myRTC.updateTime();
if (myRTC.hours == 21 && myRTC.minutes == 7 && myRTC.seconds == 0) {
digitalWrite(RELAY_PIN, LOW); // Röleyi aç ''LOW''
lcd.setCursor(0, 0);
lcd.print("SULAMA YAPILIYOR");
} else if (myRTC.hours == 21 && myRTC.minutes == 8 && myRTC.seconds == 0) {
digitalWrite(RELAY_PIN, HIGH); // Röleyi kapat ''HIGH''
lcd.setCursor(0, 0);
lcd.print(" SULAMA YAPILDI ");
}
lcd.setCursor(0, 1);
lcd.print(" Saat: ");
lcd.print(myRTC.hours);
lcd.print(":");
lcd.print(myRTC.minutes);
lcd.print(":");
lcd.print(myRTC.seconds);
delay(1000);
}
…and ?
The only thing I can see that’s missing is a condition that checks the day of the month, or day of the week - to determine every second day for triggering.
Does this work?
if(myRTC.dayofmonth % 2 == 0)
Something like that, but that has two weaknesses.
The trigger date is absolute. so you may get one day duration on short or long months, and,,,it may not fire the first day you turn it on, because it needs specifically odd/even days to trigger,
Keep a day ‘counter’ if needed, to increment, so the days are always on your schedule, not the calendar’s.
Alternately, you might choose to fire every second weekday, and not on weekends - your choice.
Since I made a garden irrigation system, it needs to be watered every 2 days.
Tell us more about the code you’re using…
Does it work at all ?
Did you consider the day timing comments above ?
this makes your loop to take just a little more than 1000mS to execute, and Murphy’s Law states that you may miss the “00” seconds mark once in a long while.
To prevent that I would make this delay less than 1000. Or get rid of
and use a flag to check the relay state
The code I wrote is working, but I don't know how to do it every 2 days. I uploaded the code the day before yesterday and it did not trigger the relay on the same day. It did not trigger yesterday either. If it triggers today, there is no problem.
If it’s working, then see post #6
void loop() {
myRTC.updateTime();
if(myRTC.dayofmonth % 2 == 0) {
if(myRTC.hours == 21 && myRTC.minutes == 0) {
digitalWrite(RELAY_PIN, LOW);
lcd.setCursor(0,1);
lcd.print("SULAMA YAPILIYOR");
}
if(myRTC.hours == 21 && myRTC.minutes == 10) {
digitalWrite(RELAY_PIN, HIGH);
lcd.setCursor(0,1);
lcd.print(" SULAMA YAPILDI ");
}
}
delay(60000);
}
That is fine, now read post #8
This might help:
uint16_t ymdToUnixDays(uint16_t y, uint8_t m, uint8_t d) {
// We use Thursday, January 1, 1970 == day 0
// Maximum is Thursday, June 5, 2149 == day 65534 == day 0xFFFE
// we return 65535 (0xFFFF) in case of invalid input
// check for out of bounds
// we have to pick *something* for an error code,
// so we will return 0xFFFF in case of out of bounds input
if ((y < 1970) || (y > 2149)) return 0xFFFF;
if ((m < 1) || (m > 12)) return 0xFFFF;
if ((d < 1) || (d > 31)) return 0xFFFF;
if (y == 2149) {
if (((m == 6) && (d > 5)) || (m > 6)) return 0xFFFF;
}
if (((m==4)||(m==11)||(m==9)||(m==6)) && (d>30)) return 0xFFFF;
if (m == 2) {
if (((y % 4) == 0) && (y != 2100)) {
if (d > 29) return 0xFFFF;
}
else {
if (d > 28) return 0xFFFF;
}
}
// first we add the whole years
uint16_t n = (y - 1970) * 365;
// then we add the leap days
n += (y - 1969) / 4;
// year 2100 is not a leap year, so we fix that
if (y > 2100) n--;
// next, we take care of the whole months
if (m > 1) n += 31;
if (m > 2) {
if (((y % 4) == 0) && (y != 2100)) n += 29;
else n += 28;
}
if (m > 3) n += 31;
if (m > 4) n += 30;
if (m > 5) n += 31;
if (m > 6) n += 30;
if (m > 7) n += 31;
if (m > 8) n += 31;
if (m > 9) n += 30;
if (m > 10) n += 31;
if (m > 11) n += 30;
// next, we take care of the days this month
n += (d - 1);
return n;
}
I'm not that knowledgeable. I do it for hobby purposes
What I want is a simple code that will turn the relay on and off at a certain time every 2 days without causing any trouble.
The function I wrote is to help with that. You feed it a year, month, and day of the month, and it gives you a day number.
ymdToUnixDays(2024, 6, 18) gives you 19892
ymdToUnixDays(2024, 6, 19) gives you 19893
ymdToUnixDays(2024, 6, 20) gives you 19894
and so forth.
Then you can use % 2
to test whether the number you get is odd or even, and based on that, determine whether or not it is time to water the garden.
This is how "An error has occurred" starts.
Why not different error codes?