Progetto Arduino rtc 1307 e uscite relè

Buongiorno a tutti.
Sto realizzando il progetto di un orologio per campanile. Ovvero ad ogni ora e ad ogni mezzora un uscita di arduino deve dare degli impulsi a due relè in base a che ore sono (es alle 6.00 deve dare 6 impulsi al relè 1 , 6.30 sono 6 impulsi al relè 1 e un impulso al relè 2 , 7.00 sono 7 impulsi al relè1 e cosi via).
Arduino tramite il modulo rtc riceve l ora esatta solo che volevo sapere se c'è qualche funzione o libreria che mi possa fare semplificare il tutto...

Far semplificare cosa? Chiarisci meglio quali sono i tuoi dubbi o difficoltà perhé non è chiaro dove ti blocchi.
P.S = l'rtc 1307 ha una precisione un poco infima se ancora non hai fatto l'acquisto valuta se passare almeno al DS3231

L rtc 1307 l' avevo gia in casa. Nel progetto ho anche aggiunto un display per visualizzare la data e l' ora e dei pulsanti per modificare sia data e ora.
La mia difficolta è quella di far si che arduino ad un determinato orario attivi un uscita con un numero di impulsi in base all orario come sopra descritto.

Allora il ds1307 non ha allarmi a bordo quindi per forza di cose devi analizzare tu l'ora e determinare se i minuti sono uguali a zero o uguali a 30 e poi attivare le relative porte.
Prima cosa che libreria hai usato per gestire l'rtc? Se ne hai usato una decente, ovvero che non ritorna i dati solo nel formato stringa (e peggio che peggio usando la classe String), allora (in pesudocodice):

minutiAttuali = libreria.dimmiMinutiAttuali()
se minutiAttuali=0 oppure minutiAttuali=30 e non ho giàSuonato allora
   oraAttuale = libreria.dimmiOraAttuale()
   attivauscitaOra N volte (tante quante sono le ore attuali) [ciclo]
   se utiAttuali=30 allora
      attivaUscitaMinuti una volta

Se hai dubbi prova a mettere giù qualcosa a livello di codice della tua soluzione anche non funzionate e posta qui il codice completo cercando di dichiarare al meglio cosa non funziona correttamente

Arduino tramite il modulo rtc riceve l ora esatta solo che volevo sapere se c'è qualche funzione o libreria che mi possa fare semplificare il tutto...

Non servono altre librerie a parte quella per RTC.

Continuamente nella funzione loop leggi le unità delle ore e dei minuti e li salvi o due variabili (oreUnit, minuteUnit)

switch ( oreUnit ) {
case 1:   // L'uno di notte no, 

     // Se (giaFatto == 0) {
            // qui il codice per i rintocchi delle ore
            giaFatto = 1;
     }
     // leggi i minuti 
     if (minuteUnit == 30) {
         // qui il codice per i rintocchi dei minuti
         delay(1000*60);  // aspetta che passi 1 minuti, pertanto minuteUnit = 30 + 1 = 31
     }
break;
case 2:
    // qui il codice per i rintocchi 
break;
}

Ovviamente si tratta di uno spunto.

[Anticipato da fabpolli]
Si in effetti ti servono ore e minuti da salvare in variabili di tipo intero senza segno, cioè byte oreUnit; ecc.

Ciao.

Ho usato le librerie RTClib e wire

https://github.com/adafruit/RTClib/blob/master/RTClib.h
Questa lib ha le funzioni per restituire anno, mese, giorno, ore ecc.

Un estratto di questa lib

uint16_t year() const       { return 2000 + yOff; }
    uint8_t month() const       { return m; }
    uint8_t day() const         { return d; }
    uint8_t hour() const        { return hh; }
    uint8_t minute() const      { return mm; }
uint8_t second() const { return ss; }

Se in quella che usi tu ci sono queste funzioni allora puoi proseguire, diversamente segui come ha detto @fabpolli.

Ciao.

michelecastelvero:
Ho usato le librerie RTClib e wire

RTClib è troppo generico ci sono decine di librerie per gestire l'rtc, ne avrai installata una dal library manager o manualemente giusto? Bene c'è sempre un link dove c'è il reference o comunque che porta al sito della libreria, mettilo sempre quando ti viene chiesto che libreria usi perché altrimenti è difficile aiutare, più dettagli metti nelle risposte meglio è, se già usi quella riportata da @Maurotec allora puoi procedere usando quella in base ai suggerimenti che ti abbiamo fornito

Appena ho avuto un pò di tempo ho iniziato ad implementare il codice:
Tutta la prima parte funziona egregiamente ovvero la visualizzazione sul display e la modifica dell ora e della data tramite pulsanti.
quando però eseguo il codice mi da errore

rintocchi = rintocchi - 12);

(exit status 1
expected ';' before ')' token)

#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>

#define BACKLIGHT 2
#define CONTRAST  3
 
#define SET       A0
#define PIU       A1
#define MENO      A2
#define relay1    8
#define rela2     9
 
char buffer[10];
unsigned long time=0;
unsigned long timeSet=0;
int  setModeTime=2000;
 
RTC_DS1307 RTC;
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
 
void setup () {
    pinMode( BACKLIGHT, OUTPUT );
    pinMode( CONTRAST, OUTPUT );
    digitalWrite( BACKLIGHT, HIGH );
    analogWrite( CONTRAST, 40 );
 
    Wire.begin();
    RTC.begin();
    lcd.begin(16, 2);
 
    if (! RTC.isrunning()) {
      Serial.println("RTC is NOT running!");
      RTC.adjust(DateTime(__DATE__, __TIME__));
    }
 
    pinMode( SET, INPUT );
    pinMode( PIU, INPUT );
    pinMode( MENO, INPUT );
}
 
void loop () {
 
    if ( analogRead( SET ) < 1000) { time = millis(); }
 
    DateTime now = RTC.now();
    lcd.clear();
 
    sprintf(buffer,  "%02d/%02d/%d", now.day(), now.month(), now.year());
    lcd.setCursor(0,0);
    lcd.print( buffer );
 
    char buffer[10] = "";
 
    sprintf(buffer,  "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.setCursor(0,1);
    lcd.print( buffer );
 
    if (time > 0 && setModeTime < (millis() - time) ) { setMode( now ); }
 
    delay(1000);
}
 
void setMode( DateTime now ) {
    boolean setMode = true;
    int setModeLevel = 0;
 
    int _day = now.day();
    int _month = now.month();
    int _year = now.year();
    int _hour = now.hour();
    int _min = now.minute();
    int _sec = now.second();
 
    lcd.clear();
    lcd.setCursor(0,0);
    sprintf(buffer,  "%s: %02d", "Giorno", _day);
    delay( 1000 );
    timeSet = millis();
 
    while ( setMode ) {
      if ( analogRead(SET) > 1000 || analogRead(PIU) > 1000 || analogRead(MENO) > 1000 ) { timeSet = millis(); }
 
      lcd.setCursor(0,0);
 
      // Set Day
      if ( setModeLevel == 0 ) {
        if ( analogRead(PIU) > 1000 && _day < 31) { _day++; }
        if ( analogRead(MENO) > 1000 && _day > 1) { _day--; }
 
        sprintf(buffer,  "%s: %02d", "Giorno", _day);
      }
      // Set Month
      if ( setModeLevel == 1 ) {
        if ( analogRead(PIU) > 1000 && _month < 12) { _month++; }
        if ( analogRead(MENO) > 1000 && _month > 1) { _month--; }
 
        sprintf(buffer,  "%s: %02d", "Mese", _month);
      }
      // Set Year
      if ( setModeLevel == 2 ) {
        if ( analogRead(PIU) > 1000 && _year < 9999) { _year++; }
        if ( analogRead(MENO) > 1000 && _year > 1900) { _year--; }
 
        sprintf(buffer,  "%s: %02d", "Anno", _year);
      }
      // Set Hour
      if ( setModeLevel == 3 ) {
        if ( analogRead(PIU) > 1000 && _hour < 24) { _hour++; }
        if ( analogRead(MENO) > 1000 && _hour > 1) { _hour--; }
 
        sprintf(buffer,  "%s: %02d", "Ora", _hour);
      }
      // Set Minute
      if ( setModeLevel == 4 ) {
        if ( analogRead(PIU) > 1000 && _min < 60) { _min++; }
        if ( analogRead(MENO) > 1000 && _min > 1) { _min--; }
 
        sprintf(buffer,  "%s: %02d", "Minuti", _min);
      }
      // Set Second
      if ( setModeLevel == 5 ) {
        if ( analogRead(PIU) > 1000 && _sec < 60) { _sec++; }
        if ( analogRead(MENO) > 1000 && _sec > 0) { _sec--; }
 
        sprintf(buffer,  "%s: %02d", "Secondi", _sec);
      }
 
      lcd.print( buffer );
      if ( analogRead(SET) > 1000 ) { lcd.clear(); setModeLevel++;  }
      if ( setModeLevel > 5 ) { setModeLevel=0; }
 
      if (timeSet > 0 && (setModeTime*2) < (millis() - timeSet) ) {
         RTC.adjust(DateTime(_year, _month, _day, _hour, _min, _sec));
         setMode = false;
      }
      delay(200);
    }
    if(now.minute() == 00 && now.second() == 00){
    int rintocchi;
    rintocchi = now.hour();
    if(rintocchi  > 12){
     rintocchi = rintocchi - 12);
    }
   
    for(int i = 0; i < now.hour(); i++){
        digitalWrite(relay1, HIGH);
        delay(1000);
        digitalWrite(relay1, LOW);
        delay(1000);
    }
}
 
if(now.minute() == 30 && now.second() == 00){
    for(int i =0; i<2; i++){
        digitalWrite(relay2, HIGH);
        delay(1000);
        digitalWrite(relay2, LOW);
        delay(1000);
    }
}
}

>michelecastelvero: in conformità al regolamento, punto 7, il codice va racchiuso all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra) e NON tra i tag quote.

In pratica, tutto il codice deve trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo.

Per questa volta ho corretto io il tuo post, ma ti prego di prestare attenzione per il futuro, Grazie.

Guglielmo

if(rintocchi  > 12) {
     rintocchi = rintocchi - 12);
    }

Noto soltanto una parentesi di troppo (o mancante).

Ciao.

gpb01:
>michelecastelvero: in conformità al regolamento, punto 7, il codice va racchiuso all'interno dei tag CODE ...

Scusami Guglielmo sono stato un pò distratto...

Si esatto manca la parentesi e poi la y nella definizione all 'inizio del codice alla parola relay2.
ho montato tutto il circuito, il codice è scritto correttamente solo che l uscita non effettua l impulso come scritto.
Ho collegato due led per prova ma non funzionano. ovviamente ho provato a vedere che effettivamente i led funzionino.

Maurotec:

if(rintocchi  > 12) {

rintocchi = rintocchi - 12);
   }



Noto soltanto una parentesi di troppo (o mancante).

Ciao.

Ti devo fare i complimenti, ci ho messo un po per capire cosa fa il codice.
Lo trovo un modo contorto di fare ma questo indica grande lucidità.

Ok, il controllo dell'ora e minuti ecc dovrebbero stare all'interno della funzione loop().

Urca questa ci ho messo ancora di più a capirla.

if (time > 0 && setModeTime < (millis() - time) ) { setMode( now ); }

Ciao.

In questi giorni ho modificato il codice e ci sono alcune incongruenze:

#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>
 
#define BACKLIGHT 2
#define CONTRAST  3
 
#define SET       A0
#define PIU       A1
#define MENO      A2
#define relay1    8
#define relay2    9 

char buffer[10];
unsigned long time=0;
unsigned long timeSet=0;
int  setModeTime=2000;
 
RTC_DS1307 RTC;
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
 
void setup () {
    pinMode( BACKLIGHT, OUTPUT );
    pinMode( CONTRAST, OUTPUT );
    pinMode( relay1, OUTPUT );
    pinMode( relay2, OUTPUT );
    digitalWrite( BACKLIGHT, HIGH );
    analogWrite( CONTRAST, 40 );
 
    Wire.begin();
    RTC.begin();
    lcd.begin(16, 2);
 
    if (! RTC.isrunning()) {
      Serial.println("RTC is NOT running!");
      RTC.adjust(DateTime(__DATE__, __TIME__));
    }
 
    pinMode( SET, INPUT );
    pinMode( PIU, INPUT );
    pinMode( MENO, INPUT );
}
 
void loop () {
  DateTime now = RTC.now();
 if(now.minute() == 00 && now.second() == 00){
    int rintocchi;
    rintocchi = now.hour();
    if(rintocchi  > 12){
        (rintocchi = rintocchi - 12);
    }
   
    for(int i = 0; i < now.hour(); i++){
        digitalWrite(relay1, HIGH);
        delay(1000);
        digitalWrite(relay1, LOW);
        delay(1000);
    }
}
 
if(now.minute() == 30 && now.second() == 00 ){
    for(int i =0; i<2; i++){
        digitalWrite(relay2, HIGH);
        delay(1000);
        digitalWrite(relay2, LOW);
        delay(1000);
    }
}
    if ( analogRead( SET ) < 1000) { time = millis(); }
 
    
    lcd.clear();
 
    sprintf(buffer,  "%02d/%02d/%d", now.day(), now.month(), now.year());
    lcd.setCursor(0,0);
    lcd.print( buffer );
 
    char buffer[10] = "";
 
    sprintf(buffer,  "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    lcd.setCursor(0,1);
    lcd.print( buffer );
 
    if (time > 0 && setModeTime < (millis() - time) ) { setMode( now ); }
 
    delay(1000);
}
 
void setMode( DateTime now ) {
    boolean setMode = true;
    int setModeLevel = 0;
 
    int _day = now.day();
    int _month = now.month();
    int _year = now.year();
    int _hour = now.hour();
    int _min = now.minute();
    int _sec = now.second();
 
    lcd.clear();
    lcd.setCursor(0,0);
    sprintf(buffer,  "%s: %02d", "Giorno", _day);
    delay( 1000 );
    timeSet = millis();
 
    while ( setMode ) {
      if ( analogRead(SET) > 1000 || analogRead(PIU) > 1000 || analogRead(MENO) > 1000 ) { timeSet = millis(); }
 
      lcd.setCursor(0,0);
 
      // Set Day
      if ( setModeLevel == 0 ) {
        if ( analogRead(PIU) > 1000 && _day < 31) { _day++; }
        if ( analogRead(MENO) > 1000 && _day > 1) { _day--; }
 
        sprintf(buffer,  "%s: %02d", "Giorno", _day);
      }
      // Set Month
      if ( setModeLevel == 1 ) {
        if ( analogRead(PIU) > 1000 && _month < 12) { _month++; }
        if ( analogRead(MENO) > 1000 && _month > 1) { _month--; }
 
        sprintf(buffer,  "%s: %02d", "Mese", _month);
      }
      // Set Year
      if ( setModeLevel == 2 ) {
        if ( analogRead(PIU) > 1000 && _year < 9999) { _year++; }
        if ( analogRead(MENO) > 1000 && _year > 1900) { _year--; }
 
        sprintf(buffer,  "%s: %02d", "Anno", _year);
      }
      // Set Hour
      if ( setModeLevel == 3 ) {
        if ( analogRead(PIU) > 1000 && _hour < 24) { _hour++; }
        if ( analogRead(MENO) > 1000 && _hour > 1) { _hour--; }
 
        sprintf(buffer,  "%s: %02d", "Ora", _hour);
      }
      // Set Minute
      if ( setModeLevel == 4 ) {
        if ( analogRead(PIU) > 1000 && _min < 60) { _min++; }
        if ( analogRead(MENO) > 1000 && _min > 1) { _min--; }
 
        sprintf(buffer,  "%s: %02d", "Minuti", _min);
      }
      // Set Second
      if ( setModeLevel == 5 ) {
        if ( analogRead(PIU) > 1000 && _sec < 60) { _sec++; }
        if ( analogRead(MENO) > 1000 && _sec > 0) { _sec--; }
 
        sprintf(buffer,  "%s: %02d", "Secondi", _sec);
      }
 
      lcd.print( buffer );
      if ( analogRead(SET) > 1000 ) { lcd.clear(); setModeLevel++;  }
      if ( setModeLevel > 5 ) { setModeLevel=0; }
 
      if (timeSet > 0 && (setModeTime*2) < (millis() - timeSet) ) {
         RTC.adjust(DateTime(_year, _month, _day, _hour, _min, _sec));
         setMode = false;
      }
      delay(200);
    }
}

1: la funzione di seguito non funziona e ad esempio per le ore 15 fa 15 impulsi e non 3.

if(rintocchi  > 12){
        (rintocchi = rintocchi - 12);

2: il mio intento è quello di fare si che ad esempio alle 15.30 faccia 3 impulsi il relè 1 e 2 impulsi il relè 2.
come è stato programmato fa soltanto i 2 impulsi il relè 2. Come posso aggirare questo inghippo ??

for(int i = 0; i < now.hour(); i++){
        digitalWrite(relay1, HIGH);
        delay(1000);
        digitalWrite(relay1, LOW);
        delay(1000);
    }
}
 
if(now.minute() == 30 && now.second() == 00 ){
    for(int i =0; i<2; i++){
        digitalWrite(relay2, HIGH);
        delay(1000);
        digitalWrite(relay2, LOW);
        delay(1000);

3: Come ultima cosa si può mettere in stand by le uscite, ad esempio non farle funzionare durante la notte ??

Allora sei in piena fase copiaincolla selvaggio, così vai poco lontano, si vede che stai brancolando nel buio più totale.
Punto 1 la funzione funzionerrebbe anche (le due parenesi tonde sono superflue) ma se inizializzi e correggi la variabile (a proposito non servirebbe l'if ma applicare il modulo 12 è sufficiente allo scopo ma non è questo a non farlo fuzionare) e poi non la usi...
Punto 2 vedi punto 1 :slight_smile: per la prima parte e per la storia dei relé se agisci solo sul relé 2 come pensi che il relé 1 possa fare qualcosa? Ci sono due modi per fare ciò che vuoi, il primo prevede di duplicare il codice (che è male ma per il momento potresti accontentarti) e l'altro è spostare un pezzo di codice e modificare la condizione del primo if
Punto 3 certo che puoi sta a te decidere di non far nulla per le ore che vuoi, chessò dalle 23:00 alle 07:00 non fare rintocchi controllando l'ora con un if che racchiude tutto il tuo codice che si occupa dei rintocchi (ad esempio ma ci sono anche altri modi, questo è quello che ritengo più semplice da farti implementare).

L'uso del test sui secondi se sono uguali a zero io lo eliminerei immediatamenente, può capitare non spesso ma potrebbe capitare che non arrivi al test esattamente al secondo zero e quindi quell'ora (o mezz'ora) non suonerebbe nulla, sostituirei quel test con una variabile (come già suggerivo nel post sopra) se il minuto è zero o trenta e la variabile è vera allora entri e suoni, metti a false la variabile. Se il minuto non è zero o trenta rimetti a true la variabile. In questo modo hai un minuto di tolleranza che è molto più che sufficiente.

mi potresti quindi dare qualche dritta riguardo a cosa modificare affichè funzioni ?

Per il punto uno la dritta l'ho fornita, usa la variabile a cui applichi il -12 visto che ora la inizializzi e non la usi.
Per gli altri punti ti suggerisco di ristrutturare il codcie come ti avevo suggerito al post #2 se non ricordo male, ti ho fornito in pseudocodice la struttura che dovrebbe avere il programma ovvero se segui le identazioni e strutturi gli if seguendo quelle vedrai che riuscirai ad ottenere il risultato voluto. Chiaro non è l'unico modo ne il più compatto e performante credo sia il più semplice da implementare.
Perdonami ma non ti scriverò il codice diretto perché non imparersti nulla, ti limiteresti a fare l'ennesimo copiaincolla senza metterci del tuo per capirlo, metti in campo le modifiche suggerite (o quantomeno provaci), iniziando dall'uso della variabile dei rintocchi, personalmente se vedo progressi poi posso anche aiutariti a rimuovere alcune inasattezze o per apportare migliorie necessarie. Ma finché quel che vedo sarà solo un copiaincolla non fornisco aiuti diretti, l'obiettivo che ti sei dato è molto semplice da realizzare, ovvio che se si è agli inizi non lo sarà immediatamente, ma se non usi questo come palestra sarai sempre più in difficoltà in futuro per progetti magari più complessi