lunes, 23 de diciembre de 2019

Temporizaciones sin delay

Vamos a considerar un programa que haga parpadear el último LED de la segunda fila y, a la vez, nos permita encender y apagar el primer LED de dicha fila con el pulsador A. En principio podríamos pensar en el siguiente código:
/* 
 * pulsadorAParpadeoLedConDelay.ino
 * Encendido-Apagado del primer LED de la segunda fila
 * con el pulsador A. Simultáneamente, parpadeo del
 * último LED de la segunda fila.
*/

boolean pulsadorA;
/*
 * Vamos a realizar el parpadeo de manera distinta,
 * utilizaremos una variable "estadoLed" para
 * guardar la situación del LED.
 */
boolean estadoLed; 

void setup() {
  pinMode(28,OUTPUT);    //Programamos los pines
  pinMode(23,OUTPUT);    //como salidas.
  pinMode(7,OUTPUT);
  pinMode(5, INPUT);     //pin pulsador como entrada
  digitalWrite(28,HIGH); //Activamos la fila.
  digitalWrite(23,HIGH); //apagamos LED 
  digitalWrite(7,HIGH);  //apagamos LED
}

void loop() {
  /* Parpadeo LED
   * estadoLed=!estadoLed
   * estadoLed toma el valor contrario al que tenía
   * (0 o 1, LOW o HIGH) en cada ciclo del bucle loop().
   */
  estadoLed=!estadoLed;
  digitalWrite(7, estadoLed);
  delay(2000);               //el programa se detiene 2 seg.
  /* 
   * Ahora gestionamos el pulsadorA y el otro LED.
   * La parada anterior provocará que no se detecten
   * correctamente las pulsaciones.
   */
  pulsadorA=digitalRead(5);
  if (pulsadorA == 0) {
    digitalWrite(23,LOW);
  }
  if (pulsadorA == 1) {
    digitalWrite(23,HIGH);
  }
}

Para evitar este problema vamos a recurrir a la instrucción "millis()", la cual nos proporciona el número de milisegundos transcurridos desde que se inicia la ejecución del programa. 
/* 
 * pulsadorAParpadeoLedSinDelay.ino
 * Encendido-Apagado del primer LED de la segunda fila
 * con el pulsador A. Simultáneamente, parpadeo del
 * último LED de la segunda fila.
*/

boolean pulsadorA;
/* 
 * millisIniciales
 * Esta variable servirá para guardar los milisegundos
 * que han pasado en el momento que iniciemos una 
 * temporizacion. Es de tipo long (4 bytes de tamaño).
 */
long millisIniciales=0;
boolean estadoLed;

void setup() {
  pinMode(28,OUTPUT);    //Programamos los pines
  pinMode(23,OUTPUT);    //como salidas.
  pinMode(7,OUTPUT);
  pinMode(5, INPUT);     //pin pulsador como entrada
  digitalWrite(28,HIGH); //Activamos la fila.
  digitalWrite(23,HIGH); //apagamos LED 
  digitalWrite(7,HIGH);  //apagamos LED
}

void loop() {
  /*
   * Si los milisegundos transcurridos menos los
   * milisegundos que guardamos al iniciar la temporización
   * son mayores de 2000, significa que ya ha
   * transcurrido ese tiempo y tenemos que cambiar
   * el estado del LED y volver a iniciar una nueva
   * temporización.
   * El programa no se detiene, sino que va realizando
   * esta pregunta en cada pasada del bucle.
   */
  if(millis() - millisIniciales > 2000){
    estadoLed=!estadoLed;
    digitalWrite(7, estadoLed);
    millisIniciales = millis();   //iniciamos nueva temporización
  }
  pulsadorA=digitalRead(5);
  if (pulsadorA == 0) {
    digitalWrite(23,LOW);
  }
  if (pulsadorA == 1) {
    digitalWrite(23,HIGH);
  }
}


Otra manera de hacerlo es creando una nueva función que podríamos llamar "delay_" que utilizaría la instrucción millis() y generaría un nuevo bucle que estaría ejecutándose todo el tiempo de dure la temporización. En él pondríamos las instrucciones relativas a los pulsadores:
/* 
 * pulsadorAParpadeoLedDelay_.ino
 * Encendido-Apagado del primer LED de la segunda fila
 * con el pulsador A. Simultáneamente, parpadeo del
 * último LED de la segunda fila.
*/

boolean pulsadorA;

void setup() {
  pinMode(28,OUTPUT);    //Programamos los pines
  pinMode(23,OUTPUT);    //como salidas.
  pinMode(7,OUTPUT);
  pinMode(5, INPUT);     //pin pulsador como entrada
  digitalWrite(28,HIGH); //Activamos la fila.
  digitalWrite(23,HIGH); //apagamos LED 
  digitalWrite(7,HIGH);  //apagamos LED
}

void loop() {
  digitalWrite(7, LOW);
  delay_(2000);
  digitalWrite(7, HIGH);
  delay_(2000);
}

/* 
 * delay_
 * Creamos una función que realiza la temporización utilizando
 * la instrucción millis() y genera un nuevo bucle que se sigue
 * ejecutando durante el tiempo que dure el retardo.
 * La variable millisIniciales está declarada como local dentro 
 * de la función.
 * Para hacer ese bucle hemos utilizado la instrucción:
 *     while(condición){  instrucciones }
 * mientras que se cumpla la condición se ejecutan las instruciones
 * que hay entre las llaves.
 * En lugar de incluir entre las llaves todas las instrucciones
 * de los pulsadores las hemos colocado en una nueva función 
 * loop_
 * mientras que (millis - millisIniciales < tiempo) 
 * ejecutamos las instrucciones colocadas en loop_
 */
void delay_(long tiempo){
  long millisIniciales = millis();
  while(millis() - millisIniciales < tiempo){
    loop_();
}
}

void loop_(){
  pulsadorA=digitalRead(5);
  if (pulsadorA == 0) {
    digitalWrite(23,LOW);
  }
  if (pulsadorA == 1) {
    digitalWrite(23,HIGH);
  }  
}










No hay comentarios:

Publicar un comentario