Problema con RTC

Buongiorno a tutti,

io ho questo programma per la gestione dell RTC

int richiesta_ora(){
    
  //inizzializza la trasmissione partendo
  //dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();

  //richiedo 7 byte dal dispositivo con
  //indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  //regupero i 7 byte relativi ai
  //corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();
  
  Serial.print(ora,HEX);
  Serial.print(minuti,HEX);
}

se scrivo ad esempio

return ora;

mi restituisce sempre 16... se scrivo

int ora_r = (int) ora;

mi restituisce dei valori assurdi...

io vorrei che l'ora fosse vista da arduino come un int in questo formato: es ora sono le 9:24 la funzione deve restituire 924 sono le 9:05 la funzione deve restituire 905 sono le 10:00 la funzione deve restituire 1000

mi sono spiegato?

possibile che la funzione che ho scritto non vada bene perchè fa un botto di richieste sull I2C?

vi ringrazio...

non hai specificato che RTC usi comunque se è un DS1307 ricordati di collegare la batteria di backup altrimenti dà valori senza senso se non c'è, anche se l'alimentazione principale è presente.

Beh intanto se ora contiene l’ora, nel tuo esempio 9 e minuti contiene i soli minuti, nel tuo esempio 24, non puoi di certo lavorare solo con ora per ottenere 924, non credi?
924 => 900+24 quindi quel 9 deve diventare 900 e poi gli sommi i minuti

leo72:
non hai specificato che RTC usi comunque se è un DS1307 ricordati di collegare la batteria di backup altrimenti dà valori senza senso se non c’è, anche se l’alimentazione principale è presente.

Aggiungo …
… se non usi la batteria è obbligatorio mettere il pin della batteria a massa !

E ricordati pure che nel DS1307 … i valori non sono in binario, ma sono espressi in BCD !!!

Guglielmo

leo72:
non hai specificato che RTC usi comunque se è un DS1307 ricordati di collegare la batteria di backup altrimenti dà valori senza senso se non c’è, anche se l’alimentazione principale è presente.

si uso un DS1307 con una batteria di backup :smiley:

nid69ita:
Beh intanto se ora contiene l’ora, nel tuo esempio 9 e minuti contiene i soli minuti, nel tuo esempio 24, non puoi di certo lavorare solo con ora per ottenere 924, non credi?
924 => 900+24 quindi quel 9 deve diventare 900 e poi gli sommi i minuti

infatti io ero arrivato a codesto punto :smiley:

gpb01:
E ricordati pure che nel DS1307 … i valori non sono in binario, ma sono espressi in BCD !!!
Guglielmo

questa era l’informazione che mi mancava… grazie milleeeeeeee

RISOLTO XD XD XD

int richiesta_ora(){
    
  //inizzializza la trasmissione partendo
  //dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();

  //richiedo 7 byte dal dispositivo con
  //indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  //regupero i 7 byte relativi ai
  //corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();
  
  int  ORA = bcd2dec(ora);
  int  MINUTI = bcd2dec(minuti);
  int orario = ORA*100+MINUTI;
  Serial.print(orario);
  return orario;

}

uint8_t bcd2dec(uint8_t bcd)
{
  return (bcd/16) * 10 + bcd%16;
}
...
  int orario = bcd2dec(ora)*100+bcd2dec(minuti);
  Serial.print(orario);
  return orario;
}
...

:D

bravo, me ne ero accorto mentre postavo...

Il DS1307 non ha il CRC per il controllo dei dati trasmessi?

No. Chiedi il valore di un registro, e lui ti rimanda indietro quel dato, stop.

non vorrei aprire un'altro topic quindi potete aiutarmi anche con questa funzione per piacere?

in pratica non ho un sensore di temperatura per gli alimentatori e vorrei che la ventola stesse accesa mezzora si e mezzora no... potete controllare se questa funzione può andare? alzo un flag ogni volta che l'orario è divisibile per 30

    if(get_ora() %30==0){ 
    if(s==0) s=1;
    else s=0;
    }
    if(s==1)analogWrite(fans[3],100);
    else analogWrite(fans[3],0);

dato che la mia funzione get_ora() mi dava un orario tipo 2148 allora per renderlo divisibile per 30min ho trasformato tutto in minuti

int get_ora(){
    
  //inizzializza la trasmissione partendo
  //dall'indirizzo 0x00
  Wire.beginTransmission(0x68);
  Wire.write((byte)0x00);
  Wire.endTransmission();

  //richiedo 7 byte dal dispositivo con
  //indirizzo 0x68
  Wire.requestFrom(0x68, 7);
  //regupero i 7 byte relativi ai
  //corrispondenti registri
  byte secondi = Wire.read();
  byte minuti = Wire.read();
  byte ora = Wire.read();
  byte giorno_sett = Wire.read();
  byte giorno_mese = Wire.read();
  byte mese = Wire.read();
  byte anno = Wire.read();

  return bcd2dec(ora)*60+bcd2dec(minuti);

}

uint8_t bcd2dec(uint8_t bcd)
{
  return (bcd/16) * 10 + bcd%16;
}

va bene secondo voi?

Ma la funzione get_ora che tipo di valore ti restituisce? Cos'è "2148"?

get_ora(); mi restituisce un int esempio sono le 16:39, get_ora(); mi restituisce 16*60+39 che sono le ore espresse in minuti...

il problema è che se tipo sono le 17:00 get_ora(); mi restituisce 1020 che rimane divisibile per 30 per 1 minuto quindi non va bene perchè la ventola si accende e si spenge 30 volte in un minuto e poi si spenge per 30min...

forse dovrei trasformare tutto in secondi però devo usare i long int giusto? perchè se ad esempio fossero le 17:00:00 get_ora(); restituirebbe 61200...

Ma non ho capito, forse mi son perso. Non usavi 16*100+59=> 1659 ?

Ma se prendessi un sensore di temperatura? :sweat_smile:

Ma se prendessi un sensore di temperatura?

Perche' ha la febbre ?

Calamaro:
il problema è che se tipo sono le 17:00 get_ora(); mi restituisce 1020 che rimane divisibile per 30 per 1 minuto quindi non va bene perchè la ventola si accende e si spenge 30 volte in un minuto e poi si spenge per 30min…

Hai semplicemente bisogno di una variabile di stato, un flag, che ti dice lo stato attuale della ventola.
Quindi la logica del tuo programma diventa questa:

SE tempo >= tempo_avvio E tempo <= tempo_arresto ALLORA
    SE stato_ventola = 0 ALLORA
        stato_ventola = 1
        AVVIA VENTOLA
    FINE
ALTRIMENTI
    SE stato_ventola = 1 ALLORA
        stato_ventola = 0
        ARRESTA VENTOLA
    FINE
FINE

In questo modo sia l’avvio che l’arresto della ventola lo fai 1 sola volta, grazie appunto al tuo flag.

nid69ita:
Ma non ho capito, forse mi son perso. Non usavi 16*100+59=> 1659 ?

no adesso uso 16*60+59 che mi da i minuti

Brunello:

Ma se prendessi un sensore di temperatura?

Perche’ ha la febbre ?

ahaha sto valutando se mettere il 4° sensore di temperatura…

leo72:

Calamaro:
il problema è che se tipo sono le 17:00 get_ora(); mi restituisce 1020 che rimane divisibile per 30 per 1 minuto quindi non va bene perchè la ventola si accende e si spenge 30 volte in un minuto e poi si spenge per 30min…

Hai semplicemente bisogno di una variabile di stato, un flag, che ti dice lo stato attuale della ventola.
Quindi la logica del tuo programma diventa questa:

SE tempo >= tempo_avvio E tempo <= tempo_arresto ALLORA

SE stato_ventola = 0 ALLORA
       stato_ventola = 1
       AVVIA VENTOLA
   FINE
ALTRIMENTI
   SE stato_ventola = 1 ALLORA
       stato_ventola = 0
       ARRESTA VENTOLA
   FINE
FINE




In questo modo sia l'avvio che l'arresto della ventola lo fai 1 sola volta, grazie appunto al tuo flag.

ok però se usassi la tua funzione e impostassi TEMPO = 17:00, per esempio, la ventola mi si accenderebbe soltanto dalle 17:00 alle 17:30

dovrei mettere un’istruzione tipo quelle in “grassetto” giusto?

SE tempo >= tempo_avvio E tempo <= tempo_arresto ALLORA
    SE stato_ventola = 0 ALLORA
        stato_ventola = 1
        AVVIA VENTOLA
    FINE
ALTRIMENTI
    SE stato_ventola = 1 [b]&&  tempo >= tempo_arresto[/b] ALLORA
        stato_ventola = 0
       [b]tempo_avvio += 30minuti
       tempo_arresto += 30minuti[/b]
        ARRESTA VENTOLA
    FINE
FINE

è troppo presto per dire: “avevo un cane e il suo nome era… BINGOOOOOW!!!” ???

AVVIA VENTOLA sarà quel che è, può essere un'istruzione singola (digitalWrite) oppure una regolazione in PWM in base ad altri parametri ecc.. Il mio era un esempio di come strutturare il codice.

si si certo, io l’avevo capito…
per renderla più dinamica ho impostato tempo avvio e tempo arresto come variabili globali che vengono settate automaticamente in void setup… la funzione è quella sotto…

int tempo_avvio;
int tempo_arresto;
void setup()
{
 tempo_avvio = get_ora()-get_ora()%30;
 
 if(tempo_avvio == 1410)
 tempo_arresto = 30; 
   else
 tempo_arresto=tempo_avvio+30;
}
void loop()
{
// inizializzo i sensori
  delay(dht.getMinimumSamplingPeriod());
  acquisisco();
  scriviseriale();
  r_ali();
}

void r_ali(){
    int s=0; 
if(get_ora() >= tempo_avvio && get_ora()<=tempo_arresto){
  if(s==0){
    analogWrite(fans[0],150);
    s=1;
  } else if(s==1 && get_ora()>tempo_arresto){
     analogWrite(fans[0],150);
     tempo_avvio +=30;
     tempo_arresto +=30;
    }
  Serial.print(tempo_avvio);
  Serial.print("\t");
  Serial.println(tempo_arresto);
  }
}

ho dovuto mette un controllo sull’ora perchè se tempo avvio è uguale a 1410 (23:30) tempo arresto mi viene 1440 (24:30) che il mio RTC mi invia come 00:30 e get_ora() me lo interpreta come 30 e quindi non credo che in quella mezzora funzionerebbe…
grazie mille ancora…