TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Suky en 18 de Agosto de 2010, 18:49:18

Título: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 18 de Agosto de 2010, 18:49:18
Pues como dice el titulo necesito implementar un algoritmo que me determine la Fecha (Año, mes, día) más hora (Hora, minutos, segundos, y hasta mili-segundos pero no importan  :mrgreen: ) entregándome como dato los mili-segundos transcurridos desde el 1 de enero a las 00:00:00.000 de 1970 en 48-bits  :z) Aquí les dejo el que he implementado en C30. Tengo uno similar en C18, pero las variables de 64-bits las creo mediante uniones y la operación de multiplicaciones se hace un poco lenta  :undecided:

Código: C
  1. unsigned long High_Data;
  2. unsigned int Low_Data;
  3. unsigned long long Elapsed_Milliseconds;
  4. unsigned long Elapsed_Days;
  5. unsigned char Elapsed_Years;
  6. unsigned char Elapsed_Years_Leap;
  7. unsigned int Days_Of_Year;
  8. unsigned char Month, Day, Hour, Minute, Second, Millisecond;
  9. unsigned int Year;
  10. unsigned long Milliseconds_Day;
  11.  
  12.  
  13. int main (int argc, char * argv[]){
  14.         //125F18457C0
  15.         // PIC 8-bits, C18.-
  16.         //High_Data=0x012A828F;
  17.         //Low_Data=0xFE28;
  18.        
  19.         Elapsed_Milliseconds=0x012A828FFE28;//((unsigned long long)(High_Data*65536)+ Low_Data);
  20.        
  21.         Elapsed_Days=Elapsed_Milliseconds/86400000;
  22.         Elapsed_Years=Elapsed_Days/365;
  23.         Elapsed_Years_Leap=(Elapsed_Years + 1)/4;
  24.         Days_Of_Year=Elapsed_Days -((Elapsed_Years_Leap*366)+(Elapsed_Years-Elapsed_Years_Leap)*365);
  25.         Year=1970+Elapsed_Years;
  26.         // 31 59 90 120 151 181 212 243 273 304 334 365
  27.         if((Year%4)!=0){
  28.                 if(Days_Of_Year<182){
  29.                         Month=6;
  30.                         Day=Days_Of_Year-150;
  31.                         if(Days_Of_Year<91){
  32.                                 if(Days_Of_Year<32){Month=1;Day=Days_Of_Year+1;}
  33.                                 else if(Days_Of_Year<60){Month=2;Day=Days_Of_Year-30;}
  34.                                 else{Month=3;Day=Days_Of_Year-58;}
  35.                         }else{
  36.                                 if(Days_Of_Year<121){Month=4;Day=Days_Of_Year-89;}
  37.                                 else if(Days_Of_Year<152){Month=5;Day=Days_Of_Year-119;}
  38.                         }
  39.                 }else{
  40.                         Month=12;
  41.                         Day=Days_Of_Year-333;
  42.                         if(Days_Of_Year<274){
  43.                                 if(Days_Of_Year<213){Month=7;Day=Days_Of_Year-180;}
  44.                                 else if(Days_Of_Year<244){Month=8;Day=Days_Of_Year-211;}
  45.                                 else{Month=9;Day=Days_Of_Year-242;}
  46.                         }else{
  47.                                 if(Days_Of_Year<305){Month=10;Day=Days_Of_Year-272;}
  48.                                 else if(Days_Of_Year<335){Month=11;Day=Days_Of_Year-303;}
  49.                         }
  50.                 }      
  51.         }else{
  52.                 if(Days_Of_Year<183){
  53.                         Month=6;
  54.                         Day=Days_Of_Year-151;
  55.                         if(Days_Of_Year<92){
  56.                                 if(Days_Of_Year<32){Month=1;Day=Days_Of_Year+1;}
  57.                                 else if(Days_Of_Year<61){Month=2;Day=Days_Of_Year-30;}
  58.                                 else{Month=3;Day=Days_Of_Year-59;}
  59.                         }else{
  60.                                 if(Days_Of_Year<122){Month=4;Day=Days_Of_Year-90;}
  61.                                 else if(Days_Of_Year<153){Month=5;Day=Days_Of_Year-120;}
  62.                         }
  63.                 }else{
  64.                         Month=12;
  65.                         Day=Days_Of_Year-334;
  66.                         if(Days_Of_Year<275){
  67.                                 if(Days_Of_Year<214){Month=7;Day=Days_Of_Year-181;}
  68.                                 else if(Days_Of_Year<245){Month=8;Day=Days_Of_Year-212;}
  69.                                 else{Month=9;Day=Days_Of_Year-243;}
  70.                         }else{
  71.                                 if(Days_Of_Year<306){Month=10;Day=Days_Of_Year-273;}
  72.                                 else if(Days_Of_Year<336){Month=11;Day=Days_Of_Year-304;}
  73.                         }
  74.                 }      
  75.         }
  76.        
  77.         Milliseconds_Day=Elapsed_Milliseconds - ((unsigned long long)Elapsed_Days*86400000);
  78.         Hour=Milliseconds_Day/3600000;
  79.         Minute=(Milliseconds_Day/60000)-((unsigned int)Hour*60);
  80.         Second=(Milliseconds_Day/1000)-((unsigned int)Minute*60)-((unsigned long)Hour*3600);
  81.         Millisecond=Milliseconds_Day-((unsigned int)Second*1000)-((unsigned long)Minute*60000)-((unsigned long)Hour*3600000);
  82.  
  83.         while(1);
  84. }


Si se les ocurre alguna sugerencia, bienvenida sea  :)


Saludos!



Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: todopic en 18 de Agosto de 2010, 19:54:55
Hola Suky, y los años bisiestos?  --->   if año/4 = año\4   bisiesto
 if  int(año/4)= año/4  ---> bisiesto....

te parece?

Norberto
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 18 de Agosto de 2010, 20:12:39
Hola Suky, y los años bisiestos?  --->   if año/4 = año\4   bisiesto
 if  int(año/4)= año/4  ---> bisiesto....

te parece?

Norberto

Eso lo tengo en cuenta con :
Código: C
  1. if((Year%4)!=0){


A eso te refieres?

Saludos!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: BrunoF en 18 de Agosto de 2010, 20:26:53
Hola Suky. Lo que estás intentando es obtener el timestamp, aunque en realidad el timestamp tiene una resolución de segundo, no de milisegundo como tu caso.

La implementación de año bisiesto está incompleta, un año es bisiesto si es múltiplo de 4, pero no de 400. Entonces, por ejemplo, el año 2000 NO fue bisiesto, pese a  ser multiplo de 4.

Necesitas la precision de milisegundos realmente? Porque sino por ahí seguro hay algún algoritmo de timestamp que te sirve, aunque dudo de la optimización del código....
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 18 de Agosto de 2010, 20:40:54
Hola Suky. Lo que estás intentando es obtener el timestamp, aunque en realidad el timestamp tiene una resolución de segundo, no de milisegundo como tu caso.

La implementación de año bisiesto está incompleta, un año es bisiesto si es múltiplo de 4, pero no de 400. Entonces, por ejemplo, el año 2000 NO fue bisiesto, pese a  ser multiplo de 4.

Necesitas la precision de milisegundos realmente? Porque sino por ahí seguro hay algún algoritmo de timestamp que te sirve, aunque dudo de la optimización del código....


Estas equivocado, los años finales de siglo son bisiestos si son divisibles por 400 (2000 fue bisiesto). Y como no creo que llegue al año 2100 no hice ese control en el algoritmo  :mrgreen:

Los milisegundos no son necesarios, por lo general las estaciones ignoran este valor y lo colocan a 000  ;-)


Saludos!

Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: BrunoF en 18 de Agosto de 2010, 20:41:23
Y lo dije todo mal!

Acabo de revisar año bisiesto en wikipedia y es un poco más complejo aún...

La idea es reducir la cantidad de multiplicaciones??

Saludos.
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: gera en 18 de Agosto de 2010, 21:45:57
Hola Suky! Muy bueno che, pero hay una cosita q me llama la atencion. La cabecera estandar:
int main (int argc, char * argv[])
Lo estas ejecutando en un pic??
saludos!!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: RICHI777 en 18 de Agosto de 2010, 21:59:04
Hola, yo utilizaria Julian Dates ( buscar en la web ) eso te da la cantidad de dias pasados desde una fecha especifica, despues solo te resta multiplicar por la cantidad de milisegundos en un dia.

Saludos !
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 19 de Agosto de 2010, 00:04:50
Y lo dije todo mal!

Acabo de revisar año bisiesto en wikipedia y es un poco más complejo aún...

La idea es reducir la cantidad de multiplicaciones??

Saludos.

Sip, es un toque más complejo. Pero en mi caso es para consultar solo si en el año que estoy trabajando es bisiesto  :undecided:

Hola Suky! Muy bueno che, pero hay una cosita q me llama la atencion. La cabecera estandar:
int main (int argc, char * argv[])
Lo estas ejecutando en un pic??
saludos!!

Sip, en C30 se utiliza esa cabecera... :roll:

Hola, yo utilizaria Julian Dates ( buscar en la web ) eso te da la cantidad de dias pasados desde una fecha especifica, despues solo te resta multiplicar por la cantidad de milisegundos en un dia.



Saludos !

Buscando! Igual tengo que implementar el caso contrario, de la fecha actual determinar los milisegundos  :)


Edit: No quiero que se mal entienda, yo presento el algoritmo que he realizado para determinar la fecha, y funciona correctamente (Puede servirle a alguien). Pero como lo mio no es la programación, de algoritmos tengo poca idea, puede que haya otra forma más simple de hacerlo  ;-)



Saludos!

Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: gera en 19 de Agosto de 2010, 00:44:26
Sip, en C30 se utiliza esa cabecera... :roll:
Y de donde recibe los parametros argc y argv? En la compu los carga el sistema operativo con los parametros que uno ponga al ejecutar el programa, pero en un pic?? O.o
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 19 de Agosto de 2010, 01:03:31
Sip, en C30 se utiliza esa cabecera... :roll:
Y de donde recibe los parametros argc y argv? En la compu los carga el sistema operativo con los parametros que uno ponga al ejecutar el programa, pero en un pic?? O.o
(http://www.clubbol.com/equipos/barcelona/fotos/img/grandes/no-tengo-ni-idea.jpg)

Lo mio fue Copy&Paste  :mrgreen:  :D :D :D

También se usa int main()...
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: gera en 19 de Agosto de 2010, 01:40:32
JAJAJA me mato la cara :D
ta bien, ya voy a ver si encuentro algo googleando jeje. Perdon por desvirtuar el hilo :P
saludosss!!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Eduardo2 en 19 de Agosto de 2010, 02:12:43
   
Código: [Seleccionar]
        Elapsed_Milliseconds=0x012A828FFE28;//((unsigned long long)(High_Data*65536)+ Low_Data);

Elapsed_Days=Elapsed_Milliseconds/86400000;
Elapsed_Years=Elapsed_Days/365;
Elapsed_Years_Leap=Elapsed_Years/4;
Days_Of_Year=Elapsed_Days -((Elapsed_Years_Leap*366)+(Elapsed_Years-Elapsed_Years_Leap)*365);
Year=1970+Elapsed_Years;
// 31 59 90 120 151 181 212 243 273 304 334 365
if((Year%4)!=0){

Estás contando los bisiestos cada 4 años pero a partir de 1970, y 1970 no fué bisiesto ==> agrega 1 día en 1970,1974,1978,1982... que no fueron bisiestos.

Si el año de base fuera un bisiesto como 1980 no habría problema.



Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 19 de Agosto de 2010, 02:27:51
   
Código: [Seleccionar]
        Elapsed_Milliseconds=0x012A828FFE28;//((unsigned long long)(High_Data*65536)+ Low_Data);

Elapsed_Days=Elapsed_Milliseconds/86400000;
Elapsed_Years=Elapsed_Days/365;
Elapsed_Years_Leap=Elapsed_Years/4;
Days_Of_Year=Elapsed_Days -((Elapsed_Years_Leap*366)+(Elapsed_Years-Elapsed_Years_Leap)*365);
Year=1970+Elapsed_Years;
// 31 59 90 120 151 181 212 243 273 304 334 365
if((Year%4)!=0){

Estás contando los bisiestos cada 4 años pero a partir de 1970, y 1970 no fué bisiesto ==> agrega 1 día en 1970,1974,1978,1982... que no fueron bisiestos.

Si el año de base fuera un bisiesto como 1980 no habría problema.


Ya se, yo calculo cuantos años bisiestos hay en el rango.. No veo el error, y como dije anteriormente, lo he probado y funciona perfectamente  :undecided:

Saludos!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: migsantiago en 19 de Agosto de 2010, 10:38:23
Hola Suky, disculpa la pregunta, ¿para qué sirve recibir esa cantidad en ms y convertirla a una fecha?

Si el PIC estuviera recibiendo tal cantidad, mejor que la PC ya se la mande completa en vez de atarearlo más. En todo lenguaje actual ya hay librerías para esas conversiones, por ejemplo:

http://dotnetperls.com/datetime-1

Y si el cálculo se hace en la PC pues estaría de sobra.
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: willynovi en 19 de Agosto de 2010, 11:11:22
Suky, muy bueno lo que presentas, no se si necesitaré algo así en algún momento pero es buenosaber que esta por aquí.

Con respecto a los años bisiestos, creo que tienen razón lo que te comentan del año 1970.
Fijate con este ejemplo a la fecha actual,

Elapsed_Years_Leap=(2010-1970)/4;  // Resultado 40/4=10

Luego en la siguiente instrucción tomas como que esos son los años bisiestos que has tenido y los consideras de 366 días, cuando en realidad como el año 1970 no fue bisiesto, si no que fue el 1972, has tenido solo 9,5 años bisiestos por lo que tomarias 9 años.

Es lo que he entendido leyendo el código que escribiste, al menos esa parte, puede que en otra sección hagas otro arreglo que no logro ver.
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 19 de Agosto de 2010, 11:41:52
Hola Suky, disculpa la pregunta, ¿para qué sirve recibir esa cantidad en ms y convertirla a una fecha?

Si el PIC estuviera recibiendo tal cantidad, mejor que la PC ya se la mande completa en vez de atarearlo más. En todo lenguaje actual ya hay librerías para esas conversiones, por ejemplo:

http://dotnetperls.com/datetime-1

Y si el cálculo se hace en la PC pues estaría de sobra.

Hola Santiago! Tu tienes toda la razón, cuando estaba estudiando el protocolo pensaba ver los datos de la manera que comentas, pero me di la grata sorpresa que se envia de esa manera  :shock: O sea es un estándar establecido que no puede modificarse  :? El protocolo es DNP3, del cual estoy haciendo el Stack, no completo, pero con muchas implementaciones. Este protocolo tiene esta estructura:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=31697.0;attach=12894)
Y además los datos son empaquetados de la siguiente forma:

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=31697.0;attach=12896)

Suky, muy bueno lo que presentas, no se si necesitaré algo así en algún momento pero es buenosaber que esta por aquí.

Con respecto a los años bisiestos, creo que tienen razón lo que te comentan del año 1970.
Fijate con este ejemplo a la fecha actual,

Elapsed_Years_Leap=(2010-1970)/4;  // Resultado 40/4=10

Luego en la siguiente instrucción tomas como que esos son los años bisiestos que has tenido y los consideras de 366 días, cuando en realidad como el año 1970 no fue bisiesto, si no que fue el 1972, has tenido solo 9,5 años bisiestos por lo que tomarias 9 años.

Es lo que he entendido leyendo el código que escribiste, al menos esa parte, puede que en otra sección hagas otro arreglo que no logro ver.

Es cierto!  :oops: No lo había analizado correctamente... Solucionando...


Saludos!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: willynovi en 19 de Agosto de 2010, 13:42:48
Sip, en C30 se utiliza esa cabecera... :roll:
Y de donde recibe los parametros argc y argv? En la compu los carga el sistema operativo con los parametros que uno ponga al ejecutar el programa, pero en un pic?? O.o

Por lo que pude ver en la documentación del C30 estos argumentos son para control del Preprocesador.
La diferencia que le veo a un programa que se ejecuta en una computadora es que en estos (los de la PC) los argumentos (parametros) se pasan al momento de ejecutar el programa.
Y para el caso del microcontrolador estos argumentos se pasan al momento de compilar el programa. Luego al momento de ejecutar es siempre el mismo programa.

Alguien mas entendido en el tema creo puede aportar mas.
De todas formas si no son necesarios se usa
int main(void)
como indicaba Suky
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: BrunoF en 19 de Agosto de 2010, 13:45:03
Será más que nada para cumplir con lo que exíge ANSI C?
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: jansuini en 15 de Noviembre de 2010, 14:40:44
Suky:
Como anda la implementación del DNP? imagino que es un esclavo. Con que pensás probarlo como master?
Sds.
Jorge
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 15 de Noviembre de 2010, 14:54:46
Suky:
Como anda la implementación del DNP? imagino que es un esclavo. Con que pensás probarlo como master?
Sds.
Jorge

Es un esclavo. Ya está implementado, o por lo menos la parte del protocolo, ya está para ser presentado  :mrgreen:


Saludos!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: jansuini en 15 de Noviembre de 2010, 15:55:31
ok,pero donde lo presentarás?
Jorge
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: Suky en 15 de Noviembre de 2010, 16:19:01
ok,pero donde lo presentarás?
Jorge

Parte de la librería la compartimos en el segundo congreso virtual de microcontroladores. Implementar este protocolo es una parte de mi tesis de grado.


Saludos!
Título: Re: Algoritmo para determinar Fecha y hora según mili-segundos pasados desde 1970
Publicado por: IngRandall en 04 de Agosto de 2011, 17:36:31
Hola, he estado trabajando con este algoritmo, y me parece muy bueno, pero ahora los estoy haciendo de forma contraria y no me esta resultando, aquí porgo el ejemplo:

    ano_rtu=11;
    mes_rtu=8;
    dia_rtu=4;
    horas_rtu=10;
    minutos_rtu=50;
    segundos_rtu=40;


   
   
   
    ano_rtu_dnp3=ano_rtu+30;

    mes_rtu_dnp3=mes_rtu;

    anos_bisiestos=((ano_rtu/4)+8);

    dias_rtu_dnp3=dia_rtu+anos_bisiestos;

    horas_rtu_dnp3=horas_rtu;

    minutos_rtu_dnp3=minutos_rtu;

    segundos_rtu_dnp3=segundos_rtu;


    Elapsed_Milliseconds=0;


    Elapsed_Milliseconds=ano_rtu_dnp3*31557600000;

    Elapsed_Milliseconds=Elapsed_Milliseconds+mes_rtu*2629800000;

    Elapsed_Milliseconds=Elapsed_Milliseconds+dias_rtu_dnp3*86400000;

    Elapsed_Milliseconds=Elapsed_Milliseconds+horas_rtu_dnp3*3600000;

    Elapsed_Milliseconds=Elapsed_Milliseconds+minutos_rtu_dnp3*60000;

    Elapsed_Milliseconds=Elapsed_Milliseconds+segundos_rtu_dnp3*1000;

    tp6=tp5=tp4=tp3=tp2=tp1=0;


    tp1=Elapsed_Milliseconds&0b11111111;
    Elapsed_Milliseconds=Elapsed_Milliseconds>>8;
    tp2=Elapsed_Milliseconds&0b11111111;
    Elapsed_Milliseconds=Elapsed_Milliseconds>>8;
    tp3=Elapsed_Milliseconds&0b11111111;
    Elapsed_Milliseconds=Elapsed_Milliseconds>>8;
    tp4=Elapsed_Milliseconds&0b11111111;
    Elapsed_Milliseconds=Elapsed_Milliseconds>>8;
    tp5=Elapsed_Milliseconds&0b11111111;
    Elapsed_Milliseconds=Elapsed_Milliseconds>>8;
    tp6=Elapsed_Milliseconds&0b11111111;



pero no me esta dando.