Skip to main content

Estructuras básicas para entendernos con Arduino

De momento, ya hemos puesto en funcionamiento nuestro Arduino y hemos visto algunos de los sensores y actuadores que podemos emplear con él, ha llegado el momento de ver con más detalle cómo darle las órdenes para hacerlo funcionar. Ya hemos visto algo de esto en los ejemplos de apartados anteriores (Véase el apartado Entender el código para encender el LED) donde aparecían funciones y palabras reservadas.

Ahora, ha llegado el momento de ir un poco más allá, para poder comunicarnos con Arduino, y para ello, va a ser necesario que conozcamos algunas estructuras básicas comunes a todos los lenguajes de programación imperativa.


Un momento... ¿programación imperativa?

A la hora de programar nuestros proyectos y dependiendo del propósito de nuestro proyecto, existen diferentes paradigmas de programación. No vamos a ahondar en este tema más allá de mencionarlo, pero al menos, es importante saber qué significa eso de programación imperativa, porque probablemente nos encontremos con ese concepto si continuamos desarrollando proyectos de programación.

Básicamente, si programamos utilizando el paradigma imperativo lo que haremos será dar órdenes explícitamente. Un ejemplo de ello sería la sentencia: "Realiza la acción que yo quiera todo el rato". ¿Nos suena de algo? Eso es exactamente lo que hace la función loop() en Arduino.

Parece lógico que para programar tengamos que dar órdenes al ordenador o microcontrolador en cuestión, pero existen otros paradigmas como, por ejemplo, el declarativo, que no funcionan así. Un ejemplo de ello sería el caso en el que a nuestro ordenador le proporcionamos una conjunto de hechos y reglas y posteriormente le hacemos una consulta para que nos devuelva esa información. Por ejemplo, si creamos una base de hechos que contenga una serie de libros y su autor, podemos preguntar: ¿Quién ha escrito este libro? Y la aplicación nos devolverá esa información.

Si tienes interés en leer más sobre este tema, puedes echarle un vistazo a estas páginas.

Existen problemas que podemos resolver empleando ambos paradigmas, cuando programamos es necesario decidir cuál es el más adecuado. No obstante, aquí no vamos a tener ese problema, porque con los proyectos que vamos a ver en este curso, siempre vamos a emplear el paradigma imperativo.

La estructura de estos programas suele representarse con lo que se conoce como diagrama de flujo. Con él, se representan los diferentes caminos que puede tomar nuestro algoritmo dependiendo de las condiciones que se cumplan o no. Estas condiciones será lo primero que veremos, ya que son la base sobre la que se construye cualquier algoritmo.

image-1662990238337.jpg




Primera estructura: condicionales

Estas estructuras se encargan de controlar qué acciones de nuestro algoritmo van a ejecutarse y cuáles no. Solo hay dos opciones, o bien se cumplirán las condiciones, o no.

Las palabras clave de esta estructura son:

IF - THEN - ELSE

IF: A esta palabra le seguirá la condición que deberá cumplirse para ejecutar una serie de acciones.
THEN:
irá seguida de las instrucciones en cuestión
ELSE:
irá seguida de las acciones que se ejecutarán en caso de que la condición no se cumpla.


Un ejemplo para verlo en acción

No hay mejor manera para entender algo que ver una demostración de su uso. Para ello, vamos a recurrir a uno de los ejemplos que nos brinda la IDE de Arduino. Este ejemplo podemos encontrarlo dentro de:

Archivo > Ejemplos > 01. Basics > Fade

image-1662994993397.02.57.png

En este ejemplo, lo que hacemos es aumentar y disminuir la luminosidad de un LED de manera progresiva, en lugar de encenderlo o apagarlo del todo, como hacíamos en la práctica del bloque anterior.

Para ello, haremos uso de unos pines especiales, los cuáles pueden ser configurados para funcionar con modulación por ancho de pulsos. Y, ¿esto qué significa? pues que no solamente tienen dos posiciones (encendido o apagado), sino que podemos controlar cómo de apagado y encendido está controlando la cantidad de energía que recibe. 

Regular esta cantidad de energía puede hacerse con la función analogWrite(). Ya habíamos visto la función digitalWrite(). Si no te acuerdas, puedes echarle un vistazo aquí. analogWrite() nos permite darle al pin elegido un valor de 0 a 255, siendo 0 totalmente apagado y 255 totalmente encendido. ¿Cuál es la particularidad de esta función? que, a diferencia de digitalWrite(), que puede ser configurada con cualquier pin, analogWrite() no.

Una lista de los pines que admiten PWM dependiendo del Arduino que estemos utilizando la encontramos aquí.

De este ejemplo, por el momento, vamos a ver concretamente la parte relacionada con el condicional, pero volveremos a él después para utilizarlo como ejemplo de uso de palabras reservadas y funciones. En este algoritmo, el condicional aparece en las siguientes líneas.

En estas líneas encontramos la palabra reservada if seguida de dos condiciones encerradas entre paréntesis. Lo que traducido a español significaría: "Si el brillo es menor o igual que cero o el brillo es mayor o igual que 255". La disyunción nos viene dada por el operador lógico OR que para Arduino se traduce como ||. Otros operadores lógicos muy comunes son AND, que se traduce por && y NOT, que se escribe !.

Entre corchetes { } encontramos la acción a realizar. En este caso, revertir la cantidad de brillo que emitirá nuestro LED: si lo hemos apagado, lo comenzaremos a encender y al revés, si lo hemos encendido completamente, comenzaremos a apagarlo.
En este caso, no existe una acción que deba ejecutarse en caso de que no se de alguna de las dos circunstancias encerradas en el condicional, pero si la hubiese aparecería detrás de la palabra else.

Por tanto, un esquema de la estructura de los condicionales sería:

if (Condición) {
    Acción A
} else {
    Acción B
}

 


Una última palabra sobre los condicionales: else if

Existe también la palabra ELSE IF, la cual indica una segunda condición.

(añadir ejemplo)


Iteraciones (For loop y while)

Definiremos como iteración a la ejecución sistemática de una serie de acciones determinadas mientras se dé una condición específica. Existe una condición que se analiza, normalmente, cada vez que se repite dicha iteración. Si esta condición se sigue cumpliendo, volveremos a repetir el proceso; si, por el contrario, ya no se cumple, pasaremos a la siguiente línea de código y ejecutaremos la acción correspondiente.


Palabras reservadas
Funciones
Librerías

FUENTES:
Programación imperativa y programación declarativa: https://www.cs.us.es/cursos/pd/temas/T1_Introduccion_PD_PF.pdf
Imagen diagrama de flujo: https://c.pxhere.com/photos/cc/97/mark_marker_hand_leave_production_planning_control_organizational_structure_work_process-774947.jpg!d
Analogwrite(): https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/