Estructura de un programa para Arduino
Los programas de Arduino se escriben en lenguaje C++ adaptado, y todos comparten el mismo esqueleto: dos funciones obligatorias, setup() y loop(). Entender qué hace cada una es lo primero, porque todo lo demás se construye encima.
El esqueleto mínimo
Este es el programa más pequeño que compila y se sube a la placa. No hace nada, pero es válido:
void setup() {
}
void loop() {
}
| Función | Cuándo se ejecuta | Para qué sirve |
|---|---|---|
setup() |
Una sola vez, al arrancar | Configurar pines, iniciar el puerto serie, dejar el estado inicial |
loop() |
Sin parar, en bucle | La lógica del programa: leer sensores, activar salidas, decidir |
Cómo funciona
setup() se ejecuta una sola vez al encender o reiniciar la placa. Ahí se configuran los pines con pinMode(), se inicializa la comunicación serie y se deja todo en su estado de partida.
loop() arranca en cuanto termina setup() y se repite indefinidamente mientras la placa tenga alimentación. Cuando llega al final vuelve a empezar por el principio, sin pausa.
Las dos funciones deben estar presentes aunque estén vacías. El sistema de Arduino las llama siempre, así que si falta alguna el programa no compila.
Un programa completo, por partes
En cuanto el proyecto crece, aparecen otras secciones. Este es el orden habitual, y es el que siguen todos los ejemplos de la serie:
// 1. Librerías externas
#include <LiquidCrystal.h>
// 2. Constantes: los pines que usa el montaje
const int LED = 13;
const int BOTON = A2;
// 3. Variables globales: el estado que hay que recordar
int contador = 0;
// 4. Configuración inicial, una sola vez
void setup() {
pinMode(LED, OUTPUT);
pinMode(BOTON, INPUT_PULLUP);
}
// 5. El bucle principal, para siempre
void loop() {
if (digitalRead(BOTON) == LOW) {
contador++;
parpadear();
delay(200);
}
}
// 6. Funciones propias, para no repetir código
void parpadear() {
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
}
| Sección | Qué va ahí |
|---|---|
| Librerías | #include de código externo, como el del LCD o el TM1637 |
| Constantes | Números que no cambian: los pines. Con const para no tocarlos por error |
| Variables globales | Valores que deben sobrevivir de una vuelta del bucle a la siguiente |
setup() | Todo lo que se prepara una vez |
loop() | La lógica que se repite |
| Funciones propias | Bloques con nombre que se llaman desde loop() |
El bucle corre mucho más rápido de lo que parece
Sin ninguna espera de por medio, loop() se ejecuta miles de veces por segundo. Por eso un botón pulsado durante un instante se lee como muchísimas pulsaciones seguidas.
Es la razón de que en los ejemplos aparezca un delay(200) después de cada pulsación, o de que haga falta guardar el estado anterior del botón para detectar solo el momento del cambio.
Por qué las variables van fuera del bucle
Una variable declarada dentro de loop() se crea y se destruye en cada vuelta, así que pierde su valor constantemente. Si el programa necesita recordar algo entre una vuelta y la siguiente —un contador, un color, si el LED está encendido— la variable tiene que declararse fuera, arriba del todo.
int contador = 0; // Global: conserva su valor
void loop() {
int temporal = 0; // Local: vuelve a 0 en cada vuelta
contador++; // 1, 2, 3, 4...
temporal++; // siempre 1
}
Con solo setup() y loop() ya se puede hacer parpadear un LED, leer un botón o controlar un buzzer. Todo lo demás son variaciones sobre este mismo esqueleto.