Documente Academic
Documente Profesional
Documente Cultură
Arduino
Lo primero que debes conocer si quieres programar electrónica con Arduino o con otro lenguaje de
programación es el entorno de desarrollo. También se suele llamar IDE del inglés Integrated
Development Environment que viene a significar Entorno de Desarrollo Integrado.
En este curso lo llamaré IDE o entorno de desarrollo indistintamente. Lo primero que tenemos que
entender es ¿qué es un IDE o entorno de desarrollo? Sigue leyendo y verás que nos es nada nuevo.
Puedes trabajar con Word (procesador de textos de Microsoft Office) o con el Bloc de notas, mucho
más básico. Pero la finalidad es la misma, poder escribir documentos.
El entorno de desarrollo de Arduino es exactamente lo mismo, la única diferencia es que tiene ciertas
herramientas que nos permitirán cargar el programa al microcontrolador además de otras
funcionalidades.
Podríamos perfectamente escribir todo el código en el Bloc de notas u otro procesador de textos. Al
final es solo eso, texto. Sin embargo, cuando queremos cargar el código al microcontrolador
necesitamos de ciertos procesos que el Bloc de notas no nos aporta.
Además, al igual que Word hace con la ortografía, el IDE de Arduino examina tu código en busca
de errores de sintaxis. Por ejemplo si te falta un punto y coma, si has escrito alguna sentencia mal,
etc…
Este software (no deja de ser un programa que se ejecuta en tu ordenador) hay que instalarlo en cada
ordenador. Según el sistema operativo que tengas instalado en tu máquina deberás instalar una versión
u otra. Todo esto lo veremos más adelante.
Para que te hagas una idea, en este enlace de GitHub, puedes acceder a todo el código del IDE de
Arduino. ¡¡¡ Es fantástico !!! Todo a nuestra disposición :). El problema es que modificar algo en ese
lenguaje no es sencillo. Está programado en Java y tienes que tener experiencia si lo quieres
modificar.
Esto a dado pie a que este IDE no se utilice solo con la placa de Arduino. En la actualidad se
pueden programar decenas de placas gracias a su condición de código abierto. Por ejemplo, el
famosos ESP8266 puede ser programado desde este entorno de desarrollo.
Además, sirve para programar todos los modelos de placas que ofrece Arduino. Es un único IDE
para gobernarlos a todos.
¿Es gratuito o de pago?
El software libre o código abierto es gratuito. Esto no quiere decir que se programe solo.
Normalmente hay una comunidad de usuarios detrás reportando y modificando el código para
corregir errores y añadir nuevas funcionalidades.
Todo esto supone un gasto que en estos momentos lo asume la empresa Arduino. Por eso es
interesante, en la medida de lo posible, dar una donación de vez en cuando. Esto ayudará a que el
software y la comunidad sigan activos proporcionando nuevas mejoras y corrección de errores.
Otra forma de colaborar es comprar solo placas originales, fabricadas por el propio Arduino. Más
adelante te hablaré de qué son placas originales y placas copias.
Una de las ventajas que tiene, gracias a la comunidad que tienen detrás y a su condición de código
abierto, es que es un software que se actualiza muy a menudo. Esto, al contrario de lo que puedas
pensar, no supone un trauma para el usuario como ocurre con otro tipo de software.
Lo importante es que de momento el aspecto general del IDE no cambia y por lo tanto, no vas a
notar apenas diferencias entre una versión y otra. Siempre encontrarás las funciones más
importantes en el mismo sitio.
Llevo años programando con este IDE y te puedo asegurar que no se nota nada a nivel de interfaz
cuando instalo una nueva versión.
El código que utilizamos para cargar en la placa de Arduino no cambia entre una versión y
otra. Si por ejemplo haces un programa en una versión y actualizan el IDE, ese mismo código es
compatible y no tendrás que modificar nada. Esto es una gran ventaja.
La última versión que está operativa y estable cuando estoy escribiendo estas líneas es la 1.8.2.
También puedes descargar las versiones antiguas del IDE accediendo a esta web. Puedes instalar
hasta la primera versión del IDE.
Conclusiones del IDE de Arduino
De esta lección me gustaría que te quedaras con ciertas claves importantes:
Un IDE no es más que un procesador de textos que nos ayuda a programar y cargar el
código a través de herramientas.
El IDE de Arduino es de código abierto (tenemos acceso a todo el código fuente) y es
gratuito (aunque conviene colaborar de alguna manera).
Sirve para programar todas las placas de Arduino y un montón de placas más de otras
marcas.
Se suele actualizar a menudo y el código que tengamos hecho en una versión es compatible
con otra versión.
Teniendo claro qué es un IDE vamos a empezar por el principio, haciendo la instalación en nuestro
ordenador.
Lección 3: Instalación del IDE de Arduino
(PC)
Esta guía te va a permitir instalar y configurar el IDE de Arduino en un PC con Windows. Es un
proceso que puede que repitamos en más de una ocasión. Te guiaré paso a paso para que no tengas
ninguna duda.
En las últimas versiones, encontramos un acceso a la nueva versión web del IDE. En este curso
vamos a trabajar con la versión de escritorio, por ahora, ya que es la más común y la más sencilla de
utilizar.
En la sección de Download tenemos acceso a las diferentes versiones según el sistema operativo. Para
Windows podemos descargar dos, Windows Installer y Windows ZIP file fon non admin install. Mi
recomendación es que te bajes la versión Windows Installer.
Como ya te he comentado en la lección anterior, es interesante colaborar con el proyecto de Arduino
para que sea sostenible. Si ya lo has hecho, haz click en JUST DOWNLOAD.
Esto te abrirá una ventana para que selecciones la carpeta donde quieres guardar el instalador. Las
selecciones y lo gurdas. Acuérdate de la ruta porque luego, tendremos que ejecutar este archivo.
Instalar el IDE de Arduino en el ordenador
Abre la carpeta donde hayas guardado el archivo y pulsa botón derecho y Ejecutar como
Administrador. Es importante este paso ya que este software requiere de permisos de administrador
para ejecutar ciertos procesos.
La primera ventana que te va a aparecer es para que aceptes la licencia del software. Haz click en I
Agree.
En la siguiente ventana nos permite seleccionar los componentes del software que queremos instalar.
Hay 5 opciones:
Ahora toca elegir donde instalarlo. Por defecto te pone la ruta C:\Program Files (x86)\Arduino que
es la que debes dejar. Haz click en Install.
Esto hará que comience la instalación. Aparecerá una barra de progreso que te irá informando cuanto
queda.
En algún momento de la instalación saldrá una venta que te hará la pregunta ¿Desea instalar este
software de dispositivo? Este software es que te va a permitir comunicar con Arduino a través del
USB. Haz click en Instalar.
Volverá a aparecer otra ventana de Seguridad de Windows donde te pregunta si quieres instalar el
Arduino USB Driver. Vuelve a hacer click en Instalar.
Y con esto damos por terminada la instalación. Al final, si todo ha ido correctamente, aparecerá la
siguiente pantalla donde pone Competed. Para cerrar el instalador haz click en Close.
Ya puedes ejecutar el IDE de Arduino y arrancarlo. Si has dejado marcado que te cree un acceso
directo en el escritorio, allí estará. Haces doble click sobre el icono y listo.
Relájate, no te preocupes, piensa que vas a empezar a escribir una carta a un amigo que en este caso
es un microcontrolador :). Para ello necesitaremos un procesador de textos y eso es lo que veremos
en esta lección, el procesador de textos (IDE) que nos permita comunicarnos con un
microcontrolador.
Vamos a dar un repaso por las partes más importantes de este software para poder empezar a trabajar
con seguridad.
Además, según van saliendo modelos, se van incorporando y verás como poco a poco la lista de
placas crecerá año a año. Para seleccionar Arduino UNO debes ir a
Herramientas>Placa>Arduino/Genuino UNO.
Para seleccionar la placa no hace falta que conectes Arduino al ordenador.
Para que aparezca en la lista tendrás que conectarlo a través del puerto USB. Es muy sencillo, cada
extremo del USB solo cabe en un sitio. Fíjate en las siguientes imágenes.
Un extremo va a la placa de Arduino y el otro extremo va al ordenador.
Ahora sí, selecciona el puerto accediendo a Herramientas>Puerto y aparecerá una lista de puertos
disponibles para seleccionar. Elige el que ponga algo relacionado con Arduino UNO.
Una de las preguntas básicas es ¿cómo se cuál es el puerto que corresponde con mi Arduino?
Imagínate que tienes dos Arduino UNO conectados al ordenador. Podríamos entrar a los paneles de
configuración del sistema operativo ya sea en Windows o MAC para averiguarlo.
Pero existe un método más sencillo que te ayudará a saber el puerto correcto para cada Arduino. Solo
tienes que conectar Arduino al ordenador, abrir el listado de puertos en Herramientas>Puerto y
memorizar la lista. No te preocupes, por lo general no tendrás más de 3 dispositivos.
Luego desconectas Arduino UNO que quieres programar o saber el puerto, y vuelves a entrar en la
lista. Verás cómo ha desparecido y por lo tanto, ya lo tienes localizado. Una solución rápida y sencilla
:).
De momento no está guardado en tu disco duro. Si quieres guardarlo tienes que ir a Archivo/Salvar.
Si el archivo es nuevo, abrirá una ventana de diálogo para que selecciones la carpeta y el nombre que
quieres dar al archivo. Por defecto, la carpeta que se abre es la que has seleccionado en la pantalla de
preferencias.
Además de poder guardarlo a través del menú Archivo/Salvar, puedes hacerlo a través del atajo de
teclado CTRL + S.
O pulsando el botón de acceso directo a guardar el archivo.
Además, es interesante conocer cómo lo guarda para no volvernos locos. Cuando guardas un fichero
en una carpeta de tu ordenador, el IDE de Arduino automáticamente crea una carpeta con el
mismo nombre de fichero y mete dentro el archivo.ino.
Sigamos con el ejemplo anterior. Has creado un programa y lo has guardado con el nombre MI-
PROGRAMA en la carpeta por defecto configurada en preferencias. Si ahora entras a esa carpeta
verás cómo ha creado una carpeta con el mismo nombre que has puesto al sketch y dentro está el
archivo MI-PROGRAMA.ino.
Es interesante recordar esto ya que puede que, si no lo sabes, no encuentres el fichero que has
guardado con el código 🙂
Una de las cosas más importantes es saber si tu código está guardado o no. Para informarte de esto,
el IDE muestra un símbolo al lado del nombre del archivo.
Yo personalmente soy un fanático de guardar a cada línea. Intento que el símbolo que hemos visto
no aparezca nunca :).
En la parte de arriba del editor encontramos los accesos directos a las funciones más utilizadas.
Empezando por la izquierda vamos ir viendo cada uno de los botones.
Verificar/Compilar
Compilar significa traducir el lenguaje que entendemos los humanos en lenguaje que entienden
las máquinas. Esta función nos va a ayudar a encontrar errores dentro del código.
El botón subir nos permite cargar el código a Arduino a través del puerto serie USB. Cuando
pulsamos este botón, además de compilar como la acción anterior, subiremos el programa al
microcontrolador de Arduino.
Esto eliminará cualquier otro programa que se haya cargado antes. Para saber que todo está
funcionando correctamente nos podemos fijar en dos luces de la placa donde pone RX y TX.
Podemos acceder también a través del atajo de teclado CTRL + U.
Y en el menú en Programa>Subir.
Nuevo
Si quieres crear un documento nuevo puedes hacerlo a través del botón o acceso directo.
O pulsando CTRL + N.
O en el menú Archivo>Nuevo.
Abrir
Este botón te permite abrir un archivo guardado en tu disco duro. Abrirá una ventana de navegación
para que busques el archivo con extensión.ino que quieres cargar en el IDE. Esta acción abre una
nueva ventana.
Por si no lo sabes, en cualquier menú de un software, cuando tentemos … al final de una opción quiere
decir que nos abrirá una nueva ventana para seleccionar alguna cosa. En este caso, nos indica que debemos
seleccionar el archivo que vamos a cargar.
Salvar
Esta opción ya la hemos visto antes, sirve para guardar el archivo en el disco duro.
El monitor serie es una de las partes más importantes en el IDE de Arduino. Te va a servir para
comunicar entre tu ordenador y Arduino y viceversa, desde Arduino a tu ordenador. Lo veremos más
adelante, pero es una ayuda fundamental para saber qué está pasando dentro del microcontrolador.
Por ejemplo, si pulsas el botón de subir, verás como aparece los siguientes mensajes:
1. Compilando programa…
2. Subiendo…
3. Subido
La consola
La consola nos va a dar información muy valiosa. Por un lado, nos mostrará si hay algún error y
donde se ha producido. Poco a poco nos iremos familiarizando con esta funcionalidad tan útil.
Por otro lado, nos muestra información relativa al proceso de subida del programa o sktetch. Nos
informa de cuanto ocupa, cuanto espacio queda de memoria en el microcontrolador, etc…
Conclusiones
En esta lección hemos visto las partes más importantes del IDE de Arduino. Con solo estas partes ya
podremos trabajar de una forma segura y empezar a programar nuestros primeros proyectos.
Quizás la primera pregunta que debamos responder es ¿qué placa elegir para empezar?
Lo realmente fascinante de Arduino, es que una vez que te inicias con una placa es sumamente
sencillo utilizar otras placas de Arduino e incluso de otras marcas.
En esta lección vamos a dar un repaso a todos los conceptos que hay detrás de esta placa tan popular.
¿Qué es un microcontrolador?
Entramos en acción y descubrimos qué hay detrás de la placa de Arduino. A simple vista, parece un
circuito sacado de algún dispositivo o de algún electrodoméstico. La realidad es que Arduino está
creado para facilitarnos la programación de un microcontrolador.
En este punto es necesario hacer una aclaración sobre qué son los microcontroladores. Si miras de
cerca tu placa, verás una pastilla o cucaracha grande donde pone ATMEL, la empresa que suministra
estos componentes a Arduino.
Verás en muchos textos que los microcontroladores los llaman MCU por sus siglas en inglés
Microcontroller Unit. Aunque no lo sepas, diariamente utilizas decenas de ellos en dispositivos
electrónicos, electrodomésticos, coches, ordenadores, etc…
Pero también existen otros circuitos integrados que se llaman microprocesadores. No hay que
confundir los términos, los microprocesadores son los procesadores que encontramos en los
ordenadores, por ejemplo. La gran diferencia que existe entre una MCU o microcontrolador y un
microprocesador es su utilidad.
Una MCU tiene como objetivo una tarea concreta, recoger los datos de un sensor y activar un
actuador, mover los motores de un sistema, etc…
Sin embargo, un microprocesador es de propósito general, puede hacer varias tareas a la vez como
por ejemplo recopilar la información de los datos, enviarlos por email y mostrarlos por una pantalla.
Un claro exponente de este tipo de dispositivos es la Raspberry Pi.
Otra de las ventajas de las MCU es que incluye en su interior las tres principales unidades funcionales:
Como supondrás, esto conlleva un ahorro de espacio increíble con respecto a los microprocesadores.
Dicho todo esto, vamos a ver qué papel juega Arduino a la hora de programar una MCU.
¿Te imaginas que tuvieras que programar ese chip? Te harías las preguntas típicas:
Son preguntas que un día alguien se las hizo y, gracias a que las pudo contestar, surgió Arduino 🙂
Todo lo que rodea a la placa de Arduino está pensado para facilitarnos la programación y
conexión con el microcontrolador. La huella o forma en la que están dispuestos los pines, la
conexión serie USB para programar y alimentar, el alimentador de baterías o pilas, en definitiva, cada
componente está puesto en su sitio para que todo sea más fácil para nosotros.
Pero, además, alrededor de Arduino se ha ido generando un mercado de componentes como sensores,
actuadores y shields a los que Arduino se conecta y dotan a la placa de funcionalidades extra.
Puerto USB
Ya hemos visto en la lección anterior que el conector USB es sencillo de conectar. Aunque parezca
que estamos trabajando con la comunicación USB la realidad es que estamos trabajando a través
del puerto serie.
Dentro de la placa de Arduino hay un conversor de USB a serie. También lo encontrarás con los
nombres de TTL o FTDI.
Esto nos facilita la tarea de programar la placa a través del puerto USB ya que nos permite cargar
los programas a través de este puerto.
Imagínate que no tuvieras ese conversor. Busca en tu ordenador si tienes un puerto serie, seguramente
no :).
La otra tarea que realiza este puerto es la de alimentación. A través del USB estamos suministrando
5V a la placa que es lo que necesita para que funcionen todos sus componentes.
Esto facilita mucho su uso ya que por un lado tenemos conectores hembra donde podemos conectar
los cables de una forma sencilla, y por otro lado vienen debidamente identificados.
Ahora te estarás preguntando ¿qué quiere decir digital? Como es algo abstracto, vamos a verlo con
un ejemplo práctico. Imagínate una paleta de colores de un pintor donde solo hay dos colores, blanco
o negro.
Si quieres pintar con un gris claro, por ejemplo, no puedes, no existe ese color. Tendrás que elegir o
blanco o negro, así de sencillo. Si esto lo llevamos al mundo de la electrónica y lo traducimos a
un voltaje como ocurre en Arduino, tendremos ALTO o BAJO en inglés LOW o HIGH.
Cada uno de estos estados corresponderá con un voltaje en el caso de la placa Arduino UNO es 0V
(LOW) o 5V(HIGH). Seguramente te estés preguntando ¿qué sucede si tengo por ejemplo 3,5V?
No es ni 5V, estado HIGH, ni 0V, estado LOW.
Internamente hay unas reglas por las que determinar si un voltaje es HIGH o LOW. Tendríamos algo
parecido a esto.
Todo lo que está entre 2V y 5V es estado HIGH. Todo lo que está entre 0V y 0,8V es estado LOW.
Entre 0,8V y 2V es una indeterminación lo que viene a decirnos que si tenemos un voltaje en ese
rango no sabrá si es HIGH o LOW y asignará un estado al azar.
Entrada (INPUT): puede leer voltaje es decir los estados LOW (0V) y HIGH (5V).
Salida (OUTPUT): puede suministrar voltaje es decir los estados LOW (0V) y HIGH (5V).
Excepción (PWM): algunos pines digitales (6 en concreto) marcados con el símbolo ~, pueden
suministrar un valor entre el rango de valores de 0V a 5V. Es una técnica llamada PWM que permite
variar el voltaje que suministramos por esos pines.
Dentro de esos 14 pines hay que destacar 3 porque realizan otras funciones además de entrada, salida
y PWM.
En la medida de lo posible se recomienda no utilizar estos pines ya que puede ocasionar interferencias con
la comunicación serie, te lo digo por experiencia :).
El pin 13 es el pin de la mala suerte. Cuenta la historia:), es broma. Este pin está conectado a un
LED de la placa y es el primero que vamos a utilizar cuando empecemos a ver el código de Arduino.
El pin AREF no se suele utilizar, sobre todo al principio, así que no lo veremos por ahora. El otro pin, el
GND, lo veremos en los pines de alimentación ya que hace la misma función que los que hay en ese zócalo.
Pines analógicos
Es el zócalo donde pone ANALOG IN y van numerados del A0 al A5, 6 pines.
Te acuerdas lo que te he dicho sobre digital, una paleta de colores con dos únicos colores el blanco y
el negro. Pues en el mundo analógico la paleta de colores ya no tiene solo dos, ahora podemos medir
diferentes tonos de gris.
Si lo traducimos al mundo electrónico de Arduino, con estos pines podremos medir diferentes
voltajes entre 0V y 5V. Muchos sensores trabajan con los pines analógicos para determinar su estado.
Pero existe un problema y es que la MCU o microcontrolador solo entiende datos digitales 0 s y
1’s. Parece una contradicción, pero es así. Para resolver esto la propia MCU dispone de un ADC
(son las siglas en inglés Analog Digital Converter o en español Conversor Analógico Digital).
Aunque parezca que es algo trivial, imagínate cuantos números hay entre 0 y 5. Si te paras a pensar
puede haber infinitos. El número 3,14159265358979323846… (número pi) está en este rango y he
parado de poner decimales.
Por lo tanto, esa conversión tiene que estar acotada por algo y a eso se le llama resolución. En el
caso del Arduino UNO esa resolución es de 10-bit lo que equivale a que solo puede haber 1024
valores posibles del 0 al 1023.
Pines de alimentación
Este zócalo de pines nos servirá para alimentar los componentes, sensores y actuadores que
conectemos a la placa.
De todos los que hay, nos tenemos que quedar con cuatro.
Estos shields (mal traducidos como escudos y que yo no volveré a pronunciar con ese nombre
:), aportan diversas funcionalidades a la placa como conexión a una red, mover motores, etc…
Estos shields los suministran diferentes fabricantes. Podemos encontrar de origen chino (sin una
marca o fabricante) o de empresas como Sparkfun y Adafruit.
Estas dos empresas son punteras y pioneras en este tipo de componentes. Te recomiendo que en la
medida de lo posible adquieras de estos fabricantes ya que son de mucha confianza.
Botón Reset
Pues hace precisamente eso, resetear la placa, pero ¿qué diablos es resetear? Lo veremos más en
profundidad cuando te hable de las funciones loop() y setup().
Básicamente consiste en comenzar de cero la ejecución, pero ojo, este botón no borra el programa
que hemos cargado. Sin embargo, cualquier valor de una variable la elimina.
Pin Reset
En algunos proyectos el botón Reset queda escondido dentro de una carcasa e imposible de ser
pulsado. En estos casos la única manera que tenemos de resetear es desconectando la alimentación.
Sin embargo, el pin Reset nos permite accionar esta función a través de poner un estado 0V (conexión
con GND o tierra).
Esto resulta muy práctico ya que, si lo cableamos con un pulsador y la configuración adecuada,
podremos resetear la placa sin desconectarlo de la red eléctrica.
LED de encendido
¿Cómo sabemos si la placa está siendo alimentada? Pues como lo hacemos con cualquier otro tipo de
dispositivo, a través de un LED.
Este LED nos permite saber si la placa recibe energía o no. Es un buen comienzo si tenemos algún
problema con la placa. Lo primero que debemos hacer es comprobar si está encendido o no.
Con respecto al rango de operación que admite este conector, sucede igual que con el pin Vin.
Podemos alimentarlo con una tensión de entre 6V y 12V.
Estas últimas características las he puesto para que te suenen cuando las veas en la placa. En el punto en el
que estamos es mejor centrarse en las características importantes y seguir avanzando. Cuando llegue el
momento ya tendrás tiempo de investigar todo lo que puedes hacer con un Arduino.
Conclusiones
En este curso vamos a trabajar con la placa Arduino UNO debido a que es la más popular, la más
vendida y el buque insignia de Arduino.
Hemos visto una introducción a una de las partes importantes a la hora de programar electrónica, el
hardware.
Dentro de todas las características y posibilidades que nos suministra la placa, hay que centrarse en
lo básico.
No te asustes por el título de esta lección, se que en estos momentos acabas de desconectar :). En esta
lección veremos que es lo que sucede cuando pulsamos en el botón subir programa del IDE de
desarrollo.
Todo esto parece magia pero la realidad es que por debajo ocurren ciertos procesos por el que el
código que escribimos en el IDE termina cargado en el microcontrolador. Es lo que sucede por detrás,
lo que no podemos ver y que te explicaré a continuación.
No voy a entrar en detalle, solo te daré los conceptos necesarios para entiendas el proceso que se
ejecuta por debajo. Es importante conocer estos conceptos para entender cómo funciona Arduino.
A todas las herramientas y procesos que están involucrados en la acción de subir el código se le llama
en informática Toolchain (en español cadena de herramientas).
Arduino tiene su propia cadena de herramientas o toolchain para subir el código que has programado
al microcontrolador.
Imagínate que escribes un libro. Desde que tu concibes la idea en tu cabeza hasta que llega a una
librería en formato libro suceden varios procesos cuyo objetivo es tener un libro.
El Toolchain de Arduino
Ya hemos visto parte de esta cadena de herramientas o toolchain en lecciones anteriores como el IDE
de desarrollo. Pero además hay más herramientas que nos permiten cargar o subir el programa al
microcontrolador.
1. IDE de desarrollo
Hace la función del procesador de textos y es donde escribimos el código. Si un escritor utiliza un
idioma (el nuestro sería el español) para programar un microcontrolador escribimos en un lenguaje
que se llama C++.
Este tipo de lenguajes se llaman de alto nivel y se entienden fácilmente por los seres humanos, aunque
necesitas tener ciertos conocimientos de inglés. Se guarda en los discos duros con extensión .ino.
El IDE hará las funciones del procesador de textos, comprobar esté bien escrito según las reglas del
lenguaje y facilitar las herramientas para hacer más fácil la codificación.
El inconveniente que existe es que el microcontrolador no entiende este lenguaje (C++), solo entiende
un lenguaje llamado código máquina. Aquí es donde entra en juego la siguiente herramienta, el
compilador.
2. El compilador
Un compilador no es más que un software que se encarga de leer el código de alto nivel (C++) y
convertirlo a código máquina. El compilador entra en acción de dos maneras, cuando pulsamos a
compilar y cuando pulsamos a subir.
El que utiliza la plataforma de Arduino se llama AVR-GCC y se encarga de reordenar el código y
buscar posibles errores de sintaxis. Es como si fuera el editor profesional, si algo está mal no permitirá
que el proceso continúe.
La salida del compilador es un archivo hexadecimal (con extensión .hex) en código máquina. En este
punto el microcontrolador ya entendería lo que queremos que haga. Ahora el problema está en mandar
ese código al microcontrolador.
3. AVRdude
El AVRdude es un programa excelente que permite subir el archivo hexadecimal de código máquina
generador por el compilador al microcontrolador a través del puerto USB.
Antiguamente, se necesitaba un hardware externo para esta tarea (los programadores PIC por
ejemplo) pero en Arduino todo está muy bien pensado.
Dentro del circuito integrado tiene cargado un software muy pequeño. Este software ya viene
precargado dentro de la placa y se llama Bootloader.
Entre estos dos programas, AVRdude y Bootloader, se encargan de coger el archivo hexadecimal en
código máquina y cargarlo en la memoria Flash para que lo pueda leer el microcontrolador.
Y este sería el toolchain o la cadena de herramientas que se ejecuta cuando damos al botón de subir
en el IDE de Arduino.
Conclusiones
Con esto terminamos este módulo donde hemos visto una introducción a la programación de Arduino
a través del IDE, el hardware que incluye la placa y como se unen estas dos patas para facilitarnos la
vida a la hora de programar un microcontrolador.
Vamos a ver la sintaxis básica que necesitamos conocer para comenzar a recorrer nuestro camino.
Esta sintaxis es la que se utiliza en todos los programas que hagamos para cualquier placa de Arduino.
¿Qué es la sintaxis de la programación?
Fuera de lo que pueda parecer, la sintaxis de la programación tiene muchas cosas en común con la
gramática y la puntuación dentro de un idioma. Me gusta utilizar esta analogía porque todo el
mundo lo puede entender.
Si sabes leer y escribir, sabes programar. Si has leído un libro (incluso me valen de ejemplo estas
mismas líneas), estarás familiarizado con la puntuación y la gramática. Sabrás qué es un punto, una
coma, guiones, tildes o el punto y coma.
Además de los signos de puntuación, un idioma tiene formas verbales, sustantivos, diptongos y
todo tipo de gramática para cada uno de ellos. La puntuación y la gramática nos ayudan a
comunicarnos entre las personas a través de la palabra escrita.
Por ejemplo, una coma transmite una pausa, un punto indica que se ha acabado una oración o la
cursiva y la negrita para hacer énfasis en palabras y frases. Estas herramientas nos ayudan a que
el lector se haga una mejor idea de lo que tenemos que transmitir.
Igual que con las palabras y frases escritas se requieren los signos de puntuación y la gramática, los
lenguajes de programación requieren de una sintaxis para comunicarnos con el compilador.
No te va a dejar pasar ni una. No te creas que es una carta que envías a un amigo donde da lo mismo
si pones alguna falta de ortografía o de puntuación, para el compilador necesitas un 10 en cada
programa.
Al principio te costará encontrar los errores o saber que significan. Sin embargo, según vas
progresando, se convertirá en algo natural, como si escribieras una carta a un amigo o un informe.
Será tu segunda lengua después de la materna.
Comentarios
Los comentarios son notas que un programador deja en el código para ayudar a comprender parte de
ese código. No se trata de poner un informe completo sobre lo que hace una sentencia, una función o
un programa completo, se trata de explicar de forma breve su función.
Es una de las partes más importantes de un programa, pero no se compila o traduce a código máquina.
El compilador obvia cada comentario y por lo tanto no lo carga en el microcontrolador.
1 //Esto es un comentario
2 int variable = 0;
Todo el texto después de la doble barra (//) se pone en color gris. Eso nos indica que esa parte es un
comentario.
La otra manera es poniendo un /* para abrir y */ para cerrar. Todo lo que esté contenido entre esos
dos marcadores será tratado como un comentario.
1 /*
5 */
6 void setup() {}
Puedes comprobar que todo lo que hay dentro está en gris, eso nos indica que es un comentario. Los
asteriscos de la izquierda no quieren decir nada. El propio IDE de desarrollo se encarga de ponerlos.
Como ya te he comentado, todos estos comentarios se ocultan al compilador, sin embargo, están
disponibles para cualquier persona que quiera consultar el código incluso tú mismo.
Por ahora no voy a entrar más en detalle, a lo largo de este curso y de los demás cursos puedes
comprobar la utilización que hago de esta herramienta. Hay que intentar ser descriptivo y explicar lo
que hace parte de nuestro código.
Punto y coma
Dentro del lenguaje de programación C++ el punto y coma (;), es como el punto y aparte en el idioma
español. Estamos diciendo que hemos completado una sentencia y a partir de ese momento,
empezamos algo nuevo sin relación a lo anterior a nivel de sintaxis.
2 int variable = 0;
Se que a lo mejor todavía no significa nada para ti el anterior código, lo que yo quiero es que te centres
en el punto y coma final. El compilador entiende que a partir de ahí todo lo que escriba será una
sentencia nueva, sin nada que ver con la anterior.
2 int variable1 = 0;
5 int variable2 = 0 ;
8 int variable3 = 0;
12 ;
Da lo mismo que tenga un espacio antes o después o que esté en otra línea. La función es la misma y
no da error de compilación.
¿Qué sucede si eliminamos el punto y coma o se nos olvida ponerlo? Vamos a comprobarlo. Copia
el siguiente código en el IDE.
2 int variable1 = 0
4 void setup() {
7 }
9 void loop() {
11
12 }
Da al botón de verificar que vimos en el anterior módulo. Esto te mostrará un error en la barra de
mensajes y en la consola.
Hemos tardado unas cuantas lecciones, pero por fin nos enfrentamos a nuestro primer error, uhuuuuu
:). Vamos a analizarlo para ver cómo tendríamos que resolverlo.
Lo primero que tengo que decir que en el caso de olvidarnos de poner un punto y coma el error es
muy descriptivo. En otras ocasiones no tendremos tanta suerte :(.
Área de mensajes
Nos muestra un mensaje bastante descriptivo “expected ‘,’ or ‘;’ before void” (en español “espera ‘,’
o ‘;’ antes de void“) es decir, que nos falta poner una coma o un punto y coma antes de la palabra void.
Consola
En la consola además nos dará más información. Ya no solo nos dice que nos falta un punto y coma,
ahora nos dice el nombre del archivo (sketch_may29) seguido de la línea (4) en la que se encuentra
el error y nos muestra donde está la palabra void dentro del código.
Editor de código
Por último, en el editor nos saldrá una franja roja en la línea donde se hace referencia en la consola.
En este caso es la línea 4.
Si pones un punto y coma al final y de das a verificar comprobarás como el error desaparece.
Palabras reservadas
Si ya has estado probando algún código con Arduino (espero que si que lo hayas hecho :), te habrás
dado cuenta que con ciertas palabras el color del texto cambia dentro del IDE de Arduino. Estas
palabras son reservadas por el lenguaje C++.
1 HIGH
2 LOW
4 true
5 false
6 this
7 INPUT
8 OUTPUT
Cada palabra reservada tiene funciones específicas para nosotros y están reservadas por el lenguaje
de programación. No podemos utilizarlas para nombrar variables, por ejemplo.
Hay unas cuantas palabras clave a parte de estas. De momento no vamos a profundizar para que se
utilizan, las iremos viendo según las vayamos necesitando.
Lo único que tienes que recordar es que, si cambia de color dentro del IDE de desarrollo, es que es
una palabra reservada.
Las funciones
Aunque parezca algo muy adelantado, es necesario conocer la sintaxis de las funciones ya que será
una de las primeras cosas que veamos. Voy a darte una descripción muy básica de su significado.
No son más que trozos de código que se usan frecuentemente dentro de un programa. Esto facilita su
utilización y el código se queda más limpio y ligero.
Imagínate que tenemos un código que transforma los grados en radianes. Esto se hace multiplicando
el número de grados por pi y dividiendo entre 180.
Si utilizas constantemente esta línea de código, quizás te interese convertirlo en una función. De esta
manera solo tendrás que escribir
1 grados_a_radianes(grados);
Mucho más fácil a que sí. Ya no es solo las funciones que nosotros mismos creamos, Arduino tiene
un montón de funciones incorporadas. Te darás cuenta porque cambian de color cuando las escribes.
1 Serial.begin(9600);
2 pinMode(13, OUTPUT);
Son como las palabras reservadas que hemos visto antes. Se puede decir que las funciones son como
los verbos de un lenguaje de programación, hacen que las cosas sucedan por y para nosotros.
Pero realmente no quiero hablarte de qué son y para qué se utilizan las funciones, todo esto lo veremos
a lo largo del curso. Lo que realmente me interesa es la sintaxis a la hora de llamar a una función.
Todas las llamadas a funciones comienzan por el nombre de la propia función. Luego va seguido de
un paréntesis abierto y si tuviera parámetros, se incluirían a continuación separados por comas. Por
último, cerramos el paréntesis y el punto y coma final para indicar que hemos acabado con esta
sentencia.
Los parámetros son información que facilitamos a la función para que realice su tarea. En el caso de
la conversión entre grados y radianes la función necesita del valor de grados. Eso es lo que le pasamos
para que realice la operación.
Puede ser que la función no admita parámetros, es bastante común. En este caso también es necesario
poner los paréntesis.
1 nombre_funcion();
El IDE de Arduino nos ayuda a localizar el paréntesis de cierre o apertura. Si te pones al lado de un
paréntesis de una función (da lo mismo a la izquierda o derecha) te señalará el cierre o apertura según
estés situado.
Diseño y tabulación del código
Cuando estamos programando es preferible ver un código estructurado y tabulado que un código sin
tabular. Como norma general, siempre que tengamos un código dentro de unas llaves ({}) se sangra
dos espacios hacia la derecha.
1 void setup() {
4 Serial.begin(9600);
5 pinMode(13, OUTPUT);
6}
Esto se puede hacer de dos maneras, dando dos veces a la tecla espacio o utilizando la tecla tabulador
(Tab). Al igual que ocurre con los comentarios, esto no tiene ningún efecto en el compilador. Solo
nos sirve para tener ordenado nuestro código.
1 void setup() {
2 Serial.begin(9600);
3 pinMode(13, OUTPUT);
4 }
5
6 void loop() {
7 if (true) {
8 // Haz aglo
9 int variable = 0;
10 }
11 }
1 void setup() {
2 Serial.begin(9600);
3 pinMode(13, OTUPUT);
4 }
6 void loop() {
7 if (true) {
8 // Haz aglo
9 int variable = 0;
10 }
11 }
Seguro que notas la diferencia :). Pero quizás te estés preguntando ¿tengo que hacerlo de forma
manual para cada línea de código?….pues no. El IDE de Arduino nos aporta dos funcionalidades que
nos ahorran el trabajo.
La primero es que siempre que pongamos abramos una llave y demos a Enter, esto nos crea la llave
de cierre y en la siguiente línea ya ha puesto la tabulación automática (dos espacios).
Y la segunda ayuda es que tenemos una opción de ordenar todo el código de forma manual. Dentro
del editor de código pulsa botón derecho y selecciona Auto Formato.
No te preocupes si ahora no le ves ninguna utilidad, ya verás como a lo largo del curso lo utilizamos
mucho.
Resumen de lo visto
En esta lección hemos empezado a ver la sintaxis de la programación de C++ comenzando por los
comentarios. Aunque no se compilen, aportan información de lo que hace el código.
El punto y coma separa cada línea de ejecución informando al compilador cuando termina una línea
y empieza otra.
A continuación, hemos visto como las palabras clave cambian de color cuando se escriben en el IDE
de Arduino, al igual que las funciones propias del lenguaje. Además, hemos visto cual es la sintaxis
cuando llamamos a una función.
Por último, hemos prestado atención a cómo dejar bien claro el código con la tabulación ya sea
automática o manual.
Una variable no es más que una herramienta de programación que nos ayuda a almacenar y recuperar
información en nuestros programas.
Memoria
Un microcontrolador, como el que utiliza Arduino, al igual que los ordenadores en general, tienen
algo que se llama memoria. La memoria nos sirve para almacenar información que utilizaremos
posteriormente y es extremadamente útil.
Por ejemplo, imagínate que quieres monitorizar la temperatura de tu casa a lo largo del día. Cada hora
vas a tomar la temperatura y en una pantalla LCD vas mostrar la temperatura más alta.
¿Cómo guardar esta información en un programa o sketch? ¿cómo recordamos donde está guardada
esa información? Gracias a la memoria todo esto es posible.
Podemos comparar la memoria como una estantería donde tenemos diferentes apartados o taquillas
donde guardamos cosas. Cada taquilla tiene un número y precisamente eso es una variable.
Si lo miramos desde un punto de vista técnico, una variable es la dirección de una ubicación dentro
de la memoria. Pero no quiero entrar en tecnicismos que no entendamos, es mejor profundizar en el
uso práctico de las variables. Sigamos con el ejemplo.
Como ya te he comentado, el objetivo del proyecto es registrar la temperatura más alta del día. Por lo
tanto, necesitamos almacenar dos datos en dos variables: la temperatura actual y la temperatura
máxima.
Esto significa que en esa estantería debemos de reservar dos taquillas, una para la temperatura actual
y otra para la máxima.
Cuando el programa empieza a funcionar, toma la primera temperatura. Esa se almacena en la taquilla
de temperatura actual. Imagínate que es 25. Al mismo tiempo la taquilla de temperatura máxima está
vacía. Si comparamos 25º con nada, esa temperatura es mayor y por lo tanto se almacenará también
en la taquilla de temperatura máxima.
Tras pasar una hora, vuelvo a tomar la temperatura. Ahora es de 26º y lo almaceno en la taquilla de
temperatura actual. Como 26º es mayor que 25º, también lo almaceno en la taquilla de temperatura
máxima. Estas dos acciones sustituyen los valores anteriores de 25º.
Con este ejemplo vemos una de las funciones más poderosas de las variables. Podemos cambiar el
valor de esa variable, pero el nombre sigue siendo el mismo ya que la variable solo contiene la
información.
Siguiendo con la analogía de la estantería, no debemos confundir la taquilla con la información que
hay dentro. La taquilla siempre tendrá el mismo número (en el caso de variables el mismo nombre),
lo que cambia es lo que hay dentro.
Vamos a recapitular lo que hemos visto hasta aquí. En nuestros programas necesitamos almacenar
información y utilizamos la memoria para ello. Sería como una estantería llena de huecos o taquillas
cada una de ellas con un nombre único. Este nombre será nuestra variable.
Conociendo el nombre podemos poner cosas dentro de la taquilla para posteriormente hacer uso de
esa información cuando lo necesitemos. Recuerda que el nombre se refiere a la ubicación y no al
contenido que hay dentro.
Tipos de datos
Además de dar un nombre a la variable, tenemos que hacer otra cosa con ella. Debemos indicar que
tipo de información vamos a almacenar en esa variable.
Creo que ya me vas conociendo y que mejor que una analogía para entender este concepto. Imagínate
que trabajas en una tienda de animales muy grande o en un zoo donde tienes tigres, gorilas, monos,
pájaros, tortugas y toda clase de animales y de todos los tamaños.
Si los vas a meter en jaulas no tiene sentido que metas a un tigre o un gato en la jaula de un canario
y viceversa. A cada uno le tienes que dar el espacio suficiente para que pueda moverse a sus anchas.
El canario a una jaula grande, donde tenga espacio para volar y sitio para posarse. A un mono o gorila
en un espacio muy grande con árboles y obstáculos que pueda trepar.
Donde quiero llegar es que no podemos coger a un gato y meterlo en la jaula del canario, no
funcionaría :). Lo mismo ocurre con las variables, tenemos que especificar el tipo de dato que vamos
a guardar.
Imagínate que tienes una variable que solo puede almacenar números enteros, positivos y negativos
(-23, -22, -15, -1, 0, 4, 17, 98). Si la declaras de este tipo solo podrá almacenar números enteros. Si
intentas almacenar por ejemplo 3,14 obtendrás un error.
Por lo tanto, cada variable solo podrá almacenar un tipo de dato especificado cuando se declara dicha
variable.
Declaración de variables
Poco a poco vamos adentrándonos en el mundo de la programación gracias al concepto fundamental
de las variables. Ya sabemos que utilizan la memoria para almacenar datos y que solo almacenan un
tipo de dato.
Ahora veremos qué es declarar una variable. Decimos declarar, pero lo que hacemos es crear una
variable. Necesitamos dos cosas, un nombre y un tipo de dato. En C++ siempre se pone el tipo de
dato primero y luego el nombre.
1 int primeraVariable;
Por ejemplo, en la anterior línea he declarado una variable del tipo entero (int) con el nombre
primeraVariable. Las variables del tipo entero pueden almacenar valores desde -32.768 a 32.767. Ese
sería su rango.
Por supuesto que no tienes que memorizar esos datos.
La palabra reservada int indica el tipo de dato entero y, como vimos en la lección anterior, en el IDE
de desarrollo cambia de color ya que reconoce todos los tipos de datos de Arduino. Luego va seguido
de un espacio y por último el nombre seguido del ya conocido punto y coma.
Nombrando variables
Los nombres de las variables no pueden tener espacios ni caracteres especiales ($, %,&,/,”, ñ, etc…).
Al final es aplicar un poco de sentido común, no tiene más. Si no te sabes todas las palabras reservadas
no te preocupes, el IDE de Arduino te ayudará a recordarlas cuando cambie de color 🙂
Los nombres de las variables tienen que ser descriptivos de lo que contiene, por ejemplo, si
almacenamos una temperatura es conveniente llamar a la variable temperaturaMaxima por ejemplo.
No tiene sentido llamarla variable1 🙂
De esta manera, cuando veamos la variable en el programa que estamos escribiendo sabremos a
simple vista que información tiene almacenada esa variable.
Una de las convenciones más habituales se llama camelCase. Lo que nos indica que, para distinguir
las palabras del nombre de una variable, siempre se ponen en mayúsculas las primeras letras de cada
palabra salvo la primera palabra.
1 int temperaturaMaxima;
2 int temperaturaActual;
3 int radiacionUV;
4 int presionAtmosferica;
1 int temperatura_maxima;
2 int temperatura_actual;
3 int radiacion_uv;
4 int presion_atmosferica;
A lo largo de los diferentes cursos de la plataforma, utilizo varias convenciones, aunque mi preferida
es camelCase. Espero que la tuya también lo sea 🙂
Inicialización de variables
Cuando hablo de inicializar una variable me refiero a asignar un valor. Por supuesto que esto solo se
puede hacer una vez que conozcamos el tipo de dato e incluso se puede hacer en la misma línea.
Podemos decir que es el tiempo que tarda entre la declaración y la asignación de un valor. Si se hace
todo en la misma línea ese tiempo es prácticamente despreciable.
A continuación, dos ejemplos, el primero declara una variable y luego se inicializa con un valor.
1 int temperaturaMaxima;
2 temperaturaMaxima = 25;
Hasta ahora lo que habíamos visto es que al declarar una variable poníamos el tipo, el nombre y el
punto y coma. Para inicializar una variable o para asignar un valor a la variable utilizamos el operador
de igualdad que no es más que el signo igual (=).
Si queremos cambiar el valor en cualquier momento, solo tenemos que poner el nombre de la variable,
el operador de asignación (=), el valor que queremos asignar y lo más importante, el punto y coma
final.
Como ves es muy sencillo, solo tenemos que conocer el tipo de dato y ya podemos almacenar un
valor en la memoria.
Resumen de lo visto
Recapitulemos lo que hemos visto en esta lección. Una variable es solo el nombre que hemos puesto
a una posición de memoria y las utilizamos para almacenar y recuperar datos en nuestro programa.
Para declarar una variable hay que decir qué tipo de dato vamos a almacenar y darle un nombre. El
nombre debe seguir unas reglas básicas y como costumbre deberíamos utilizar alguna convención
como camelCase.
Para inicializar o asignar un valor utilizamos el signo igual u operador de asignación. Si es la primera
vez que lo hacemos se llama inicialización y si queremos cambiar el valor en la ejecución del
programa se llama asignación.
Si repasamos lo aprendido en lecciones anteriores, sabemos que cuando se declara una variable hay
que asignar un tipo de dato. Esto no es más que comunicar al compilador que tipo de dato vamos a
almacenar.
Lo hacemos poniendo antes del nombre una palabra reservada del lenguaje que identifica la
información que vamos a almacenar. Pero los tipos de datos dan más información:
Entero (int)
El tipo de dato entero se escribe en C++ como int. Es el más utilizado y debes acostumbrarte lo antes
posible a él. Ya hemos visto algún ejemplo donde lo utilizamos.
El rango de valores viene determinado por la cantidad de memoria que reserva. Para un entero se
utilizan 2 bytes es decir 16-bit. Esto nos da un rango de entre -32.768 y 32.767. El mayor número que
podemos almacenar con 2 bytes (16-bit) es el 1111111111111111 (son 16 unos).
Si ese valor lo traducimos a decimal nos da 65.535. Ese sería el valor máximo que podemos obtener,
pero como este tipo de dato almacena valores positivos y negativos, tenemos que dividir ese valor
entre dos y nos da 32.767,5.
Por lo tanto, el rango de valores es desde -32.768 a 32.767. Da lo mismo que en una variable de tipo
entero almacenemos un 3 o 30.000, el compilador va a reservar los 2 bytes de memoria lo utilicemos
o no.
Dentro de las capacidades de la memoria de un microcontrolador, 2 bytes no significan tanto. Por este
motivo, los enteros (int) son tan utilizados.
Ahora bien, ¿qué pasa si ponemos un número fuera de ese rango? Lo que ocurre es muy curioso, se
da la vuelta es decir comienza por el otro extremo. Por ejemplo, si tenemos una variable entera con
el valor 32.767 y le sumamos uno, el valor que toma es -32.768.
Del mismo modo que si tengo una variable con el valor -32.768 y le resto uno, se obtiene como
resultado 32.767.
Todo esto nos lleva a un punto muy interesante. Cuando declaramos una variable tenemos que ser
conscientes del valor que va a almacenar e intuir como de grande puede llegar a ser. Con esa variable
podemos hacer diferentes operaciones y por lo tanto, podrá exceder el rango por arriba o por abajo.
Ya has visto el resultado, si no llevamos cuidado podemos tener un resultado bastante extraño.
Pero ¿qué ocurre si quiero almacenar un número superior a 32.767?. Bueno, tenemos un par de
opciones. La primera que vamos a ver es almacenar ese valor en un entero algo especial, entero sin
signo (unsigned int).
¿Qué ocurre si sabemos que solo vamos a trabajar con números positivos? Si utilizamos una variable
entera, estaremos desperdiciando la mitad del espacio ya que la parte negativa no la vamos a utilizar.
Puede ser el caso en donde almacenemos cuantos días han pasado desde una determinada fecha, la
presión atmosférica o la humedad relativa del aíre. Estos valores no son nunca negativos y resulta
más conveniente utilizar un entero sin signo.
Para utilizar este tipo de dato, solo tenemos que indicarlo justo antes del tipo de dato int con la palabra
reservada unsigned (en español significa sin signo). Con esto conseguimos que el rango de valores
sea de 0 a 65.535. Eso sí, la reserva de memoria sigue siendo la misma 2 bytes o 16-bit.
El funcionamiento es igual que un entero con signo (int). Si tenemos una variable con un valor de
65.535 y le sumamos 1, el resultado será 0 ya que empieza por el otro extremo.
Aun así, si con esto no tenemos suficiente ahora vamos a ver un tipo de dato que puede almacenar
números positivos y negativos más grandes.
Con este tipo de variables podemos almacenar valores muy altos. Es conveniente hacer un pequeño
estudio del valor máximo que podemos llegar a almacenar y buscar el tipo de dato más adecuado.
Decimal (float)
Hasta ahora hemos visto números enteros, pero ¿qué pasa si queremos almacenar un número decimal?
En programación a este tipo de número se les llama de coma flotante de aquí el nombre del tipo de
dato, float.
Para separar la parte decimal de la parte entera se utiliza el “.”. Puede resultar extraño ya que
nosotros utilizamos la “,”. Esto es debido a la influencia anglosajona en los lenguajes de
programación.
El rango de valores que podemos almacenar es de 3.4028235 x 1038 hasta -3.4028235 x 1038. Son
números realmente grandes, pero al contrario de lo que podamos pensar, solo utiliza 4 bytes de
memoria (32-bit). Es la misma memoria que un entero largo.
¿Cómo es posible que utilicemos la misma cantidad de memoria en un entero largo y un número
decimal? Todo se reduce a la precisión. En realidad, un número de coma flotante es bueno hasta 6 o
7 cifras. Esto incluye a la parte decimal y a la parte entera.
Se consigue almacenar debido a como se almacenan los números de coma flotante con una notación
científica utilizada dentro de las CPU, GPU y demás unidades de procesamiento. Esto permite
representar números extremadamente grandes y pequeños de una manera muy eficiente y compacta.
En Arduino lo que sucede es que a partir de las 7 cifras van a ser redondeados sin saber muy bien
como lo hace el compilador. Esto implica que no sean una buena elección en estos casos.
En el ejemplo anterior he utilizado una notación especial para inicializar un número de coma flotante.
Es otra manera de expresarlo. A través de la letra E indicamos cuantos ceros acompañan a la cifra
anterior. En el caso de 12E3 es lo mismo que 12 x 1000 = 12.000.
Si te soy sincero, casi nunca utilizo esta notación, pero está bien que la conozcas por si acaso.
Siempre que nos sea posible utilizaremos variables enteras para evitarnos problemas de precisión y
para que los cálculos sean más rápidos. A nivel de computación, los microcontroladores tardan
menos en hacer operaciones con enteros que con números de coma flotante.
Byte (byte)
Existe otro tipo de dato que es el más pequeño de los que hemos visto hasta ahora, es el byte. Puede
almacenar un número de 0 a 255 y por lo tanto es sin signo. Como su nombre indica solo ocupa un
byte.
Igualmente, si queremos representar el número 255 en binario, tendrás que poner ocho unos seguidos
(11111111). Esto sería el máximo y representa 1 byte es decir 8-bit.
El objetivo de esta lección no es profundizar en el sistema binario, por ahora. Hay mucha literatura y
páginas web donde puedes encontrar información sobre este sistema de numeración.
Es un tipo de dato muy interesante. En principio solo admite 2 valores (1 y 0) pero ¿qué ocurre si le
asignamos un valor diferente?
Como hemos visto con los casos anteriores, cuando llegamos al final de rango empezamos por el
principio. Esto no se cumple con un booleano. Si es 0 será falso (false) y si es diferente de cero será
verdadero (true).
Para decir que una variable es falsa, tenemos varios métodos. Asignando el valor de 0 o las palabras
reservadas false y LOW. No te preocupes si no encuentras sentido ahora mismo a todo esto, más
adelante lo veremos en detalle.
2 boolean boolConCero = 0;
Si queremos asignar un valor verdadero, solo tenemos que poner cualquier número distinto de cero o
las palabras reservadas true y HIGH.
2 boolean boolConNumero1 = 1;
Este tipo de variables se utiliza para comprobar una situación que solo puede estar en dos estados,
¿ha pasado por aquí true/false?, ¿ha superado la temperatura? o ¿ha sumado el número true/false?
Carácter (char)
Llegamos al último tipo de dato que vamos a ver, el carácter representado por char. Utiliza un byte
de la memoria y nos permite almacenar una letra, pero lo hace de una forma especial.
Realmente estamos almacenando una letra como si fuera un número. Este sistema se llama ASCII y
gracias a una tabla podemos saber la correspondencia entre letra y número. Con un solo byte podemos
representar todas las letras (mayúsculas y minúsculas) y un montón de símbolos.
Todo esto implica que podemos asignar un número o una letra según nos convenga.
Las dos variables anteriores tienen el mismo valor, la letra ‘p’. Esto nos da muchas posibilidades ya
que se pueden hacer operaciones matemáticas con estas variables, aunque de momento no vamos a
entrar en ello.
Resumen de lo visto
En esta lección hemos visto diferentes tipos de datos los cuales sirven para almacenar una información
específica.
Los enteros (int), enteros sin signo (unsigned), enteros largos (long) y enteros largos sin signo
(unsigned long) almacenan números sin decimales, números enteros. Utilizar uno u otro dependerá
del número más grande que queramos almacenar.
Los números con decimales (también llamados de coma flotante) se almacenan en float. Permiten
almacenar números más grandes, pero debemos tener cuidado con la precisión.
Los bytes son el tipo de dato numérico más pequeño y solo necesita un byte de la memoria.
En todos estos casos debemos prestar especial atención cuando nos salimos del rango por delante y
por detrás. Esto implica que comienza por el extremo opuesto.
El tipo booleano (boolean) solo admite 1-bit (0 o 1). El tipo carácter (char) sirve para almacenar letras
en texto o en número (código ASCII).
Veremos cómo hacer llamadas a funciones, sus parámetros, argumentos y las diferentes formas en
las que podemos encontrarnos las funciones.
Cuando veamos la estructura de un programa de Arduino, será lo primero que veamos. Las
funciones loop() y setup() son lo más básico en cuanto a la programación de electrónica.
Como ya te comenté, las funciones son como los verbos de un lenguaje de programación. Si quieres
que algo se haga, probablemente estará contenido dentro de una función.
Pero si queremos utilizar todas estas funciones tenemos que saber cómo hacerlo. Es muy sencillo,
solo tienes que poner el nombre de la función y abrir y cerrar un paréntesis. En ocasiones, entre esos
paréntesis ponemos valores (esto son los parámetros). Por último, no te olvides del punto y coma al
final.
1 //Aplicamos 5 voltios al pin 5
2 digitalWrite(5, HIGH);
La función digitalWrite nos permite aplicar un estado alto (HIGH – 5v) o bajo (LOW – 0V). Para
aplicar este voltaje tenemos que decirle a la función a que pin. Por eso, en la llamada ponemos el
nombre de la función y entre paréntesis el número de pin (en este caso el 5) y que voltaje queremos
sacar por ese pin (5V poniendo HIGH en el ejemplo).
Cuando escribimos digitalWrite lo que estamos haciendo es una llamada a la función. Este es un
término bastante utilizado en la programación y al que debes acostumbrarte.
Ahora te estarás preguntando ¿cómo sé qué parámetros admite cada función? En el caso de
digitalWrite te lo he dicho yo y es una función que se utiliza mucho. Con el tiempo lo terminarás
aprendiendo.
Pero en otros casos no es tan sencillo. Para saber qué parámetros necesita una función de Arduino
tenemos que ir a ver la referencia del lenguaje. Para que te hagas una idea es como si fuera una guía
o manual de usuario.
Casi todos los lenguajes de programación tienen su referencia y en ella podemos ver toda la
información (llamadas a funciones, parámetros, valor que devuelve, etc…). En Arduino la podemos
encontrar en https://www.arduino.cc/en/reference/.
El inconveniente es que está en inglés, pero es muy sencillo de seguir. Si entras en digitalWrite verás
lo siguiente.
En la referencia de digitalWrite encontramos todo lo necesario para saber cómo utilizar esta función:
Con el tiempo no necesitarás acceder a la referencia ya que conocerás las funciones más importantes
de memoria. Pero siempre tienes que tenerlo en cuenta para saber dónde acudir.
Parámetros y argumentos
Ahora que sabemos qué es una función y como llamar a esa función, es conveniente aclarar cierta
terminología. Como hemos visto antes, los parámetros son los datos que espera una función. Si nos
fijamos en digitalWrite, los parámetros de una función son pin (el número de pin) y value (el estado
del pin).
Sin embargo, llamamos argumentos al valor real que se pasa a la función. En nuestro ejemplo de
digitalWrite tenemos como argumentos el número 3 y la palabra reservada HIGH.
Son los valores específicos que le pasamos a la función. Dentro de la función se almacenan en los
parámetros.
Puede parecer un poco confuso pero la realidad es que es como se llaman en programación. Debes
familiarizarte ya que a lo largo del curso yo diferenciaré entre estos dos conceptos. Además,
seguramente lo encuentres escrito de esta manera en algún sitio.
Lo que realmente está haciendo esta función es algo físico. Está activando o desactivando algún
mecanismo electrónico para suministrar 5V o 0V.
Pero existen otro tipo de funciones que nos dan información de un determinado pin. Por ejemplo, la
función digitalRead. Esta función nos informa en qué estado está un pin.
Para almacenar la información del estado del pin utilizamos una variable del tipo entero (int). La
función digitalRead admite un parámetro. En el ejemplo pasamos como argumento el pin 5. Lo que
hace esta función es comprobar el estado del pin y devolverlo a la variable estadoPin.
Bien, hasta ahora hemos visto funciones que admiten parámetros, pero también hay funciones que no
tienen ningún parámetro. Por ejemplo millis().
Esta función lo que hace es calcular los milisegundos transcurridos desde que la placa de Arduino
empezó a ejecutar el programa. Como ves no necesita ningún parámetro. Por si sola sabe lo que tiene
que hacer.
Devuelve el número de milisegundos que han transcurrido en un entero largo sin signo como podemos
ver en la referencia del lenguaje.
Pero también podemos crear nuestras propias funciones. Imagínate que creas una que nos permita
encender una luz del salón.
2 encenderLuzSalon();
Lo importante en esta lección es que las funciones tienen algo más detrás que la simple llamada.
Podemos verlo como si fuera un iceberg. Nosotros solo vemos una parte de la función, pero por
debajo hay mucha más información.
En muchos casos nosotros solo veremos la llamada a la función, sin saber muy bien qué hace por
debajo. En otras ocasiones sí que tendremos que saber qué hace e incluso (como veremos
posteriormente) tendremos que programar dicha función.
Todos los lenguajes de programación tienen decenas o centenas de funciones. Algunas se utilizan
más que otras. Seguramente cuando termines el curso ya te habrás familiarizado con una docena de
ellas, las que más frecuentemente vamos a utilizar.
Resumen de lo visto
Una función tiene como objetivo que el código sea limpio y fácil de leer. Además, nos permite acceder
de una forma rápida y fácil a un código muy útil.
La llamada a una función se hace a través de su nombre y pasando los argumentos que necesite. La
diferencia entre parámetros y argumentos es que estos últimos son el valor específico que le damos a
los parámetros.
Hay funciones de todo tipo. Algunas admiten parámetros y otras no. Unas devuelven algún valor y
otras no. Para saber cómo llamar a una función, que parámetros admite y que valor devuelve lo mejor
es acudir a la referencia del lenguaje.
Sin embargo, tus empleados no son muy fieles. Tienes una gran rotación debido a que la mayoría de
ellos son adolescentes. Esto implica que cada dos por tres se marcha uno y entra un empleado nuevo.
Esto implica que cada vez que entra un empleado nuevo tienes que formarlo. Para agilizar esta tarea
decides hacer dos procedimientos:
El procedimiento de apertura de restaurante aglutina todas esas tareas que se deben hacer para abrir
el restaurante. Abrir las puertas delanteras y traseras, poner el cartel de abierto, sacar los ingredientes
de la nevera, sacar las masas para las pizzas, etc…
Este procedimiento solo se hace una vez al día, cuando se abre el restaurante. Una vez terminado, se
guarda en la estantería hasta la próxima vez que se abra el restaurante.
Por otro lado, existe el procedimiento de atender a un cliente. Es lo que tiene que hacer cada empleado
para dar el mejor servicio a cada cliente. Se enumera paso a paso cada tarea que tiene que realizar.
Podría ser algo parecido a esto. Cuando un cliente entra se da la bienvenida “Hola, bienvenido a la
pizzería Arduino”. Se pregunta qué tipo de pizza desearían comer, si quiere algún ingrediente extra,
que van a beber. También se pregunta si es para comer en el restaurante o para llevar, etc… Creo que
se entiende lo que quiero decir.
Por lo tanto, un empleado recurrirá una vez al procedimiento de apertura y cada vez que venga un
cliente recurrirá al procedimiento de atención al cliente.
Ahora te estarás preguntando ¿qué tiene que ver una pizzería con Arduino? Bueno, un programa de
Arduino tiene que hacer cosas similares a una pizzería. Además, los dos son de origen italiano 😉
La función setup()
En un programa de Arduino, hay cosas que solo tienen que hacerse una sola vez. Cosas como:
Todas estas tareas se tienen que realizar una sola vez. Podemos decir que son las condiciones iniciales
del programa. Este tipo de tareas son las que van en la función setup().
Vamos a comenzar a ver esta función más en detalle. En primer lugar, al igual que pasaba con las
palabras reservadas o los tipos datos, la función setup() tiene un color especial en el IDE de Arduino.
Este color indica que el IDE de Arduino identifica esta función como un tipo especial que se utiliza
para el control de la estructura del código. Como toda función tiene un paréntesis que abre y otro que
cierra. Sin embargo, esta función no necesita de ningún argumento para operar.
A la izquierda de la palabra setup está la palabra void (significa vacío). Lo que indica es que esta
función no devolverá ningún valor o dato.
Por lo tanto, esta función no necesita ningún argumento y no devuelve ningún valor, pero sí que hace
algo. Su trabajo consiste en ejecutar todo el código que hay dentro de ella. Esto se delimita con las
llaves ({}).
La función setup es lo primero que se ejecuta cuando lanzamos el programa de Arduino. Una vez que
se ejecuta la función setup, el programa irá línea por línea ejecutando cada una de ellas.
Lo más importante de esta función es que SOLO SE EJECUTA UNA VEZ. Esto es muy importante,
el código que hay entre esas dos llaves solo se ejecutará una vez.
Es como el empleado que abre la pizzería, busca el procedimiento de apertura lo sigue a rajatabla y
una vez que ha terminado lo guarda y pasa al siguiente procedimiento.
La función loop()
En un programa de Arduino, lo siguiente que se ejecuta es la función loop. Su significado es
repetición y la función se parece a la función de setup.
No requiere de ningún argumento, pero tiene los paréntesis de apertura y cierre. No devuelve ningún
valor por lo que tiene la palabra void a la izquierda. A continuación, tiene la apertura y cierre de llaves
({}). Al igual que a la función setup, cuando se ejecuta la función loop va línea por línea ejecutándose.
La gran diferencia que existe entre la función setup y la loop es que cuando se ejecuta todo el código
de la función loop, el programa vuelve al principio y vuelve a ejecutar todo. Entra en un bucle sin
final una y otra vez.
Sucede lo mismo que en la pizzería con el procedimiento de atención al cliente. Cuando llega el
primer cliente se ejecutan todas las tareas para atenderle. Luego viene otro cliente y se vuelven a
ejecutar las mismas tareas, así indefinidamente.
Una de las preguntas más comunes es ¿cómo de rápido se ejecuta esta función? Esto viene
determinado por cada microcontrolador. En el caso de Arduino UNO, el microcontrolador que utiliza
es el ATmega328P y tiene una velocidad de 20MHz (megahercios).
Esto equivale a 20.000.000 de instrucciones por segundo. Sí, has leído bien, 20 millones :). Esto no
quiere decir que son 20 millones de línea de código. Te recuerdo que el código que tu escribes
luego se traduce a código máquina.
Cada línea de código que tu escribes se puede traducir a múltiples instrucciones, pero aun así, si
tenemos 1.000 instrucciones tardaría 0,00005 segundos. Un tiempo despreciable. Esto implica que la
función loop la ejecutará un montón de veces por segundo en concreto 20.000 veces en un segundo.
Sin embargo, la analogía con la pizzería no encaja perfectamente con la función loop. El empleado
siempre va a esperar a que llegue un nuevo cliente para iniciar el procedimiento. Esto no sucede en
la función loop.
En el programa de Arduino, siempre que se llegue a la última línea de código de la función loop,
volverá al principio para volver a ejecutar todo. No se espera a cualquier entrada externa para hacerlo.
Imagínate en ese empleado que atiende al primer cliente. Hace todo el procedimiento y como
resultado tiene una deliciosa pizza Cuatro Estaciones (uhmmmmm que hambre 🙂 Cuando llega el
segundo cliente el resultado es una pizza Margarita. ¿Qué ha cambiado si hemos seguido el mismo
procedimiento en los dos casos?
Pues sencillamente ha cambiado que el segundo cliente a pedido una pizza diferente, es decir, ha
cambiado la entrada. Lo mismo sucede en el programa de Arduino, aun ejecutando el mismo código
tendremos resultados diferentes debido a los valores de las entradas.
Por ejemplo, tenemos una cubeta donde hay agua y queremos medir su nivel. Si está por encima de
un umbral emitimos un pitido de alarma y si está por debajo del umbral no suena nada. A medida que
el bucle se ejecuta una y otra vez, el nivel de agua varía. Si supera el umbral suena la alarma y si no
lo supera no suena.
Esto es solo un ejemplo, realmente se pueden hacer cosas extraordinarias con Arduino.
Hay una última cosa que tienes que tener en cuenta. Todos los programas de Arduino necesitan
tener declaradas la función setup y loop. De otra manera no te dejará compilar el código.
Son tan importantes que cuando creas un programa o sketch nuevo el IDE de Arduino las inserta
automáticamente.
Revisión de lo visto
En esta lección hemos viso dos funciones muy importantes dentro del lenguaje de Arduino, la función
setup y loop.
La función setup es la primera que se ejecuta y solo lo hace una vez. Sirve para iniciar variables,
librerías o cualquier cosa que necesite tener condiciones iniciales.
La función loop se ejecuta después de la función setup. Todo lo que pongamos dentro de esta función
se ejecutará indefinidamente hasta que apaguemos el Arduino o pulsemos el botón de reset. Lo hace
a una velocidad muy rápida (20MHz).
Tanto la función setup como la loop son necesarios en cualquier programa. Sin ellos el programa no
compila.
Las aplicaciones de este tipo de sensores son muchas, desde una simple
estación meteorológica hasta un sistema de alarma capaz de detectar la
presencia de un ser vivo. Voy a clasificar los diferentes sensores en tres tipos
dependiendo de a quien va dirigido.
En estos son en los que más me voy a centrar porque son los que más comunes
y los que más vamos a utilizar. En total son 5 sensores que analizaremos al
detalle.
Fuentes de alimentación
Gestión de baterías
Accesorios
Climatización
Voltaje de operación: de 4 V a 30 V
Rango de temperaturas: -55º C a 150º C
Precisión: ±0,5º C
Conversión: 10 mV / ºC
Tiempo de respuesta (100%): 4 min.
Offset: 0 V
Hoja de características técnicas
Para ver cómo configurar este sensor mira el artículo donde te lo explicamos
todo.
Es muy parecido a el LM35 la gran diferencia entre los dos es que en el TMP36
podemos medir temperaturas bajo cero sin necesidad de suministrar una voltaje
negativo. Este sensor ya viene preparado para este rango.
Existen de dos tipos. Por un lado los que funcionan a 3,3V y los que funcionan a
5V. Aunque cualquiera de los dos puede funcionar con el rango que marca la hoja
de características técnicas, también nos avisa que si el varía del valor nominal,
la precisión puede degradarse 1ºC/V.
Lo podemos encontrar por 4,56€ sin la resistencia pull up y por 5,31 € listo para
conectar a nuestro Arduino.
Respecto a sus prestaciones, el rango abarca temperaturas bajo cero, tiene una
precisión mayor y la resolución es de 16 bit, aunque sigue siendo un sensor muy
lento ya que podemos obtener una muestra cada 2 segundos.
Con este tipo de sensores seremos capaces de medir en entornos con grandes
fluctuaciones y con mucha precisión.
Para conectar con Arduino, utiliza el protocolo I2C. Puedes acceder a la hoja de
características técnicas para ver sus especificaciones.
Su coste no es muy elevado, casi 9€, debido a su simplicidad, son solo dos
cables de metal sensible.
Por lo tanto hay que utilizar un convertidor de analógico a digital ADC como
el MAX6675. Puedes encontrar todo el conjunto por casi 11€.
Pero cuando estamos hablando de otros tipos de casos donde la temperatura nos
sirve, por ejemplo, para detectar movimiento o el número de personas que hay
en una habitación, estos sensores no nos van a servir para nada.
Aquí entran en juego los sensores con características especiales y que no son
para utilizar en la típica estación meteorológica. Se utilizan para proyectos muy
especiales.
Podemos comunicar de dos maneras con este sensor, por el protocolo I2C y
mediante un pin PWM.
Sin duda alguna es toda una cámara térmica y un dispositivo muy deseado para
todos los que nos gusta trastear con la electrónica.
Una de las ventajas que nos ofrece el DHT11, además de medir la temperatura
y la humedad, es que es digital. A diferencia de sensores como el LM35, este
sensor utiliza un pin digital para enviarnos la información y por lo tanto, estaremos
más protegidos frente al ruido.
En la versión sin PCB tenemos 4 pines y en la versión con PCB tenemos 3 pines.
Los pines de la versión sin PCB del DHT11 son:
VCC: alimentación
I/O: transmisión de datos
NC: no conecta, pin al aire
GND: conexión a tierra
Alimentación de 3,5 V a 5 V
Consumo 2,5 mA
Señal de salidaDigital
Temperatura
Humedad
Por lo tanto, partimos de una señal analógica que luego es convertida en formato
digital y se enviará al microcontrolador. La trama de datos es de 40 bits
correspondiente a la información de humedad y temperatura del DHT11.
0011 0101 + 0000 0000 + 0001 1000 + 0000 0000 = 0100 1101
Conectando el DHT11 a Arduino
Como tenemos dos versiones del sensor de temperatura y humedad DHT11,
vamos a ver cómo tendríamos que conectarlo a Arduino en los dos casos. Te
recuerdo que vamos a trabajar con un pin digital.
Una vez hayas leído y entendido las consideraciones, vamos a ver los circuitos
eléctricos para los dos modelos.
Este modelo de DHT11 dispone de 3 pines, la toma de tierra GND, para los datos
DATA y para la alimentación VCC (de 3,5V a 5V). En la siguiente imagen puedes
ver el esquema de conexión con Arduino.
Programando el DHT11 desde el IDE de
Arduino
Si tuvieras que programar desde cero el sensor de temperatura y humedad
DHT11, sería francamente complicado. Sin embargo, las librerías que hay
entorno a Arduino nos facilitan mucho la vida. Este es un claro ejemplo.
Recuerda, si no sabes instalar una librería te recomiendo que leas este tutorial
donde te explico cómo instalar una librería de Arduino.
1 // Incluimos librería
2 #include <DHT.h>
5 #define DHTPIN 2
Por último declaramos el objeto DHT con los parámetros pin y tipo de DHT.
Función setup
1 void setup() {
6 dht.begin();
7}
Función loop
1 void loop() {
3 delay(5000);
6 float h = dht.readHumidity();
8 float t = dht.readTemperature();
10 float f = dht.readTemperature(true);
11
16 }
17
22
23 Serial.print("Humedad: ");
24 Serial.print(h);
25 Serial.print(" %\t");
26 Serial.print("Temperatura: ");
27 Serial.print(t);
28 Serial.print(" *C ");
29 Serial.print(f);
30 Serial.print(" *F\t");
32 Serial.print(hic);
33 Serial.print(" *C ");
34 Serial.print(hif);
35 Serial.println(" *F");
36
37 }
1 // Incluimos librería
2 #include <DHT.h>
5 #define DHTPIN 2
11
12 void setup() {
14 Serial.begin(9600);
15
17 dht.begin();
18
19 }
20
21 void loop() {
23 delay(5000);
24
26 float h = dht.readHumidity();
28 float t = dht.readTemperature();
30 float f = dht.readTemperature(true);
31
35 return;
36 }
37
42
43 Serial.print("Humedad: ");
44 Serial.print(h);
45 Serial.print(" %\t");
46 Serial.print("Temperatura: ");
47 Serial.print(t);
48 Serial.print(" *C ");
49 Serial.print(f);
50 Serial.print(" *F\t");
52 Serial.print(hic);
53 Serial.print(" *C ");
54 Serial.print(hif);
55 Serial.println(" *F");
56
57 }
Conclusiones sobre el sensor DHT11
Una de las partes más importantes a la hora de hacer nuestros proyectos Maker
es la investigación. Cuando queremos hacer una estación de temperatura, por
ejemplo, debemos conocer los diferentes sensores que tenemos a nuestra
disposición.
Por un lado, nos permite mantener una posición que indiquemos, siempre que
esté dentro del rango de operación del propio dispositivo. Por otro lado, nos
permite controlar la velocidad de giro, podemos hacer que antes de que se
mueva a la siguiente posición espere un tiempo.
El ejemplo más típico es un coche teledirigido, esos que utilizan los niños y no
tan niños. Estos juguetes suelen tener un mando a distancia donde podemos
controlar la velocidad y el giro del coche. Precisamente el giro se suele hacer con
un servomotor donde indicamos, en cada momento, la posición o el ángulo de
giro que queremos que tenga en un preciso momento.
Características técnicas de un servomotor
con Arduino
Hay varios modelos de servomotor con Arduino. En este caso vamos a utilizar un
Micro Servo 9g SG90 de Tower Pro. Como siempre digo, hay que mirar la ficha
técnica del producto. Todos tienen un funcionamiento muy parecido y la
programación puede variar muy poco.
Aunque el servo puede moverse con una resolución de más de 1 grado, este es
el máximo de resolución que vamos a conseguir debido a la limitación de la señal
PWM que es capaz de generar Arduino UNO.
Estos motores funcionan con una señal PWM, con un pulso de trabajo entre 1 ms
y 2 ms y con un periodo de 20 ms (50 Hz). ¿Qué quiere decir todo esto? Este
dato nos indica la velocidad máxima a la que podemos mover el servomotor con
Arduino. Solo podremos cambiar de posición cada 20 ms. Esto dependerá del
tipo y marca de nuestro servo.
El elegir una salida PWM u otra da lo mismo, todas las salidas de este tipo
funcionan igual.
1 /*
3 https://programarfacil.com
4 */
5
7 #include <Servo.h>
10 Servo servoMotor;
11
12 void setup() {
14 Serial.begin(9600);
15
17 servoMotor.attach(9);
18 }
19
20 void loop() {
21
22 // Desplazamos a la posición 0º
23 servoMotor.write(0);
24 // Esperamos 1 segundo
25 delay(1000);
26
28 servoMotor.write(90);
29 // Esperamos 1 segundo
30 delay(1000);
31
33 servoMotor.write(180);
34 // Esperamos 1 segundo
35 delay(1000);
36 }
1 /*
3 https://programarfacil.com
4 */
7 #include <Servo.h>
8
10 Servo servoMotor;
11
12 void setup() {
14 Serial.begin(9600);
15
17 servoMotor.attach(9);
18
20 servoMotor.write(0);
21 }
22
23 void loop() {
24
25 // Vamos a tener dos bucles uno para mover en sentido positivo y otro en sentido negativo
28 {
30 servoMotor.write(i);
33 }
34
37 {
39 servoMotor.write(i);
41 delay(25);
42 }
43 }
Conclusión
Controlar un servo desde Ardunino es una tarea muy sencilla gracias al uso de la
librería Servo.h.
Tipos de potenciómetro
El potenciómetro nos proporciona una resistencia variable según vayamos
modificando su posición. Si está totalmente cerrado obtendremos como salida el
máximo voltaje (el de entrada), si lo tenemos totalmente abierto, obtendremos 0
voltios y si lo tenemos en una posición intermedia obtendremos una fracción del
voltaje de entrada proporcional a la posición en la que se encuentre. Este
comportamiento se llama divisor de tensión.
Existen varios tipos de potenciómetros, pero los más comunes y con los que casi
siempre vamos a trabajar son:
Los primeros son los que utilizaremos normalmente y son los más comunes en
los kit de Arduino. Los segundos potenciómetros se suelen utilizar para circuitos
de audio. Si tienes un aparato multimedia que tenga un botón para girar y
modificar el sonido, estarás utilizando un potenciómetro logarítmico.
En los primeros, a mitad del recorrido del potenciómetro nos devuelve el 50% del
voltaje, pero esto no ocurre en el logarítmico ya que a mitad del recorrido nos
devolverá un porcentaje superior, la proporción en este caso no es lineal y
describe una curva ascendente.
Y como la mejor manera de entender algo son los ejemplos, empezamos con uno
que mediante el monitor serie podremos ir viendo que valores vamos obteniendo
en un pin analógico según vayamos modificando la posición del potenciómetro.
El código
Y el código que debes cargar en la placa es el siguiente.
1 //Variable donde almacenaremos el valor del potenciometro
2 long valor;
4 void setup() {
6 Serial.begin(9600);
10
11 }
12
13 void loop() {
15 valor = analogRead(A0);
16
19 Serial.println(valor);
20 delay(1000);
21
22 }
Una vez hayas subido el código del potenciómetro a la placa, abre el monitor
serie. La salida dependerá donde la posición del potenciómetro, ves girando la
rueda y verás como el valor se va modificando.
El código
Vamos a utilizar la propiedad del potenciómetro de resistencia variable para
encender uno u otro LED. Haremos una serie de if para determinar que LED
encender y apagar los otros, según el valor que obtengamos en la entrada del pin
analógico. El código sería el siguiente.
2 long valor;
5 int LED_1 = 2;
6 int LED_2 = 3;
7 int LED_3 = 4;
8 int LED_4 = 5;
10 void setup() {
11 //Inicializamos la comunicación serial
12 Serial.begin(9600);
13
16
17 pinMode(LED_1, OUTPUT);
18 pinMode(LED_2, OUTPUT);
19 pinMode(LED_3, OUTPUT);
20 pinMode(LED_4, OUTPUT);
21 }
22
23 void loop() {
25 valor = analogRead(A0);
26
29 Serial.println(valor);
30
32 {
33 digitalWrite(LED_1, HIGH);
34 digitalWrite(LED_2, LOW);
35 digitalWrite(LED_3, LOW);
36 digitalWrite(LED_4, LOW);
37 }
38
40 {
41 digitalWrite(LED_1, LOW);
42 digitalWrite(LED_2, HIGH);
43 digitalWrite(LED_3, LOW);
44 digitalWrite(LED_4, LOW);
45 }
46
48 {
49 digitalWrite(LED_1, LOW);
50 digitalWrite(LED_2, LOW);
51 digitalWrite(LED_3, HIGH);
52 digitalWrite(LED_4, LOW);
53 }
54
56 {
57 digitalWrite(LED_1, LOW);
58 digitalWrite(LED_2, LOW);
59 digitalWrite(LED_3, LOW);
60 digitalWrite(LED_4, HIGH);
61 }
62 }
Conclusión
El potenciómetro es un componente electrónico muy utilizado en Arduino y es
conveniente saber cómo se utiliza.
Hay varias páginas donde nos ofrecen fichas técnicas de componentes. Dos de
las más famosas son Datasheet Catalog y All Datasheet.
Identifica cada segmento LED con una letra. Así tenemos identificados cada
uno de ellos. Este componente tiene 10 pines. Antes de hacer ninguna conexión
debemos identificar los pines.
Pines Segmentos
1 e
2 d
4 c
6 b
7 a
9 f
10 g
¿Y qué pasa con el resto de pines? Nos quedan por saber qué hacer con los
pines 3, 5 y 8. ¿Te acuerdas que hemos visto que hay un punto para indicar la
orientación del display 7 segmentos?, pues este va conectado al pin número
5.
Los otros dos pines funcionarán como cátodo o ánodo, dependiendo del tipo
de display de 7 segmentos con el que estemos trabajando. Solo debemos utilizar
una de esas dos conexiones, se trata de pines redundantes.
Al final, la tabla que relaciona los pines con los LEDs quedaría de la siguiente
manera.
Pines Segmentos
1 e
2 d
3 ánodo/cátodo común
4 c
5 DP (punto)
6 b
7 a
8 ánodo/cátodo común
9 f
10 g
Bueno, pues ya tenemos relacionados los pines con los segmentos (circuito
eléctrico interno), ahora vamos a ver cómo mostrar un número en el display de 7
segmentos.
Mostrando un número en el display 7 segmentos
Para poder mostrar un número en el display 7 segmentos, lo que tenemos
que hacer es iluminar aquellos segmentos para formar dicho número. Por
ejemplo, si queremos mostrar el 4, debemos activar los segmentos f, g, b y c y
desactivar el resto de segmentos.
Como estos tienen una relación con los pines de Arduino, solo tendríamos que
poner en estado alto (HIGH) o bajo (LOW) esos pines (en la siguiente sección
veremos los tipos de displays que tenemos a nuestra disposición). Todo esto lo
haremos a nivel de programación. En el ejemplo de código, podrás ver cómo se
hace.
Arduino UNO
Protoboar (placa de prototipado)
Cables para hacer conexiones
1 pulsador
1 resistencia de 10 kΩ
1 resistencia de 220 Ω
1 display de 7 segmentos
Ánodo común
Como ves en las imágenes anteriores, no hay gran diferencia. Solo la conexión
del pin número 3. En cátodo común va a tierra (GND) y en ánodo común va a la
fuente (5 V). Donde si veremos diferencia es a la hora de programar.
El pulsador siempre debe ir acompañado de una resistencia pull down o pull up.
Dependerá del estado que queramos tener cuando la conexión con la entrada
digital esté al aire.
1. Leemos el pulsador
1. Si está en estado alto
1. Obtenemos número aleatorio
2. Mostramos el número en el display
3. Esperamos un tiempo hasta permitir otra jugada
2. Si está en estado bajo
1. No hacemos nada
Variables y constantes
Comenzamos con una buena práctica. Declarar todas las constantes que
relacionan los pines con los componentes. En este caso solo vamos a declarar
una constante, el pulsador.
1 // Constantes pines
2 #define PULSADOR 10
Este tipo de arrays, donde tenemos 2 dimensiones, lo podemos ver como una
tabla. Para acceder a un elemento tenemos que indicar la fila y la columna
donde se encuentra dicho elemento. Esto viene indicado por el valor entre
corchetes [columna] [fila].
En este caso crearemos un array con 10 elementos que serían los 10 números
posibles, del 0 al 9. Cada elemento contendrá 1 array de 8 elementos que
serían los pines a los que está conectado el display de 7 segmentos (7 para
cada segmento y el punto).
2 byte numero[10][8] =
3 {
4 { 1, 1, 1, 1, 1, 1, 0, 0 }, // 0
5 { 0, 1, 1, 0, 0, 0, 0, 0 }, // 1
6 { 1, 1, 0, 1, 1, 0, 1, 0 }, // 2
7 { 1, 1, 1, 1, 0, 0, 1, 0 }, // 3
8 { 0, 1, 1, 0, 0, 1, 1, 0 }, // 4
9 { 1, 0, 1, 1, 0, 1, 1, 0 }, // 5
10 { 1, 0, 1, 1, 1, 1, 1, 0 }, // 6
11 { 1, 1, 1, 0, 0, 0, 0, 0 }, // 7
12 { 1, 1, 1, 1, 1, 1, 1, 0 }, // 8
13 { 1, 1, 1, 0, 0, 1, 1, 0 } // 9
14 };
Este array solo sirve para cátodo común. Si tenemos el otro tipo de display 7
segmentos, debemos cambiar los unos por los ceros y los ceros por unos.
Función setup
En esta función tenemos que establecer las condiciones iniciales. Lo primero es
iniciar el monitor serie.
1 void setup() {
3 Serial.begin(9600);
Luego seguimos con los segmentos del display. Hay que poner todos los pines
donde está conectado (del 2 al 9) en modo salida (OUTPUT). Podemos
hacerlo de dos maneras, hacerlo de uno a uno o con un bucle. La dificultad de
este bucle es que no debemos empezar por el cero. Los pines que utilizamos
son del 2 al 9, haremos un bucle que recorra todos estos números.
Dentro utilizaremos la variable del bucle como número de pin. Es muy sencillo, lo
puedes comprobar a continuación.
3 {
4 pinMode(i, OUTPUT);
5 }
2 pinMode(PULSADOR, INPUT);
Por último, establecemos la semilla fija para obtener el valor aleatorio a través de
la función random. Esta semilla será una entrada analógica.
2 randomSeed(analogRead(A0));
3}
Como semilla, elegir un pin analógico que no se utilice. Como ya hemos visto con
el pulsador, no establecer una resistencia pull down o pull up produce una
indeterminación. Esto nos permitirá seleccionar un número aleatorio verdadero.
Función loop
Ahora vamos con la parte que se repite constantemente. Como hemos visto en
la descripción del algoritmo, lo primero es leer el pin digital donde tenemos
conectado el pulsador. Luego comprobamos si está en estado alto (pulsado).
1 void loop() {
5 // Si está pulsado
6 if (valor == HIGH)
7 {
6 {
7 digitalWrite(e + 3, numero[randomNumber][e]);
8 }
10 delay(500);
11 }
12 }
1 { 0, 1, 1, 0, 0, 0, 0, 0 }
El primer elemento indica el primer LED (corresponde con la letra e y el pin 2).
Por lo tanto, el pin 2 al valor que nos indica el array, 0 V (LOW).
El siguiente elemento es el pin 3 (letra c), lo tenemos que poner a nivel alto 5 V
(HIGH). Y así con todos los elementos.
El orden nos dirá el pin (hay que sumar dos ya que hemos empezado a conectar
por el pin 2) y el valor nos dirá en que estado 0 (LOW) y 1 (HIGH).
Código completo
A continuación te dejo todo el código para que lo puedas copiar fácilmente.
1 // Constantes pines
2 #define PULSADOR 10
5 byte numero[10][8] =
6 {
7 { 1, 1, 1, 1, 1, 1, 0, 0 }, // 0
8 { 0, 1, 1, 0, 0, 0, 0, 0 }, // 1
9 { 1, 1, 0, 1, 1, 0, 1, 0 }, // 2
10 { 1, 1, 1, 1, 0, 0, 1, 0 }, // 3
11 { 0, 1, 1, 0, 0, 1, 1, 0 }, // 4
12 { 1, 0, 1, 1, 0, 1, 1, 0 }, // 5
13 { 1, 0, 1, 1, 1, 1, 1, 0 }, // 6
14 { 1, 1, 1, 0, 0, 0, 0, 0 }, // 7
15 { 1, 1, 1, 1, 1, 1, 1, 0 }, // 8
16 { 1, 1, 1, 0, 0, 1, 1, 0 } // 9
17 };
18
19 void setup() {
21 Serial.begin(9600);
22
25 {
26 pinMode(i, OUTPUT);
27 }
28
30 pinMode(PULSADOR, INPUT);
31
33 randomSeed(analogRead(A0));
34 }
35
36 void loop() {
40 // Si está pulsado
41 if (valor == HIGH)
42 {
43
46
49 {
50 digitalWrite(e + 3, numero[randomNumber][e]);
51 }
52
53 delay(500);
54 }
55 }
Conclusión
Una de las ventajas que tenemos de mostrar la información con un display de 7
segmentos, es que es muy sencillo y vistoso. Aquí hemos visto un ejemplo para
mostrar un número del 1 al 6.