TECNOLOGÍA ROBÓTICA - Arduino

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 53

2.3. LA TARJETA ARDUINO UNO R3.

Arduino es una tarjeta controladora electrónica que integra un microcontrolador y un conjunto de pines de
entrada y salida a los que podemos conectar sensores y actuadores electrónicos. Los sensores se conectan
a los pines de entrada, y los actuadores a los pines de salida. Aunque hay múltiples versiones de Arduino
nosotros trabajaremos con la tarjeta Arduino UNO R3 (ver figura 2.15).

Figura 2.15. Tarjeta Arduino UNO R3.

Con la tarjeta Arduino y el correspondiente programa de control podemos controlar sistemas automáticos
cuyos sensores detecten algún tipo de magnitud física (luz, calor, movimiento, etc.), y en base a ella,
activen un actuador (como una pequeña bombilla, un LED, un servomotor, un motor DC, un relé, etc.).
Algunos ejemplos de automatismos que podemos montar con Arduino son un sistema para la apertura y
cierre de una puerta, un robot móvil que detecte obstáculos o que siga una línea negra, un detector de luz y
de oscuridad, etc.

PINES DE ENTRADA Y SALIDA.

Los pines de entrada y salida sirven para que la tarjeta Arduino interaccione con el “mundo exterior”. Si
queremos leer el valor de la magnitud física medida por un cierto sensor (por ejemplo, la cantidad de luz
detectada por un resistor LDR), debemos conectar el sensor a uno de los pines de entrada (en este caso, a
un pin de entrada analógica). De esta forma, y con una simple instrucción de lectura en el programa de
control, podremos registrar el valor medido por ese sensor. Si nuestra intención es activar un actuador
tras haber leído el valor captado por el sensor (por ejemplo, encender un LED si el sensor detecta
oscuridad), debemos conectar ese actuador a uno de los pines de salida, el cual le proporcionará la
corriente necesaria para hacerlo funcionar. Como veremos en breve, en el programa de control es
obligatorio añadir instrucciones que indiquen explícitamente la función que desempeña cada uno de los pines
usados en nuestro proyecto (esto es, si el pin actúa como entrada o como salida).

PINES ANALÓGICOS Y DIGITALES.

Tanto los pines de entrada como los de salida operan con unos voltajes de entre y . Sin embargo, los
pines de entrada y de salida pueden ser tanto analógicos como digitales. ¿Qué diferencia hay?

Los pines digitales solo pueden entregar o recibir dos valores posibles: “HIGH” (equivalente a un 1 lógico) y
“LOW” (equivalente a un 0 lógico). Un voltaje de entre y se interpretará como un valor “LOW”, y
una voltaje de entre y como un valor “HIGH”. Por otro lado, los pines analógicos pueden entregar
o recibir muchos voltajes intermedios dentro del rango de a .
46
Por consiguiente, en Arduino tenemos pines de entrada digitales y analógicos para conectar los sensores, y
pines de salida digitales y analógicos para conectar los actuadores. Vamos a explicar estos conceptos con
un poco más de detalle:

Pines de entrada analógicos.

Los 6 pines etiquetados como ANALOG IN, y numerados del A0 al A5, son pines de entrada analógicos.
¿Para qué sirven? La mayoría de los sensores que usaremos en nuestros proyectos son analógicos, lo que
significa que emplean todo un conjunto de voltajes posibles para representar la variación de la magnitud
física medida. Este tipo de sensores debe conectarse obligatoriamente a los pines de entrada analógicos, y
no a los digitales. Los pines de entrada analógicos tienen una resolución de 10 bits, lo que significa que
pueden diferenciar hasta 1024 voltajes de entrada posibles en el rango de a .

Pines de entrada y salida digitales.

Los 14 pines etiquetados como DIGITAL (PWM ∽), y numerados del 0 al 13, son pines digitales que se
pueden configurar como entradas o como salidas.

Ahora bien, si los sensores se conectan a las entradas analógicas, ¿para qué sirven las entradas digitales?
Las entradas digitales son útiles cuando las señales que necesitamos leer solo toman dos valores posibles.
Por ejemplo, imaginar que queremos usar un pulsador para encender un LED. Para ello, podemos hacer un
montaje donde al activar el pulsador entren al pin digital de entrada, y al desactivarlo entren . De
esta forma, la lectura del pin digital de entrada será “HIGH” cuando reciba y “LOW” cuando reciba .

Por su parte, las salidas digitales permiten activar un receptor que solo pueda tomar dos estados. Por
ejemplo, si queremos controlar en encendido y apagado de un LED, podemos conectar ese LED a un pin
digital de salida.

Figura 2.16. Salidas analógicas.

Pines de salida analógicos.

De los 14 pines digitales, hay 6 de ellos (los pines etiquetados con el símbolo ∽) que son salidas digitales
que simulan salidas analógicas (ver sección 2.8). Las señales que proporcionan estas salidas analógicas son
47
muy útiles para controlar actuadores que pueden tomar más de dos estados posibles. Algunos ejemplos son
el control de servomotores para llevarlos a una posición determinada, el ajuste de la velocidad de giro de
un motor DC, o el control del nivel de iluminación de un LED. Estas salidas analógicas tienen una resolución
de 8 bits, lo que significa que pueden proporcionar hasta 256 salidas distintas (por ejemplo, 256 posiciones
posibles de un servomotor, o 256 posibles niveles de iluminación de un LED, ver figura 2.16).

HARDWARE BÁSICO.

La figura 2.17 muestra los componentes hardware básicos de la placa Arduino UNO R3:

Figura 2.17. Hardware de la tarjeta Arduino UNO R3.

 14 pines digitales de entrada/salida que operan entre y . Estos pines solo pueden tomar dos
valores o estados posibles: “HIGH” (equivalente a un 1 lógico) y “LOW” (equivalente a un 0 lógico). Cada
uno de estos pines de entrada/salida puede recibir o entregar una intensidad máxima de .

Los pines digitales 3, 5, 6, 9, 10 y 11 son salidas digitales que pueden configurarse como salidas
analógicas capaces de proporcionar hasta 256 voltajes distintos entre y .

Los pines 0 (RX) y 1 (TX) pueden usarse como entrada y salida para las comunicaciones serie a través del
puerto USB, respectivamente.

 1 pin digital de toma de tierra (GND) que se usa como nivel de referencia de para los sensores o
actuadores conectados a los pines digitales de entrada/salida.

 6 pines de entrada analógica que pueden recibir hasta 1024 valores de voltaje posibles entre y .
Como los pines digitales, los pines de entrada analógica pueden recibir una intensidad máxima de .

48
 Microcontrolador ATmega 328. Este dispositivo es el cerebro de Arduino, y es donde se almacena y
ejecuta el programa de control. El microcontrolador se programa utilizando el entorno de programación
de Arduino (IDE de Arduino), del que hablaremos más adelante.

 Un puerto USB que cumple varias funciones:

1) Alimentación de la placa cuando está conectada al ordenador.


Como todo circuito electrónico, Arduino necesita una alimentación eléctrica para funcionar. Cuando la
placa Arduino está conectada al ordenador (para cargar un programa, o para la comunicación serie
entre la placa y el ordenador), la conexión USB alimenta a la placa Arduino con un voltaje total de .

2) Carga de los programas al microcontrolador.


El programa de control que escribimos en el IDE de Arduino se carga en el microcontrolador a través
del puerto USB.

3) Comunicación de datos entre la placa y el ordenador.


Arduino también utiliza el puerto USB para el intercambio de información entre la placa y el
ordenador en tiempo de ejecución, como por ejemplo, los valores leídos por las entradas, o los valores
proporcionados por las salidas.

 Jack de alimentación. Si ya hemos descargado el programa de control y queremos trabajar con la placa
Arduino sin conectarla a un ordenador, debemos alimentarla con una fuente externa (una pila de , una
fuente de alimentación, etc.) conectada al jack de alimentación. El voltaje de alimentación externa
recomendado para no dañar la placa está en el intervalo entre los y los . Este jack incluye un
diodo de protección para evitar dañar la placa por un exceso de corriente.

 5 pines de alimentación. El sistema automático a controlar con Arduino suele montarse en una
protoboard auxiliar. Para alimentar los circuitos montados en la protoboard utilizaremos la propia
tarjeta Arduino a modo de pila. Arduino incorpora cinco pines de alimentación que funcionan como sigue:

 Un pin “Vin” que proporciona el voltaje máximo con el que se está alimentado Arduino (ya sea a través
del puerto USB, o externamente a través del jack de alimentación).
 Un pin que proporciona una tensión de y una intensidad máxima de .
 Un pin que proporciona una tensión de y una intensidad máxima de .
 Dos pines “GND” de toma de tierra, o nivel de referencia de .

A modo de ejemplo, si conectamos al jack una pila de , en el pin “Vin” dispondremos de un voltaje de
aproximadamente (hay que restar el pequeño voltaje del diodo de protección). Además, los pines de
alimentación de y también ofrecen esos voltajes, aunque la fuente externa sea de . Lo más
habitual es usar el pin de como positivo, y uno de los pines “GND” como negativo ( ).

 Botón de reset. El botón de reset permite reiniciar el programa cargado en el microcontrolador,


interrumpiendo la ejecución actual. Es importante tener en cuenta que pulsar el botón de reset no borra
el programa, solo lo reinicia.

SHIELDS PARA ARDUINO. (*)

Los llamados Shields (escudos) son tarjetas que añaden funcionalidades extra a la placa Arduino. La
intensidad máxima que proporcionan las distintas salidas es de , un valor insuficiente para actuadores
como motores, relés, o electroválvulas. Para poder activar estos dispositivos existen unas placas adaptadas
a los pines de Arduino que se ensamblan directamente encima de ella a modo de "escudo" (de ahí el nombre
de “Shields”), y que ofrecen pines adicionales para alimentar los receptores que Arduino no puede
alimentar por sí sola. También hay otros tipos de Shields que ofrecen funciones adicionales, como conexión
49
Ethernet, WIFI, GPS, etc. Actualmente hay decenas de ellas en el mercado. La figura muestra un Shield
para la activación de motores (izquierda), y otro para conectarnos a redes WiFi (derecha).

Figura 2.18. Shields de Arduino para motor (izquierda) y WiFi (derecha).

2.4. TRABAJAR CON ARDUINO.

Para poder realizar proyectos tecnológicos con Arduino necesitamos varios recursos hardware y software,
que vamos a describir a continuación:

IDE DE ARDUINO.

Para escribir y transferir el programa de control a la placa, necesitamos instalar en nuestro ordenador el
entorno de programación Arduino, más conocido como IDE Arduino (IDE Integrated Development
Environment).

Figura 2.19. IDE Arduino.


50
El IDE Arduino está constituido por un editor de texto para escribir el código del programa de control, un
área de mensajes, una barra de herramientas con botones para las funciones más comunes, y un conjunto
de menús. El IDE permite la conexión vía USB del ordenador con Arduino para cargar los programas a la
placa y comunicarse con ellos.

Para descargar el IDE Arduino debemos acudir a la página https://www.arduino.cc/en/Main/Software y


seleccionar el instalable adecuado para nuestro sistema operativo.

Opcionalmente, también podemos crear nuestros proyectos Arduino on – line en la propia web de Arduino,
mediante la aplicación Arduino Web Editor. Para ello, debemos acudir a la página
https://create.arduino.cc/ y crearnos una cuenta. Nuestros proyectos se guardarán en la nube, y estarán
accesibles siempre que dispongamos de conexión a Internet.

SIMULADOR TINKERCAD.

Autodesk TinkerCAD es una herramienta on – line inicialmente desarrollada para diseñar modelos 3D,
aunque nosotros la utilizaremos para montar virtualmente nuestros proyectos y simular su correcto
funcionamiento antes de implementarlos físicamente.

Figura 2.20. Ventana de diseño de circuitos en TinkerCAD.

Para poder usar el simulador TinkerCAD debemos acudir a la web https://www.tinkercad.com/ y crear una
cuenta. (En este caso, basta con usar nuestra cuenta de Google). Para diseñar el sistema de control, lo
único que tenemos que hacer es montar el circuito usando los múltiples dispositivos incluidos en la galería
de componentes del TinkerCAD. Y para comprobar su correcto funcionamiento, basta con copiar el
programa de control (ya sea en código nativo o mediante bloques) en la zona de código, y pulsar el botón de
“Iniciar Simulación”.

Opcionalmente, también podemos usar el programa Fritzing (https://fritzing.org), un software que nos
permite diseñar nuestros proyectos en una protoboard virtual. En particular, y si trabajamos con la tarjeta
Arduino, Fritzing nos permite montar el circuito, editar el código del programa de control, y finalmente
enviarlo directamente a la tarjeta Arduino. La única pega es que Fritzing solo permite realizar la fase de
diseño, pero no simular el funcionamiento del sistema.

51
TARJETA ELECTRÓNICA ARDUINO Y KITS DE COMPONENTES.

Por último, para poder montar físicamente los proyectos diseñados necesitamos adquirir una placa Arduino
UNO R3, y un kit de componentes básicos.

Arduino es una plataforma abierta, lo que significa que su hardware y software son de dominio público, y no
pertenecen a ninguna compañía. Cualquier empresa o individuo podría construir su propia placa Arduino y
desarrollar su propio IDE. Por supuesto, también hay a la venta versiones comerciales ya construidas, y a
precios bastante asequibles (rondando los 20 € por placa).

Una vez dispongamos de la placa Arduino, hemos de asegurarnos de que se comunica con el ordenador.
Primero conectamos la placa al ordenador por USB. A continuación abrimos el IDE Arduino, y en el menú de
“Herramientas”, nos aseguramos de que el ordenador ha reconocido la placa conectada. Por último, y de
nuevo en el menú “Herramientas”, buscamos la opción "Puerto", y seleccionamos el puerto COM al que se ha
conectado Arduino.

Figura 2.21. Kit de iniciación de Arduino.

Además de la placa Arduino, también necesitaremos adquirir los componentes y dispositivos necesarios
para montar nuestros proyectos (típicamente, una protoboard, sensores, actuadores, resistores,
potenciómetros, etc.). Aunque podemos acudir a una tienda de electrónica y comprar los componentes que
necesitemos para nuestro proyecto actual, también se venden kits que incluyen algunos de los componentes
más habituales, y que podemos adquirir en un solo lote a precios muy razonables (40 €). Un ejemplo es el kit
de iniciación a Arduino mostrado en la figura 2.21, que incluye la propia placa Arduino UNO R3.
52
Una alternativa a los kits de componentes discretos son los Shields multifunción que integran muchos de
los componentes electrónicos más comunes en proyectos de Arduino. Estos Shields nos permiten tener la
electrónica ya preparada, para no preocuparnos de montar y cablear los circuitos de control en una
protoboard. En el mercado existen muchos ejemplos de Shields multifunción que incluyen componentes
como botones, zumbadores, LEDs, displays 7 segmentos, potenciómetros, e interfaces para el control de
sensores, servomotores, etc. Algunos ejemplos son Echidna, BQ Zum Kit, Grove Starter Kit, Makey Makey,
NanoPlayBoard, EduBasica, etc. (Para más información, consultar el enlace
https://aprendiendoarduino.wordpress.com/2018/05/06/hardware-arduino-para-la-educacion/).

NOTA IMPORTANTE: En algunos casos tal vez no tengamos o no queramos invertir el dinero que cuesta
una placa Arduino y los componentes o Shields necesarios para montar físicamente nuestros proyectos.
No pasa nada: Todavía podemos aprender a diseñar sistemas de control con Arduino, solo que deberemos
conformarnos con simular nuestros proyectos en TinkerCAD, sin implementarlos físicamente.

METODOLOGÍA DE TRABAJO.

Con tantas herramientas y recursos puede que todavía no tengamos claro qué pasos debemos seguir para
desarrollar nuestros proyectos con Arduino. A modo de resumen, la secuencia de trabajo es la siguiente:

1) Usamos un simulador (TinkerCAD o Fritzing) para diseñar la electrónica del sistema a montar.
2) Escribimos el programa de control con el IDE de Arduino.
3) Simulamos el funcionamiento del sistema de control diseñado (circuito y programa) en TinkerCAD.
4) Retocamos el diseño y/o el programa si el sistema simulado no funciona como esperábamos.
5) Tras verificar el correcto funcionamiento del sistema, realizamos el montaje físico con componentes
reales (tarjeta Arduino, protoboard, cables, sensores, actuadores, resistencias, potenciómetros, etc.) y
cargamos mediante el IDE de Arduino el programa de control en la tarjeta Arduino.

NOTA IMPORTANTE: En el caso de no disponer de los recursos hardware necesarios para montar
físicamente el sistema de control, solo necesitaremos TinkerCAD para diseñar, programar, y simular
nuestro sistema.

2.5. PROGRAMAR ARDUINO.

Todo programa de Arduino presenta la siguiente estructura básica:

// Declara tus variables aquí:


int x = 0;

void setup() {
// Escribe el código de configuración aquí, para ejecutarlo una vez.
}

void loop() {
// Escribe el programa principal aquí, para ejecutarlo repetidamente.
}

, donde podemos distinguir las siguientes partes:

1) Declaración de las variables globales: int x = 0;

2) Configuración inicial de Arduino: void setup() {…}

3) Bucle de control de Arduino: void loop() {…}

53
PRIMERA PARTE: DECLARACIÓN DE LAS VARIABLES GLOBALES.

Al principio del código se definen las variables globales que usará el programa. Una variable es un valor que
Arduino puede almacenar en su memoria, y que posteriormente puede consultar, utilizar, o modificar.
Podemos imaginar que una variable es como una caja etiquetada con un nombre en la que podemos guardar
un cierto valor, y que posteriormente podemos usar refiriéndonos al nombre de la caja que lo contiene.

Pero antes de utilizar una variable debemos declararla. La declaración de una variable especifica el
nombre de la variable, el tipo de dato que va a almacenar, y opcionalmente, su valor inicial. Los tipos de
datos más comunes en Arduino son:

 int: variable que almacena (con 2 bytes) un número entero entre y . (Por ejemplo, int
ledPin = 7;).
 unsigned int: variable que almacena (con 2 bytes) un número entero entre y , esto es, un
entero sin signo.
 long: variable que almacena (con 4 bytes) un número entero largo entre y .
 unsigned long: variable que almacena (con 4 bytes) un número entero largo entre entre y
, esto es, un entero largo sin signo. (Por ejemplo, unsigned long milisegundos =
100000000;).
 float: variable que almacena (con 4 bytes) un número decimal entre y
. (Por ejemplo, float voltage = 4.5;).
 char: variable que almacena un carácter, como una letra o símbolo (1 byte). También se puede emplear
para un número entero entre a . (Por ejemplo, char letra = 'a';)
 const: tipo que especifica que el valor de la “variable” definida se mantendrá constante, y no podrá
cambiar durante todo el programa. (Por ejemplo, const float pi = 3.1416;). Otra forma de
definir una constante es mediante la instrucción #define pi 3.1416 (sin punto y coma al final).

Como en todo lenguaje de programación, las variables declaradas en Arduino pueden tener dos ámbitos
posibles: (1) Si la variable se declara al principio del programa, esa variable tiene un ámbito global y puede
usarse en cualquier parte del programa. (2) Si la variable se declara en cualquier otro lado (dentro de una
función, de un bucle, etc.), esa variable tiene un ámbito local, y sólo podrá usarse en esa parte del
programa. Las variables locales no existen fuera de la región donde se declaran.

A la hora de declarar una variable, se recomienda utilizar un nombre que nos ayude a recordar qué dato
está almacenando. Si necesitamos utilizar dos o más palabras para nombrar una variable, lo habitual es
emplear la notación “camelCase”, que consiste en escribir con mayúscula la primera letra de cada palabra
del nombre, excepto la primera. Algunos ejemplos son ledPin, estadoAnterior, lecturaSensorLuz,
etc.

SEGUNDA PARTE: CONFIGURACIÓN INICIAL DE ARDUINO.

Este bloque sólo se ejecuta una vez al principio del programa, y es donde se especifica la configuración
inicial de Arduino, a saber:

1) Qué pines de Arduino actuarán como entradas y como salidas:

pinMode(2,OUTPUT); //El pin 2 se usará como salida digital.


pinMode(3,OUTPUT); //El pin 3 se usará como salida digital o analógica.
pinMode(8,INPUT); //El pin 8 se usará como entrada digital.

Los pines de entrada analógicos (A0, A1, A2, A3, A4, A5) no se definen en el setup(), puesto que solo
pueden actuar como entradas analógicas.

54
2) Si vamos a establecer una conexión serie con el ordenador (a través del puerto USB):

Serial.begin(9600); /* Esta instrucción requiere los bits por segundo


con los que se establecerá la conexión serie entre
Arduino y el ordenador (9600 bps en este caso). */

3) Si vamos a utilizar números aleatorios:

randomSeed() //Esta instrucción inicia la generación de números aleatorios.

TERCERA PARTE: BUCLE DE CONTROL.

Esta parte aloja el código que Arduino estará ejecutando ininterrumpidamente. Este bloque debe incluir
todas las instrucciones, órdenes, comandos, y funciones que sean necesarias para que el sistema de control
funcione como necesitamos. A lo largo de las sucesivas prácticas iremos viendo cuáles son estas
instrucciones y funciones.

Con esto ya disponemos del marco teórico esencial para empezar a trabajar con Arduino. Pongámonos
manos a la obra.

2.6. PRÁCTICAS CON ARDUINO (1): SALIDAS DIGITALES.

Para ordenarle a Arduino que ponga un “0” lógico (nivel “LOW” o ) o un “1” lógico (nivel “HIGH” o ) en
una de sus salidas digitales (pines del 0 al 13), usamos los siguientes comandos:

digitalWrite(4, LOW); // Pone 0 V en el pin 4.


digitalWrite(4, HIGH); // Pone 5 V en el pin 4.

Para que Arduino haga una pausa en la ejecución del programa antes de seguir con la siguiente instrucción,
utilizamos la siguiente función:

delay(200); // Hace una pausa de 200 milisegundos.

PRÁCTICA 1: PARPADEO DE UN LED.

Vamos a montar un sistema automático que mantenga un LED encendiéndose y apagándose indefinidamente.
Para ello, conectamos un LED (y su resistencia de protección correspondiente) a un pin digital que
configuraremos como salida, y escribiremos el programa que lo encenderá y apagará a intervalos de 1
segundo.

Figura 2.22. Montaje del proyecto del LED parpadeante (pin 7).

55
La figura 2.22 muestra el montaje en TinkerCAD del sistema de control, con el circuito montado en una
miniplaca de pruebas. En este caso, hemos optado por usar como salida digital el pin número 7. Para
empezar, usamos un cable para conectar el pin digital a la patilla de entrada de la resistencia de protección
de . Después conectamos directamente la patilla de salida de la resistencia al ánodo del LED.
Finalmente, usamos otro cable para conectar el cátodo del LED al pin digital “GND”. De esta forma, cuando
el programa de control ponga la salida digital a , el LED estará polarizado en directa y se encenderá. Y
cuando el programa ponga la salida digital a , el LED no estará alimentado y no se encenderá.

El programa de control es muy sencillo:

void setup(){
pinMode(7, OUTPUT); // Define el pin digital 7 como salida.
}

void loop(){
digitalWrite(7, HIGH); // Pone 5 V en la salida digital 7.
delay(1000); // Espera 1000 milisegundos(ms) = 1 segundo.
digitalWrite(7, LOW); // Pone 0 V en la salida digital 7.
delay(1000); // Espera 1000 milisegundos(ms) = 1 segundo.
}

Notar que este programa no incluye la parte de declaración de variables globales, porque aquí no son
estrictamente necesarias. Sin embargo, es muy cómodo utilizar variables para luego modificar rápidamente
los parámetros del programa, como el tiempo de espera (variable t) o el pin al que se conecta el LED
(variable pinLed):

int t = 1000; // La variable 't' almacena el tiempo de espera.


int pinLed = 7; /* La variable 'pinLed' almacena el pin al que conectamos
el LED. /*
void setup(){
pinMode(pinLed, OUTPUT); // Define el pin digital 'pinLed' como salida.
}

void loop(){
digitalWrite(pinLed, HIGH); // Pone 5 V en la salida digital 'pinLed'.
delay(t); // Espera 't' milisegundos(ms).
digitalWrite(pinLed, LOW); // Pone 0 V en la salida digital 'pinLed'.
delay(t); // Espera 't' milisegundos(ms).
}

Si lanzamos la simulación en TinkerCAD, veremos que el LED se enciende y se apaga ininterrumpidamente


tras cada segundo.

EJERCICIO 2. Cambiar el tiempo de parpadeo. A modo de ejercicio, trata de cambiar el programa para
que el LED parpadee más rápido (cada medio segundo) y más lento (cada segundo y medio).

El pin digital 13 es especial, ya que integra una resistencia de protección para los LEDs que le conectemos.
Si usamos el pin digital 13 como salida, el LED no necesita una resistencia de protección, y puede
conectarse directamente. (Esto solo es cierto para el pin número 13. El resto de pines no integran una
resistencia de protección, y tenemos que añadirla al circuito). Y lo que es más, la placa Arduino incluye un
pequeño LED interconectado con el pin digital número 13, por lo que ni siquiera sería necesario montar el
LED. Este LED integrado se localiza justo bajo los pines digitales 13 y GND, y está etiquetado con una “L”.

En caso de utilizar el pin 13, el programa de control sería calcado al anterior (tan solo habría que cambiar
el valor de la variable pinLed de 7 a 13). En el caso de usar el LED integrado, el montaje ni siquiera
necesitaría conectar un LED externo al pin 13, y constaría únicamente de la propia tarjeta Arduino.

56
PRÁCTICA 2: SEMÁFORO.

En la siguiente práctica vamos a diseñar un semáforo. Para ello, utilizamos tres LEDs (rojo, amarillo, y
verde), que se van encendiendo secuencialmente: Primero se enciende el LED rojo durante 4 segundos. A
continuación se apaga y se enciendo el LED amarillo durante 1,5 segundos. Después se apaga y se enciende
el LED verde durante 3 segundos, para apagarse finalmente y repetir de nuevo el ciclo. El montaje es el
siguiente:

Figura 2.23. Montaje del proyecto del semáforo.

El programa de control es muy parecido al del LED parpadeante:

int ledRojo = 7;
int ledAmarillo = 8;
int ledVerde = 9;

void setup(){
pinMode(ledRojo, OUTPUT);
pinMode(ledAmarillo, OUTPUT);
pinMode(ledVerde, OUTPUT);
}

void loop(){

digitalWrite(ledRojo, HIGH);
delay(4000);
digitalWrite(ledRojo, LOW);
digitalWrite(ledAmarillo, HIGH);
delay(1500);
digitalWrite(ledAmarillo, LOW);
digitalWrite(ledVerde, HIGH);
delay(3000);
digitalWrite(ledVerde, LOW);
}

Montamos el sistema de control en TinkerCAD, escribimos el código, y comprobamos que el diseño funciona
como se esperaba.

EJERCICIO 3. Luz que avanza a través de 5 LEDs. Crea un sistema de control en el que una luz avance a
través de 5 LEDs. Para ello, monta un circuito con cinco LEDs y sus resistencias de protección
correspondientes. El programa de control empezará encendiendo el primer LED durante medio segundo.
Nada más apagarse el primer LED, se enciende el segundo LED durante otro medio segundo, y así

57
sucesivamente, hasta llegar al quinto LED. Cuando el quinto LED se apaga, el ciclo se repite y vuelve a
encenderse el primero.

ESTRUCTURAS CONDICIONALES.

Las estructuras condicionales se utilizan para hacer que se ejecuten unas ciertas instrucciones en el caso
de cumplirse una cierta condición. Esa condición debe ser una expresión booleana, esto es, una expresión
que, una vez evaluada, solo pueda arrojar dos resultados posibles: Verdadero (1, True, Sí, etc.) o falso (0,
False, No, etc.). Por ejemplo:

a == 3 // ¿Es la variable 'a' igual a 3?


b > 10 // ¿Es la variable 'b' mayor que 10?
c < 25 // ¿Es la variable 'c' menor que 25?
d >= -7 // ¿Es la variable 'd' mayor o igual que -7?
e <= 206 // ¿Es la variable 'e' menor o igual que 206?
f != 0 // ¿Es la variable 'f' distinta de 0?

CUIDADO: No confundir el operador de asignación = que usamos a la hora de declarar e inicializar


variables con el operador de comparación de igualdad == que usamos en las expresiones booleanas.

Algunos ejemplos de estructuras condicionales son los siguientes:

if (x < 10) {

/* Las instrucciones entre las llaves se ejecutarán únicamente si el valor de


la variable x es menor de 10. */

if (digitalRead(2)) {

/* Las instrucciones entre las llaves se ejecutarán únicamente si la lectura


del pin digital 2 es un nivel alto o 5 V (lo que equivale a un 1 lógico). */

Hay otra variante de la estructura condicional que, además de especificar qué instrucciones deben
ejecutarse si se cumple una condición, también nos permite indicar qué instrucciones deben ejecutarse si
no se cumple esa misma condición:

if(x < 10) {


/* Este bloque de código se ejecuta si la variable x es menor de 10. */
}
else {
/* Este otro bloque de código se ejecuta en caso contrario (esto es, cuando x
sea mayor o igual que 10 */
}

Con la estructura if - else Arduino puede tomar dos comportamientos distintos. Si necesitamos que
existan más opciones, debemos añadir nuevas condiciones de la siguiente manera:

if(x < 10) {


/* Este bloque de código se ejecuta si el valor de la variable x es menor de
10. */
}

58
else if(x < 20) {
/* Este bloque de código se ejecuta si el valor de x es mayor e igual que 10 y
menor que 20. */
}
else if(x < 30) {
/* Este bloque de código se ejecuta si el valor de x es mayor o igual que 20 y
menor que 30. */
}
else {
/* Este bloque de código se ejecuta si no se ha cumplido ninguna de las
condiciones previas (esto es, cuando x sea mayor o igual que 30). */
}

En ocasiones, las expresiones booleanas que necesitaremos usar en las estructuras condicionales son más
complejas. Por ejemplo, a veces necesitaremos que se cumplan dos condiciones simultáneamente, otras
veces querremos que se cumpla una de dos condiciones posibles, o incluso que no se cumpla una condición.
Para ello están los operadores lógicos &&, ||, y !.

&& /* Este operador sirve para indicar que queremos que se cumplan más de una
condición o expresión booleana simultáneamente. Equivale al operador lógico
AND. */

|| /* Este operador sirve para indicar que queremos que se cumpla al menos una
de entre varias condiciones o expresiones booleanas (el símbolo | se escribe
presionando simultáneamente las teclas ALT GR 1). Equivale al operador lógico
OR. */

! /* Este operador sirve para indicar QUE lo que queremos es que no se cumpla
una condición (esto es, que se cumpla lo contrario a esa condición). Equivale
al operador lógico NOT. */

Algunos ejemplos:

if (x > 3 && x < 7) {


// Este bloque de código se ejecuta si x está comprendido entre 3 y 7.
}

if (x < 2 || x > 5) {
// Este bloque de código se ejecuta si x es menor de 2 o mayor de 5.
}

if (!digitalRead(2)) {
/* Este bloque de código se ejecuta si la lectura digital no es 1 (esto es, si
es 0). */
}

PRÁCTICA 3: PARPADEO ACELERADO.

En este ejemplo de uso de la estructura if vamos a hacer que un LED parpadeante se encienda y se apague
cada vez más rápido. El montaje es el mismo que el del parpedeo de un LED (ver figura 2.22).

A continuación tenemos el programa de control. Prestar especial atención al papel que desempeña la
estructura condicional:

int t = 1000; //tiempo de las pausas.


int pinLed = 7;

59
void setup(){
pinMode(pinLed, OUTPUT);
}

void loop(){
digitalWrite(pinLed, HIGH);
delay(t);
digitalWrite(pinLed, LOW);
delay(t);
t = t - 50; // Después de cada ciclo, recortamos 50 ms el tiempo.
if(t < 1) { // Si el tiempo de la pausa se hace menor que 1 ms…
t = 1000; // … reiniciamos t a 1000 ms y …
delay(2000); // … hacemos una pausa de 2 s.
}
}

Notar que cada vez que se repite el loop(), disminuimos el tiempo de espera en . Este tipo de
decrementos lineales no siempre son los más adecuados. Cambia el programa y prueba un decremento del
tipo t = t / 1.1 (esto es, a cada iteración, divide el tiempo de espera entre 1,1).

BUCLES FOR.

Si hemos completado el ejercicio 3, nos daremos cuenta de que el código es muy repetitivo. Los bucles for
nos permiten repetir la ejecución de un cierto conjunto de instrucciones un número determinado de veces.
Este tipo de bucles se controlan mediante una variable (a la que por costumbre suele denominarse i), a la
que debe darse un valor inicial, una condición para finalizar el bucle, y una expresión que actualice su valor
tras cada repetición (iteración). Un ejemplo de bucle for es el siguiente:

for (int i=4; i<10; i=i+1) {


// Bloque de código dentro del bucle.
}

En primer lugar, notar que debemos inicializar la variable i del bucle (y también declararla si no es una
variable global ya definida al principio del programa). Como la variable i se ha declarado dentro del bucle,
se trata de una variable local que no tendrá validez fuera de él.

¿Cómo funciona el bucle? La variable i comienza tomando un valor de 4, y a continuación, se ejecutan las
instrucciones contenidas dentro de las llaves del bucle. Después, el valor de i se actualiza según la
expresión i=i+1 (esto es, su valor actual se incrementa en una unidad), y las instrucciones dentro del
bucle vuelven a ejecutarse. Mientras i sea menor que 10, el bucle continuará repitiendo la ejecución de las
instrucciones dentro del bucle. En este ejemplo, el bucle se repetirá 6 veces, con i tomando los valores 4,
5, 6, 7, 8, y 9 (esto es, el bucle pasa por 6 iteraciones, cada vez con un valor de i diferente). Además, y si
así lo necesitamos, podemos utilizar el valor de la variable i en las instrucciones dentro del bucle.

PRÁCTICA 4: LUZ QUE AVANZA A TRAVÉS DE 5 LEDS (CON BUCLES).

En este ejemplo vamos a resolver el ejercicio 3 de forma más eficiente, utilizando un bucle for. Para ello,
vamos a conectar cinco LEDs (y sus resistencias protección correspondientes) a los pines digitales 1, 2, 3,
4, y 5. La figura 2.24 muestra el montaje necesario.

El programa de control consta básicamente de un bucle for. Notar que inicializamos la variable i de
control del bucle a 1, el bucle se estará repitiendo hasta que i sea menor o igual que 5, y a cada repetición
del bucle, la variable i se actualiza incrementando su valor en una unidad. Nada más entrar en el bucle, i
toma el valor 1. La primera instrucción del bucle (digitalWrite(i,HIGH);) pone el pin digital 1 a nivel
alto ( ) para encender el primer LED. La segunda instrucción (digitalWrite(i-1,LOW);) no tiene
60
efecto, porque pone el pin digital 0 (que no estamos usando) a nivel bajo ( ). Tras una espera de 1
segundo, el bucle for se repite con la variable con la variable i tomando un valor de 2. La primera
instrucción pone en el pin 2 para encender el segundo LED, la segunda pone en el pin 1 para apagar el
primer LED, y la tercera hace otra pausa de 1 segundo. El bucle continúa repitiéndose hasta que i se hace
igual a 5; la primera instrucción enciende el LED 5, la segunda apaga el LED 4, y la tercera fuerza una pausa
de 1 segundo. Como ya no se cumple la condición i<=5, el programa sale del bucle for y se ejecuta la
instrucción digitalWrite(5,LOW); que pone en el pin 5 para apagar el último LED. Con esto
llegamos all final del loop(), y el programa salta de nuevo al for para volver a ejecutarlo desde el
principio (esto es, con i tomando el valor 1).

void setup() {
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
}

void loop() {

for(int i=1; i<=5; i=i+1){


digitalWrite(i,HIGH); // Encendemos el LED actual (pin i).
digitalWrite(i-1,LOW); // Apagamos el LED anterior (pin i-1).
delay(1000);
}

digitalWrite(5,LOW); /* Al salir del bucle for apagamos el último LED


porque i-1 nunca se hace igual a 6. */
}

Figura 2.24. Luz que avanza a través de 5 LEDs (con bucles).

PRÁCTICA 5: EL COCHE FANTÁSTICO.

Vamos a montar un sistema de control que implemente la luz del coche fantástico, una famosa serie de TV
de los años 80. Para ello, utiliza 5 LEDs que se vayan encendiendo progresivamente uno tras otro, como en
el ejercicio 3. Pero en este caso, al encenderse el último LED cambiamos el sentido y los encendemos
progresivamente en orden inverso, esto es, del último al primero. Al llegar al primero, el ciclo se repite.

61
El montaje es el mismo que en el ejercicio previo. El programa de control lo tenemos más abajo. Notar que
usamos dos bucles, uno para ir encendiendo y apagando los LEDs desde el 2 al 6, y otro para ir apagando y
encendiendo los LEDs desde el 6 al 3. (No llegamos a encender el 2 porque de ello ya se encargará el primer
bucle cuando el loop vuelva a repetirse).

Notar también que en el setup() hemos utilizado otro bucle for para definir los pines digitales 1, 2, 3, 4,
y 5 como salidas.

void setup() {
for(int k=1; k<=5; k=k+1){
pinMode(k,OUTPUT);
}
}

void loop() {

for(int i=1; i<=5; i=i+1){


digitalWrite(i,HIGH); // Encendemos el LED i.
digitalWrite(i-1,LOW); // Apagamos el LED anterior (i-1).
delay(250);
}

for(int i=5; i>2; i=i-1){


digitalWrite(i,LOW); // Apagamos el LED i.
digitalWrite(i-1,HIGH); // Encendemos el LED anterior (i-1).
delay(250);
}

digitalWrite(2,LOW); */ Apagamos manualmente el segundo LED, porque en


el 2º bucle la variable i nunca toma el valor 2. */
}

2.7. PRÁCTICAS CON ARDUINO (2): ENTRADAS DIGITALES.

Para indicarle a Arduino que lea el valor digital (HIGH o LOW) que haya en una cierta entrada digital (del 0
al 13), utilizamos la siguiente función:

val = digitalRead(6);

(Notar que la variable val no está declarada, por lo que deberemos haberla declarado al principio del
programa de control. Además, debemos recordar de configurar el pin 6 como entrada en el setup()
mediante la instrucción pinMode(6, INPUT);).

La función val = digitalRead(6) asigna a la variable val el valor leído del pin digital 6. Si en el pin 6
hay menos de Arduino lo interpretará como una lectura de un valor LOW, y si hay más de lo
interpretará como un valor HIGH. La variable val puede ser utilizada posteriormente en el código del
programa. Si val se utiliza como un número, podrá ser 0 (si el valor leído fue LOW) o 1 (si fue HIGH); si
se utiliza como una expresión booleana, podrá ser False (si el valor leído fue LOW) o True (si fue HIGH).

EL PULSADOR COMO SENSOR DIGITAL.

Todo sensor que únicamente reporte dos valores posibles constituye un sensor digital. El ejemplo más
evidente es el pulsador. Para poder conectar un pulsador a una entrada digital debemos añadir una
resistencia de drenaje (típicamente de ) que absorba las fluctuaciones de tensión que se producen al
pulsar y soltar el pulsador. (De otra forma, no podríamos distinguir los valores LOW y HIGH).

62
Para conectar la resistencia de drenaje, tenemos dos alternativas: El montaje pull-down y el montaje pull-
up.

Figura 2.25. Montajes pull-down y pull-up.

Suponer que conectamos el pulsador al pin digital 4. En el montaje pull-down, al pulsar el pulsador entran
directamente al pin 4, y la instrucción digitalRead(4)leerá un valor “HIGH”. En el montaje pull-up,
al pulsar el pulsador la corriente va directamente hacia tierra ( ) y al pin 4 entran , por lo que la
instrucción digitalRead(4)leerá un valor “LOW”. Notar que ambos montajes funcionan de forma
opuesta. Elegiremos un montaje u otro dependiendo del comportamiento que necesitemos en nuestro
circuito.

PRÁCTICA 6: ACTIVAR EL PARPADEO DE UN LED CON UN PULSADOR.

En los ejemplos trabajados hasta ahora hemos visto cómo programar Arduino para que ejecute
repetitivamente ciertas acciones. Sin embargo, en estos ejemplos Arduino trabajaba de forma
completamente autónoma, sin ninguna interacción con el exterior. En este ejemplo vamos a montar un
sistema en el que un LED comience a parpadear al pulsar un pulsador. El montaje es el siguiente:

Figura 2.26. Parpadeo de un LED activado con pulsador.

Aquí estamos usando el pin digital 4 como entrada, y el pin digital 7 como salida (hecho que deberemos
reflejar en el setup() del programa de control). Notar que en este montaje distinguimos dos partes: (1)
El circuito del LED y su resistencia de protección (a la derecha de la protoboard), y (2) el circuito pull-
down del pulsador y la resistencia de (a la izquierda de la protoboard).

63
Observar que el circuito del LED lo conectamos a los pines digitales 7 (salida) y GND. Como siempre, al
poner un valor “HIGH” en el pin 7, el diodo estará polarizado en directa y se encenderá. Y al poner un valor
“LOW” en el pin 7, el diodo no estará alimentado y se apagará. Sin embargo, el circuito pull-down no puede
alimentarse de esta forma, ya que necesita estar conectado de forma permanente a un voltaje de . Para
alimentar este circuito utilizamos los pines de alimentación “5 V” y “GND”.

El programa de control es sencillo:

void setup(){
pinMode(4, INPUT);
pinMode(7, OUTPUT);
}

void loop(){
if (digitalRead(4)) {
digitalWrite(7, HIGH);
delay(500);
digitalWrite(7, LOW);
delay(500);
}
}

Notar que si presionamos el pulsador, el pin 4 recibirá un nivel alto. La estructura condicional comprueba si
al leer el pin digital 4 obtenemos un nivel HIGH (esto es, comprueba si estamos pulsando el pulsador). En
ese caso, ponemos un nivel alto en el pin 7 para activar el LED, esperamos medio segundo, ponemos un nivel
bajo para apagar el LED, esperamos medio segundo, y este ciclo se repite mientras continuemos pulsando el
pulsador.

Este programa nos obliga a mantener el pulsador presionado para que el LED parpadee. Una alternativa es
programar el sistema para que al pulsar el pulsador se desencadene una secuencia de, digamos, 5
parpadeos. Para ello, debemos cambiar el programa de control para que incluya un bucle for:

void setup(){
pinMode(4, INPUT);
pinMode(7, OUTPUT);
}

void loop(){
if (digitalRead(4)) {
for (int i=1; i<=5; i=i+1) {
digitalWrite(7, HIGH);
delay(500);
digitalWrite(7, LOW);
delay(500);
}
}
}

EJERCICIO 4. Apaga un LED, enciende otro. Crea un sistema en el que haya un LED rojo encendido. Al
pulsar un pulsador, se apaga el LED rojo y se enciende un LED azul durante 5 segundos. Transcurrido ese
tiempo, se apaga el LED azul y vuelve a encenderse el LED rojo.

EJERCICIO 5. Disparando ráfagas. Diseña un sistema en el que, cada vez que se pulse un pulsador, se
desplace una luz a través de 5 LEDs.

64
PRÁCTICA 7: CONTAR HASTA TRES.

En este ejemplo vamos a construir un sistema con tres LEDs y un pulsador, en el que cada vez que
activemos el pulsador, se enciende un LED adicional. El sistema comienza con los tres LEDs apagados. Al
apretar el pulsador la primera vez, solo se enciende el primer LED. Al pulsarlo por segunda vez, se
encienden los dos primeros LEDs. Y al pulsarlo por tercera vez, se encienden los tres LEDs. Si volvemos a
pulsar, se apagan todos los LEDs, y el sistema queda en su estado inicial, a la espera de que volvamos a
pulsar para encender los LEDs.

La figura 2.27 muestra el montaje necesario. Como en el ejemplo previo, para conectar el pulsador al pin 4
utilizamos un circuito pull – down. La conexión de los tres LEDs a las entradas digitales es la habitual.

Figura 2.27. Activación secuencial de tres LEDs con un pulsador.

El programa de control es el siguiente:

int p = 0; // Variable para contar las pulsaciones.

void setup(){
pinMode(4, INPUT);
// Bucle para definir los pines 8, 9, y 10 como salidas.
for (int i=8; i<=10; i=i+1){
pinMode(i, OUTPUT);
}
}

void loop(){
if (digitalRead(4)) {
p = p + 1;
}
if (p == 1){
digitalWrite(8, HIGH);
}
if (p == 2){
digitalWrite(9, HIGH);
}
if (p == 3){
digitalWrite(10, HIGH);
}

65
if (p == 4){
for (int i=8; i<=10; i=i+1){
digitalWrite(i, LOW);
}
p = 0;
}
delay(200);
}

El programa comienza declarando una variable global p donde almacenaremos el número de pulsaciones. En
este caso, vamos a usar el pin digital 4 como entrada, y los pines 8, 9, y 10 como salidas. Para definir tres
pines como salidas, podemos usar un bucle for que repita esta acción tres veces, una por cada pin de
salida. El bucle principal comienza determinando si el usuario ha activado el pulsador, y en su caso,
incrementa en una unidad el valor de p. A continuación, comprobamos el valor actual de p para determinar
cuántas veces se ha presionado el pulsador, y actuar en consecuencia. Notar que cuando el usuario ha
pulsado 4 veces el pulsador, debemos apagar los tres LEDs, y reiniciar el valor de p a 0. Finalmente,
introducimos un pequeño retardo para separar las pulsaciones.

EJERCICIO 6. Encendido secuencial. Diseña un sistema con un pulsador y tres LEDs. Cada vez que se
active el pulsador, se encenderá el siguiente LED y se apagará el anterior. El sistema empieza con los tres
LEDs apagados. Al pulsar por primera vez, solo se enciende el primer LED; si pulsamos por segunda vez, se
apaga el primer LED y solo se enciende en segundo; y si pulsamos por tercera vez, se apaga el segundo LED
y solo se enciende el tercero. Una nueva pulsación deja el sistema en el estado inicial, preparado para
volver a encender los LEDs de forma secuencial.

2.8. PRÁCTICAS CON ARDUINO (3): SALIDAS ANALÓGICAS.

Para indicarle a Arduino que coloque en un cierto pin un determinado valor de tensión entre y
(pudiendo seleccionar entre 256 valores intermedios posibles, de 0 a 255), empleamos la siguiente orden:

analogWrite(11,214); /* Coloca en el pin 11 un valor de salida de


214, que equivale a unos 4,2 V. */

Figura 2.28. Señales digitales PWM que simulan salidas analógicas.

66
Recordemos las salidas analógicas son realmente salidas digitales PWM que simulan salidas analógicas. Las
salidas PWM (Pulse Width Modulation Modulación por Anchura de Pulso) proporcionan señales cuadradas
donde la duración del nivel ( ) alto de cada pulso puede tomar 256 valores posibles. De esta forma, el
valor promedio de la señal digital de salida se asemeja al de la señal analógica que se persigue imitar (ver
figura 2.28). Notar que, con 256 valores posibles entre y , cada valor equivale a un incremento de
voltaje de ⁄ . Por ejemplo, el valor 214 equivale a ( ⁄ ) .

PRÁCTICA 8: ENCENDIDO Y APAGADO GRADUAL DE UN LED.

Para ilustrar el uso de las salidas analógicas, vamos a montar un sistema en el que un LED se enciende y se
apaga de forma gradual: El LED comienza apagado, y va encendiéndose ganando intensidad. Cuando alcanza
su nivel de luminosidad máximo, el brillo comienza a disminuir hasta apagarse, y así sucesivamente.

El montaje es muy sencillo, y solo debemos tener la precaución de usar una de las salidas digitales PWM. En
este caso, hemos usado la salida 10 (ver figura 2.33).

Figura 2.29. Encendido y apagado gradual de un LED.

A continuación mostramos el programa de control. Para empezar, definimos las variables brillo (que
almacenará el valor de voltaje que escribiremos en la salida analógica) e incremento (con la cual
podremos actualizar el valor de la variable brillo a cada repetición del bucle loop()). A continuación,
definimos el pin digital 10 como salida. Notar que en esta definición, no hace falta indicar que este pin va a
usarse realmente como una salida analógica simulada.

En el bucle principal, usamos la instrucción analogWrite(10, brillo) para poner en el pin 10 el valor
de voltaje indicado por la variable brillo. A continuación, variamos el valor de brillo en 5 unidades (el
valor de la variable incremento), y comprobamos si esta variación nos ha hecho llegar al valor máximo o
mínimo de voltaje (255 o 0, respectivamente). En tal caso, cambiamos el signo de la variable incremento.
Por ejemplo, si estamos aumentando el brillo del LED (incremento = 5) y llegamos al valor máximo de
voltaje (255), cambiamos el valor de incremento a para que el brillo empiece a disminuir Pero si estamos
reduciendo el brillo del LED (incremento = -5) y llegamos al valor mínimo de voltaje (0), cambiamos el
valor de incremento a ( ) para que el brillo comience a aumentar.

int brillo = 0;
int incremento = 5;

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

67
void loop() {
analogWrite(10, brillo);
brillo = brillo + incremento;
if(brillo == 0 || brillo == 255) {
incremento = -incremento;
}
delay(50);
}

2.9. PRÁCTICAS CON ARDUINO (4): COMUNICACIÓN CON EL PC.

En ocasiones es muy útil visualizar en el ordenador los valores presentes en los pines de entrada y de salida
de Arduino. Otras veces es necesario enviar información a Arduino desde el teclado del ordenador. En esta
sección veremos cómo poner en comunicación la placa Arduino con un ordenador. Los pasos a seguir son los
siguientes:

1) Establecimiento de la conexión.

En primer lugar indicamos en el setup() que vamos a establecer una comunicación serie entre Arduino
y el ordenador. Para ello disponemos de la instrucción Serial.begin(). Esta instrucción necesita que
configuremos los baudios (bits por segundo) con los que se establecerá la conexión serie entre Arduino y
el PC. Por defecto trabajaremos a 9600 baudios.

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

2) Transferencia de datos.

Tras establecer las conexión, y dentro del loop(), utilizamos las distintas funciones que nos permiten
enviar y recibir datos hacia y desde el ordenador:

void loop() {

/* Funciones para enviar datos de Arduino al ordenador. */

Serial.print(val); // Imprime en pantalla el valor de la variable val.

Serial.println(val); /* Imprime en pantalla el valor de val e inserta un


cambio de línea. */

Serial.print("hola amigos");// Imprime en pantalla el texto "hola, amigos".

/* Funciones para enviar datos del ordenador a Arduino.


Los datos a enviar del ordenador a Arduino se insertan con el teclado en el
monitor en serie del IDE Arduino o del simulador TinkerCAD. */

val = Serial.read(); /* Lee los datos almacenados en el buffer de


recepción del puerto serie.

Serial.flush(); /* Vacía el buffer de recepción del puerto serie


para poder recibir y almacenar nuevos datos. */
}

Cuando Arduino establece una comunicación serie con el PC necesita utilizar los pines digitales 0 y 1 (RX y
TX) para recibir y transmitir datos, por lo tanto no debemos utilizarlos como entradas o salidas de nuestro
circuito. Asociados a estos pines, la placa Arduino incorpora dos LEDs que se iluminan cuando hay recepción

68
(RX) y transmisión (TX) de datos entre Arduino y el PC. El LED RX se ilumina cuando Arduino recibe datos
desde el PC, y el LED TX se ilumina cuando Arduino envía datos al PC.

Figura 2.30. Pines y LEDs para la comunicación serie entre Arduino y el ordenador.

Para visualizar en la pantalla del ordenador los datos que Arduino ordena imprimir, o para poder mandarle
datos a Arduino a través del teclado del ordenador, debemos usar la ventana del monitor en serie del IDE
Arduino o del simulador TinkerCAD.

PRÁCTICA 9: MONITORIZAR EL ESTADO DE UN PULSADOR.

Vamos a montar un sistema que nos permita ver en la ventana del monitor serie si un pulsador está activado
(ON) o desactivado (OFF). La figura muestra el montaje necesario (un simple circuito pull - down).

Figura 2.31. Montaje para monitorizar el estado de un pulsador.

El programa de control es el siguiente:

int val; // Variable para almacenar el valor leído en el pin 4.

void setup() {
pinMode(4, INPUT); // Configura el pin digital 4 como entrada.
Serial.begin(9600); // Establece comunicación con el puerto serie.
}

69
void loop() {
val = digitalRead(4); // Guarda en val el valor leído del pin digital 4.
Serial.print("La lectura es = ");
Serial.print(val);
Serial.print('\t'); // Escribe una tabulación.
if(val)
// Si val == True el pulsador está activado.
Serial.println("El estado del pulsador es ON");
else
// En caso contrario (val == false) el pulsador está desactivado.
Serial.println("El estado del pulsador es OFF");
delay(200);
}

Notar que si el bloque de código del if (y de else) solo incluye una instrucción, podemos prescindir de las
llaves. Si ejecutamos el programa y abrimos el monitor serie, veremos la salida del programa en la ventana
del ordenador. La figura 2.32 muestra la salida del monitor serie del simulador TinkerCAD para este
programa de control.

Figura 2.32. Monitor serie para monitorizar el estado de un pulsador.

PRÁCTICA 10: CONTROL DE UN LED CON EL TECLADO.

En esta práctica vamos a escribir un programa de control para encender y apagar un LED con el teclado del
ordenador. Usaremos la tecla E para encender el LED, y la tecla A para apagarlo. La electrónica es la
siguiente:

Figura 2.33. Montaje para el control de un Led con el teclado.

70
El programa de control es sencillo:

int val;

void setup(){
pinMode(7, OUTPUT);
Serial.begin(9600);
}

void loop(){
val = Serial.read(); // Guarda en val el último carácter leído.
if(val == 'e') {
digitalWrite(7, HIGH); // Enciende el LED.
Serial.println("LED Encendido.");
}
if(val == 'a') {
digitalWrite(7, LOW); // Apaga el LED.
Serial.println("LED apagado.");
}
}

La figura 2.34 muestra el monitor serie de TinkerCAD. En la zona de entrada de texto del monitor
escribimos 'e' o 'a' (y pulsamos en ”Enviar”) para encender o apagar el LED con el teclado. Como vemos,
el programa también imprime por pantalla el estado actual del LED.

Figura 2.34. Monitor serie para el control de un LED con el teclado.

EJERCICIO 7. LEDs rojo y azul. Diseña un sistema con dos LEDs, uno rojo y otro azul. El sistema
funciona de la siguiente manera: Al pulsar la tecla R se enciende el LED rojo y se apaga el LED azul. Y al
pulsar la tecla B se enciende el LED azul y se apaga el LED rojo.

AMPLIACIÓN: Si te sobra tiempo, elige otras dos teclas (por ejemplo, las teclas de los dígitos 0 y 2) para
hacer que se apaguen ambos LEDs y se enciendan ambos LEDs.

2.10. PRÁCTICAS CON ARDUINO (5): ENTRADAS ANALÓGICAS.

Las entradas A0, A1, A2, A3, A4, y A5 son pines de entrada analógicos. Como estos pines solo pueden
actuar como entradas analógicas, no hace falta configurarlos en el setup().

La instrucción básica para leer el valor registrado por una entrada analógica es:

val = analogRead(A3); /* Guarda en la variable val el valor de la lectura


digital del pin A3, que podrá ser un número
cualquiera entre 0 y 1023 */

71
La lectura de una señal analógica de entrada podrá tomar cualquier valor comprendidos entre 0 y 1023, que
se corresponderá con uno de los 1024 valores posibles dentro del rango de a . Normalmente, a los
pines de entrada analógico conectaremos sensores analógicos, esto es, sensores que reporten múltiples
voltajes dentro de un rango de valores posibles. Estos sensores analógicos sueles ser dispositivos como
potenciómetros, LDRs (fotoresistencias), NTCs (termistores), sensores de sonido, sensores de ultrasonido,
etc.

SENSORES ANALÓGICOS (1): POTENCIÓMETRO.

Un potenciómetro es un resistor que proporciona una resistencia variable en función de la posición de su


palanca o cursor (wiper). Este dispositivo es muy empleado para controlar la cantidad de corriente que
circula hacia un receptor. Para conectar correctamente un potenciómetro a un circuito debemos unir la
patilla 1 al positivo, la patilla 3 al negativo (o viceversa), y la central (2) a la patilla de entrada del receptor
(LED, motor, bombilla, etc.) que queremos controlar. Conectar el potenciómetro adecuadamente es esencial
para evitar cortocircuitos.

Figura 2.35. Patillaje de un potenciómetro (símbolo eléctrico y modelo de TinkerCAD).

Podemos usar un potenciómetro como sensor analógico conectando la patilla 2 a una de las entradas
analógicas de Arduino (digamos, la A3), y funcionará de la siguiente manera: Si el potenciómetro se ajusta a
de resistencia (cursor totalmente girado en sentido antihorario), la entrada analógica A3 registrará un
valor de 1023 (analogRead(A3) ). Si el potenciómetro se ajusta exactamente a su valor
intermedio de resistencia (cursor en su posición media), la entrada analógica A3 registrará un valor de 512
(analogRead(A3) ). Y si el potenciómetro se ajusta a su valor máximo de resistencia (cursor
completamente girado en sentido horario), la entrada analógica A3 registrará un valor de 0
(analogRead(A3) ).

PRÁCTICA 11: CONTROL DE UN LED CON UN POTENCIÓMETRO.

Para mostrar el uso de un potenciómetro como sensor analógico, vamos a implementar un sistema en el que
controlaremos el nivel de luminosidad de un LED en función de la posición del cursor de un potenciómetro
de control. Además, el sistema permitirá visualizar en el monitor serie el valor registrado por la entrada
analógica a la que se conecta el potenciómetro.

Figura 2.36. Montaje para el control de un LED con un potenciómetro.


72
La figura muestra el montaje del sistema, donde observamos que hemos conectado el potenciómetro a la
entrada analógica A0, y el LED a la salida analógica 3. Notar que, como vamos a controlar su nivel de
luminosidad, el LED debe conectarse a una salida analógica, y no a una digital.

A continuación tenemos escrito el programa de control. Para empezar, definimos dos variables enteras,
val y brillo. En val almacenamos el valor leído en la entrada analógica A0, mientras que en brillo
guardaremos el nivel de luminosidad con el que encenderemos el LED a través de la salida analógica 3. En el
setup() definimos el pin 3 como salida, pero notar que no hemos definido el pin A0 como entrada, porque
no es necesario. Además, establecemos la conexión serie con el ordenador a . En el bucle principal
leemos y guardamos en val el valor proporcionado por el potenciómetro a través de la entrada analógica
A0 (que será un número entre 0 y 1023), e imprimimos ese valor en la ventana del monitor serie. Ahora, en
base al valor proporcionado por el potenciómetro a través de A0, vamos a ajustar el brillo del LED a través
de la salida analógica 3. Sin embargo, las entradas analógicas reciben un valor entre 0 y 1024, mientras que
las salidas digitales producen un valor entre 0 y 255. Para convertir el valor leído en la entrada A0 en un
valor que podamos escribir en la salida 3, debemos hacer una conversión de 1024 valores posibles a la
entrada a solo 256 valores posibles a la salida. Eso lo conseguimos dividiendo la variable val entre 4, y
guardando el resultado en la variable brillo (brillo = val / 4). Para terminar, imprimimos en el
monitor serie el valor de brillo, y colocamos ese valor en la salida analógica 3 para encender el LED ese
valor de luminosidad.

int val, brillo;

void setup() {
pinMode(3, OUTPUT); // Utilizamos la salida analógica 3.
Serial.begin(9600);
// No hay que configurar la entrada analógica A0.
}

void loop() {
val = analogRead(A0); // Registra el valor de la señal analógica A0.
Serial.print("Lectura entrada analogica = ");
Serial.print(val); // Imprime dicha lectura.
Serial.print('\t');
brillo = val / 4; // Escala los 1024 valores a 256 (dividiendo entre 4).
Serial.print("Valor del brillo del LED = ");
Serial.println(brillo); // Imprime el valor del brillo.
analogWrite(3, brillo); // Enciende el LED con una intensidad = brillo.
delay(200);
}

La figura muestra la salida del monitor serie de TinkerCAD para este programa.

Figura 2.37. Salida del monitor serie con el cursor girando en sentido horario.

73
Al girar el cursor en sentido horario la resistencia del potenciómetro aumenta, la señal leída por la entrada
analógica A0 disminuye de valor, y el nivel de brillo con el que encendemos el LED es cada vez menor. Y a la
inversa, al girar el cursor en sentido antihorario la resistencia del potenciómetro disminuye, la señal
registrada por la entrada analógica A0 aumenta de valor, y el nivel de brillo con el que encendemos el LED
es cada vez mayor.

EJERCICIO 8. Control de luminosidad opuesto. Diseña un sistema con dos LEDs de distinto color. En
este sistema tenemos un potenciómetro que controlará la luminosidad de ambos LEDs simultáneamente,
pero de forma opuesta: Conforme el nivel de luminosidad de un LED va aumentando, el nivel de luminosidad
del otro LED va disminuyendo, y viceversa.

SENSORES ANALÓGICOS (2): FOTORRESISTOR LDR.

Un fotorresistor o LDR (Resistor Dependiente de la Luz) es un resistor cuya resistencia depende de la


cantidad de luz que incida sobre él, por lo que funcionan como sensores de luz. Cuando la luz incide sobre el
LDR, el material del que está fabricado se vuelve más conductor, y su resistencia disminuye. Y al contrario,
cuanta menos luz incida sobre el LDR, mayor es su resistencia. Esto implica que un LDR puede permitir el
paso de una mayor o menor intensidad de corriente eléctrica dependiendo de la luz que reciba.

Figura 2.38. LDR, símbolo, y gráfica de resistencia VS. iluminación.

Para usar un LDR como sensor analógico debemos realizar un montaje como el mostrado en la figura 2.39,
en el que la una de las patillas del LDR se conecta al positivo, y la otra patilla se conecta a un pin de entrada
analógico y a una resistencia “pull - down” de conectada a tierra ( ) por el otro extremo.

Figura 2.39. Conexión de un LDR a la placa Arduino.

Una vez conectado, el LDR actúa de la siguiente manera: A plena luz el LDR presenta su resistencia más
baja, y el valor leído por la entrada analógica será alto (en torno a 1000). Conforme disminuye la luz
74
incidente el LDR ofrece más resistencia, y el valor registrado por la entrada analógica disminuye. Cuando
está a oscuras el LDR ofrece su resistencia máxima, y el valor captado por la entrada analógica será bajo
(alrededor de 50).

PRÁCTICA 12: SENSOR DE LUZ.

Para mostrar un ejemplo de uso del LDR vamos a montar un sensor de luz, en el que monitorizaremos las
señales leídas por la entrada analógica a través del monitor serie. El montaje es el siguiente:

Figura 2.40. Sensor de luz.

El programa lo tenemos a continuación:

int val;

void setup() {
Serial.begin(9600); // No hay que configurar la entrada analógica A2.
}

void loop() {
val = analogRead(A2); // Guarda en val la lectura de la entrada analógica A2.
Serial.print("Lectura entrada analogica = ");
Serial.println(val); // Imprime dicha lectura.
}

MAPEAR Y RESTRINGIR DATOS.

En el ejemplo de control de un LED con un potenciómetro nos vimos obligados a convertir los valores
registrados por el sensor (el potenciómetro), que estaban dentro del rango de 0 a 1024, a los valores que le
podríamos pasar al actuador (el LED), los cuales pertenecían a rango de 0 a 255. En este caso la conversión
era sencilla, puesto que bastaba con dividir entre cuatro, pero en otras ocasiones las conversiones podrían
no ser tan evidentes. Para solventar este problema Arduino ofrece la función map(), la cual permite
convertir un valor de entrada dentro de un cierto rango (por ejemplo, ) a un valor de salida
perteneciente a otro rango distinto (por ejemplo, ). La sintaxis es la siguiente:

valorSalida = map(valorEntrada, minEntrada, maxEntrada, minSalida, maxSalida);

75
Los cinco argumentos que necesita recibir esta función para funcionar son:

 valorEntrada: valor perteneciente al rango de entrada que queremos convertir al rango de salida.
 minEntrada: Valor mínimo del rango de entrada.
 maxEntrada: Valor máximo del rango de entrada.
 minSalida: Valor mínimo del rango de salida.
 maxSalida: Valor máximo del rango de salida.

El valor de retorno de esta función (valorSalida) es el valor de entrada convertido al rango de salida
una vez realizado el “mapeo” entre rangos.

Esta función es muy útil para tomar una lectura de un pin de entrada analógico y utilizarlo en un pin de
salida analógico. A modo de ejemplo, imaginar que tenemos un sensor de luz (LDR) conectado a una entrada
analógica que reporta valores dentro del rango – , y que con él queremos controlar el nivel de
iluminación de un LED conectado a una salida analógica que recibe valores dentro del rango – . Para
convertir el valor leído por el sensor (almacenado en la variable lecturaLDR) a un valor con el que
podamos iluminar de forma proporcional al LED (y que almacenaremos en la variable brilloLED) utilizamos
la siguiente instrucción:

brilloLED = map(lecturaLDR,0,600,100,300);

Para evitar salirnos de los rangos de operación habituales, Arduino incluye la función constrain():

valorSalida = constrain(valorEntrada, valorMínimo, valorMáximo);

Esta función obliga al valor de entrada a ceñirse al rango indicado por los valores valorMínimo y
valorMínimo: Si valorEntrada está dentro del rango especificado por valorMínimo y
valorMínimo, la función devuelve ese mismo valor de entrada (valorSalida = valorEntrada). Pero
si valorEntrada es mayor que valorMáximo o menor que valorMínimo, devuelve ese valor máximo o
mínimo, respectivamente (valorSalida = valorMáximo, ó valorSalida = valorMínimo).

brilloLED = constrain(brilloLED,100,300);

PRÁCTICA 13: LUZ NOCTURNA AUTOMÁTICA.

En esta práctica vamos a implementar un sistema que ilumine un LED con una intensidad que sea
inversamente proporcional al nivel de luminosidad ambiental captado por un LDR. (Esto es, el sistema hará
brillar el LED con más intensidad cuanto más oscuro esté). El montaje es el siguiente:

Figura 2.41. Luz nocturna automática.


76
Aquí tenemos escrita la primera versión del programa de control:

int lecturaLDR, brilloLED;

void setup() {
pinMode(9, OUTPUT);
Serial.begin(9600); // No hay que configurar el pin A5.
}
void loop() {
lecturaLDR = analogRead(A5); // Valor de lectura de la señal de entrada.
Serial.print("Lectura entrada analogica = ");
Serial.print(lecturaLDR); // Imprime esa lectura.
Serial.print('\t');
brilloLED = map(lecturaLDR, 0, 1023, 0, 255); // ESTE MAPEADO ES PROVISIONAL.
Serial.print("Valor del brillo del LED = ");
Serial.println(brilloLED); // Imprime el valor del brillo del LED.
analogWrite(9, brilloLED); // Enciende el LED con una intensidad = brilloLED.
}

En este programa comenzamos registrando la lectura detectada por el LDR a través de la entrada
analógica A5, guardando este valor en la variable lecturaLDR, e imprimiéndolo en la pantalla del monitor
serie. A continuación usamos la función map() para convertir el valor registrado por el LDR (para el que
suponemos un rango de valores posibles entre 0 y 1023) al rango de valores aceptados por la salida
analógica 9 a la que está conectada el LED (para la que sabemos que el rango de valores posibles se
extiende de 0 a 255), y guardamos el valor convertido en la variable brilloLED. Finalmente, imprimimos
por pantalla el valor de brilloLED, y se lo pasamos a la salida analógica 9 para que encienda el LED con un
nivel de brillo inversamente proporcional a la cantidad de luz detectada por el LDR.

En este programa, la instrucción brilloLED = map(lecturaLDR, 0, 1023, 0, 255) es provisional,


porque hemos asumido que el LDR reporta valores dentro del rango desde 0 hasta 1023, y no sabemos si el
sensor opera de esta forma. Por consiguiente, cuando lancemos la simulación por primera vez deberemos
observar el monitor para identificar los valores mínimo y máximo que reporta realmente este sensor. En mi
caso, observo que el sensor lee valores entre 54 y 954, por lo que cambio la instrucción de mapeo a
brilloLED = map(lecturaLDR, 54, 954, 0, 255). Además, compruebo que para valores altos de
lecturaLDR (esto es, con el LDR a plena luz) el LED brilla con más intensidad, lo que me obliga a cambiar
el orden de los valores mínimo y máximo para que el circuito funcione como debe, por lo que la instrucción
queda como brilloLED = map(lecturaLDR, 974, 54, 0, 255). Finalmente, usamos la función
brilloLED = constrain(brilloLED, 0, 255) para asegurar que el valor que toma la variable
brilloLED se restringe al rango . El programa queda como sigue:

int lecturaLDR, brilloLED;

void setup() {
pinMode(9, OUTPUT);
Serial.begin(9600); // No hay que configurar el pin A5.
}

void loop() {
lecturaLDR = analogRead(A5); // Valor de lectura de la señal de entrada.
Serial.print("Lectura entrada analogica = ");
Serial.print(lecturaLDR); // Imprime esa lectura.
Serial.print('\t');
brilloLED = map(lecturaLDR, 974, 54, 0, 255);
brilloLED = constrain(brilloLED, 0, 255);
Serial.print("Valor del brillo del LED = ");
Serial.println(brilloLED); // Imprime el valor del brillo del LED.
analogWrite(9, brilloLED); // Enciende el LED con una intensidad = brilloLED.
}
77
EJERCICIO 9. Parpadeo controlado por luz. Diseña un sistema con un LED y un sensor de luz LDR que
controle la velocidad de parpadeo del LED: Al aumentar el nivel de luminosidad, el parpadeo del LED se
acelera, y viceversa (al disminuir el nivel de luminosidad, el parpadeo del LED se ralentiza).

SENSORES ANALÓGICOS (3): INTEGRADO TMP36.

Aunque el sensor de temperatura más habitual es el resistor NTC (un resistor cuyo valor de resistencia
disminuye al aumentar la temperatura), un sensor de temperatura muy usado en Arduino es el integrado
TMP36. El TMP36 es un sensor de temperatura digital. A diferencia de los NTCs, en los que la lectura de la
temperatura se obtiene a partir de su resistencia eléctrica, el TMP36 es un integrado con su propio
circuito de control, que proporciona un voltaje de salida proporcional a la temperatura ambiental. La señal
captada por el TMP36 es lineal con la temperatura: Cuanto más elevada es la temperatura, mayor es el
valor de la señal registrada.

Figura 2.42. TMP36 y gráfica de voltaje de salida VS. temperatura.

El TMP36 es muy fácil de usar en los montajes Arduino. Como vemos, el integrado presenta tres patillas de
conexión: Con el lado plano del encapsulado mirando hacia nosotros la patilla de la izquierda ( ) se
conecta al positivo (típicamente ); la patilla de la derecha (GND) se conecta al negativo ( ); y la
patilla central ( ), que es la que ofrece el valor captado, se conecta a una entrada analógica.

PRÁCTICA 14: TERMÓMETRO DE LEDS.

Vamos a emplear el sensor TMP36 y tres LEDs para construir un termómetro: A medida que la temperatura
aumente, los LEDs se irán encendiendo progresivamente. La figura 2.43 muestra el montaje con TMP36.
Notar que en ambos montajes hemos usado laa entrada analógica A5, y las salidas digitales 2, 4, y 7.

Figura 2.43. Termómetro de LEDs con TMP36.


78
El programa de control dependerá del tipo de sensor que empleemos en nuestro montaje, ya que en general
el NTC y el TMP36 reportarán valores dentro de distintos rangos. El programa que escribimos a
continuación está diseñado para trabajar con el TMP36:

void setup() {
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
pinMode(7, OUTPUT);
Serial.begin(9600);
}

void loop() {
int lectura = analogRead(A5);
Serial.println(lectura); /* Mostramos los valores de las lecturas
captadas por el TMP36 para hallar su rango. */
int luces= map(lectura, 20, 358, 0, 3); /* Mapea las lecturas a 4 valores
posibles: <1, <2, <3, =3 */
luces = constrain(luces, 0, 3);

if(luces < 1) {
analogWrite(2, LOW);
digitalWrite(4, LOW);
digitalWrite(7, LOW);
}
else if(luces < 2) {
digitalWrite(2, HIGH);
analogWrite(4, LOW);
digitalWrite(7, LOW);
}
else if(luces < 3) {
digitalWrite(2, HIGH);
digitalWrite(4, HIGH);
analogWrite(7, LOW);
}
else {
digitalWrite(2, HIGH);
digitalWrite(4, HIGH);
digitalWrite(7, HIGH);
}
delay(200);
}

EJERCICIO 10. LED controlado por temperatura. Diseña un sistema de control del nivel de luminosidad
de un LED en función de la temperatura: Cuanto más alta es la temperatura, más intensamente brilla el
LED.

2.11. PRÁCTICAS CON ARDUINO (6): NÚMEROS ALEATORIOS.

En ocasiones necesitaremos usar números aleatorios para programar comportamientos impredecibles en


nuestros sistemas de control. Para configurar la generación de números aleatorios a partir de las señales
de ruido de fondo electromagnético captadas en un pin de entrada analógica (rayos cósmicos,
interferencias electromagnéticas de teléfonos móviles, emisiones de luces fluorescentes, etc…) añadimos
la instrucción randomSeed() al setup() de nuestro programa:

void setup() {
randomSeed(analogRead(A0)); /* Genera números aleatorios utilizando la
lectura del pin de entrada analógica A0 */
}

79
Una vez configurada la generación de números aleatorios, usamos la instrucción random() dentro del
bucle principal para obtener números enteros aleatorios en el rango de valores especificado:

void loop() {
rnd = random(200); /* Asigna a la variable rnd un valor aleatorio
comprendido entre 0 y 199. */
rnd = random(100, 200); /* Asigna a la variable rnd un valor aleatorio }
comprendido entre 100 y 199. */
}

PRÁCTICA 15: DADO EN ARDUINO.

Vamos a utilizar la placa Arduino para programar un “dado” que obtenga valores aleatorios entre 1 y 6. Para
imprimir en la pantalla del monitor serie una nueva tanda de valores bastará con apretar el botón de reset
de la placa Arduino. Para este sistema no debemos montar ningún circuito; solo necesitamos la placa
Arduino. El programa de control es el siguiente:

int dado; // Variable para guardar el número aleatorio obtenido en una tirada.

void setup() {
randomSeed(analogRead(A0)); /* Inicia la generación de números
aleatorios a partir de la lectura
del ruido de fondo en A0. */
Serial.begin(9600);
Serial.println("Nueva tanda de tiradas:");
}

void loop() {
dado = random(1, 7); /* Asigna a la variable 'dado ' un valor aleatorio
entre 1 y 6. */
Serial.println(dado);
delay(500);
}

La figura muestra la salida del monitor serie para este programa para varias tandas de valores. Como
vemos, la generación de números aleatorios es impredecible.

Figura 2.44. Salida del programa del dado.


80
EJERCICIO 11. Vela. Diseña un sistema que utilice un Led rojo o naranja para simular una vela (por
ejemplo, en el montaje de un belén). Para ello, haz que el brillo y el tiempo de encendido del LED vaya
cambiando aleatoriamente.

EJERCICIO 12. LED aleatorio. Monta un sistema con 5 LEDs y un botón. A cada pulsación del botón, el
sistema debe encender un LED aleatorio del grupo de cinco LEDs.

2.12. PRÁCTICAS CON ARDUINO (7): REPRODUCIR SONIDOS.

Para montar automatismos que reproduzcan sonidos necesitaremos usar zumbadores.3 Los zumbadores son
dispositivos fabricados con materiales piezoeléctricos (típicamente cuarzo), que al ser sometidos a un
voltaje eléctrico variable vibran produciendo un sonido de un tono u otro.

Las funciones para reproducir sonidos son las siguientes:

tone(6, 1350); /* El altavoz conectado al pin 6 emite un sonido de frecuencia


1350 Hz con una duración indeterminada. Tras un tone() se suele
añadir un delay() que permita escuchar esa frecuencia haciendo
una pausa en el programa. */

noTone(6); // El altavoz conectado al pin 6 deja de sonar.

tone(9, 4500, 200); /* El altavoz conectado al pin 9 emite un sonido de


frecuencia 4500 Hz durante un tiempo de 200 milisegundos
y después se detiene. */

En el caso de que queramos que Arduino reproduzca una canción, resulta muy útil conocer qué frecuencia
(en hertzios) se corresponde con cada nota musical. La tabla muestra la frecuencia asociada a cada nota
musical, según la escala. (Por cierto, recordar que para escribir números decimales se usa el punto y no la
coma). También nos conviene saber que el oído no se percibe el redondeo de estas frecuencias a números
enteros.

Figura 2.45. Frecuencia (en hertzios) de las notas musicales.

3
En la práctica, también podríamos usar altavoces. Pero como TinkerCAD no incluye un módulo que nos permita
simular altavoces, aquí solo usaremos zumbadores.
81
PRÁCTICA 16: THEREMIN.

Un theremín es un instrumento musical electrónico que se controla sin necesidad de contacto físico directo
entre el intérprete y el instrumento. En esta práctica vamos a montar un theremín que reproducirá
distintas notas en función de la posición de la mano en relación a un LDR funcionando como sensor de
proximidad: Cuanto más cerca esté la mano del LDR, menos luz recibirá.

Figura 2.46. Zumbador piezoeléctrico, símbolo, y modelo de TinkerCAD.

TinkerCAD no dispone de altavoces, y solo ofrece un componente zumbador piezoeléctrico al que denomina
piezo. El piezo es un dispositivo con polaridad, lo que significa que una de sus patillas debe conectarse al
positivo, y la otra al negativo. La figura 2.46 muestra el patillaje del piezo de TinkerCAD.

La figura 2.47 muestra el montaje del proyecto, donde observamos que hemos usado la entrada analógica
A2 para conectar el LDR, y la salida analógica 5 para alimentar al zumbador.

Figura 2.47. Montaje del Theremín.

El programa de control simplemente mapea el rango de lecturas ofrecidas por el LDR a través de la entrada
A2 para adaptarlo al rango de frecuencias que le podemos pasar al zumbador (que sabemos que se extiende
desde los hasta los , aproximadamente) mediante la función tone(). El programa también
emplea el monitor serie para visualizar el valor máximo y mínimo de las lecturas captadas por el LDR, y
ajustar la función map() de forma correspondiente.

int lecturaLDR; // Variable que almacena la lectura del LDR.


int frecuencia; // Variable que almacena la frecuencia a reproducir.

void setup() {
pinMode(5, OUTPUT);
Serial.begin(9600); // Para visualizar las lecturas del LDR.
}

82
void loop(){
lecturaLDR = analogRead(A2);
Serial.print("Lectura de entrada: ");
Serial.print(lecturaLDR);
Serial.print('\t');
frecuencia = map(lecturaLDR, 54, 974, 65, 15805);
// Recordar que debemos afinar los valores máx. y mín. de la entrada.
frecuencia = constrain(frecuencia, 65, 15805);
Serial.print("Frecuencia del sonido: ");
Serial.println(frecuencia);
tone(5, frecuencia, 200);
delay(250); // Forzamos una pausa entre notas para poder escucharlas.
}

EJERCICIO 13. Piano. Diseña un sistema con 7 botones. Al pulsar cada uno de los botones, suena una de
las siete notas musicales de la escala 1 (ver tabla previa).

2.13. PRÁCTICAS CON ARDUINO (8). SERVOMOTORES. (*)

Un servomotor es un motor que se caracteriza por su precisión, pues puede situar su eje en una posición
cualquiera dentro de un rango de giro, normalmente de a . Por lo tanto, los servomotores no son
motores pensados para mover una carga o un móvil que recorra cierta distancia, sino para movimientos de
precisión (como el de un brazo robot) cuyo margen de maniobra no exceda su rango de giro.

Figura 2.48. Servomotor .

Los servomotores disponen de tres cables que debemos conectar de forma correcta: El cable rojo se
conecta al positivo (típicamente, a una alimentación de , el cable marrón o negro se conecta a tierra
( ), y el cable amarillo, naranja, o blanco se conecta al pin de control (normalmente un pin digital PWM).

NOTA: Debido a su alto consumo energético, al trabajar con motores y servomotores se recomienda
utilizar una alimentación externa externa (fuente de alimentación, pilas, etc.). La corriente que ofrece
el puerto USB no es suficiente para alimentar estos dispositivos, y suele provocar malfuncionamientos
(como por ejemplo, vibraciones de los servomotores).

Ahora, ¿cómo controlamos la operación del servomotor desde nuestro programa de control? Para empezar,
debemos añadir una librería específica que nos permita el contro del servomotor. Una librería es una
colección de funciones especialmente creadas para facilitar el manejo de ciertos dispositivos, y que no está
cargada por defecto en Arduino para ahorrar espacio en su memoria. Para cargar la librería de control de
servomotores, basta con escribir la instrucción:

#include <Servo.h> // Añade a Arduino ña librería de control de servos.

83
A continuación, y como si de una variable se tratara, debemo declarar nuestro servomotor asignándole un
nombre. Esto lo hacemos con el siguiente comando:

Servo nombreServo; // Declara un Servo cuyo nombre será 'nombreServo'.

Despues, en el setup() debemos configurar el pin de salida que Arduino va a utilizar para controlar el
servomotor. Para ello utilizamos la función attach(pin):

nombreServo.attach(10); // El servomotor se controlará mediante el pin 10.

Finalmente, para controlar el servomotor dentro del loop(), usamos la función write(ángulo):

nombreServo.write(45); // Sitúa el eje del servo en la posición 45º.

PRÁCTICA 17: GIRO DE UN SERVOMOTOR.

En esta práctica vamos a controlar un servomotor con dos pulsadores (P1 y P2). Cada vez que apretemos el
pulsador P1, el servomotor girará . Al apretar el pulsador P2, el servomotor volverá a su posición inicial.

La figura 2.49 muestra el montaje, donde observamos que los pulsadores P1 y P2 están conectados a las
entradas digitales 7 y 8, respectivamente. Por su parte, el servomotor está conectado a la salida digital 10
(PWM).Notar que cada pulsador necesita su propio montaje pull – down.

Figura 2.49. Giro de un servomotor.

El programa de control es el siguiente:

#include <Servo.h>

Servo girador; // Declaramos nuestro servomotor, con nombre 'girador'.


int posInicial = 40; // Definimos 40º como posición inicial.
int incremento = 10;
int posActual = posInicial; /* Nada más empezar, el servo estará en la
posición inicial. */
void setup() {
pinMode(7, INPUT);
pinMode(8, INPUT);
girador.attach(10); // Conectamos el servo al pin digital 10.
girador.write(posInicial);// Ubicamos el servo en la posición inicial (40º).
}

84
void loop() {
if(digitalRead(7)) { // Al pulsar P1...
posActual = posActual + incremento; // ...la posición actual cambia en 10º.
girador.write(posActual);
delay(1000); // Pausa para que el servo tenga tiempo de moverse.
}
if(digitalRead(8)) { // Al pulsar P2...
girador.write(posInicial); // ...el servo vuelve a su posición incial...
posActual = posInicial; // ...y reiniciamos la posición actual a 40º.
delay(1000);
}
}

EJERCICIO 14. Control de un servomotor por temperatura. Diseña un programa un sistema que active el
giro de un servomotor cuando un sensor de temperatura detecte que hace calor.

2.14. PRÁCTICAS CON ARDUINO (9): ASPECTOS AVANZADOS.

FUNCIONES DE TIEMPO.

En la sección 2.6 presentamos la función delay(), que nos permite pausar la ejecuación del programa un
cierto número de milisegundos antes de seguir con la siguiente instrucción.

delay(500); // Pausa la ejecuación del programa 500 ms.


Otras funciones de tiempo útiles son las siguientes:

delayMicroseconds(350); //Realiza una pausa en el programa de 350 μs.

x = millis(); /* Asigna a x (variable de ipo unsigned log) el número de


milisegundos transcurridos desde que se reseteó por última vez
la placa Arduino (máx. 50 días)*/

x = micros(); /* Asigna a (variable de ipo unsigned log) el número de


microsegundos transcurridos desde que se reseteó por última vez
la placa Arduino (máx. 70 minutos)*/

Debemos tener algunas precauciones a la hora de usar estas funciones de tiempo: Cuando necesitemos
hacer pausas largas (por ejemplo, del orden de un minuto), tal vez debamos usar como argumentos de las
funciones delay() y delayMicroseconds() valores del tipo long o unsigned long. Si utilizásemos
un delay(60*1000); no conseguiríamos una pausa de 1 minuto, porque Arduino interpretaría los números
60 y 1000 como enteros (int), y el resultado rebasaría el valor límite de 32767, dando un valor real de
5536 (ver sección 2.5). Para indicarle a Arduino que interprete un número como un valor de tipo long o
unsigned long, debemos escribir tras él las letras l (o L) y ul (o UL), respectivamente. Por ejemplo,
1000L considera el valor 1000 como una variable del tipo long, y 32767ul considera el valor 32767 como
una variable del tipo unsigned long. De esta forma, la instrucción delay(60*1000L); hará una pausa
real de 1 minuto.

Otro ejemplo de uso de estas funciones es el siguiente: Suponer que necesitamos hacer parpadear un LED
sin usar la función delay(), ya que entre tanto queremos realizar otras tareas y no podemos detener el
programa. En tal caso, debemos hacer uso de la función millis():

int estado = LOW;


unsigned long tiempo = 0;
unsigned long intervalo = 500;

85
void setup() {
pinMode(13, OUTPUT);
}

void loop() {
if(tiempo + intervalo < millis()) { //es la condición para que…
estado = !estado; //… parpadee el LED, …
digitalWrite(13, estado);
tiempo = millis();
}

//… permitiendo seguir ejecutando el resto del código


}

Un función de tiempo muy útil es la función pulseIn(pin, valor), que determina el tiempo
transcurrido (en milisegundos) hasta que el pin digital de entrada indicado vuelva a registrar el mismo valor
de lectura (“LOW” o “HIGH”). Esta función permte leer sensores que funcionen emitiendo y recibiendo
pulsos de duración variable, como son los sensores ultrasónicos, los sensores de infrarrojos, etc.

x = pulseIn(7, HIGH); /* Asigna a x el tiempo transcurrido hasta que el


pin de entrada indicado vuelva a registrar un pulso
en estado HIGH. */

SENSOR ULTRASÓNICO.

Un sensor de ultrasonidos es un dispositivo para medir distancias. Su funcionamiento se base en el envío


de un pulso de alta frecuencia no audible por el ser humano. Este pulso rebota en los objetos cercanos y se
refleja hacia el sensor, que dispone de un micrófono adecuado para captar esa frecuencia. Conocida la
velocidad del sonido, podemos medir el tiempo transcurrido entre el pulso emitido y el reflejo recibido
para estimar la distancia al objeto contra el que ha impactado el pulso emitido.

Los sensores de ultrasonidos son sensores de baja precisión. La orientación de la superficie a medir puede
provocar que la onda se refleje, falseando la medición. Además, no resultan adecuados en entornos con
gran número de objetos, dado que el sonido rebota en las superficies generando ecos y falsas mediciones.
Tampoco son apropiados para el funcionamiento en el exterior y al aire libre. Pese a ello, los sensores de
ultrasonidos son ampliamente empleados: En robótica es habitual montar uno o varios de estos sensores,
por ejemplo, para la detección de obstáculos, la determinación de la posición del robot, la creación de
mapas de entorno, o para el escape de laberintos. En aplicaciones en que se requiera una precisión superior
en la medición de la distancia, suelen acompañarse de medidores de distancia por infrarrojos y sensores
ópticos. El modelo comercial más común es el HC-SR04, que posee 4 pines de conexión: Dos patillas son de
alimentación ( y GND), una para el disparador de ultrasonido (Trigger), y otra para el receptor del eco
del ultrasonido (Echo).4

Figura 2.50. Sensor de ultrasonidos.

4
También existe un modelo con tres patillas, en el que el disparador (trigger) y el receptor (echo) comparten
una patilla común. Aquí solo trabajaremos con el modelo de cuatro patillas.
86
Su uso es sencillo: Con el disparador enviamos un pulso a nivel alto (“HIGH”), y calculamos el tiempo que
dicha señal tarda en llegar rebotada al receptor. Sabiendo que la velocidad del sonido es de unos ⁄
, podemos calcular la distancia al obstáculo aplicando la siguiente fórmula:

, donde es la distancia al obstáculo (en ), y es el tiempo transcurrido entre el envío del pulso y la
recepción del eco (en ). Esta fórmula proviene de despejar la distancia de la ecuación cinemática
⁄ . La razón por la que dividimos por 2 es que es el tiempo
que tarda la señal en llegar al obstáculo y volver rebotada, por lo que la distancia obtenida es el dos veces
la distancia al objeto detectado.

PRÁCTICA 19: MEDICIÓN DE LA DISTANCIA A UN OBJETO.

En esta práctica usaremos el sensor ultrasónico para medir y mostrar por el monitor serie la distancia a un
objeto. La figura 2.51 muestra el montaje necesario, donde hemos usado el pin digital 7 como salida para
enviar el pulso a nivel alto, y el pin digital 8 como entrada para detectar el eco recibido.

Figura 2.51. Medición e la distancia a un objeto.

El programa de control es el siguiente:

int triggerPin = 7, echoPin = 8; /* Pines a los que conectamos las


patillas Trigger y Echo del sensor.

/* Variable para almacenar el intervalo de tiempo entre el envío de la señal y


la recepción del rebote. */
long intervalo;

/* Variable para calcular y almacenar la distancia (en cm) al obstáculo


detectado. */
float distancia;

87
void setup() {
Serial.begin(9600);
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop() {
/* Hacemos un disparo emitiendo un pulso a nivel alto de 10 μs de duración.
Para generar un pulso limpio primero ponemos la salida a LOW durante 4 μs, y
a continuación, la ponemos a HIGH durante otros 10 μs. Para terminar de
conformar el pulso, volvemos a poner la salida a LOW. */

digitalWrite(triggerPin, LOW);
delayMicroseconds(4);
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);

/* Calculamos el intervalo de tiempo transcurrido entra la emisión del pulso


y la recepción del eco. Para ello usamos la función pulseIn(), que nos
permite medir el tiempo transcurrido (en μs) hasta que la entrada digital
vuelve a recibir un pulso a nivel HIGH (esto es, hasta que recibe la señal
rebotada). */

intervalo = pulseIn(echoPin, HIGH);

/* El sonido viaja a 340 m/s = 0.034 cm/μs, pero como la señal recorre
dos veces la distancia hasta el objeto (ida y vuelta), para obtener esa
distancia (cm) debemos multiplicar la velocidad por el intervalo, y
dividir entre dos. */

distancia = (0.034 * intervalo) / 2;

/* Imprimimos en el monitor serie el intervalo de tiempo medido, y la


distancia calculada. */

Serial.print("Tiempo empleado: ");


Serial.print(intervalo);
Serial.print(" microsegs.");
Serial.print('\t');
Serial.print("Distancia: ");
Serial.print(distancia);
Serial.println(" cm.");
delay(1000); // Pausa para poder leer los datos en el Serial Monitor.
}

EJERCICIO 15. Asistente de aparcamiento. Diseñar un sistema con un LED y un sensor de ultrasonidos
HC-SR04 que controle la velocidad de parpadeo del LED, de la siguiente forma: Cuanto más cerca detecte
el sensor la repsenciade un obstáculo, más rápido parpadea el LED, y viceversa. AMPLIACIÓN: Añade un
zumbador al sistema, y prográmalo para conseguir que el zumbador pite cada vez más rápido cuanto más
cerca esté el obstáculo detectado.

ARRAYS Y STRINGS.

Un array es una variable que almacena una lista de valores, a los cuales podemos acceder a través de su
índice. Un ejemplo es el siguiente:

int datos[] = {4, 7, 9, 12, 18}

88
El array datos es una lista de varioas enteros, donde el entero en el índice 0 es 4, el entero en el índice 1
es 7, el entero en el índice 2 es 9, etc:

datos[0] = 4; datos[1] = 7; … datos[4] = 18;

En este primer ejemplo no hemos especificado el tamaño del array porque hemos incluido el valor de todos
los datos que contiene. Sin embargo, si no declaramos los valores iniciales, debemos especificar el tamaño
del array entre corchetes:

int datos[5];

También podemos almacenar datos en forma de matriz o array multidimensional, donde cada dato estará
identificado por un doble índice (o triple, o cuádruple, etc…). En los arrays multidimensionales sí que es
necesario especificar el tamaño de las distintas dimensiones desde el principio, aún cuando declaremos
todos sus elementos.

int matriz[3][3] = {{2, 4, 8}, {3, 9, 27}, {5, 25, 125}};

, donde:

matriz[0][0] = 2; matriz[0][1] = 4; … matriz[2][2] = 125;

Un string (o array de caracteres) es una variable que almacena una cadena de caracteres, y que se emplea
para almacenar textos. Existen varias opciones:

char letra = 'a' /* String que slmacena un solo carácter (escrito entre
comillas simples). */

char texto = "Me gusta Arduino." /* String que slmacena un texto(escrito


entre comillas dobles). */

Los 18 caracteres que componen la cadena de texto "Me gusta Arduino." (17 caracteres 1 carácter
no imprimible para indicar el fin de la cadena: '\0') se almacenan como valores independientes dentro del
array. Por ejemplo:

char texto[0] = 'M'; char texto[2] = ' '; char texto[16] = '.';

Otra forma equivalente (aunque más engorrosa) de declarar individualmente los distintos elementos del
mismo array es la siguiente:

char texto[] = {'M', 'e', ' ', 'g', 'u', 's', 't', 'a', ' ', 'A', 'r', 'd',
'u', 'i', 'n', 'o', '.'};

La notación con asterisco (*) constituye otra variante para declarar palabras, frases, o incluso arays de
palabras y frases, donde cada elemento del array equivalente es un carácter, una palabra, o una frase:

char* palabra = "Arduino";


char* frase = "Me gusta Arduino.";
char* color[] = {"Rojo", "Azul", "Verde limón"};

, siendo:

char* palabra[0] = 'A';


char* color[0] = "Rojo";
char* color[2] = "Verde limón";

89
La función sizeof() permite reconocer el tamaño del array, en número de bytes. Por ejemplo:

int edades[] = {36, 5, 68, 15, 22, 41};


char texto[] = "Me llamo Daniel";

int x = sizeof(edades); /* La variable x tomará un valor de 12 (cada valor


de tipo int ocupa 2 bytes). */
int y = sizeof(texto); /* La variable y tomará un valor de 16 (cada
carácter del texto ocupa 1 byte + 1 byte del
carácter de final de cadena. */

Para obtener el número de elementos que contiene un array, podemos utilizar las siguientes instrucciones:

int a = sizeof(edades) / 2; // En este ejemplo, a = 6.

int b = sizeof(texto) - 1; // En este ejemplo, b = 15.

DEFINIR FUNCIONES.

Aunque Arduino viene con algunas funciones preconstruidas (como pinMode(), delay(),
digitalWrite(), analogRead(), etc.), este lenguaje también nos permite definir nuestras propias
funciones.
Para definir una función que no devuelva ningún valor, utilizamos la siguiente sintaxis:

void nombreFuncion(a, b, …){

// Código de la función.

, donde a, b, etc. son los parámetros (con nombres a nuestra elección) que debemos pasarle a nuestra
función para que opere correctamente, y que podemos utilizar como variables en el código que define su
comportamiento. Si esas variables no estaban decaaradas con anterioridad, debemos declararlas en la
definición de la función:

void nombreFunción(int a, int b, …){


// Código de la función.
}

Si necesitamos que la función devuelva algún valor, debemos declarar el tipo de valor que devuelve la
función como si de una variable se tratara (int, long, float, etc.). Además, para que la función devuelva
un valor, debemos utilizar la sentencia return dentro del código de la función, acompañada del valor que
deseamos devolver. Un ejemplo es el siguiente:

float media (int num1, int num2) {


return (num1 + num2)/2
}

Para terminar, las funciones suelen definirse en la última parte del programa, tras el bucle loop().

90
DISPLAY DE 7 SEGMENTOS.

Un dispositivo de salida muy utilizado es el display de 7 segmentos, que suele


emplearse para mostrar números o letras. El display posee 10 patillas: Los 7 pines
para los segmentos que permiten formar el número (a, b, c, d, e, f, g), el pin de
punto decimal (dp), y dos pines para el ánodo común (com).

Figura 2.52. Display 7 segmentos.

Para utilizar un display de 7 segmentos en nustros proyectos debemos conectar una de las dos patillas del
ánodo común al positivo ( ) y el resto de patillas (los segmentos y el punto decimal) a un pin de salida
digital a través de una resistencia de . De esta forma se encenderán los segmentos conectados a una
salida digital a nivel “LOW”.

PRÁCTICA 20. CUENTA ATRÁS.

En esta práctica vamos a montar y a programaar un sistema que realice una cuenta atrás: 9, 8, 7, 6, 5, 4, 3,
2, 1, y 0. El paso de un número al anterir se realiza en lapsos de 1 segundo. Al llegar a 0, la cuenta atrás
vuelve a reiniciarse y comienza de nuevo en el 9.

El circuito de control del sistema es el siguiente:

Figura 2.53. Cuenta atrás.

A continuación tenemos el programa de control del sistema electrónico de la figura. Para comenzar,
declaramos una serie de variables, como son los pines digitales con los que activaremos cada uno de los 7

91
segmentos, y los segmentos a activar para construir cada uno de los dígitos del 0 al 9. A continuación
definimos todos los pines digitales conectados a los segmentos como pines de salida.

Ya en el bucle principal utilizamos un doble bucle for anidado (esto es, un bucle for dentro de otro bucle
for) para implementar la cuentra atrás en el display de 7 segmentos. El bucle for externo hace que la
variable i tome todos los valores desde 9 a 0. Para cada uno de estos valores, el bucle for interno activa los
segmentos necesarios para mostrar en el display el dígito correspondiente, haciendo uso de las variables
pinSegmentos[] y segmentosNumero[][].

int pinSegmentos[] = {2, 3, 4, 5, 6, 7, 8, 9}; //(a, b, c, d, e, f, g, .)


byte segmentosNumero[10][8] = {
{1,1,1,1,1,1,0,0}, //número 0: segmentos a,b,c,d,e,f
{0,1,1,0,0,0,0,0}, //número 1: segmentos b,c
{1,1,0,1,1,0,1,0}, //número 2: segmentos a,b,g,e,d
{1,1,1,1,0,0,1,0}, //número 3: etc…
{0,1,1,0,0,1,1,0}, //número 4: etc…
{1,0,1,1,0,1,1,0}, //número 5
{1,0,1,1,1,1,1,0}, //número 6
{1,1,1,0,0,0,0,0}, //número 7
{1,1,1,1,1,1,1,0}, //número 8
{1,1,1,1,0,1,1,0} }; //número 9

void setup() {
for(int i=2; i<=9; i=i+1){
pinMode(i, OUTPUT);
}
}

void loop() {
for(int i=9; i>=0; i=i-1) { // Bucle para la cuenta atrás del 9 al 0.
for(int j=0; j<sizeof(pinSegmentos)/2; j=j+1){
digitalWrite(pinSegmentos[j], !segmentosNumero[i][j]);

/* Recordemos que a la hora de interpretar una señal digital, los valores


1, HIGH, y TRUE significan lo mismo. Y lo mismo ocurre con los valores
0,LOW y FALSE. Recordar que cada segmento se enciende cuando el pin
correspondiente está a LOW. Por consiguiente, y habiendo definido
la variable segmentosNumero como lo hemos hecho (1=segmento encendido),
aquí debemos especificar que el pin j escriba lo contrario de lo que
la variable segmentosNumero indica: Si es un 1 que ponga un LOW (o 0), y
si es un 0 que ponga un HIGH (o 1) */
}
delay(1000);
}
}

EJERCICIO 16. Número aleatorio. Diseña un sistema con un pulsador y un display de 7 segmentos, y
prográmalo para que, cada vez que pulsemos el pulsador, el display muestre un número aleatorio entre el 0 y
el 9.

PANTALLA LCD.

Uno de los dispositivos más interesantes para Arduino es la pantalla LCD. Las pantallas LCD utilizan las
propiedades de la luz polarizada para mostrar la información que deseemos en una pantalla. A partir de una
serie de filtros, consigue mostrar la información gracias a la iluminación de fondo.

Hay una amplia gama de pantallas LCD para Arduino. Aparte de las funcionalidades extra que puedan
ofrecer cada una de ellas, se distinguen por su tamaño (número de filas y número de columnas). Nstros
92
trabajaremos con una pantalla LCD , que se caracteriza por disponer de 2 filas con 16 caracteres
cada una.

Figura 2.54. Pantalla LCD y pines de conexión.

Uno de los modelos de LCD más utilizados con Arduino es el HD44780, que consta de 16 pines de
conexión (de los cuales solo debemos conectar 6 a la placa Arduino). La tabla a continuación lista los pines
de conexión de este LCD:

Pines de conexión del LCD


1 VSS Negativo de la alimentación del LCD ( )
2 VDD Positivo de la alimentación del LCD ( )
3 Se conecta a un potenciómetro o a una resistencia fija para
V0
controlar la luminosidad de los caracteres en pantalla.
4 RS Register Select
5 Read/Write. Lo conectamos a , porque solo vamos escribir datos
RW
En la LCD, no a leer datos de ella.
6 E Enable.
7 DB0
8 DB1 Bus para la transmisión de datos al LCD a 8 bits.
9 DB2 (Nosotros no lo usaremos, porque ysaremos el bus de 4 bits).
10 DB3
11 DB4
12 DB5
Bus para la transmisión de datos al LCD a 4 bits.
13 DB6
14 DB7
15 Ánodo del LED de iluminación de la pantalla LCD.
LED-A
Se conecta a a través de una resistencia de .
16 Cátodo del LED de iluminación de la pantalla LCD.
LED-K
Se conecta a .

Figura 2.55. Pines de conexión del LCD .

93
Por consiguiente, podemos conectar la pantalla LCD como muestra la figura:

Figura 2.56. Conexión de la pantalla LCD a Arduino.

A continuación, vamos a ver las instrucciones que nos permiten configurar la pantalla LCD. En primer lugar,
debemos abrir la librería LiquidCrystal.h:

#include <LiquidCrystal.h>

A continuación debemos declarar nuestra pantalla LCD como si de una variable se tratara, y asignarle un
nombre. Además debemos especificar los pines que vamos a usar para conectar la LCD con Arduino. La
sintaxis es la siguiente:

LiquidCrystal nombreLcd (RS, E, DB4, DB5, DB6, DB7);

, donde RS, E, DB4, DB5, DB6, y DB7 son los números de los pines digitales de Arduino a los que
conectamos los pines RS, E, DB4, DB5, DB6, y DB7 del LCD.

Seguidamente, y ya dentro del setup(), debemos iniciar la librería para nuestra LCD. Para ello utilizamos
la función begin(), especificando el tamaño del LCD (que en nuestro caso es caracteres):

nombreLcd.begin(16, 2);

Una vez inicializada la pantalla, las instrucciones que nos permiten programar la pantalla LCD son las
siguientes:

nombreLcd.setCursor(7, 0); /* Sitúa el cursor de la pantalla LCD 16x2 en


la primera línea (0), sexto carácter (7). */

nombreLcd.print("Hola!"); /* Imprime en la posición indicada previamente


el texto escrito entre comillas, y sitúa el cursor
tras el último caracter. */

nombreLcd.clear(); /*Borra todo el contenido de la pantalla y sitúa


el cursor en la posición (0,0). */

94
nombreLcd.write(symbol[i]); /* Se emplea para mandar un caracter a la LCD.
Por ejemplo, para mandar el caracter '+', cuyo
código ASCII es el 00101011 (43), podemos hacerlo
de varias formas: */

byte mas = B00101011; /* Definición del código ASCII del carácter '+'
como una variable (La B es para especificar que está
en binario. */
nombeLcd.write(mas); // Para mandarlo como variable.
nombreLcd.write(B00101011); // Se puede mandar en binario (B).
nombreLcd.write(43); // Se puede mandar en decimal.
nombreLcd.write(0x2B); // Se puede mandar en hexadecimal (0x).

nombreLcd.createChar(numero, dato);

/*Esta función permite definir un carácter creado por nosotros mismos, en la


forma de una matriz de 5x8 píxeles. Para ello debemos generar dicho carácter a
través de 8 números binarios de 5 bits, correspondientes a cada una de las
filas que componen dicho carácter. Nuestro display LCD puede almacenar 8
símbolos diseñados por nosotros, y debemos indicar dónde almacenalos a través
de un número (de 0 a 7). Esta instrucción se incluye dentro void setup(). Para
imprimir dicho carácter en la pantalla LCD usamos la función
nombreLcd.write(número). A modo de ejemplo, para crear e imprimir un carácter
en forma de sonsira, hacemos lo siguiente:

byte sonrisa[8] = {B00000,


B00000,
B01010,
B00000,
B10001,
B01110,
B00000,
B00000};

void setup() {
nombreLcd.createChar(0, sonrisa); //será mi caracter 0
}

void loop() {
nombreLcd.write(0);
}

*/

PRÁCTICA 21. PROBANDO EL LCD.

Vamos a diseñar un sistema para probar el funcinamiento de la pantalla LCD. El montaje de la electrónica
del sistema es el de la figura 2.56. El programa del sistema simplemente utiliza las instrucciones de control
de la pantalla LCD para imprimir un mensaje, y una carácter de sonrisa definido por nosotros. El programa
de control es el siguente:

#include <LiquidCrystal.h>

// Conexiones:
// Pin RS del LCD al pin 12 de Arduino.
// Pin E del LCD al pin 10 de Arduino.
// Pines DB4,DB5,DB6,DB7 del LCD a los pines 5,4,3,2
// de Arduino, respectivamente.

95
// Sintaxis: LiquidCrystal lcd(RS, E, DB4, DB5, DB6, DB7);

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

byte sonrisa[8] = {
B00000,
B10001,
B00000,
B00000,
B10001,
B01110,
B00000,
};

void setup()
{
lcd.begin(16,2); // Inicia el LCD y especifica un tamaño 16x2.
lcd.clear(); // Limpia la pantalla del LCD.
// Sitúa el cursor en la primera línea (0), primer carácter (0).
lcd.setCursor(0,0);
lcd.print("Hola mundo!!!!!!"); // Texto a mostrar en la ubicación indicada.
// Sitúa el cursor en la segunda línea (1), primer carácter (0).
lcd.setCursor(0,1);
lcd.print("Probando LCD. "); // Texto a mostrar en la ubicación indicada.
// Creamos el símbolo al que llamaremos "0" con el patrón especificado
// en la var. "sonrisa".
lcd.createChar(0, sonrisa);
// Sitúa el cursor en la segunda línea (1), decimocuarto carácter (15).
lcd.setCursor(15, 1);
// Escribimos el carácter "0" (sonrisa) en la posición indicada.
lcd.write(byte(0));
}

void loop()
{
delay(1000);
// Apaga la pantalla LCD.
lcd.noDisplay();
delay(500);
// Enciende la pantalla LCD.
lcd.display();
}

PRÁCTICA 22. PECERA EN UN LCD.

Vamos a programar la pantalla LCD para mostrar un pez que se desplaza por la pantalla, y va haciendo
pequeñas pompitas. El programa puede ser el siguiente:

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 10, 5, 4, 3, 2);

byte pescadoIzquierda[] =
{B00000,B00000,B00000,B00000,B01101,B11110,B01101,B00000};
byte pescadoDerecha[] =
{B00000,B00000,B00000,B00000,B10110,B01111,B10110,B00000};
byte pescadoCentro[] =
{B00000,B00000,B00000,B00000,B00100,B01110,B00100,B00000};
byte burbuja1[] = {B00010,B00000,B00100,B00010,B00100,B01110,B00100,B00000};
byte burbuja2[] = {B00000,B00100,B00010,B00000,B00100,B01110,B00100,B00000};
96
byte burbuja3[] = {B00100,B00000,B00000,B00000,B00100,B01110,B00100,B00000};
byte x = 0;
byte y = 0;
int tiempo = 600;

void setup() {
lcd.begin(16,2);
lcd.createChar(0, burbuja1); // Creamos los caracteres de los peces.
lcd.createChar(1, burbuja2);
lcd.createChar(2, burbuja3);
lcd.createChar(3, pescadoIzquierda);
lcd.createChar(4, pescadoDerecha);
lcd.createChar(5, pescadoCentro);
}

void loop() {
desplazarDerecha(9); // El pez nadará hacia la derecha 10 posiciones …
pararCentro(); // … se parará mirando al frente …
pompas(); // … respirará echando pompas …
y = 1; // … bajará a la fila inferior …
desplazarIzquierda(5); // … nadará hacia la izquierda 6 posiciones …
pararCentro(); // … se parará otra vez …
pompas(); // … hará pompas otra vez …
y = 0; // … subirá a la fila superior …
desplazarDerecha(11); /* … nadará hacia la derecha 12 posiciones
y se perderá. */
delay(tiempo*10); // Tras un tiempo considerable …
x = 0;
y = 0; // … aparecerá de nuevo en la posición 0,0.
}

void desplazarDerecha(int posiciones) {


lcd.setCursor(x, y);
lcd.write(4); // Carácter del pez mirando hacia la derecha.
delay(tiempo);
for(int i=0; i<posiciones; i++) {
lcd.scrollDisplayRight();
delay(tiempo);
x++;
}
lcd.clear();
}

void desplazarIzquierda(int posiciones) {


lcd.setCursor(x, y);
lcd.write(3); // Carácter del pez mirando hacia la izquierda.
delay(tiempo);
for(int i=0; i<posiciones; i++) {
lcd.scrollDisplayLeft();
delay(tiempo);
x--;
}
lcd.clear();
}

void pararCentro() {
lcd.setCursor(x, y);
lcd.write(5);
delay(tiempo);
lcd.clear();
}

97
void pompas() {
for(int i=0; i<3; i++) {
lcd.setCursor(x, y);
lcd.write(i);
delay(tiempo);
}
lcd.clear();
}

EJERCICIO 17. Animación en la pantalla LCD. Diseña un sistema con una pantalla LCD donde muestres
una animación a tu gusto (una cara que hace muecas, un muñeco andando, un coche moviéndose, una avioneta
volando, etc.). Sé creativo y sorprende a tus compañeros.

98

También podría gustarte