meerdere relais + rtc3231 + I2C

ik ben bezig met een projectje maar het wil maar niet lukken. ben zelf ook niet echt thuis in c+ al is code mij niet geheel onbekend c+ ook niet meer dankzij solo learn.

ik ben bezig met een arduino mega daaraan is een rtc 3231 gekoppeld en een i2c 2X16 display
de ingestelde tijd word weergegeven op de lcd display tot zover werkt het.
ik wil er in totaal 4 relais mee kunnen schakelen aan de hand van een x aantal uur.

de bijeen geschraapte code tot zover ( relays stuk werkt maar deels) als ik in de void setup de relais aanzet "RELAY_ON" gaat het ledje van dat aan

als ik time.h include en dit in de loop zet gaan de relais aan/uit maar stopt de tijd me lopen tot de loop reset als dit er niet inzit blijft de tijd gewoon lopen
//---( Turn all 4 relays ON in sequence)---
digitalWrite(Relay_1, RELAY_ON);// set the Relay ON
delay(1000); // wait for a second
digitalWrite(Relay_2, RELAY_ON);// set the Relay ON
delay(1000); // wait for a second
digitalWrite(Relay_3, RELAY_ON);// set the Relay ON
delay(1000); // wait for a second
digitalWrite(Relay_4, RELAY_ON);// set the Relay ON
delay(4000); // wait see all relays ON

//---( Turn all 4 relays OFF in sequence)---
digitalWrite(Relay_1, RELAY_OFF);// set the Relay OFF
delay(1000); // wait for a second
digitalWrite(Relay_2, RELAY_OFF);// set the Relay OFF
delay(1000); // wait for a second
digitalWrite(Relay_3, RELAY_OFF);// set the Relay OFF
delay(1000); // wait for a second
digitalWrite(Relay_4, RELAY_OFF);// set the Relay OFF
delay(4000); // wait see all relays OFF

// ds3231 met LCD-I2C
// ds3231 library:
// https://learn.adafruit.com/adafruit-ds3231-precision-rtc-breakout/wiring-and-test
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
// liquid cristal library:
// https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
//

#include <Wire.h>
#include "RTClib.h"
#include "DS3232RTC.h"
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD adres is 0x27, 16 karakters, 2 regels
RTC_DS3231 rtc;
//relay functions
#define RELAY_ON 0
#define RELAY_OFF 1
//relay nr poort
#define Relay_1 30
#define Relay_2 31
#define Relay_3 32
#define Relay_4 33

int val;
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void setup () {

 //relay
  pinMode(Relay_1, OUTPUT); //relay1 30
  pinMode(Relay_2, OUTPUT); //relay2 31
  pinMode(Relay_3, OUTPUT); //relay3 32
  pinMode(Relay_4, OUTPUT); //relay4 33    
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_OFF);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF);
  
  //rtc [
setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() != timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
       Serial.println("RTC has set the system time");
  
  /// lcd code [
  lcd.init();   
  
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.print("Donkere wolken");
  lcd.setCursor(1, 1);
  lcd.print("D3mons alpha");
  delay(2000);
  lcd.clear();
  /// lcd code ]

  pinMode (13, OUTPUT);
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif
  Serial.begin(9600);

     
  delay(3000); // wait for console opening
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop () {
  DateTime now = rtc.now();

  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  /// lcd code[
  lcd.setCursor(3, 0);
  lcd.print(now.year(), DEC);
  lcd.print('/');
  lcd.print(now.month(), DEC);
  lcd.print('/');
  lcd.print(now.day(), DEC);
  lcd.setCursor(0, 1);
  lcd.print(" (");
  lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
  lcd.print(" ");
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
  lcd.print(':');
  lcd.print(now.second(), DEC);
  lcd.print(")");
  lcd.print(" ");
  lcd.print(" ");
  lcd.print(" ");
  lcd.print(" ");
  /// lcd code]

  if (now.second() > 1 && now.second() < 30) { // led aan tussen 0 en 30 sec. 
    digitalWrite (13, HIGH);
  }
  else {
    digitalWrite (13, LOW);
  }
  Serial.println();
  delay(1000);
  lcd.clear();


}

void AutomaticProgram() 
{   //we are using hour as a value the rest is ignored.
  DateTime now = rtc.now();
    val = (now.hour(), DEC); //aan tussen 3 en 23
    if ((3 == val))             
    {
    digitalWrite(Relay_1, RELAY_ON);
    }
    else if ((23 == val))
    {
    digitalWrite(Relay_1, RELAY_OFF);
    }
   
}

ik kreeg ineens een ingeving aan de hand van het lcd ledje datknipperde

// ds3231 met LCD-I2C
// ds3231 library:
// https://learn.adafruit.com/adafruit-ds3231-precision-rtc-breakout/wiring-and-test
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
// liquid cristal library:
// https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
//

#include <Wire.h>
#include "RTClib.h"
#include "DS3232RTC.h"
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD adres is 0x27, 16 karakters, 2 regels
RTC_DS3231 rtc;
//relay functions
#define RELAY_ON 0
#define RELAY_OFF 1
//relay nr poort
#define Relay_1 30
#define Relay_2 31
#define Relay_3 32
#define Relay_4 33

int val;
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void setup () {

 //relay
  pinMode(Relay_1, OUTPUT); //relay1 30
  pinMode(Relay_2, OUTPUT); //relay2 31
  pinMode(Relay_3, OUTPUT); //relay3 32
  pinMode(Relay_4, OUTPUT); //relay4 33    
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_OFF);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF);
  
  //rtc [
setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() == timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
       Serial.println("RTC has set the system time");
  
  /// lcd code [
  lcd.init();   
  
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.print("Donkere wolken");
  lcd.setCursor(1, 1);
  lcd.print("D3mons alpha");
  delay(2000);
  lcd.clear();
  /// lcd code ]

  pinMode (13, OUTPUT);
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif
  Serial.begin(9600);

     
  delay(3000); // wait for console opening
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop () {
  DateTime now = rtc.now();

  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

  /// lcd code[
  lcd.setCursor(3, 0);
  lcd.print(now.year(), DEC);
  lcd.print('/');
  lcd.print(now.month(), DEC);
  lcd.print('/');
  lcd.print(now.day(), DEC);
  lcd.setCursor(0, 1);
  lcd.print(" (");
  lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
  lcd.print(" ");
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  lcd.print(now.minute(), DEC);
  lcd.print(':');
  lcd.print(now.second(), DEC);
  lcd.print(")");
  lcd.print(" ");
  lcd.print(" ");
  lcd.print(" ");
  lcd.print(" ");
  /// lcd code]

  if (now.hour() > 4 && now.hour() < 24){
    digitalWrite (Relay_1, RELAY_ON);
    Serial.print("Relay_1 ON: ");
  }
  else {
    digitalWrite (Relay_1, RELAY_OFF);
    Serial.print("Relay_1 off");
    }
  if (now.hour() > 5 && now.hour() < 24) {
    digitalWrite (Relay_2, RELAY_ON);
    Serial.print("Relay_2 ON: ");
  }
  else {
    digitalWrite (Relay_2, RELAY_OFF);
    Serial.print("Relay_2 off: ");
  }

  if (now.hour() > 12 && now.hour() < 24) {
    digitalWrite (Relay_3, RELAY_ON);
    Serial.print("Relay_3 ON: ");
  }
  else {
    digitalWrite (Relay_3, RELAY_OFF);
    Serial.print("Relay_3 off: ");
  }

  if (now.hour() > 13 && now.hour() < 23) {
    digitalWrite (Relay_4, RELAY_ON);
    Serial.print("Relay_4 ON: ");
  }
  else {
    digitalWrite (Relay_4, RELAY_OFF);
    Serial.print("Relay_4 off: ");
  }
    
  Serial.println();
  delay(1000);
  lcd.clear();
}

dit lijkt te werken, is dit echter de juistemanier ?

Dit is onzin in je eerste programma

  val = (now.hour(), DEC); //aan tussen 3 en 23

Dit is beter

  val = now.hour(); //aan tussen 3 en 23

Wat betreft je tweede programma, het lijkt goed en het werkt :wink: Als dit alles is wat je programma moet doen zou ik het gewoon zo laten.

Je kunt uiteraard dingen verbeteren. Bv functies gebruiken voor het tonen van de tijd en voor het aansturen van de relais; en dan die functies aanroepen vanuit loop(). En de delay proberen kwijt te raken door gebruik te maken van een benadering gebaseerd of millis().

Je daysOfTheWeek[7][12] verspilt wat bytes. Aangezien iedere tekst maar drie karakters is, kun je dat veranderen naar daysOfTheWeek[7][4]; als je niet begrijpt waarom het 4 is en niet 3, zul wat onderzoek moeten doen naar zogenaamde c-strings.

het is niet alles wat ik wil dat het kan/moet doen. maar het is wel de primaire functie.
lcd was niet primair. en liep ik na een 20 minuten goed werken tegen een probleem aan. de serialmonitor blijft gewoon de goede tijd aangeven maar de lcd display gaat ineens alemaal onleesbare tekens produceren hier en daar een herkenbaar tekentje tussen door maar niet meer de tijd. heb de lcd er tussen uit gehaald en uit de code gehaald eerst focus opde primair bedoelde functie

liep vanochtend tegen een probleempje aan dat die 2e relai on 05:25 nog uit was pas na 6 uur aansprong.
dus weer een beetje getweakt.

// ds3231 library:
// https://learn.adafruit.com/adafruit-ds3231-precision-rtc-breakout/wiring-and-test
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib

#include <Wire.h>
#include "RTClib.h"
#include "DS3232RTC.h"

RTC_DS3231 rtc;

//relay functions
#define RELAY_ON 0
#define RELAY_OFF 1

//relay nr poort
#define Relay_1 30
#define Relay_2 31
#define Relay_3 32
#define Relay_4 33

char daysOfTheWeek[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

void setup () {

 //relay
  pinMode(Relay_1, OUTPUT); //relay1 30
  pinMode(Relay_2, OUTPUT); //relay2 31
  pinMode(Relay_3, OUTPUT); //relay3 32
  pinMode(Relay_4, OUTPUT); //relay4 33    
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_OFF);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF);
  
  //rtc [
setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() == timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
       Serial.println("RTC has set the system time");
  
  Serial.begin(9600);
  
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    //rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
}

void loop () {
  DateTime now = rtc.now();

  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();

//relays
  if (now.hour() >= 4 && now.hour() < 24){
    digitalWrite (Relay_1, RELAY_ON);
    Serial.print("Relay_1 ON: ");
  }
  else {
    digitalWrite (Relay_1, RELAY_OFF);
    Serial.print("Relay_1 off");
    }
  if (now.hour() >= 5 && now.hour() < 24) {
    digitalWrite (Relay_2, RELAY_ON);
    Serial.print("Relay_2 ON: ");
  }
  else {
    digitalWrite (Relay_2, RELAY_OFF);
    Serial.print("Relay_2 OFF: ");
  }

  if (now.hour() >= 12 && now.hour() < 24) {
    digitalWrite (Relay_3, RELAY_ON);
    Serial.print("Relay_3 ON: ");
  }
  else {
    digitalWrite (Relay_3, RELAY_OFF);
    Serial.print("Relay_3 OFF: ");
  }

  if (now.hour() >= 13 && now.hour() < 24) {
    digitalWrite (Relay_4, RELAY_ON);
    Serial.print("Relay_4 ON: ");
  }
  else {
    digitalWrite (Relay_4, RELAY_OFF);
    Serial.print("Relay_4 OFF: ");
  }
    
  Serial.println();
  delay(1000);
}
 && now.hour() < 24

Kan now.hour() ooit 24 of meer zijn?
Als dat niet zo is, hoef je er ook niet op te testen. Het kan geen kwaad, maar is overbodig.

d3mons:
de lcd display gaat ineens allemaal onleesbare tekens produceren hier en daar een herkenbaar tekentje

Dit komt waarschijnlijk door storing bij het schakelen van je relais. (Als dit optreedt, krijg je je lcd weer in het juiste standje door opnieuw lcd.init() aan te roepen, maar voorkomen is natuurlijk veeel beter dan genezen.)
Kun je laten zien wat voor relais je gebruikt en hoe het is bedraad?

als het goed is niet. de rtc telt van 00:00:00:000 tot 23:59:59:999 en reset dan op 0

https://nl.aliexpress.com/item/4-channel-relay-module-4-channel-relay-control-board-with-optocoupler-Relay-Output-4-way-relay/32649659086.html?spm=a2g0s.9042311.0.0.1dc84c4dxNCec4

gnd - gnd
vcc - vcc 5v (breadboard gevoed met ywrobot power mb v2)
vn1 30
vn2 31
vn3 32
vn4 33
met een jumper op jd/vcc opde relai's plaat

Het is niet wat ik dacht. (Dat je bijv. een relais direct met een i/o pin schakelt, geen diode over de spoel hebt, ...)
Die relais module heeft optocouplers en diodes aan boord.
Je zou geen last moeten hebben van inductie pieken van je spoelen.
Je kan proberen wat ontkoppel capaciteit dichtbij de voeding van de relais module en dichtbij de voeding van de display module te zetten. 10 tot 100µF of zo?

Nu het dus niet is wat ik dacht, weet ik het eigenlijk ook niet. (Sorry.)
Voor mij zou de volgende verdachte de voeding zijn.

Hoe wordt je ywrobot breadboard voeding gevoed?
Die voeding kan 700mA leveren. Maar kan denk ik zelf niet veel vermogen verstoken.

De spoelen in de relais hebben een weerstand van 70Ω. Bij 5V is dat ruim 70mA per relais. Maal 4 is bijna 300. Plus de LEDs in de optocouplers, plus wat tolerantie, plus wat marge, ronden we af op 400mA. Laten de Arduino en de display module ieder 50mA trekken, plus 20mA backlight, plus ongeveer nul voor de RTC, alles ruim geschat, zitten we aan de 500mA met alle 4 relais aan.

700mA zou voldoende moeten zijn maar niet ruim.

Uiteindelijk zou je 2 aparte spanningsregelaars kunnen gebruiken:
1 voor het deel met gevoelige digitale electronica: de MCU, display, RTC,
en 1 voor het deel met inductie en gedender en veel variatie in belasting: de relais.

zou wel een foto willen plaatsen maar formaat werkt niet mee

mr robot is gevoed met bijgeleverde 900ma voeding (deze is met smeltlijm vast gezet op breadboard want die liet me temakelijk los en al ist maar 5 volt heb geen zin in vonkjes door contact foutjes,

deze voorziet 2 banen van + en -
opde voorste heb ik momenteel de realtine clock lcd stond daar eerst ook op de lcd op

en opde andere kant zit aleen de relai's
voeding arduino komt met usb vande mr robot

ps ben van opleidig en werk geralateerd geen leek op electra. ende ruis die schakelen van een relais geeft wou ik iid niet over de gevoeligere electra hebben

d3mons:
deze voorziet 2 banen van + en -

Die 2 banen zijn verbonden. Die 2 regelaars zijn 1 voor 3.3V en 1 voor 5V. Niet 1 per baan.

d3mons:
ps ben van opleidig en werk geralateerd geen leek op electra.

Oh ik wel. Ben van opleiding en werk een software man.
Wat ik van electronica weet is door experimenteren, spelen, lezen, meten.
Waarschijnlijk weet je meer dan ik.

eentje links en eentje rechts ?

deze zijn toch niet onderling ook nog verbonden zeker

ik heb 3 jaar inde caroserie bouw( mobiele medice trailers) met electra gespeeld in het magazijn/werkplaats. stond daar voornamelijk in het magezijn maar afentoe tijdens overwerk ect liep ik graag me met een van de electriciens, in me opleiding ict medewerker ooit ook instalatie techniek gehad en met een dikke 8 voor geslaagd destijds. weet wel hoe het hoort pas het aleen niet altijd toe. 0.75 en 0.5 draad wil ik nog wel eens gewoon vertinnen als ik het voor mezelf gebruik al weet ik dat het volgens de nen met een hulsje hoort. al geloof ik dat ik dat bij arduino beter niet kan doen. als ik ga solderen pakik

code had ik dan voorheen heelwijnig van gegeten, beetje standaard html ccs java dingentjes maar lang niet diepgaand

d3mons:
eentje links en eentje rechts ?

deze zijn toch niet onderling ook nog verbonden zeker

Niet in het breadboard zelf, maar in de ywrobot voeding.

Linker baan - J4 & J5 - J2 - J3 - J6 & J7 - Rechter baan

dat zou ik bij een volgende lcd test dan eens anders doen 2e voeding erbij pakken voor de arduino en lcd via een 5v laten komen/telefoon lader kom je ook een eind 0.9/2.5 ampere tegen woordig / of ff shopen bij ali binnekort

beetje jammer dat die priciezie realtime clock niet zo precies
6 minuten verloop ondertussen tussen rtc en computer
das voornu opzich geen ramp afentoe even synchronizeren met de computer.

binnenkort eens even rondkijken op ali

leek vraagje hoe kan ik de if het beeste aanpassen als ik ook naar minuten wil laten kijken

if (now.hour() >= 4 (now.minute() >= 30) && now.hour() < 24) {
digitalWrite (Relay_1, RELAY_ON);

is zeker te gemakelijk gedacht

Het is zelfs iets te moeilijk gedacht.

Je had in je 'if' al 2 tests, die beide waar moeten zijn: hour >= 4 EN hour < 24
Je kan daar op dezelfde manier nog een derde (en vierde enz..) aan toevoegen.
(Zie in de Language Reference de 'boolean operators'.)

Wat ik persoonlijk zou doen is de tijd (in uren en minuten) omrekenen naar 1 waarde waar gemakkelijk mee te werken is:

  int dagTijd = 100 * now.hour() + now.minute();

  if (dagTijd >= 800 && dagTijd < 900)
  { // tussen 8 en 9 uur 's ochtends
    
  }

  if (dagTijd >= 1745)
  { // na kwart voor zes 's middags
    
  }

(Ik weet dat een uur geen 100 minuten heeft, maar zolang we die waarden niet van elkaar aftrekken om een tijdsspanne te bepalen geeft het niet, en zijn de getallen lekker herkenbaar.)