Estructuras de control Dentro de las estructuras de control se engloban todos los estamentos que sirven para guiar al programa en una u en otra dirección y en función de si se cumplen o no las condiciones que marquemos al programa. Dentro de estas estructuras podemos encontrar condicionales, bucles o elementos de control de flujo, los que trataremos a continuación. Condicionales Los condicionales permiten tomar decisiones y realizar acciones en función de una serie de datos. Gracias a ellas diremos qué pasos queremos que siga la aplicación en cada momento para que se cumpla el objetivo que deseamos alcanzar. if (si...) es un estamento que se utiliza para comprobar si una determinada condición se cumple. Si la condición se cumple, se pasará a ejecutar las sentencias encerradas dentro del bloque if , si no se cumple la condición, el programa saltará este bloque sin ejecutar ninguna instrucción. Ejemplo: if (x==10) //Si x es igual a 10 ejecuta la instrucción { ejecuta instrucciones; } if... else (si... si no...) if... else funciona de igual forma que if, pero añade la posibilidad de que la condición no se cumpla, pasando a ejecutar las instrucciones encerradas dentro de else. Ejemplo: if (y != 10) // Si "y" es distinto de 10 ejecuta las instrucciones { ejecuta instrucciones; } else //si no, ejecuta esta instrucción { ejecuta instrucciones; } Estos condicionales pueden ir precedidos de otras estructuras condicionales del mismo tipo, anidando unas dentro de otras y haciendo que sean mutuamente excluyentes. El caso en particular es cuando tomamos una decisión de encender o no un artefacto cumpliendo cierta condición, como una temperatura o valor analógico dado. Ejemplo: if(valor < 100) // Si valor es menor que 100 ejecuta la instrucción { ejecuta instrucciones; } else if(valor >= 500) // Si valor es mayor o igual que 500 ejecuta la instrucción { ejecuta instrucciones; } else //si no se cumplen las condiciones anteriores, ejecuta esta instrucción { ejecuta instrucciones; } switch Como vimos anteriormente, los bloques “else if” se tienen en cuenta siempre y cuando las condiciones evaluadas hasta entonces hayan sido falsas, y la condición del propio “else if” sea la cierta. Es decir, un bloque if(condicion1){} else if(condicion2){} se puede leer como “si ocurre condición 1, haz el interior del primer if, y si no, mira a ver si ocurre condicion2, y (solo) si es así, haz entonces el interior del else if”. Esta es una manera válida de hacer comprobaciones de condiciones múltiples, pero existe otra forma más práctica y fácil de hacer lo mismo: utilizar el bloque “switch”. Su sintaxis es la siguiente: Ejemplo: switch (expresión) { case valor1://Se ejecutarán cuando “expresión” sea igual a “valor1” break; case valor2://Se ejecutarán cuando “expresión” sea igual a “valor2” break; /*Puede haber los “case” que se deseen, y al final una sección “default” (opcional)*/ default: //Se ejecutan si no se ha ejecutado ningún “case” anterior } Un bloque “switch” es como una especie de “if else” escrito más compactamente. Como se puede ver, consta en su interior de una serie de secciones “case” y, opcionalmente, de una sección “default”. Nada más llegar a la primera línea del “switch”, primero se comprueba el valor de la variable o expresión que haya entre sus paréntesis siguiendo las mismas reglas y operadores posibles usados en un “if” estándar. Si el resultado es igual al valor especificado en la primera sección “case”, se ejecutarán las instrucciones del interior de la misma y se dará por finalizado el “switch”, continuando la ejecución del sketch por la primera línea después de la llave de cierre. En caso de no ser igual el resultado de la expresión a lo especificado en el primer “case” se pasará a comprobarlo con el segundo “case”, y si no con el tercero, etc. Por último, si existe una sección “default” –opcional- y el resultado de la expresión no ha coincidido con ninguna de las secciones “case”, entonces se ejecutarán las sentencias de la sección “default”. En una sección “case” el valor a comparar sólo puede ser de tipo entero. Otros lenguajes de programación permiten comparar otros tipos de datos o comparar rangos de valores en un solo “case”, o comparar más de un valor individual en un solo “case”, etc., pero el lenguaje Arduino no. Hay que hacer notar que una vez ejecutada una de las secciones “case” de un bloque “switch” ya no se ejecutan más secciones “case”, aunque estas también dispongan del resultado correcto de la expresión evaluada: esto es así gracias a la instrucción “break;”, que comentaremos en breve. No es necesario ordenar las secciones “case” según sus valores (de menor a mayor, o de mayor a menor), pero sí es imprescindible que la sección “default” (en caso de haberla) sea la última sección, y no puede haber más que una. Es posible anidar sentencias “switch” sin ningún límite (es decir, se pueden poner nuevas sentencias “switch” dentro de una sección “case”). break break se usa para salir de un bucle do, for o while, saltándose la ejecución normal del bucle. También se usa para salir de una instrucción switch. Ejemplo for (x = 0; x < 255; x ++) { analogWrite (PWMpin, x); sens = analogRead (sensorPin); if (sens > threshold) // rescata un sensor { x = 0; break; } } Bucles Los bucles son elementos que hacen que el programa entre en un ciclo de repetición mientras se cumplan las condiciones del bucle, es decir, la retroalimentación de la variable controlada y la variable de referencia que nos dará un valor true o false, generando la repetición hasta que se cumpla una condición o repitiéndose un número específico de veces. for El bucle for se usa para repetir un número determinado de veces un bloque de sentencias. Cada vez que se terminan de ejecutar las sentencias encerradas dentro del bucle, se comprobará la condición inicial, repitiéndose el bucle mientras se cumpla dicha condición. Ejemplo: for(inicialización; condición; expresión) { ejecuta instrucciones; } Como se observa en el ejemplo anterior, la estructura for, está formado por 3 partes • • • Inicialización Condición del bucle Expresión (puede ponerse dentro de las sentencias del bucle). Ejemplo de bucle for: for (int x=0; x<10; x++) { digitalWrite (13, HIGH); //envía un 1 al pin 13 delay (500); //espera 500ms digitalWrite (13, LOW); //envía un 0 al pin 13 delay (500); //espera 500ms } En donde dentro del for, declaramos la variable entera x y la inicializamos en 0 (int x=0). El segundo parámetro es la condición, en la cual comparamos que la variable x sea menor a 10 (x<10). El tercer parámetro que es de control, incrementa el valor de x en 1 después de finalizar cada bucle. while El bucle while es un bucle que se repetirá constantemente mientras se cumpla la expresión del bucle. Dentro de la expresión del bucle se pueden usar variables que cambien dentro del propio bucle o que tomen el valor de alguna de las entradas de Arduino que podemos tener asociadas a sensores u otros elementos. La diferencia con el for en que podemos controlar el ciclo por fuera o por dentro del mismo. Ejemplo: while (sensor < 150) //ejecuta el bucle mientras "sensor" sea menor a 150 { ejecuta instrucciones; } do... while El bucle do... while funciona de la misma manera que while, con la única diferencia de que va a ejecutar al menos 1 vez el bucle, ya que la condición del mismo se comprueba al final. Ejemplo: do { sensor = analogRead (1);//asigna a "sensor" el valor de la entrada analógica 1 } while (sensor < 150); //repite el bucle mientras "sensor" sea menor que 150