millis()

De ArduWiki
Revisión del 00:37 25 jul 2019 de Kike GL (Discusión | contribuciones) (Ejemplo 2)

Saltar a: navegación, buscar

Descripción

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

Sintaxis

millis();

Parámetros

Nada.

Retornos

Número de milisegundos desde que el programa se inició. Numero tipo unsigned long.

Comentario 1

Ya que una variable unsigned long almacena numero entre 0 y 4,294,967,295 (2^32-1), esta función se vuelve a 0 a los 49.71 días pero eso no representa ningún problema para los cálculos porque al no aceptar numero negativos la variable se da la vuelta por decirlo de alguna manera.

Para que te quede claro simplificaremos con un ejemplo: supongamos que nuestra variable solo soporte 0 a 99 osea 100 números. Ahora te pregunto cuanto es 0 - 1 ? en nuestro ejemplo la respuesta correcta es 99 porque es el numero que esta antes de 0. Exactamente por el otro extremo el numero que sigue de 99 es 0. A esto se le llama lógica boleana.

Ahora supongamos que quieres prende un foco por 10 números e inicias el proceso en 22, por lo que preguntas if (números - tiempo = 10), se apagaría cuando números llegue a 32 (32 - 22 = 10). Ahora supón que se prende en 95, cuando apagara ? la respuesta es cuando números llegue a 5 (5 - 95 = 10).

Tip: Este comando tarda 21 ciclos de CPU.


Comentario 2

Se puede resetear el temporisador de millis() ?

extern volatile unsigned long timer0_millis;
unsigned long nuevo_valor = 0;

void setup(){
  //Algo
}

void loop(){
  //Algo
  //--------

  //Change Millis
  setMillis(nuevo_valor);
}

void setMillis(unsigned long nuevo_valor){
  uint8_t oldSREG = SREG;
  cli();
  timer0_millis = nuevo_valor;
  SREG = oldSREG;
}

Advertencias

  • Tenga en cuenta el tipo de valor que retorno millis() es unsigned long y pueden producirse errores lógicos si hacer operaciones aritméticas con otros tipos de datos más pequeños como: byte o int, incluso los long con signo pueden producir errores de calculo.
  • millis() funciona mediante una interrupción (la misma de micros()); por lo tanto, su valor dejará de incrementar durante una rutina de servicio de interrupción (ej.: posterior a attachInterrupt()), o mientras no se llame a interrupts() después de llamar a noInterrupts().

Ejemplo 1

Parpadeo del LED incorporado sin usar delay()

unsigned long t;                     //Es muy importante respetar el tipo de dato

void setup() {
   pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
   if (milis() - t >= 500){
      t = millis();                                       //Guarda la hora de cada cambio.
      digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));  //Invierte valor del pin.
   }
}

Ejemplo 2

Parpadeo sin usar delay()

unsigned long t;                         //Es muy importante respetar el tipo de dato
const int d = 2000;                      //Duración en milisegundos del ciclo completo
void setup() {
   pinMode(13, OUTPUT);
}
void loop() {
   t = millis();
   if (t%d > d/2){
      digitalWrite(13, HIGH);             //Prende LED
   }else{
      digitalWrite(13, LOW);              //Apaga LED
   }
}

Ejemplo 3

En este ejemplo simularemos las direcionales de un auto, para lo que tenemos 2 pulsadores y 2 LED. Cada vez que pulso un botón el LED correspondiente parpadea cada 250 ms durante 3 segundos.

unsigned long izq,der,ti,td;
bool LEDi,LEDd,actual_i,actual_d,anterior_i,anterior_d;

void setup(){
   pinMode(2, INPUT);   //Pulsador derecho
   pinMode(3, INPUT);   //Pulsador izquierdo
   pinMode(8, OUTPUT);  //LED izquierdo
   pinMode(9, OUTPUT);  //LED derecho
}
 
void loop(){
   //Prende
   actual_i = digitalRead(3);
   if (actual_i && !anterior_i){
       LEDi = true;
       izq = millis();
   }
   anterior_i = actual_i;
   actual_d = digitalRead(2);
   if (actual_d && !anterior_d){
       LEDd = true;
       der = millis();
   }
   anterior_d = actual_d;
   //Parpadea
   if (LEDi && (millis()-ti > 250)){
      digitalWrite(8, !digitalRead(8));
      ti = millis();
   }
   if (LEDd && (millis()-td > 250)){
      digitalWrite(9, !digitalRead(9));
      td = millis();
   }
   //Apaga
   if (millis() - izq > 3000){
       LEDi = false;
       digitalWrite(8, LOW);
   }
   if (millis() - der > 3000){
       LEDd = false;
       digitalWrite(9, LOW);
   }
}

Nota: Hay 3 zonas en el código la primera llamada prende, aunque en realidad solo cambia el estado de una variable de tipo flag (LEDi o LEDd) e inicia el tiempo total de 3 seg (ti o td). Una 2da zona donde se hace parpadear los LED mientras la variable flag este en verdadero (LEDi o LEDd). Por ultimo esta la zona de apagado que es cuando se cumplan los 3 segundos.


Vea también


Referencias externa