En esta lección vas a aprender dos cosas nuevas
- Cómo realizar una secuencia de acciones repetidamente
- Cómo iterar con un bucle por distintos periféricos
Vamos a necesitar lo siguiente
- Una placa controladora de la familia Arduino
- Cuatro LEDs
Control de flujo
La programación secuencial consiste en ejecutar un serie de órdenes o comandos uno después de otros, estos comandos pueden leer información (a través de los sensores), ejecutar acciones (por ejemplo, mover un servo), o simplemente realizar alguna operación interna (como realizar una suma).
En la lección anterior vimos un ejemplo en el que se alteraba el orden de ejecución de un programa con la sentencia if-else, estas instrucciones se llaman instrucciones de control de flujo.
Pongamos un ejemplo: imaginemos un programa donde, si la lectura de la cantidad de luz es menor de 300, enciende un LED y, de lo contrario, lo apaga. En función de una variable realizo la acción encender LED o la acción apagar LED . Esto se ve claro en la siguiente imagen
Realizando tareas repetidamente con el bucle for
El bucle for es otro modo de modificar el flujo en el que se ejecuta un programa haciendo que una serie de instrucciones se repitan un número dado de veces, por ejemplo, podría querer que un LED parpadease 10 veces yel flujo del programa sería algo así.
Vamos a hacer este último programa explicándolo paso a paso
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
int led_pin = 5; //pin donde se conecta el LED bool primeraVez = true; //para saber cuándo es la primera vez void setup() { pinMode(led_pin, OUTPUT); } void loop() { // la primera vez haremos parpadear el LED 10 veces if (primeraVez){ primeraVez = false; //ya no sera más la primera vez for (int i = 0; i<10; i=i+1){ digitalWrite(led_pin,HIGH); //ENCENDER LED delay(1000); //pausar 1 segundo digitalWrite(led_pin,LOW); //apagar LED delay(1000); //pausar 1 segundo } }else{ digitalWrite(led_pin,LOW); //apagar LED } } |
Vamos a analizar por bloques
1 2 3 4 5 6 7 |
int led_pin = 5; //pin donde se conecta el LED bool primeraVez = true; //para saber cuándo es la primera vez void setup() { pinMode(led_pin, OUTPUT); } |
En este bloque usamos variables globales para indicar el número de PIN al que se conecta el LED. Además, creamos una variable booleana (admite los valores verdadero y falso). Utilizaremos esta variable para saber si es la primera vez que se ejecuta el programa. Es un recurso habitual en programación, al ejecutarse la función loop() una y otra vez, si queremos que un programa se ejecute solo una vez es necesario hacer esto o algo parecido.
1 2 3 4 5 6 7 8 9 10 |
void loop() { // la primera vez haremos parpadear el LED 10 veces if (primeraVez){ primeraVez = false; //ya no sera más la primera vez ... }else{ digitalWrite(led_pin,LOW); //apagar LED } } |
La primera vez que se ejecute la función loop() la variable primeraVez vale true (verdadero), por ello entramos en el if, y ejecutamos lo que viene a continuación. La primera instrucción es asignar a la variable primeraVez el valor false (falso), por ello, la próxima vez que se ejecute la función loop() ya no se cumplirá la condición y se ejecutará por lo tanto digitalWrite(led_pin, LOW) dejando el LED apagado indefinidamente.
Ahora vamos a entrar a analizar el bucle for
1 2 3 4 5 6 |
for (int i = 0; i<10; i++){ digitalWrite(led_pin,HIGH); //ENCENDER LED delay(1000); //pausar 1 segundo digitalWrite(led_pin,LOW); //apagar LED delay(1000); //pausar 1 segundo } |
En primer lugar
1 |
for (int i = 0; i<10; i=i+1) |
El bucle for tiene tres partes
- Variable sobre la que se itera, y valor inicial, en este caso int i=0. Iteramos con una variable llamada i que es un entero y cuyo valor inicial será 0.
- Condición de control, es decir, el bucle for se repetirá mientras esta condición siga siendo verdadera: i < 10 . Esta comprobación se realizará al principio de cada iteración, es decir, si la condición es falsa la primera vez, no se realiza ninguna iteración.
- Acción a ejecutar al final de la iteración, en este caso i=i+1. Es decir, después de cada iteración i se incrementa una unidad (podría ser cualquier otra operación). Es importante notar que esto se realiza al finalizar la iteración, por lo que en la primera iteración, i vale 0.
De este modo la secuencia de ejecución seŕia
- i=0, ¿ i < 10 ? : sí, parpadeo una vez, incremento i. Luego i=1
- i=1, ¿ i < 10 ? : sí, parpadeo una vez, incremento i. Luego i=2
- i=2, ¿ i < 10 ? : sí, parpadeo una vez, incremento i. Luego i=3
- …
- i=9, , ¿ i < 10 ? : sí, parpadeo una vez, incremento i. Luego i=10
- i=10, , ¿ i < 10 ? : No, salgo del bucle for.
Iterando con el bucle for
Otro uso de los bucles for es utilizar la variable de control, en el ejemplo anterior i para realizar alguna operación, por ejemplo, ¿recordáis las luces del coche fantástico?, vamos a hacer que 5 LEDs se enciendan de modo secuencial, de modo que se encienda cada vez uno más y luego se apaguen todos.
Supongamos que los LEDs están conectados a los pines del 2 al 6, la secuencia seŕia
- Todos apagados
- LED 2 encendido
- LEDs 2, 3 encendidos
- LEDs 2, 3, 4 encendidos
- LEDs 2, 3, 4, 5 encendidos
- LEDs 2, 3, 4, 5, 6 encendidos
y esto una y otra vez
¿cómo sería el código?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void setup() { //utilizamos el bucle for para poner los pines en modo OUTPUT for (int i=2;i<=6;i=i+1) pinMode(i, OUTPUT); } void loop() { //apagamos todos los LED for (int i=2;i<=6;i=i+1) digitalWrite(i, LOW); //apagamos LED i delay(100); //pausamos 100 milisegundos //encendemos secuencialmente el LED 2, 3, 4, 5, 6 for (int i=2;i<=6;i=i+1){ digitalWrite(i, HIGH); //encendemos LED i delay(200); //pausamos 200 milisegundos } } |
En la función setup() ponemos todos los pines en los que hay LED en modo OUTPUT. En lugar de hacerlo uno por uno lo hacemos con un for, ahorrando código. Esto sería equivalente a hacer
1 2 3 4 5 |
pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(6,OUTPUT); |
En la función loop() primero apagamos todos los LED (del mismo modo) y luego pausamos 100 milisegundos. Posteriormente vamos encendiendo uno a uno con una cadencia de 200 milisegundos, consiguiendo el efecto deseado.
Una vez que se han encendido todos volvemos a empezar con el loop(), es decir, volvemos a apagar y a encender uno detrás de otro, y así indefinidamente.
¿Cómo sería un programa que en lugar de apagarlos todos de golpe los va apagando secuencialmente?, se decir, enciende uno a uno con una cadencia de 200 milisegundos, y después los va apagando en orden inverso.
Para obtener más información sobre el for consulta la referencia de Arduino.
Ejercicio
¿Recuerdas el ejercicio propuesto al final de la entrada sobre las sentencias condicionales if-else? A continuación puedes ver la solución. No dudes en contactar con nosotros si no entiendes algo.
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 |
int ledPin; //global variable for the pin number /** * This funcions receives a char as parameter * and switchs on/off the LED depending on its value */ void manageChar(int Pin, char c){ Pin -= 48; //if the char equals if(c=='H'){ digitalWrite(Pin, HIGH); //switch LED on } //if the char equals L if(c=='L'){ digitalWrite(Pin,LOW); //switch LED off } } /** * This function stops execution of program until * something is received through serial port * The received chars are sent to manageChar function */ void waitForInput(){ //While there is no data on Serial input while(Serial.available()==0){ delay(500); // wait 500 ms and check again } // hey!! something arrived // while there is data pending while(Serial.available()>0){ int incomingPin = Serial.read(); char incomingChar = Serial.read(); manageChar(incomingPin, incomingChar); } // when arrived here, Serial is empty and we have received something // that is what we wanted! } void setup(){ Serial.begin(9600); //start serial communiation at bautrate 9600 for (ledPin=0; ledPin<10; ledPin++){ pinMode(ledPin, OUTPUT); //sets the LED pin as output } } void loop(){ waitForInput(); //waits for serial port input } |