3. Pushbuttons

Goals

  • Read the status of a button.
  • Program Arduino to respond to user keystrokes.

Picuino UNO shield buttons

The shield has a six-button keyboard. Each button is identified with a number or a constant that bears its name. The name of each push button can be seen on the silkscreen on the printed circuit board. The six constants and numbers that represent the buttons are the following:

Constant Button
KEY_LEFT 1
KEY_RIGHT 2
KEY_UP 3
KEY_DOWN 4
KEY_ENTER 5
KEY_BACK 6

The key number will be represented in the manual as keyNum.

The keyPressed function

int keyPressed(int keyNum)

This function returns the value of a button. Returns the value 1 if the button is pressed and 0 if it is not. The value of this function filters out electrical noise and bounce.

Electrical noise is interference associated with electric motors, switches, modern energy-saving lamps or mobile phones. Any of these devices can cause a button to appear to be pressed for a brief moment even though it is not. It is highly recommended to filter this noise to avoid 'false' or 'ghost' keystrokes.

Bouncing is a phenomenon that causes the push button to not make contact for a short period of time, a few milliseconds, right after it is pressed because the sheet metal 'bounces' and stops making contact. This phenomenon can cause one click to be interpreted as two clicks, so it is recommended that you filter it to eliminate it.

The disadvantage of this noise filter is that this function has a 20 millisecond delay in responding from when the actual state of the switch changes to when it returns the correct value. If the KEY_ALL argument is used, the function returns a number that depends on the sum of the keys that are pressed.

Button pressed Decimal value Binary value
KEY_LEFT 1 0b000001
KEY_RIGHT 2 0b000010
KEY_UP 4 0b000100
KEY_DOWN 8 0b001000
KEY_ENTER 16 0b010000
KEY_BACK 32 0b100000

If button 4 is pressed, the function will return the value 8. With button 6 pressed, the function will return the value 32. If both buttons 4 and 6 are pressed at the same time, the function will return the sum of 8 and 32 i.e. 40.

keyNum: número del 1 al 6 que representa al pulsador del que se solicita su valor. El valor 0 representa a todos los pulsadores juntos.

Se pueden utizar también los valores predefinidos KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_ENTER, KEY_BACK y KEY_ALL.

Turn on a led with a button

The following program will turn on led D1 when button 1 is pressed (KEY_LEFT)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Enciende el led D1 cuando se pulse el pulsador 1

#include <Picuino.h>

void setup() {
   pio.begin();   // Inicializa el shield Picuino UNO
}

void loop() {
   int on_off;
   on_off = pio.keyPressed(KEY_LEFT); // Lee el estado del pulsador 1
   pio.ledWrite(1, on_off);           // Enciende el led D1 si está
                                      // presionado el pulsador 1
}

Turn off a led with a button

The following program will perform the opposite function to the previous one, it will turn off led D1 when button 1 is pressed (KEY_LEFT)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Apaga el led D1 con el pulsador 1

#include <Picuino.h>

void setup() {
   pio.begin();                  // Inicializa el shield Picuino UNO
}

void loop() {
   int on_off;
   on_off = pio.keyPressed(1);   // Lee el estado del pulsador 1
   pio.ledWrite(1, !on_off);     // Enciende el led D1 si no está
                                 // presionado el pulsador 1
}

The Arduino language allows you to write the last function of the above program in other ways. These are some alternatives, they all achieve the same result.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Enciende el led D1 si el pulsador 1 no está presionado

// Función NOT lógico
pio.ledWrite(1, !on_off);

// Función Negación binaria
pio.ledWrite(1, ~on_off);

// Función resta
pio.ledWrite(1, 1-on_off);

// Funciones de comparación
pio.ledWrite(1, (on_off == 0));
pio.ledWrite(1, (on_off < 1));

// Función XOR
pio.ledWrite(1, on_off ^ 1);

As you can see, the language is very rich in expressions.

The keyValue function

int keyValue(int keyNum)

This function is similar to the keyValue function seen above. Returns the value of a button. If the key is pressed, it returns the value 1; if the key is not pressed, it returns the value 0. This function does not filter out electrical noise like the keyPressed() function does.

This function returns the immediate state of the button and therefore can return false values ​​caused by electrical noise or bounces.

As an advantage, this function returns the value of the button without a time delay in the response.

keyNum: número del 1 al 6 que representa al pulsador del que se solicita su valor. El valor 0 representa a todos los pulsadores juntos.

Se pueden utizar también los valores predefinidos KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_ENTER, KEY_BACK y KEY_ALL.

Exercises

Program the code needed to solve the following problems.

  1. Turn on led D1 with button 1 and turn off led D1 with button 2. Correct the syntactic errors of the following program.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    // Enciende el led D1 con el pulsador 1 y
    // apaga el led D1 con el pulsador 2
    
    #include <Picuino.h>
    
    void setup() {
       pio.Begin();                 // Inicializa el shield Picuino UNO
    }
    
    void loop() {
       if (pio.keypressed(1))       // Si (pulsador 1 está presionado)
          pio.ledWrite(1, LED_ON);  //   Enciende led D1
       if (pio.keypressed(2))       // Si (pulsador 2 está presionado)
          pio.ledWrite(1, LED_OFF)  //   Apaga el led D1
    
  2. Turn on all the leds as follows. LED D1 will light up when button 1 is pressed. Then LED D2 will light up when button 2 is pressed. The program will continue in this way until all the LEDs light up. Complete the program below.

    // Enciende todos los leds uno a uno y por orden
    // con todos los pulsadores
    
    #include <Picuino.h>
    
    void setup() {
       pio.begin();   // Inicializa el shield Picuino UNO
    
       // Mientras (pulsador 1 no esta presionado), espera
       while (pio.keyPressed(1) == 0);
    
       // Enciende el led D1
       pio.ledWrite(1, LED_ON);
    
    
    }
    
    void loop() {
    }
    
  3. When starting, turn on led D1. When button 1 is pressed, led D1 will go out and the next led will light up. The light will thus move to the right, until it starts at led D1 again. Complete the program below according to the comments.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // Mover la luz de los leds hacia la derecha
    // con los pulsadores
    
    #include <Picuino.h>
    
    int i;
    
    void setup() {
       pio.begin();              // Inicializa el shield Picuino UNO
       i = 1;                    // El primer led encendido es el 1
    }
    
    void loop() {
       pio.ledWrite(i, LED_ON);  // Enciende el led i
       if (pio.keyPressed(i)) {  // Si (pulsador i está presionado)
          pio.                   //    Apaga el led i
          i =                    //    Aumenta i en una unidad
          if (i > 6) i = 1;      // Si (i es mayor que 6) i vale 1
          pio.                   //    Enciende el led i
       }
    }
    
  4. Modify the previous program so that the leds light up from D6 to D1. When it is time to turn off led D1, led D6 will light up again.

  5. The three leds D1, D2 and D3 will light up when the three buttons 1, 2 and 3 are pressed at the same time. It uses the '&&' operator that evaluates if two conditions occur at the same time. Complete the program below according to the comments.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // Enciende los leds D1, D2, D3 cuando
    // se presionen los pulsadores 1, 2 y 3
    
    #include <Picuino.h>
    
    void setup() {
       pio.begin();                // Inicializa el shield Picuino UNO
    }
    
    void loop() {
    
       if (pio.keyPressed(1)  &&   // Si ( (pulsador 1 presionado) y
           pio.keyPressed(2)  &&   //      (pulsador 2 presionado) y
           pio.keyPressed(3)) {    //      (pulsador 3 presionado))
          pio.                     //    Enciende los leds D1, D2 y D3
    
    
       }
    }
    
  6. After pressing the sequence of buttons 2, 4 and 1 in order, an electronic lock will open. The opening will be indicated by turning on the red, yellow and green leds in sequence, one every second. Fill in the gaps in the program below according to the comments.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    // Cerradura electrónica
    
    #include <Picuino.h>
    
    int step;
    
    void setup() {
       pio.begin();   // Inicializa el shield Picuino UNO
       step = 1;      // Espera la pulsación del primer pulsador
    }
    
    void loop() {
    
       // Si (etapa del programa es 1)
       if (step == 1) {
    
          // Si (solo el pulsador 2 presionado)
          if (pio.keyPressed(0)==0b000010) {
    
             // Espera a que no esté presionado
             while(pio.keyPressed(2));
    
             // Pasa a la siguiente etapa del programa
             step = 2;
          }
       }
    
       // Si (etapa del programa es 2)
       if (step == 2) {
          // Si (solo el pulsador 4 presionado)
          if (pio.keyPressed(0)==0b001000) {
    
             // Espera a que no esté presionado
             while(pio.keyPressed(4));
    
             // Pasa a la siguiente etapa del programa
             step = 3;
          }
       }
    
       // Si (etapa del programa es 3)
       if (step == 3) {
          // Si (solo el pulsador 1 presionado)
          if (                       ) {
    
             // Espera a que no esté presionado
    
    
             // Pasa a la siguiente etapa del programa
    
          }
       }
    
       // Si (etapa del programa es 4)
       if (step == 4) {
    
          // Enciende el led rojo y espera un segundo
          pio.ledWrite(1, LED_ON);
          delay(1000);
    
          // Enciende el led amarillo y espera un segundo
          pio.ledWrite(2, LED_ON);
          delay(1000);
    
          // Enciende el led verde y espera un segundo
          pio.ledWrite(3, LED_ON);
          delay(1000);
    
          // Apaga todos los leds
          pio.ledBegin();
    
          // Pasa a la primera etapa del programa
          step = 1;
       }
    }