bclose

Condicionales y botones

La instruccion if

Objetivos

.

 
    • Lógica digital y algebra de Bool.
    • Los condicionales.Instrucción if.
    • Botones, pulsadores y pullups.
    • Debouncing.

 

Material requerido.

ArduinoUNO Arduino Uno o similar. Un PC con el entorno de Arduino correctamente instalado y configurado.
Img_3_4Una Protoboard.
componenteUn diodo LED.
Img_5_1 Un pulsador.
 Img_3_5 Dos resistencias de 330 Ohmio.
Img_3_6Algunos cables de Protoboard..

Kit de inicio para seguir el curso

.

Kit Arduino

Kit de inicio

Kit Arduino

Para poder seguir los tutoriales y los cursos de arduino que publicamos en prometec.net, te recomendamos que compres nuestro kit de inicio. Trae todos los componentes necesarios.

Comprar Kit Arduino

Lógica digital y algebra de Bool

.

En la sesión anterior presentamos el tipo de variable bool destacando que solo puede tomar dos valores: True o False. Aunque para quienes no estén acostumbrados al algebra booleana o binaria puede parecer excesivo dedicar un tipo a algo tan simple, en la práctica buena parte de las instrucciones de programación se apoyan o dependen de este tipo de variables.

La razón práctica es que con frecuencia hay que tomar decisiones para seguir un camino u otro en función de que se cumpla una condición dada; Esta condición se debe evaluar necesariamente,  a True o False para tomar una decisión sin duda posible.

Por ejemplo, en las sesión 4 usamos la instrucción for  y comentamos que la iteración se mantiene mientras se cumpla una cierta condición. Esta condición debe ser evaluable a True o False, es decir es un booleano.

Existen otras muchas instrucciones que se apoyan en los valores booleanos, (como los condicionales if que veremos en esta sesión)  pero en un modo muy explicito toda la computación actual se basa en la lógica digital de solo dos valores que solemos llamar 1 y 0, pero que con todo derecho podemos llamar a estos valores True y False.

Los ordenadores modernos funcionan mediante la aplicación del algebra de bool a variables booleanas y con un juego completo de operadores lógicos como la negación, que vimos en la sesión anterior, mas operadores lógicos como AND, OR, + y – .

 

La instrucción if

 

En este capítulo vamos a presentar unas instrucciones nuevas de C++, que nos permitan tomar decisiones para hacer una cosa u otra.

La instrucción if es muy sencilla de usar, basta con pasarle entre paréntesis una variable o condición que se evalúe a true o false. Si el resultado es true se hace el bloque que viene a continuación y en caso contrario se ejecuta el bloque que hay detrás del else si existe.

Si no existe la clausula del esle, entonces el bloque que sigue al if, se ejecuta o no, en función de la condición y luego sigue con la secuencia de instrucciones a continuación.

     if ( condición)
          {   
              instrucción 1 ;
              instrucción 2 ;
              ................
          }
     else 
         {
              instruccion20 ;
              instruccion21 ;
              ..............
 }

Recordemos que en el circuito de la sesión anterior disponíamos de un pulsador y de un LED, en esta sesión vamos a continuar con el mismo circuito y para conseguir que el LED se encienda o apague al pulsar el botón. Para ello podríamos mantener  la misma función setup() y escribir el loop() diferente:

     void loop()
          {
              bool valor = digitalRead(boton) ;
              if ( valor)
                   digitalWrite( LED, HIGH) ;
              else
                   digitalWrite( LED, LOW) ; 
           }

Leemos primero el botón a una variable bool y después decidimos si encender o apagar el LED dependiendo de qué su valor sea True o False.

 
  • Recordemos que un bloque es un conjunto de instrucciones encerrados entre llaves y que hay un caso particular en el que se pueden omitir si y solo si, el bloque consta de una única instrucción como es nuestro caso.
  • Se puede utilizar una instrucción if omitiendo la cláusula de else si se desea, pues esta es opcional.
 

Volviendo con los botones

 

Vamos con un programa diferente. Queremos que el botón actúe como un interruptor, que al pulsarlo una vez se encienda, y la próxima vez lo apague. Podríamos plantear algo así y os recomiendo que lo probéis en vuestro Arduino:

     int LED = 10 ; int boton = 6 ;
     bool estado = false ;
     void setup()
          {
             pinMode( LED, OUTPUT) ;
             pinMode( boton , INPUT_PULLUP) ;
             digitalWrite(LED , LOW) ; // Apagamos el LED al empezar
          }
     void loop()
          { 
              bool  valor =  digitalRead(boton) ;                 //leemos el botón: false  =  LOW
              if ( valor == false )                               // esto es que han pulsado el botón
                   {
                        estado = ! estado ;                       // cambiamos el estado
                        digitalWrite(LED, estado) ;            // escribimos el nuevo valor
                   }
          }

La idea es definir una variable llamada estado al principio para guardar la situación del LED. El loop comprueba si se ha pulsado el botón, y de ser así invierte su estado,  y después escribe el valor de estado en el LED. Si estaba encendido lo apaga. Si estaba apagado se enciende.

Aunque parece un plan perfecto, en la práctica no va a funcionar. En el tiempo que nosotros tardamos entre pulsar y liberar el botón, nuestro humilde Arduino es capaz de leer unos cuantos miles de veces el pulsador e invertir el valor del LED otras tantas.

Por eso, si lee un número par de veces dejara el LED como estaba y si lo lee un número impar de veces lo invertirá. En la práctica la situación del LED se torna aleatoria, y si pulsáis repetidamente el botón veréis que el resultado es impredecible.

Otra fuente de problemas es que en el mundo real un interruptor no cambia de un estado a otro de forma perfecta, sino que suele rebotar y causar varios conexiones y desconexiones muy rápidas antes de quedar en un valor estable. A esto se le llaman rebotes (bouncing) y al procedimiento para eliminar estos rebotes se le llama debouncing en la jerga electrónica.

El debouncing se puede hacer por hardware con un conjunto de resistencia y condensador, o por software, mucho más frecuentemente (por más barato) y para esto una solución es nuevamente frenar a Arduino y hacerle esperar un tiempo entre 50 y 250 mili-segundos una vez que detecta que se ha pulsado el botón, de modo que nos dé tiempo a liberar el pulsador:

     void loop()
           {          
               bool  valor =  digitalRead(boton) ;                 //leemos el botón: false = LOW
              if ( valor == false )                               // esto es que han pulsado el botón
                  {
                      estado = ! estado ;                        // cambiamos el estado
                      digitalWrite(LED, estado) ;            // escribimos el nuevo valor
                      delay(250) ;
                  }
            }
 
  • Muy importante: Nótese que la condición es (valor == false), con doble = . En C++ la comparación de dos valores usa ==, la asignación de valor a una variable solo uno. Esto es fuente de errores frecuentes al principio (entre novicios inexpertos).
 

Este lapso de 250 ms es suficiente para pulsar y liberar el botón cómodamente. Si probáis esta variante veréis que ahora el LED invierte su valor cada vez que pulsas, siempre y cuando no te demores demasiado en liberar el botón.

Pero… ¿Qué pasa cuando dejas el botón pulsado?

Pues sencillamente que el LED invierte su estado cada 250 ms (milisegundos) y tenemos otra variante del blinking LED.

Si queremos poder mantener pulsado sin que se produzca este efecto hay que sofisticar un poco más el programa:

     int LED = 10 ; int boton = 6 ;
     bool estado = true ;
     bool estado_anterior = true ;

     void setup()
          { 
               pinMode(boton, INPUT_PULLUP);        //Hemos eliminado R3 
               pinMode(LED, OUTPUT);
          }

     void loop()
          {
               estado = digitalRead(boton);
               if (estado != estado_anterior)      //hay cambio : Han pulsado o soltado
                  {
                     if (estado == LOW)            //Al pulsar botón cambiar LED, pero no al soltar
                           digitalWrite(LED, !digitalRead(LED));
                     estado_anterior = estado ;     // Para recordar el ultimo valor
                  }
           }

Ya dijimos que para comprobar si dos valores son iguales usamos ==, Para comprobar si son diferentes usamos != , y existen otros operadores relacionales

 
  • Igual que: ==
  • Distinto de: !=
  • Mayor que: >
  • Mayor o igual: >=
  • Menor que: <
  • Menor o igual: <=
 

Vale la pena comentar aquí que, a pesar de su aparente inocencia, los botones tienen una sorprendente habilidad para complicarnos la vida, y que en la práctica la combinación de rebotes y la necesidad de corregirlos, junto al uso de pullups que garanticen la correcta lectura, pueden hacer que su uso se pueda complicar mucho más de lo que parece, sino se estudia el problema con calma.

Por último, una condición lógica se puede construir mediante los operadores lógicos AND, OR, y NOT cuyos símbolos son respectivamente: &&, || y !

Si usáramos un circuito dos pulsadores con pullups (True, si no se pulsa) y un LED, dependiendo del comportamiento que se busque podemos especificar diferentes condiciones:

 
  • If ( boton1 && boton2) Que ambos botones estén sin pulsar
  • If ( !( boton1 && boton2)) Que ambos estén pulsados.
  • If( boton1 || boton2 ) Que al menos uno este sin pulsar, o ambos.
 

Resumen de la sesión

.

 
    • Hemos visto la instrucción if / else.
    • Vimos varios programas con pulsadores y como hacer el debouncing.
    • Hemos presentado los operadores lógicos de relación y comparación.
    • Continuamos escribiendo pequeños programas para desarrollar la forma de pensar necesaria para escribir nuestras propias aplicaciones.

 

 

 

 

(145) Comments

    • Luis E. Castro

    Buenos días y un cordial saludo desde Colombia

    Resulta que estaba haciendo pruebas con el código que nos sugieren en la página. Inicialmente pasé a mano el código al Arduino por cuestiones de costumbre. Mi código quedó de la siguiente forma:

    int LED = 10; // Declaramos tipo entero la variable LED igual a PIN_10
    int PS = 6; // Declaramos tipo entero la variable LED igual a PIN_6
    bool ES_A = true; // Declaramos en tipo bool la variable ES_A igual a true o 1
    bool ES_B = true; // Declaramos en tipo bool la variable ES_B igual a true o 1

    void setup()
    {
    pinMode(PS, INPUT_PULLUP); // Iniciamos la variable PS como entrada
    pinMode(LED, OUTPUT); // Iniciamos la variable LED como salida
    digitalWrite(LED, LOW); // Escribimos la variable LED en LOW
    }

    void loop()
    {
    ES_A = digitalRead(PS); // Igualamos la variable ES_A a la lectura de PS
    if(ES_A != ES_B) // Condición si ES_A diferente a ES_B
    {
    if(ES_A == LOW) // Condición si ES_A igual a LOW o 0
    {
    digitalWrite(LED, !digitalRead(LED)); // Escribimos la variable LED según la lectura negada de LED
    ES_B = ES_A; // Igualamos la variable ES_B a ES_A
    }
    }
    }

    Salvé el programa en el arduino y lo probé pero al pulsar el botón el LED quedaba encendido y no se apagaba al pulsar de nuevo ni manteniendo el pulso.

    Inicialmente pensé que algo andaba mal en el programa pero revisé linea por linea y todo estaba correcto (obviamente con los nombres de variables diferentes) a excepción de la segunda condición de if que en mi código tenia las llaves y en el código de la página no las tenía.

    Borre las llaves y nuevamente programé el arduino y funcionó perfecto pero me quedé con la inquietud de ¿por qué con llaves no funcionó?. Espero que alguno me pueda dar una explicación clara ya que estoy en proceso de aprendizaje por medio de esta página.

    También quiero agradécele a los creadores de la página y a los creadores del contenido de la misma. ¡Excelente trabajo!

    Posdata: Sería bueno si en los comentarios se pudiera editar el texto para, por ejemplo, resaltar las líneas de código.

      • Ivan Uriarte

      Hola Luis y gracias por tus palabras. La diferencia es que sin llaves sólo afecta a la siguiente línea, pero tu los has colocado de forma que afecta a las dos siguientes. SI quieres ponerlo con llaves debería ser así:

      void loop()
      {
      ES_A = digitalRead(PS); // Igualamos la variable ES_A a la lectura de PS
      if(ES_A != ES_B) // Condición si ES_A diferente a ES_B
      {
      if(ES_A == LOW) // Condición si ES_A igual a LOW o 0
      {
      digitalWrite(LED, !digitalRead(LED)); // Escribimos la variable LED según la lectura negada de LED
      }
      ES_B = ES_A; // Igualamos la variable ES_B a ES_A
      }
      }

    • Alberto Armisen

    buenas tardes quiero enviar un sms cuando se cierre un contacto tengo el programa que envia sms, pero solo los envia cuando lo subo al arduino, quiero un modulo autonomo que mande el sms cuando cierro un circuito

      • Ivan Uriarte

      Hola Alberto, echa un ojo a esta sesión, no tienes más que meter la función para mandar el sms dentro del if donde leemos el pulsador.

    • Vera

    Hola, necesito ayuda, tengo que hacer un circuito con 3 botones y dos leds, las indicacion es que el primer led sea encendido con un solo boton y se va a presionar 3 veces, la primera vez se tiene que prender 3 segundos, la segunda vez debe mantenerse prendido, la tercera vez apagarse; lo mismo con los otros dos botones y el led, ambos botones deben presionarse tres veces cumpliendo con lo antrerior, ya lo estuve intentando y no paso de la primera instruccion, no se como hacer que el boton identifique cuantas veces lo estoy presionando, ya lo intente con el if y un contador pero no funciona, les agradeceria mucho si me pueden ayudar, por favor.

      • Ivan Uriarte

      Hola Vera, en el if donde detectas si lo han pulsado tienes que meter el contador. A parte dentro de ese if tienes que anidar otro if por cada cosa que quieras hacer (1, 2 y 3) Y ya cuando llegue a tres lo reinicias a cero. Si tienes problemas me comentas. Un saludo.

    • Lola

    Buenas, estoy trabajando en un proyecto sobre semáforo, donde tengo 4 botones. Cada boton tiene la función de prender el led verde de cada carril. Tendria que usar este codigo para controlar los botones?

      • Ivan Uriarte

      Hola Lola, efectivamente este tutorial puede servirte, pero tendrías que usar cuatro pulsadores y cuatro leds.

    • Josue

    HOLA necesito ayuda debo realizar una programación la cual al mantener presionado el botón solo se cumpla una vez la condición que esta adentro ya sea un if ejemplo entonces debe encenderse en un tiempo y luego apagarse pero si se mantiene presionado aun el botón no debe hacer nada .

      • Ivan Uriarte

      Hola Josue, el programa de esta sesión es justo lo que debería hacer.

    • Luis

    buenas tardes
    me podrian ayudar tengo este programa pero no e tenido la solucion para agregar otro boton para cuando lo active realize un desconteo a la cuenta que tengo

      • Ivan Uriarte

      Hola Luis, primero prueba si los botones funcionan correctamente al poner los dos juntos y luego solo es cuestión de hacer un if para cada uno.

    • Juan

    Necesito,ayuda por favor “Quiero entender un motorcito y que cuando esté encendido el motor encienda un led,y cuando no esté encendido el motor apague el LED,y todo esto sea controlado,por un botón pulsador”

      • Ivan Uriarte

      Hola Juan, y dónde tienes el problema? Sería muy sencillo, es lo mismo que hacemos en esta sesión pero dentro del mismo if hacer el resto de cosas. Qué motor estás utilizando?

    • Cristian

    Hola. muchas gracias por el curso. Es muy bueno.
    Tengo una duda respecto al programa. Hice uno que recibe cuatro señales de una placa inalambrica de control remoto. La placa entrega los 5v con cada pulsación en el control. Eh hecho llegar esos pulsos a los pines 1 a 4 de Arduino, de modo que las entradas son PULLDOWN con las resistencias correspondientes. Quiero que con cada pulso, se active una salida distinta para alimentar un banco de reles utilizando los pines 5 a 8. Pero el resultado es que los reles se activan solo despues de soltar cada botón. Funciona bien, pero quisiera que los reles se activen inmediatamente al presionar cada botón del control.
    Agradecere su ayuda!
    Aquí esta mi programa:

    int bota = 4;
    int botb = 3;
    int botc = 2;
    int botd = 1;
    int R1 = 5;
    int R2 = 6;
    int R3 = 7;
    int R4 = 8;
    bool estado1 = true;
    bool estado_anterior1 = true;
    bool estado2 = true;
    bool estado_anterior2 = true;
    bool estado3 = true;
    bool estado_anterior3 = true;
    bool estado4 = true;
    bool estado_anterior4 = true;

    void setup() {

    pinMode(bota, INPUT);
    pinMode(botb, INPUT);
    pinMode(botc, INPUT);
    pinMode(botd, INPUT);
    pinMode(R1, OUTPUT);
    pinMode(R2, OUTPUT);
    pinMode(R3, OUTPUT);
    pinMode(R4, OUTPUT);
    }

    void loop() {

    estado1 = digitalRead(bota);
    if ( estado1 != estado_anterior1)
    {
    if(estado1==LOW)
    digitalWrite(R1, !digitalRead(R1));
    estado_anterior1 = estado1;
    }

    estado2 = digitalRead(botb);
    if ( estado2 != estado_anterior2)
    {
    if(estado2==LOW)
    digitalWrite(R2, !digitalRead(R2));
    estado_anterior2 = estado2;
    }

    estado3 = digitalRead(botc);
    if ( estado3 != estado_anterior3)
    {
    if(estado3==LOW)
    digitalWrite(R3, !digitalRead(R3));
    estado_anterior3 = estado3;
    }

    estado4 = digitalRead(botd);
    if ( estado4 != estado_anterior4)
    {
    if(estado4==LOW)
    digitalWrite(R4, !digitalRead(R4));
    estado_anterior4 = estado4;
    }

    }

    PD: ¿Esta bien escrito o debí haberlo hecho de alguna otra manera mas resumida?
    Gracias.

      • Prueba TPV TPV

      Hola Christian,

      Cuando la cosa se complica conviene simplifar un poco. Empieza haciendo el programa y circuito solo con un rele y prueba lo que ocurre. veras que es mucha mas sencillo

      • Prueba TPV TPV

      Cuando la cosa se lia, es mejor simplificar. Empieza con un solo rele en el programa y comprueba lo que pasa y me dices ¿Vale?

  • hola pido ayuda, al apretar un boton se accione un relevador por unos 2 seg, el boton estara apretado y cuando pasen los 2 seg inicie todo hasta apretar el boton.
    ayudenme

      • Ivan Uriarte

      Puedes hacer un contador con la función milis() que inicies la primera vezz que pulses el pulsador y luego vas comprobando hasta que pasen los 2000 ms

    • Adriana

    Hola soy nueva en esto y me gustaria saber como puedo hacer un codigo donde emplee 4 botones en los cuales si los 4 estan pulsados accionen un servo o un selenoide, muchas gracias

      • Ivan Uriarte

      Hola Adriana, el programa sería exactamente como este pero metiendo && dentro del if para leer los 4 pulsadores.

    • Rubenqd

    Muy interesante la información. Estoy tratando de hacer un programa con 8 leds y cuatro botones. Cada botón me inicie una secuencia diferente te al presionar. Veo que usas una entrada y salida, pero si te tengo ocupadas todas las ranuras como podría hacerlo? Entiendo que puedo hacer el input d con el botón, pero y la salida? Si cada botón me inicia una secuencia.

      • Ivan Uriarte

      Hola Ruben, puedes usar los pines A0 a A5 como entradas y salidas digitales también.

  • hola amigo buen dia me gustaria saber como puedo hacer un codigo donde emplee 4 botones en los cuales si los 4 estan pulsados enciendan un led y si por lo menos uno no se encuentra pulsado no se encienda el led

      • Ivan Uriarte

      Hola Fernando, tienes que conectar los 4 pulsadores a 4 entradas digitales y luego sólo tendrías que hacer una estructura if else, en el if utilizas && para poner varias condiciones. En este caso que estén las 4 entradas activadas. Un saludo.

    • Marcos

    Buenas tardes!
    He instalado un pulsador con 3 Blinkin LEDs alternantes, y a la hora de iniciar la secuencia va perfecto. El problema es que una vez inicio el loop de blinks, para detenerlo, a menos que mantenga pulsado el pulsador hasta que coincida con el final de la secuencia de loop o que pulse exactamente en el mismo final, no se apaga el circuito.
    No sé si me estoy explicando… básicamente, no me recoge el INPUT del pulsador hasta que no termina la secuencia entera programada de ejecutarse al completo. Y solo lo acepta si intercalo ese INPUT entre loop y loop. ¿Qué estoy haciendo mal?

    Os dejo el programa que estoy utilizando:
    int boton = 12 ;
    int LED1 = 6 ;
    int LED2 = 7 ;
    int LED3 = 8 ;
    bool estado = false ;

    void setup() {
    // put your setup code here, to run once:
    pinMode ( boton , INPUT ) ;
    pinMode ( 6 , OUTPUT );
    pinMode ( 7 , OUTPUT );
    pinMode (8, OUTPUT);
    digitalWrite(6,LOW);
    digitalWrite(7,LOW);
    digitalWrite(8,LOW);
    }

    void loop() {
    // put your main code here, to run repeatedly:
    bool valor = digitalRead ( boton ) ;//PULLUP
    if ( valor == false ) //pulsado boton
    {estado = !estado ;
    delay(500);}

    if ( estado == true)
    { digitalWrite(LED1,HIGH);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,HIGH);
    delay(500);
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,HIGH);
    digitalWrite(LED3,LOW);
    delay(500);}
    else
    digitalWrite(LED1,LOW);
    digitalWrite(LED2,LOW);
    digitalWrite(LED3,LOW);
    }

      • Ivan Uriarte

      Hola, si te fijas el programa sólo comprueba el pulsador al principio de la secuencia, luego si lo tocas en medio no se entera. Puedes intercalar ese if entre la secuencia o trabajar con interrupciones, que es ya un poco más lío.

    • Jose Antonio

    Buenos días.
    Tengo una consulta, estoy intentando realizar un cronómetro descendente (el código del cronometro ya lo tengo hecho y funciona), pero quiero poder aumentar los minutos antes de que empiece la cuenta, para poder personalizarlo. Estoy intentando hacerlo basándome en lo que usted ha publicado, para que cuando se pulsa el botón minutos se aumente en 1, pero me estoy volviendo loco, no se si sería tan amable de ayudarme.
    Gracias.
    Saludos.

      • Ivan Uriarte

      Hola José Antonio, depende uin poco cómo hayas progrtamado el cronómetro, pero en teoría con que metas en el loop un conidicional if en el que leas el botón y dentro sumes 1 a la variable minutos, o 60 a la variable segundos debería ser suficiente.

    • Salvador

    Hola, si tengo leds que prendenen una secuencia y al presionar un boton se inicie la secuencia y al volverlo a presionar, se quede encendido el led en el momento que se presiono el boton y que al presionar otra vez continue la secuencia donde la paramos, ¿que haria para parar y continuar la secuencia?

      • Juan carlos macho mangas

      Hola Salvador, depende un poco del tipo de secuencia que estes usando, pero si es un for que empieza en un valor digamos cero, puedes hacerle empezar desde una variable p, que controlas cuando quieres empezar a meda secuencia ¿Vale?

Give a Reply

WordPress Anti-Spam by WP-SpamShield