Sesión 3: Arduino

Currículo: aquí encontrarás el desarrollo detallado de los contenidos que forman parte de la primera sesión del Curso avanzado de pensamiento computacional, robótica e internet de las cosas, impartido por el CEP de Huelva – Isla Cristina.

Tabla de contenidos

1. Introducción a Arduino

En esta sesión del curso intermedio ya introdujimos qué era Arduino, describimos la placa con mucho detalle y explicamos concienzudamente cómo se realizaba todo el proceso de diseño del circuito y la posterior carga del programa en la placa. Para continuar con lo que nos ocupa en este curso avanzado consideraremos que todo eso ya está asimilado.

Daremos un breve repaso a continuación, pero si no dominas los conceptos, deberías parar aquí, repasar lo que vimos en aquella sesión y luego continuar por aquí de nuevo.

2. Programación textual

Como ya hemos dicho en alguna ocasión, todo lo que conocemos de Arduino hasta ahora ha sido programado usando distintas herramientas de programación por bloquesTinkercad, ArduinoBlocks, mBlock,…- que lo que hacían era traducir los bloques a código C++ que luego llevábamos a Arduino IDE para que lo subiera a la placa.

Hacerlo de esta manera es muy didáctico, aprendemos rápido porque los bloques son muy intuitivos, pero llega el momento en el que se nos queda corto. A veces necesitamos programar un sensor o un actuador para el que no hay bloque en esas aplicaciones, o necesitamos hacerlo con unas estructuras de datos que no están disponibles en las herramientas de programación por bloques.

Nosotros nos proponemos desbloquear todo el potencial de Arduino, para poder usar cualquier sensor y cualquier actuador que encontremos que cubra nuestras necesidades. Y para conseguirlo el único camino es aprender a programar.

Vamos a iniciar ahora un camino complejo, pero muy gratificante. Lo único que te separa del dominio total de la robótica es la paciencia para aprender y el tiempo para practicar lo que veremos en esta sesión.

Así que, ten paciencia y concéntrate que aquí vamos.

3. Monitor serie

Antes de coger un solo cable, necesitamos entender cómo saber qué está ocurriendo dentro del microcontrolador -placa Arduino-.

El monitor serie es una herramienta que nos permite enviar y recibir información entre el ordenador y Arduino.

Veamos la estructura mínima de un programa Arduino:

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("Hola desde Arduino");
  delay(1000);
}

setup(): se ejecuta una sola vez.

loop(): se ejecuta continuamente.

Serial.begin(9600): inicia la comunicación entre el ordenador y la placa.

Serial.println(): escribe información en el monitor serie y deja el cursor en la línea siguiente.

ℹ️ Una variable es una zona de memoria a la que le asignamos un nombre y que usamos para almacenar un valor que podamos usar más tarde. Puedes pensar en ellas como un cajón con nombre que siempre tiene el último contenido que almacenaste.

Por ejemplo: si tengo una variable Días y he guardado el 7. Si posteriormente guardo el 30, cuando vaya a usar la variable encontraré un 30 porque es el último valor que almacené.

De esta manera, puedo tener una variable llamada contador que cuente los segundos que han pasado desde que se inició el programa:

void setup() {
  Serial.begin(9600);
}

int contador = 0;

void loop() {
  Serial.println(contador);
  contador++;
  delay(1000);
}

4. Salida digital con un LED

Ahora que ya sabes cómo obtener información de lo que está pasando dentro de Arduino, es cuando realmente empezamos a controlar el mundo físico.

🔴 Vamos a crear un circuito con un LED, algo que ya sabemos de sobra:

Ahora programaremos la placa para que el LED se encienda 1s, se apague 1s y así indefinidamente:

int led = 2;

void setup() {
  pinMode(led, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);
  delay(1000);

  digitalWrite(led, LOW);
  delay(1000);
}

Veamos qué significan esas líneas de código:

pinMode(): configurar un pin, el primer parámetro es qué pin estamos configurando y el segundo parámetro si ese pin va a funcionar en modo entrada o en modo salida.

digitalWrite(): escritura digital, el primer parámetro indica en qué pin debe escribir y el segundo parámetro indica qué valor debe escribir si HIGH o LOW. Es decir: enviar corriente o dejar de hacerlo.

delay(): pausa la ejecución del programa la cantidad de milisegundos que le indiques.

Esto último también lo podemos controlar con una variable, así cuando queramos hacer cambios solo tendremos que cambiar el valor en un único lugar:

int led = 2;
int tiempo = 500;

void setup() {
  pinMode(led, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);
  delay(tiempo);

  digitalWrite(led, LOW);
  delay(tiempo);
}

5. Estructuras repetitivas con zumbadores

Un zumbador, como ya sabes, es un componente electrónico que emite sonido cuando se le excita eléctricamente.

Desde el punto de vista del circuito y de la programación funciona igual que el LED:

int zumbador = 2;
int tiempo = 500;

void setup() {
  pinMode(zumbador, OUTPUT);
}

void loop() {
  digitalWrite(zumbador, HIGH);
  delay(tiempo);

  digitalWrite(zumbador, LOW);
  delay(tiempo);
}

Con la excusa de usar este componente vamos a introducir el concepto de bucle o estructura repetitiva.

Por ejemplo: si queremos programar un timbre que cada vez que se pulsa suena tres veces, no vamos a escribir las mismas líneas de código tres veces, lo que hacemos es escribirlas una vez y hacerlas ejecutar tres veces:

int zumbador = 2;
int tiempo = 200;

void setup() {
  pinMode(zumbador, OUTPUT);
}

void loop() {

  for(int i = 0; i < 3; i++) {

    digitalWrite(zumbador, HIGH);
    delay(tiempo);

    digitalWrite(zumbador, LOW);
    delay(tiempo);

  }

  delay(2000);

}

int i = 0: crea una variable que inicializa a 0 para controlar cuantas veces se ejecuta el bucle.

i < 3: condición para controlar cuándo debemos parar.

i++: cómo de rápido avanzamos, en este caso avanzamos de uno en uno con cada repetición.

6. Entradas analógicas con servomotor y potenciómetro

Hemos visto cómo hacer funcionar dos actuadores: un LED que se enciende y un zumbador que pita.

🔴 Ahora veremos cómo podemos leer los valores de un sensor -el potenciómetro- para intervenir sobre un actuador -el servomotor-.

Internamente un potenciómetro es una resistencia variable que nos permite leer valores entre 0 y 1023.

Veámoslo usando un pequeño circuito y el monitor en serie:

int pote = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int valor = analogRead(pote);

  Serial.println(valor);

  delay(200);
}

analogRead(pote): lee el valor analógico que está ofreciendo el potenciómetro y luego lo almacenamos en una variable llamada valor.

Para mover el servomotor simplemente lo conectamos en el mismo circuito:

Y le colocamos el ángulo dependiendo de la posición que tenga en cada momento el potenciómetro:

#include 

Servo miServo;
int pote = A0;

void setup() {
  miServo.attach(6);
}

void loop() {
  int valor = analogRead(pote);
  
  int angulo = map(valor, 0, 1023, 0, 180);
  miServo.write(angulo);

  delay(15);
}

miServo.attach(6): el servomotor lo tenemos conectado a la “salida analógica” 6, que es el lugar al que Arduino enviará la cantidad de grados que debe girar.

map(): lo usamos para transformar escalas. Como nuestro potenciómetro lee valores entre 0 y 1023, y nuestro servomotor funciona con ángulos de 0 a 180, tenemos que transformar la escala para lograr moverlo a todas las posiciones de manera proporcional.

7. Condicionales con el sensor de ultrasonidos

El sensor HC-SR04 es muy adecuado para introducir las estructuras condicionales, porque permite plantear situaciones reales: una barrera de parking, un robot que evita obstáculos, una papelera automática o una alarma de proximidad.

El sensor HC-SR04 tiene cuatro pines:

  • VCC: se conecta a 5V.
  • Trig: es el pin que recibe la orden de Arduino para emitir el pulso ultrasónico, es decir la onda que viajará.
  • Echo: es el pin que devuelve a Arduino cuánto tiempo ha tardado en volver el eco, es decir la onda tras chocar con un obstáculo.
  • GND: se conecta tierra.

Sabiendo esto vamos a diseñar y programar un circuito que funcione como una alarma de proximidad. No nos limitamos a leer la distancia, sino que añadimos un LED y un zumbador activo para que el sistema haga algo visible y audible.

El circuito tendrá este comportamiento: si un objeto está a menos de 20 cm, se encenderá el LED y sonará el zumbador. Si está más lejos, todo permanecerá apagado.

Vamos con el circuito:

Ahora colocaremos el código y a continuación su explicación línea a línea:

int trig = 9;
int echo = 10;
int led = 7;
int buzzer = 6;

void setup() {
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(led, OUTPUT);
  pinMode(buzzer, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  digitalWrite(trig, LOW);
  delayMicroseconds(2);

  digitalWrite(trig, HIGH);
  delayMicroseconds(10);

  digitalWrite(trig, LOW);

  long duracion = pulseIn(echo, HIGH);

  float distancia = duracion * 0.034 / 2;

  Serial.print("Distancia: ");
  Serial.print(distancia);
  Serial.println(" cm");

  if (distancia < 20) {
    digitalWrite(led, HIGH);
    digitalWrite(buzzer, HIGH);
    Serial.println("Objeto demasiado cerca");
  } else {
    digitalWrite(led, LOW);
    digitalWrite(buzzer, LOW);
    Serial.println("Zona libre");
  }

  delay(300);
}

Líneas 1-4: creamos las variables que van a almacenar los pines en los que están conectados todos los componentes.

Líneas 7-10: configuramos cada pin para indicar en qué modo van a funcionar.

Líneas 16-17: primero nos aseguramos de que el disparador de la onda ultrasónica está apagado.

Líneas 19-20: lo activamos durante 10 microsegundos y se lanza la onda.

Línea 22: lo apagamos otra vez. Ese pulso breve es la orden para que el sensor haga la medición.

Línea 24: pulseIn() mide cuánto tiempo permanece el pin echo en estado HIGH. Ese tiempo se mide en microsegundos. Usamos long porque el número puede ser más grande que un int normal.

Línea 26: el sonido viaja aproximadamente a 0,034 cm por microsegundo. Como el sonido va hasta el objeto y vuelve, dividimos entre 2. Aquí aparece una variable de tipo float, porque la distancia puede tener decimales.

Líneas 28-30: comprobamos con el monitor serie que el sensor está midiendo bien.

Líneas 32-40: si la distancia es menor de 20 cm, encendemos el aviso. En caso contrario, lo apagamos.

8. Programar cualquier componente

Una vez que conocemos lo básico de la programación, ya podemos embarcarnos en la fabricación de cualquier sistema que se nos ocurra.

No es necesario saber programar cada sensor/actuador que nos encontremos porque TODOS se programan igual. Lo único que cambia es cómo tratan la relación voltaje-unidad física que proporcionan.

Por ejemplo, llega a nuestras manos este sensor de temperatura LM35:

Nosotros no necesitamos saber cómo está fabricado ni qué características tiene para programarlo, ya que se observa a simple vista que tiene tres pines, uno de tierra, otro de voltaje y otro de señal. Como es un sensor sabemos que nos va a proporcionar una entrada y como se trata de temperatura, debemos usar un pin analógico de entrada.

Sabiendo esto, ya podemos programar algo que muestre por el monitor serie qué está leyendo.

Lo que sí debemos hacer es acudir a la documentación del sensor para saber qué es ese valor que está entregando: si voltios, milivoltios, grados kelvin o un valor analógico 0-1023. Una vez que lo sepamos modificamos nuestro programa con las operaciones matemáticas sencillas para convertir la señal de entrada en algo significativo para nosotros y ya está.

Este sensor en concreto devuelve un valor entre 0 y 1023. Y sabemos que usa 10mV por cada grado centígrado. Así que lo que debemos hacer es leer el valor del sensor, calcular cuantos voltios está devolviendo (lo podemos saber porque lo estamos alimentando con 5V) y ese valor multiplicarlo por 100 para pasarlo a grados centígrados.

const int pinLM35 = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {

  // Leemos el valor analógico (0-1023)
  int lectura = analogRead(pinLM35);

  // Convertimos a voltaje
  float voltaje = lectura * (5.0 / 1023.0);

  // LM35: 10 mV por cada grado
  float temperatura = voltaje * 100.0;

  Serial.print("Temperatura: ");
  Serial.print(temperatura);
  Serial.println(" °C");

  delay(1000);
}


Espero que hayas aprovechado estos contenidos, que los repases y por supuesto, que los pongas en práctica en tu aula.

Si quieres compartir con nosotros tu experiencia, no dudes en dejar un comentario.

👋 Hasta la próxima sesión.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *