Diferencia entre revisiones de «millis()»

De ArduWiki
Saltar a: navegación, buscar
(Ejemplo)
(Ejemplo 2)
 
(No se muestran 18 ediciones intermedias del mismo usuario)
Línea 19: Línea 19:
  
 
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).
 
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 ==
 
== Comentario 2 ==
Línea 52: Línea 54:
  
 
== Ejemplo 1 ==
 
== Ejemplo 1 ==
Parpadeo sin usar [[delay()]]
+
Parpadeo del LED incorporado sin usar [[delay()]]
  
 
<syntaxhighlight lang="c++">
 
<syntaxhighlight lang="c++">
unsigned long hora = 0;                    //Es muy importante respetar el tipo de dato
+
unsigned long t;                    //Es muy importante respetar el tipo de dato
 +
 
 
void setup() {
 
void setup() {
   pinMode(13, OUTPUT);
+
   pinMode(LED_BUILTIN, OUTPUT);
 
}
 
}
 +
 
void loop() {
 
void loop() {
   if (milis() - hora >= 500){
+
   if (milis() - t >= 500){
       hora = millis();                     //Guarda a hora de cada cambio
+
       t = millis();                                       //Guarda la hora de cada cambio.
       digitalWrite(13, !digitalRead(13));  //Invierte valor del pin
+
       digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));  //Invierte valor del pin.
 
   }
 
   }
 
}
 
}
Línea 68: Línea 72:
  
 
== Ejemplo 2 ==
 
== Ejemplo 2 ==
Parpadeo sin usar [[delay()]]
+
Parpadeo cada segundo sin usar [[delay()]].
  
 
<syntaxhighlight lang="c++">
 
<syntaxhighlight lang="c++">
unsigned long t = 0;                     //Es muy importante respetar el tipo de dato
+
unsigned long t;                         //Es muy importante respetar el tipo de dato
unsigned int d = 2000;                   //Duración en milisegundos del ciclo completo
+
const int d = 2000;                     //Duración en milisegundos del ciclo completo
 
void setup() {
 
void setup() {
 
   pinMode(13, OUTPUT);
 
   pinMode(13, OUTPUT);
Línea 81: Línea 85:
 
       digitalWrite(13, HIGH);            //Prende LED
 
       digitalWrite(13, HIGH);            //Prende LED
 
   }else{
 
   }else{
       digitalWrite(13, LOW);              //Prende LED
+
       digitalWrite(13, LOW);              //Apaga LED
 +
  }
 +
}
 +
</syntaxhighlight>
 +
 
 +
== 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.
 +
 
 +
<syntaxhighlight lang="c++">
 +
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);
 
   }
 
   }
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
{{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 ==
 
== Vea también ==
* [[micros()]]
+
<categorytree mode=all>Funciones tiempo</categorytree>
  
== Referencias ==
+
== Referencias externa ==
 
* [https://www.arduino.cc/reference/es/language/functions/time/millis/ Guia de referencia de Arduino]
 
* [https://www.arduino.cc/reference/es/language/functions/time/millis/ Guia de referencia de Arduino]
 
* [https://tomblanch.wordpress.com/2013/07/27/resetting_millis/ Resetting the Arduino millis() count] - Tom Blanchard
 
* [https://tomblanch.wordpress.com/2013/07/27/resetting_millis/ Resetting the Arduino millis() count] - Tom Blanchard
 +
* [https://www.gammon.com.au/millis millis() desbordamiento, es malo ?] - Nick Gammon
 +
* [https://www.gammon.com.au/blink Como hacer varias cosas a la vez] - Nick Gammon
 +
* [http://www.gammon.com.au/statemachine Maquina de estados] - Nick Gammon
  
[[Category:Funciones]]
+
[[Category:Funciones tiempo]]

Revisión actual del 20:38 24 jul 2019

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 cada segundo 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