Go Down

Topic: Progetto Arduino rtc 1307 e uscite relè (Read 355 times) previous topic - next topic

michelecastelvero

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...

fabpolli

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

michelecastelvero

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.

fabpolli

#3
May 08, 2019, 05:56 pm Last Edit: May 08, 2019, 05:57 pm by fabpolli
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):
Code: [Select]

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

Maurotec

Quote
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)

Code: [Select]

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.

michelecastelvero


Maurotec

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
Code: [Select]

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.

fabpolli

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

michelecastelvero

#8
May 22, 2019, 08:45 pm Last Edit: May 22, 2019, 09:27 pm by gpb01
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
Quote
rintocchi = rintocchi - 12);
(exit status 1
expected ';' before ')' token)


Code: [Select]
#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);
    }
}
}

gpb01

#9
May 22, 2019, 09:29 pm Last Edit: May 22, 2019, 09:30 pm by gpb01
>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
Search is Your friend ... or I am Your enemy !

Maurotec

Code: [Select]

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

Noto soltanto una parentesi di troppo (o mancante).

Ciao.

michelecastelvero

#11
May 23, 2019, 09:36 pm Last Edit: May 23, 2019, 10:17 pm by gpb01
>michelecastelvero: in conformità al regolamento, punto 7, il codice va racchiuso all'interno dei tag CODE ...
Scusami Guglielmo sono stato un pò distratto...

michelecastelvero

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.

Code: [Select]

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

Noto soltanto una parentesi di troppo (o mancante).

Ciao.


Maurotec

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.
Code: [Select]

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


Ciao.


michelecastelvero

In questi giorni ho modificato il  codice e ci sono alcune incongruenze:
Code: [Select]
#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.
Code: [Select]
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 ??

Code: [Select]
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 ??

Go Up