Los delay en Arduino, son para noobs

Holi

Ayer (13 de julio) fue la primera reunión de la Comunidad Arduino Chiquimula y luego de 11 horas de viaje ( normalmente son 4 ) por fin pude llegar y compartir con los miembros. Estaba lloviendo :V y hoy esta haciendo el calor mítico de chiquimula.

El dia de hoy vamos a entender porque debemos de usar la funcion delay en muy contadas ocasiones, en vez de delay, vamos a utilizar un comparativo de los milisegundos del reloj y el tiempo que queremos que se ejecute lo que nosotros queremos.

Delay

Primero, vamos a entender que es lo que hace la funcion delay.
En la pagina de Arduino nos dice que, pausa el programa en la cantidad de milisegundos que pongamos entre los paréntesis “delay (milisegundos)”, lo malo de esta funcion que si bien es cierto que es de las primeras cosas que uno aprende, es que detiene completamente el cpu del arduino, por ende si queremos un control de sistemas en tiempo real, no debemos de usarlo.

Pero, ¿porqué no debemos usarlo?

Los sistemas embebidos jamas deben de pausarse, deben de ser en tiempo “real”. La razon principal es porque detiene completamente el CPU es como entrar en un ciclo

while(tiempo < milisegundos){
tiempo++
}

Cuando entramos a este loop o ciclo, no hay manera de salir hasta que se incumpla la condición. Entonces si nosotros somo los creadores del sistema de refrigeracion de la central nuclear de nuestro pais, hacemos un sistema que tenga que detectar la temperatura del reactor y de casualidad la estamos midiendo cada 5 segundos, solo como control, para evaluar si la temperatura supera el valor maximo, cuando la temperatura sea mayor activara el sistema de refrigeración, que se tarda 2 segundos en activarse, entonces tenemos un tiempo total de 7 segundos,  si de pura casualidad la temperatura se empieza a elevar de 1 segundo para otro y en el segundo 3 ya supero la temperatura para que se encienda el sistema de refrigeracion, entonces debemos de esperar otros 4 segundos donde no sabemos que pasa si la temperatura se sigue elevando a ese ritmo.

Otro caso, no tan trágico como el que acabamos de leer seria unn control en tiempo real de la velocidad de un carro, donde si tenemos un limite de velocidad que no debemos de superar (150 km/h ) y nuestro programa lo hicimos mal porque solo vamos a evaluar que cuando la velocidad sea igual a 150 que emita una alerta,  pero si es mayor no haga nada, entonces si vamos a 149 km/h y en medio segundo subimos a 152km/h nunca sabremos que excedimos el limite de velocidad, esto es importante en carros autónomos.

Pero bueno vuelvo a reiterar que no debemos de parar NUNCA, nuestros sistemas embebidos.

Solución

Esto se resuelve de una manera elegante, bonita y facil. Vamos a evaluar los tiempos desde que es encendido el Arduino, con la funcion milis(), entonces lo que vamos a evaluar es que millis menos tiempo anterior no sea mayor al tiempo establecido, es decir  milis() – tiempoAnterio > tiempoEstablecido, esto puede funcionar con cualquier microcontrolador midiendo cualquier timer.

int tiempoEstablecido= 3;// segundos
long tiempoAnterior;

void setup(){
tiempoAnterior = millis();
}

void loop(){
if(millis() - tiempoAnterior > tiempoEstablecido*1000){// multiplicamos por mil ya que lo que estamos evaluando son milisegundos y no los segundos de la variable tiempoEstablecido
//ejecutar codigo
}


}

En el ejemplo anterior podemos verificar que todo corre de una buena manera, ahora vamos a un ejemplo mas concreto el cual no se podia hacer antes con el delay que es hacer parpadear en diferentes tiempos a 3 leds.

int tiempoLed1 = 3; // segundos
int tiempoLed2 = 1; // segundos
int tiempoLed3 = 10; // segundos
long tiempoAnterior1;
long tiempoAnterior2;
long tiempoAnterior3;
int led1 = 13;
int led2 = 12;
int led3 = 11;
void setup() {
 pinMode(led1, OUTPUT);
 pinMode(led2, OUTPUT);
 pinMode(led3, OUTPUT);
 tiempoAnterior1 = millis();
 tiempoAnterior2 = millis();
 tiempoAnterior3 = millis();
}

void loop() {
 if (millis() - tiempoAnterior1 > tiempoLed1 * 1000) { // multiplicamos por mil para segundos
 tiempoAnterior1 = millis();
 digitalWrite(led1, !digitalRead(led1));
 }
 if (millis() - tiempoAnterior2 > tiempoLed1 * 1000) { // multiplicamos por mil para segundos
 tiempoAnterior2 = millis();
 digitalWrite(led2, !digitalRead(led1));
 }
 if (millis() - tiempoAnterior3 > tiempoLed1 * 1000) { // multiplicamos por mil para segundos
 tiempoAnterior3 = millis();
 digitalWrite(led3, !digitalRead(led1));
 }
}

Al final vamos a tener leds brillando en diferente tiempo sin usar delay 🙂

Eso ha sido todo por el dia de hoy nos vemos en el próximo que sera desde costa rica en el Encuentro CentroAmericano De Software Libre. Estare actualizando codigos no bloqueantes en este repo de github. Si tienes codigos y no utilizas delay puedes compartirlo al repo y lo compartimos 🙂

No lo olviden: Solo necesitan una excusa para cambiar el mundo. 

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: