Funciones de tiempo, fecha y hora

Arduino tiene algunas funciones que manejan directamente los temporizadores y tienen usos diversos. Pero recuerda que Arduino no tiene un temporizador permante como si es el modulo RTC asi que no puede saber la fecha y hora. Todos sus temporizadores se resetean al desconectar la energía.

1. Tiempos

En Arduino tenemos algunas funciones que detienen la ejecución del boceto. Tenga mucho cuidado ya que durante ese tiempo el uC no hace nada mas que esterar se cumpla el retardo.

1.1 delay()

Pausa el programa por la cantidad de milisegundos especificado como parámetro. No devuelve nada.

delay(ms);

ms es un unsignet long.

delay(1000); //1 segundo

Si bien es fácil crear un LED parpadeante con la funcion delay() y muchos bocetos lo usan, también es usado como antirrebote de pulsadores, el uso de delay() en un boceto tiene inconvenientes importantes. Ninguna otra lectura o manipulacion de de puerto, cálculos matemáticos puede ejecutarse durante la función de retardo, por lo que, en efecto, detiene la mayoría de otras actividades. Para obtener enfoques alternativos para controlar el tiempo, consulte las funciónes millis() o micros().

Los programadores más conocedores generalmente evitan el uso de la funcion delay() de más de 10 de milisegundos, a menos que el boceto de Arduino sea muy simple.

1.2 delayMicroseconds()

Pausa el programa por la cantidad de microsegundos especificado como parámetro. Actualmente, el valor más grande que producirá un retraso preciso es 16383.

delayMicroseconds(us);

us es un unsignet long.

delayMicroseconds(1000); //1 ms

1.3 micros()

Devuelve la cantidad de microsegundos desde que la placa Arduino comenzó a ejecutar el programa actual. Este número se desbordará (volverá a cero), después de aproximadamente 70 minutos. En las placas Arduino de 16 MHz (por ejemplo, Duemilanove y Nano), esta función tiene una resolución de cuatro microsegundos (es decir, el valor devuelto siempre es un múltiplo de cuatro). En placas Arduino de 8 MHz (por ejemplo, el LilyPad), esta función tiene una resolución de ocho microsegundos.

unsigned long tiempo;
tiempo = micros();

Tenga cuidado de no intentar hacer operaciones matemáticas con números int porque serán muy pequeños.

1.4 millis()

Devuelve la cantidad de milisegundos desde que la placa Arduino comenzó a ejecutar el programa actual. Este número se desbordará (volverá a cero), después de aproximadamente 50 días.

Una variable unsignet long ocupa 4 bytes (32 bits) es decir el valor mas alto que puede guardar es 4,294,967,286 milisegundos, si dividimos entre 86,400,000 (24x60x60x1000) nos dara 49.71 dias.

unsigned long tiempo;
tiempo = millis();

Tenga cuidado de no intentar hacer operaciones matemáticas con números int porque serán muy pequeños.

2. Fecha y hora

Los temporizadores internos de Arduino son de corto plazo. Pero que hacer cuando requerimos por ejemplo poner fecha y hora en nuestro tabulador de datos de sensores (datalogger) para un analisis posterior ? Estas funciones están disponibles si añades la librería estandar de Arduino Time.h o la nueva TimeLib.h

Lo primero que hace la librería Time.h es definir un tipo especial de variable que llamamos time_t de 32 bits, que es la base de todo, porque almacena valores de tiempo en un formato especial calculado como el número de segundos transcurridos desde el 1-ENE-1970, llamada fecha Unix.

time_t hoy = now();
Funciones incluidas
FuncionDescripciónrango
millis()milisegundos0~999
second()Segundos0~59
minute()Minutos0~59
hour()Horas0~23
day()Dias1~31
dayStr(day())DiasCadena para imprimir
dayShortStr(day())DiasCadena para imprimir
weekday()Dia de la semana1~7,1=domingo
month()Mes1~12
monthStr(month())MesCadena para imprimir
monthShortStr(month())MesCadema para imprimir
year()Añoaño de 4 digitos
hourFormat12()Pone en formato de 12 horas0~12
isAM()AMVerdadero por la mañana
isPM()PMVerdadero por la tarde
now()Tiempo UnixSegundos desde 1-ENE-1970

Fantástico ya tenemos creada nuestra variable del tipo time_h con la hora actual según nuestro Arduino... pero espera no que Arduino no sabia la fecha ni hora ? exacto lo que acabas de obtener es un porquería y hay que arreglar al Arduino.

2.1 setTime()

Esta es la función que nos permite decirle al Arduino en que dia y hora estamos.

setTime(ss);
setTime(hh,mm,ss,dia,mes,año);
#include lt;Time.h>
setTime(8,0,0,14,7,2018); //14-JUL-2018 08:00:00

2.2 adjunstTime()

adjustTime();

2.3 timeSet()

timeSet();

2.4 dayStr()

dayStr();

2.5 dayShortStr()

dayShortStr();

2.6 monthStr()

monthStr();

2.7 monthShortStr()

monthShortStr();

2.8 makeTime()

Esta es una función que nos permite crear tiempos Unix fácilmente para hacer calculo entre dos fechas luego.

tmElements_t  tx;
   tx.Second = Segundos; (0~59)
   tx.Minute = Minutos; (0~59)
   tx.Hour = Horas; (0~23)
   tx.Day = Dia; (1~31)
   tx.Month = Mes; (1~12)
   tx.Year = Año; (0~99) Diferencia desde 1970.
tmElements_t  t;
   t.Second = 0;
   t.Minute = 10;
   t.Hour = 8;
   t.Day = 14;
   t.Month = 7;
   t.Year = 48; //2018-1970
t1 = makeTime(t);
#include lt;Time.h>
time_t t0,t1,dif;
void setup(){
	Serial.begin(115200);
}
void loop(){
	t0 = ponFecha(2018, 11, 6, 20, 17, 0);  //6-NOV-2018 20:17:00
    printFecha(t0);
    t1 = ponFecha(2018, 11, 13, 16, 45, 0);  //13-NOV-2018 16:45:00
    printFecha(t1);
    printFecha(t1 - t0);
    Serial.println("--------------------------------------------------");
    dif =  t1 - t0:
    Serial.print(String(year(dif)) + " años, "  + String(month(dif)-1 )+" meses,");
    Serial.println(String(day(dif))+ " dias," + String(hour(dif))+ " horas");
    Serial.println("---------------------------------------------------");
    delay(5000);
}
time_t ponFecha(int y, int m, int d, int hh, int mm, int ss){  
	tmElements_t f;
      f.Second = ss;
      f.Minute = mm;
      f.Hour = hh;
      f.Day = d;
      f.Month = m;
      f.Year = y - 1970 ; 
      return makeTime(f);
}
void printFecha(time_t  t){
	if (day(t) < 10){
		Serial.print("0");
	}
    Serial.print(day(t));
    Serial.print(+ "-");
	if (month(t) < 10){
		Serial.print("0");
	}
	Serial.print(month(t));
	Serial.print(+ "-");
    Serial.print(year(t));
    Serial.print(" ");
	if (hour(t) < 10){
		Serial.print("0");
	}
    Serial.print(hour(t));
	Serial.print(":");
	if (minute(t) < 10){
		Serial.print("0");
	}
	Serial.print(minute(t));
	Serial.print(":");
	if (second(t) < 10){
		Serial.print("0");
	}
    Serial.println(second(t));
	Serial.print(".");
	if (millis(t) < 100){
		Serial.print("0");
		if (millis(t) < 10){
			Serial.print("0");
		}
	}
    Serial.println(millis(t));
}

2.9 NTP

Network Time Protocol o NTP es un protocolo de internet que maneja la fecha en la red.

void setup(){
 Serial.begin(9600);
 Ethernet.begin(mac, ip, gateway);
 Serial.println("Esperando sincronizacion");
 setSyncProvider(getNtpTime);
 while (timeStatus() == timeNotSet)
 ; //Espera hasta que proveedor responda
}

void loop(){
	//Muestra hora solo si cambia
	if (now() != prevDisplay){
		prevDisplay = now();
		muestraHora();
	}
}

void muestraHora() {
	printDigits(hour());
	Serial.print(':');
	printDigits(minute());
	Serial.print(':');
	printDigits(second());
	Serial.print(' ');
	printDigits(day());
	Serial.print('-');
	printDigits(month());
	Serial.print('-');
	Serial.println(year());
}

void printDigits(int digits) {
	if (digits < 10){
		Serial.print('0');
	}
	Serial.print(digits);
}

2.10 timeStatus()

Nos permite saber el estado la la sincronización de nuestro reloj.

2.11 setSyncProvider

Define el proveedor de sincronización externo.

2.12 setSyncInterval()

Define el intervalo de sincronización en segundos.

2.13 Sincronizar con monitor serie

#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 

// T1262347200 //noon Jan 1 2010

void setup() {
	Serial.begin(9600);
}

void loop() {
	if (Serial.available()) {
		processSyncMessage();
	}
	if (timeStatus() == timeNotSet){
		Serial.println("Esperando la sincronisación externa");
	}else{
		digitalClockDisplay();
	}
	delay(1000);
}

void digitalClockDisplay() {
	printDigits(day());
	Serial.print('-');
	printDigits(month());
	Serial.print('-');
	Serial.print(year());
	Serial.print(' ');
	printDigits(hour());
	Serial.print(':');
	printDigits(minute());
	Serial.print(':');
	printDigits(second());
	Serial.println();
}

void printDigits(int digits) {
	if (digits < 10){
		Serial.print('0');
	}
	Serial.print(digits);
}

void processSyncMessage() {
	//if time sync available from serial port, update time and return true
	//time message consists of header & 10 ASCII digits
	while (Serial.available() >= TIME_MSG_LEN) { 
		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') {
					//convert digits to a number
					pctime = (10 * pctime) + (c - '0');
				}
			}
			//Sync Arduino clock to the time received on the serial port
			setTime(pctime); 
		}
	}
}