Pages: [1]   Go Down
Author Topic: [ Risolto ] Aiuto per l'uso della libreria time.h, now() e timestamp  (Read 1284 times)
0 Members and 1 Guest are viewing this topic.
Rome
Offline Offline
Sr. Member
****
Karma: 9
Posts: 371
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti,
ancora io che chiedo per la gestione del tempo:
ho bisogno di eseguire confronti tra il valore restituito da now() (i secondi trasforsi dal 1.1.1970 a now()) ed un timestamp futuro che quindi dovrei calcolarmi, solo che non riesco a capire come calcolarlo...
Da un bel po mi sbatto per capire come si calcola e creare una funzioncina, ma il valore che tiro fuori tenendo conto anche degli anni bisestili, non è mai affidabile, nel senso che ho cercato di raggiungere il risultato confrontandolo anche con quello restituito da due servizi on line:

http://www.timestampconvert.net/index.php?to=2ts&month=10&day=06&year=2013&hour=11&min=23&sec=15&ts=1347693604

http://www.unixtimestamp.com/index.php

che a loro volta restituiscono per la stessa data valori diversi, ottenedo a mia volta un terzo risultato  smiley-sad
Ho cercato invano anche su internet formule per il calcolo per poter a mia volta crearmi una funzioncina affidabile, ma non trovo nulla, quindi eccomi qui a chiedere aiuto...

Grazie in anticipo a tutti.

Riccardo
« Last Edit: September 19, 2012, 01:16:09 pm by riciweb » Logged

Riccardo

Selvazzano Dentro - Padova
Offline Offline
Edison Member
*
Karma: 37
Posts: 1274
"Chi sa fa, chi non sa insegna"
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Lo UNIX Time è il numero di secondi trascorsi a partire dal 01/01/1970 e rappresenta un metodo rapido e semplice per calcolare il tempo nei calcolatori, grazie al fatto che si opera con numeri interi.

Il secondo link che hai fornito è sicuramente il più utile, in quanto l'ora che indica è riferita al GMT 0 (meridiano di Greenwich), da cui derivare tutti gli altri. Noi siamo in GMT +1 quindi lo UNIX Time "nostro" è quello indicato sul sito +2 ore espresse in secondi: una per il calcolo del fuso ed una per l'ora legale. Quindi X + (2 x 60 x 60).

L'altro sito fa la stessa cosa, ma considera un GMT -5 più l'eventuale ora legale (ecco il motivo dei diversi risultati).

Rimane il problema del calcolo dei giorni, complicato dal fatto che ogni 4 anni un anno è bisestile... ti ho dato un indizio ora prova a sviluppare un codice!

Ettore Massimo Albani
Logged

Rome
Offline Offline
Sr. Member
****
Karma: 9
Posts: 371
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Allora, allora,
ho preso l'esempio della libreria time.h denominato "TimeRTC" e l'ho modificato
per vedere se riesco a calcolare il timestamp, il codice è quello che segue:

Code:
/*
 * TimeRTC.pde
 * example code illustrating Time library with Real Time Clock.
 *
 */

#include <Time.h> 
#include <Wire.h> 
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t

void setup()  {
  Serial.begin(9600);
  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");     
}

unsigned long miotimestamp;
const unsigned long totmesiinsecondi [12]  = {0,2678400,5097600,7776000,10368000,13046400,15638400,18316800,20995200,23587200,26265600,28857600};
                   
const unsigned long annoinsec = 31536000;  // Un anno espresso in secondi
const unsigned long giornoinsec = 86400;   // Un giorno espresso in secondi
const int orainsec = 3600;                 // Un'ora spressa in secondi
const int announix = 1970;
int bisestile;

void loop()
{
  int indicetotmesi = month()-1;
  miotimestamp = ((year() - announix) * annoinsec) + ((int((year() - 1968) / 4)) * giornoinsec) + totmesiinsecondi[indicetotmesi] + (day() * giornoinsec) + (hour() * orainsec) + (minute() * 60) + second();
//                (gli anni trascorsi da epoc    ) + (giorni aggiuntivi per gli anni bisestili) + (leggo nel vettorequanti sec.   + (giorni del mese in   + (ore att. in secondi)
//                                                                                                 sono passati dall' inizio anno    corso in secondi)
//                                                                                                 alla fine del mese precedente
//                                                                                                 tenedo conto della variabilità
//                                                                                                 dei mesi) 

   bisestile = (year() % 4); 
   
   if ((month() == 2) && (day() <= 29) && (bisestile = 0))
     {  miotimestamp = miotimestamp - giornoinsec; }
     // se l'anno rilevato è bisestile la formula sopra aggiunge un giorno anche se ancora non è passato il 29 febbraio quindi verifico le condizioni ed eventualmente sottraggo un giorno   
     
   digitalClockDisplay(); 
   delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.print("    Timestamp = ");
  Serial.print(now());
  Serial.print("    MioTimestamp = ");
  Serial.print(miotimestamp);
  Serial.print("    Differenza = ");
  Serial.println(miotimestamp - now());
 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Nel serial monitor, il mio timestamp è costantemente magggiore rispetto a quello di now() di 20864 secondi  smiley-sad, ossia 5 ore 47 minuti e 44 secondi:

20:56:57 15 9 2012    Timestamp = 1347742617    MioTimestamp = 1347763481    Differenza = 20864

Da ore cerco di capire dove sta l'inghippo ma proprio non lo vedo  smiley-cry,
Mi rendo conto che la domanda è impegnativa, ma qualcuno riesce a capire dove sbaglio... smiley-roll-sweat

Grazie Riccardo
Logged

Riccardo

Rome
Offline Offline
Sr. Member
****
Karma: 9
Posts: 371
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Lo UNIX Time è il numero di secondi trascorsi a partire dal 01/01/1970 e rappresenta un metodo rapido e semplice per calcolare il tempo nei calcolatori, grazie al fatto che si opera con numeri interi.

Il secondo link che hai fornito è sicuramente il più utile, in quanto l'ora che indica è riferita al GMT 0 (meridiano di Greenwich), da cui derivare tutti gli altri. Noi siamo in GMT +1 quindi lo UNIX Time "nostro" è quello indicato sul sito +2 ore espresse in secondi: una per il calcolo del fuso ed una per l'ora legale. Quindi X + (2 x 60 x 60).

L'altro sito fa la stessa cosa, ma considera un GMT -5 più l'eventuale ora legale (ecco il motivo dei diversi risultati).

Ettore Massimo Albani

Ciao,
scusami se nel post precedente ho dimenticato di ringraziarti, ero così preso dal risolvere il mio quesito che ho tralasciato le buone maniere.
Ti ringrazio ora scusa il ritardo.

Ad ogni modo il tuo post, ha risolto in parte il dubbio che avevo sul calcolo del timestamp, nel senso che una volta assunto che la differenza tra i risultati ottenuti via web dipendeva dal fuso orario ed eventualmente anche dall'ora legale, mi sono detto che la funzione now() aplicata all'orario catturato dal mio RTC (DS1307) non ne sarebbe stata influenzata e mi sono messo a scrivere le poche righe che ho postato,ottenedo appunto la differenza per eccesso che ho già scritto.

Oggi ho fatto un'altra prova ancora, ho attaccato un Mega 2560 che avevo da parte, ed ho applicato la mia formula anche all'esempio della libreria che riguarda la sincronizzazione attraverso la seriale "TimeSerial", il codice è quello che segue:

Code:

/*
 * TimeSerial.pde
 * example code illustrating Time library set through serial port messages.
 *
 * Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970)
 * you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2010
 T1262347200 
 *
 * A Processing example sketch to automatically send the messages is inclided in the download
 */
 
#include <Time.h> 

#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message
#define TIME_REQUEST  7    // ASCII bell character requests a time sync message

unsigned long miotimestamp;
const unsigned long totmesiinsecondi [12]  = {0,2678400,5097600,7776000,10368000,13046400,15638400,18316800,20995200,23587200,26265600,28857600};
                   
const unsigned long annoinsec = 31536000;  // Un anno espresso in secondi
const unsigned long giornoinsec = 86400;   // Un giorno espresso in secondi
const int orainsec = 3600;                 // Un'ora spressa in secondi
const int announix = 1970;
int bisestile;


void setup()  {
  Serial.begin(9600);
  setSyncProvider( requestSync);  //set function to call when sync required
  Serial.println("Waiting for sync message");
}

void loop(){   
 
  if(Serial.available() )
  {
    processSyncMessage();
  }
  if(timeStatus()!= timeNotSet)   
  {
    digitalWrite(13,timeStatus() == timeSet); // on if synced, off if needs refresh 
    digitalClockDisplay(); 
    int indicetotmesi = month()-1;
    miotimestamp = ((year() - announix) * annoinsec) + ((int((year() - 1968) / 4)) * giornoinsec) + totmesiinsecondi[indicetotmesi] + (day() * giornoinsec) + (hour() * orainsec) + (minute() * 60) + second();
//                  (gli anni trascorsi da epoc    ) + (giorni aggiuntivi per gli anni bisestili) + (leggo nel vettorequanti sec.   + (giorni del mese in   + (ore att. in secondi)
//                                                                                                 sono passati dall' inizio anno    corso in secondi)
//                                                                                                 alla fine del mese precedente
//                                                                                                 tenedo conto della variabilità
//                                                                                                 dei mesi) 

   bisestile = (year() % 4); 
   
   if ((month() == 2) && (day() <= 29) && (bisestile = 0))
     {  miotimestamp = miotimestamp - giornoinsec; }
     // se l'anno rilevato è bisestile la formula sopra aggiunge un giorno anche se ancora non è passato il 29 febbraio quindi verifico le condizioni ed eventualmente sottraggo un giorno   
     
     
  }
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.print("    Timestamp = ");
  Serial.print(now());
  Serial.print("    MioTimestamp = ");
  Serial.print(miotimestamp);
  Serial.print("    Differenza = ");
  Serial.println(miotimestamp - now());
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void processSyncMessage() {
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    char c = Serial.read() ;
    Serial.print(c); 
    if( c == TIME_HEADER ) {       
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        c = Serial.read();         
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number   
        }
      }   
      setTime(pctime);   // Sync Arduino clock to the time received on the serial port
    } 
  }
}

time_t requestSync()
{
  Serial.write(TIME_REQUEST); 
  return 0; // the time will be sent later in response to serial mesg
}

Anche in questo caso la differenza è stata di 20863 sec (1 in meno rispetto all'ora presa dall'RTC):

12:00:01 1 1 2010    Timestamp = 1262347201    MioTimestamp = 1262368064    Differenza = 20863

Me lo aspettavo in parte, ma ho voluto provare ugualmente...

Potrei anche fermarmi qui e semplicemente sottrarre l'eccedenza, ma mi rimarrebbe il tarlo di sapere cosa sbaglio...

Con sintesi estrema, devo eseguire in modo regolare x operazioni all'interno di un intervallo di tempo che può accavallarsi alla mezzanotte, quindi con i timestamp eseguo semplici confronti ed Arduino fa o legge qualcosa, diversemente dovrei raffontare orari che a mezzanotte si azzerano e via dicendo, non che non si faccia, ma con i timestamp il codice sarebbe decisamente più snello e risparmierei un bel po' di memoria.

Grazie a chiunque vorrà aiutarmi.

Ancora grazie a cyberhs.

Riccardo
Logged

Riccardo

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ti posso dare un piccolo aiuto, nel senso che le funzioni di conversione di UNIX hanno fatto penare anche me.
Se ti prendi la mia lib swRTC, nel codice ci sono 2 algoritmi per passare da un timestamp ad un dato istante e viceversa. Le funzioni non sono legate al solo timestamp UNIX ma accettato una qualsiasi epoca.
« Last Edit: September 17, 2012, 02:19:13 pm by leo72 » Logged


Rome
Offline Offline
Sr. Member
****
Karma: 9
Posts: 371
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie Leo72,
ci guardo di sicuro, la tua libreria l'avevo già scaricata, perché come avrai capito mi interessa molto il controllo del tempo...
Spero prima o poi di svelare l'arcano...

Grazie.

Riccardo.
Logged

Riccardo

Rome
Offline Offline
Sr. Member
****
Karma: 9
Posts: 371
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti,
ho seguito il consiglio di Leo72,
e dalla sua libreria ho estrapolato la sua funzione "getTimestamp" per confrontarne/capirna il funzionamento, l'ho adattata all'esempio della libreria time che si chiama "TimeSerial" per fare delle prove:

Code:
/*
 * TimeSerial.pde
 * example code illustrating Time library set through serial port messages.
 *
 * Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970)
 * you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2010
 T1262347200 
 *
 * A Processing example sketch to automatically send the messages is inclided in the download
 */
 
#include <Time.h> 

#define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by unix time_t as ten ascii digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message
#define TIME_REQUEST  7    // ASCII bell character requests a time sync message

//////////  VARIABILI DI LEO72

byte daysPerMonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
unsigned long time=0;
unsigned long tmstp;

void setup()  {
  Serial.begin(9600);
  setSyncProvider( requestSync);  //set function to call when sync required
  Serial.println("Waiting for sync message");
}

void loop(){   
  time = 0;
  if(Serial.available() )
  {
    processSyncMessage();
  }
  if(timeStatus()!= timeNotSet)   
  {
    digitalWrite(13,timeStatus() == timeSet); // on if synced, off if needs refresh 
    tmstp = now();
    Leo72();
    digitalClockDisplay(); 
  }
  //delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.print("    Timestamp = ");
  Serial.print(now());
  Serial.print("    LeoTimestamp = ");
  Serial.print(time);
  Serial.print("    LeoTimestamp-Timestamp = ");
  Serial.println(time - tmstp);
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void processSyncMessage() {
  // if time sync available from serial port, update time and return true
  while(Serial.available() >=  TIME_MSG_LEN ){  // time message consists of a header and ten ascii digits
    char c = Serial.read() ;
    Serial.print(c); 
    if( c == TIME_HEADER ) {       
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){   
        c = Serial.read();         
        if( c >= '0' && c <= '9'){   
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number   
        }
      }   
      setTime(pctime);   // Sync Arduino clock to the time received on the serial port
    } 
  }
}

time_t requestSync()
{
  Serial.write(TIME_REQUEST); 
  return 0; // the time will be sent later in response to serial mesg
}


void Leo72()
{ time += (year()- 1970)*365.2422;
for (int i=0; i < month()-1; i++){
time += daysPerMonth[i]; //find day from month
}
time = ( time + day() ) * 24; //find hour from day
time = ( time + hour() ) * 60; //find minute from hours
time = ( time + minute() ) * 60; //find seconds from minute
time += second(); // add seconds
if (time>951847199) { time +=86400; } //year 2000 is a special leap year, so 1 day must be added if date is greater than 29/02/2000
        time -=86400UL; //because years start at day 0.0, not day 1.
      }

dal serial monitor, passando "T1347738804" che corrisponde come data 15/09/2012 ore 19:53:24 ecco la conferma:

Code:
Waiting for sync message
T19:53:24 15 9 2012    Timestamp = 1347738804    LeoTimestamp = 1347738804    LeoTimestamp-Timestamp = 0
19:53:25 15 9 2012    Timestamp = 1347738805    LeoTimestamp = 1347738805    LeoTimestamp-Timestamp = 0
19:53:26 15 9 2012    Timestamp = 1347738806    LeoTimestamp = 1347738806    LeoTimestamp-Timestamp = 0
19:53:27 15 9 2012    Timestamp = 1347738807    LeoTimestamp = 1347738807    LeoTimestamp-Timestamp = 0
19:53:28 15 9 2012    Timestamp = 1347738808    LeoTimestamp = 1347738808    LeoTimestamp-Timestamp = 0

Ora non mi rimane che scrivere la procedurina alla quale passare i valori che voglio per calcolare i timestamp futuri, che schiappa che sono due giorni per far girare sto sketchino...

Grazie a tutti, ma soprattutto a Leo72.

Riccardo.
Logged

Riccardo

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bravo, mi fa piacere che tu abbia risolto, anche se ho potuto aiutarti il giusto dati i miei impegni.
Ah... ricordati: condividere condividere condividere  smiley-wink
Logged


Pages: [1]   Go Up
Jump to: