Go Down

Topic: DS3231, problema estrapolazione dati ( e forse altro) (Read 532 times) previous topic - next topic

propifol

ciao a tutti!

Vi scrivo perchè ho un problema con un DS3231 collegato ad un arduino nano 328P.

Il programma che sto scrivendo dovrebbe scrivermi i secondi su seriale ma evidentemente non ho capito bene come funzioni la comunicazione tra l'RTC e l'arduino.
Ho letto il datasheet (gli inzirizzi sono a pagina 11)  e ho cercato di capire come fare funzionare la comunicazione tra questo sensore e l'arduino senza l'utilizzo di librerie esterne (come consigliava un utente qui sul forum in una vecchia discussione che ho trovato mentre cercavo di risolvere il problema).

Vi incollo anche il codice che ho scritto, con tanto di commenti: vi prego di non risparmiarmi critiche.



Code: [Select]
#define ripeti 1
#define bit_vettore 7

void decabin(int num);

    int bin[bit_vettore]={0,0,0,0,0,0,0};

 

#include<Wire.h>

int ind_RTC = 0x57;    // indirizzo sensore RTC
int ind_sec    = 0;    // Indirizzo decine di secondi
int ind_min    = 1;    // Indirizzo decine di minuti
int ind_ora    = 2;    // Indirizzo ore
int ind_g_sett = 3;    // Indirizzo giorni della settimana

int sec        = 0;    // Secondi
int u_min      = 0;    // Unità di minuti
int d_min      = 0;    // Decine di minuti
int u_ore      = 0;    // Unità di ore
int d_ore      = 0;    // Decine di ore
int g_sett     = 0;    // Giorno della settimana

  int tmp=0;

                           
int j=1; // serve per un ciclo nel loop()


void setup() {

 
  Serial.begin(9600);   // frequenza di trasmissione tra Arduino e PC



  Serial.print("SI COMINCIA!!!!!     \n"); // Stampa su monitor seriale la stringa in argomento
}

void loop() {
int i=0;      // serve per ciclare in tutte le funzioni del programma
int k = 0;    // serve per ciclare in tutte le funzioni del programma

sec =0 ;
 
  if(j==1){                    // serve per non ripetere il loop grazie a...
j=ripeti;                      // ... questo: se j==0,scrive una volta sola. se j!=0, ripete all'infinito.








Wire.begin(); // inizializzo la libreria Wire
     
      Wire.beginTransmission(ind_RTC); // inizio la trasmissione con l'RTC
      Wire.write(ind_sec);             // voglio leggere i minuti
      Wire.endTransmission();          // ho finito di leggere i minuti
      Wire.requestFrom(ind_RTC,1);     // richiedo il valore acquisito...
      tmp= Wire.read();                // ... e lo salvo in tmp
     
                   decabin(tmp);  // adesso quel valore lo converto in binario e salvo ogli cifra di quel numero binario nel vettore globale bin[];
         
// PARTE CON IL MSB
      sec = (4*bin[0]+2*bin[1]+bin[2]) * 10 +8*bin[3]+4*bin[4]+2*bin[5]+bin[6];
//qui sopra ho trasformato i 7 bit che mi ha trasmesso l'rtc in secondi,
//partendo dai primi tre che mi indicano le decine dei secondi
//e proseguendo con gli ultimi 4 che mi indicano le unità.
// Questo metodo non funziona.


     
Serial.println(sec); // stampo su seriale i secondi
   
    delay(2000); //aspetto due secondi prima di ricominciare il loop



  } // CHIUSA GRAFFA DELL'IF(j==0), NON DEL LOOP!!!


}// QUESTA INVECE È PROPRIO LA CHIUSA GRAFFA DEL LOOP







void decabin(int num){       // Questa funzione converte il numero decimale passatogli in argomento in binario
                             // salvandone ciascun bit in un elemento del vettore bin []. Questa funziona, l'ho provata.
     int i =0;
   
  for(i=0;i<bit_vettore;i++){


      bin[i]= (num%2);
     
      num = floor(num/2);    // lo so che il floor non serve perchè la variabile è di tipo int...
     

  }

   
  }
 
 

nid69ita

Perchè non usare una libreria già fatta ? Solo scopo conoscitivo del Wire ?
my name is IGOR, not AIGOR

propifol

Ciao e grazie per la risposta!

Ho provato ad installare alcune librerie per il funzionamento del DS3231 ma nessuna di queste in realtà funzionava, quindi ho cercato su questo forum ed ho trovato questa discussione:

https://forum.arduino.cc/index.php?topic=435573.0

da lì ho pensato di fare tutto con la libreria Wire, che credo possa permettermi anche di comprendere appieno la comunicazione I2C senza scorciatoie.


brunello22

Non ho guardato lo sketch, o meglio mi sono fermato alle prime righe

perchè dai 0x57 come address ?  è 0x68 quello corretto

Code: [Select]

int ind_RTC = 0x57;    // indirizzo sensore RTC



propifol

Non ho guardato lo sketch, o meglio mi sono fermato alle prime righe

perchè dai 0x57 come address ?  è 0x68 quello corretto

Code: [Select]

int ind_RTC = 0x57;    // indirizzo sensore RTC



ti ringrazio moltissimo per il consiglio, ho corretto subito :)

Il problema però persiste... l'output su monitor seriale è il seguente:

SI COMINCIA!!!!!     
70
8
48
4
44
24
64
14
54
34
74
12
52
2
42
22
62
12
52
32
72
10
50
6
46
26
66
16
56
36
76
14
54
1

e poi ovviamente continua


nid69ita

Io uso la lib senza problemi.    rtc by makuna
my name is IGOR, not AIGOR

propifol

Io uso la lib senza problemi.    rtc by makuna
Innanzi tutto ti ringrazio tantissimo perché l'ho scaricata e sembra funzionare, anche se, dal momento che vorrei imparare, mi piacerebbe non utilizzare librerie ove (forse?) non sono necessarie e soprattutto capire cosa sto sbagliando nell'estrapolazione dei dati che cerco di fare con il mio programma... dopotutto ci sarà qualcuno che le librerie le scrive e quindi sa come trasformare ciò che esce dall'SDA in fantastici dati.

brunello22

Quote
soprattutto capire cosa sto sbagliando nell'estrapolazione dei dati che cerco di fare con il mio programma.
E' quello il punto, non si capisce cosa vuoi fare

A questo  Link c'è un tutorial su come si legge un RTC senza libreria


PaoloF_60

soprattutto capire cosa sto sbagliando nell'estrapolazione dei dati che cerco di fare con il mio programmai.
Non hai letto con attenzione il datasheet
"The contents of the  time  and  calendar  registers  are  in  the  binary-coded  decimal (BCD) format."

Quindi se l' orologio segna le 15,40 i dati ti arrivano cosi

(0001 0101)  (0100 0000) ogni 4 bit si ha un digit se come hai fatto tu converti in decimale hai 21 e 64 invece che 15 e 40 e il tuo orologio da i numeri !

Ciao
Paolo

gpb01

"The contents of the  time  and  calendar  registers  are  in  the  binary-coded  decimal (BCD) format."
Esatto ... occorrono queste due piccole funzioni di conversione da e verso il BCD ...

Code: [Select]
uint8_t decToBcd(uint8_t val) {
  return ( (val / 10 * 16) + (val % 10) );
}

uint8_t bcdToDec(uint8_t val) {
  return ( (val / 16 * 10) + (val % 16) );
}

La prima converte il valore decimale in BCD e la seconda dal BCD in decimale.

Guglielmo
Search is Your friend ... or I am Your enemy !

zoomx

Dal gestore librerie installa la RTClib che ti permette di usare le stesse funzioni su diversi RTC hardware e uno software con millis.
Tra gli esempi ce n'è uno per DS3131.

Per il datalogger leggiti i post in inglese su questo blog
https://thecavepearlproject.org/
L'autore scrive in inglese anche su questo forum.
Ci sono un sacco di trucchi per realizzare un economico datalogger con Pro Mini e DS3231 e l'autore ha parecchia esperienza rispetto agli altri progetti che ho visto.

Io ho usato anche lo shield con il DS1307 e la microSD ma non va bene per i progetti a batteria a meno di non usare batterie giganti o solo per poco tempo.

propifol

Esatto ... occorrono queste due piccole funzioni di conversione da e verso il BCD ...

Code: [Select]
uint8_t decToBcd(uint8_t val) {
  return ( (val / 10 * 16) + (val % 10) );
}

uint8_t bcdToDec(uint8_t val) {
  return ( (val / 16 * 10) + (val % 16) );
}

La prima converte il valore decimale in BCD e la seconda dal BCD in decimale.

Guglielmo
Non hai letto con attenzione il datasheet
"The contents of the  time  and  calendar  registers  are  in  the  binary-coded  decimal (BCD) format."

Quindi se l' orologio segna le 15,40 i dati ti arrivano cosi

(0001 0101)  (0100 0000) ogni 4 bit si ha un digit se come hai fatto tu converti in decimale hai 21 e 64 invece che 15 e 40 e il tuo orologio da i numeri !

Ciao
Paolo
Grazie mille per l'aiuto, siete stati molto cortesi e disponibili!


Ad ogni modo io pensavo di fare esattamente quello che mi avete detto voi tramite questa riga:


 sec = (4*bin[0]+2*bin[1]+bin[2]) * 10 +8*bin[3]+4*bin[4]+2*bin[5]+bin[6];


questi sono proprio solo i secondi dell'orario. in pratica converto in decimale i primi tre bit, memorizzati nel vettore, per creare le decine di secondi (quello che sarebbe il MSB delle decine dei secondi lo ignoro perchè dal datasheet si evince che è sempre 0, infatti le decine dei secondi vanno da 0 a 5 e non servirebbe). I 4 bit rimanenti, memorizzati negli altri elementi del vettore, una volta convertiti sempre nella riga qui sopra diventano le unità dei secondi.



 

propifol

Dal gestore librerie installa la RTClib che ti permette di usare le stesse funzioni su diversi RTC hardware e uno software con millis.
Tra gli esempi ce n'è uno per DS3131.

Per il datalogger leggiti i post in inglese su questo blog
https://thecavepearlproject.org/
L'autore scrive in inglese anche su questo forum.
Ci sono un sacco di trucchi per realizzare un economico datalogger con Pro Mini e DS3231 e l'autore ha parecchia esperienza rispetto agli altri progetti che ho visto.



Ti ringrazio moltissimo per il consiglio e qualora avessi bisogno in futuro userò il sito che mi hai linkato come fonte per informazioni "certificate" :)

Stasera comunque ho finito quello che dovevo fare, a meno che non siano necessarie modifiche in futuro.

Io ho usato anche lo shield con il DS1307 e la microSD ma non va bene per i progetti a batteria a meno di non usare batterie giganti o solo per poco tempo.
Io ne avevo acquistato uno tempo fa e mi ero trovato malissimo (ho scritto per la prima volta su questo forum proprio per chiedere chiarimenti ): pensa che ho acceso e fatto partire l'rtc a settembre e riprovandolo la settimana scorsa mi segnava dicembre come "mese attuale"  (quindi ha accumulato un ritardo di tre mesi in sette mesi)! Probabilmente sono stato sfortunato io con lo shield ma ora che ho provato il DS3231 probabilmente userò solo più questo. È vero che non ha lettore sd incorporato ma

Come batterie si potrebbe usare una maxi powerbank per esempio?

zoomx

Anche i DS1307 che ho usato io danno questi problemi probabilmente perché il quarzo non è preciso e magari perché non è accoppiato bene al chip.

E' saltata una parte di ciò che hai postato ma si, i power bank vanno bene a meno di autoscarica. Il tizio del blog usa delle alcaline non ricaricabili. Non è un esperto di elettronica ma sui datalogger con componenti economici ha sperimentato molto e, soprattutto, li ha usati sul campo. Su alcune cose che lui descrive sul campionamento analogico ho dei dubbi ma in fondo io uso quasi solo sensori digitali.
Leggi le modifiche ai moduli DS3231, va rimosso un diodo e anche il led.
Lui poi usa i ProMini cloni cinesi dove rimuove il led e taglia la pista che viene dal regolatore, cosa che ho fatto anche io, il consumo in sleep cala drasticamente.
Lui poi usa la versione a 3.3V 8MHz per cui si collega direttamente alla microSD usando l'adattatore microSD/SD realizzato per il vecchio modello di RaspberryPI. Ma puoi utilizzare anche un adattatore normale a cui saldi i fili o dei pin.
L'alternativa sarebbe usare la versione più comune a 16MHz ma a 3.3V invece che a 5V solo che siamo fuori dalle specifiche, usando i 3.3V si potrebbe andare al massimo a 12MHz. PErò molti hanno provato e sembra che la cosa vada probabilmente perché la maggior parte del tempo la MCU è in sleep.
Nel suo blog c'è una pagina apposta per la realizzazione del datalogger con solo i 3 componenti che ti ho descritto ma non ricordo il link.

Go Up