Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Primeros Pasos Con Arduino
Primeros Pasos Con Arduino
PRIMEROS PASOS
CON ARDUINO
1 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Cuando comenzamos a trabajar con Arduino, parece que la cantidad de cosas que hay que
aprender es tan grande que parece inabordable. Necesitamos aprender conceptos de electricidad,
electrnica, programacin, algo de ingeniera. Y dependiendo de lo que quieras hacer, algo de
matemticas y mucha fsica.
Hemos diseado este itinerario pensando en la gente que como t, que probablemente tenga que
empezar desde el principio.
Por eso, estos primeros captulos esta pensados para irte llevando de la mano, en los conceptos
bsicos que vas a necesitar en la aventura que empiezas, e ir presentando todas las ideas
necesarias para ir siguiendo el curso en orden.
Iremos mezclando componentes electrnicos con la ley de Ohm e irn apareciendo las primeras
instrucciones de Arduino C++, con algunos programas y circuitos en los que haremos prcticas.
Las primeras sesiones de este tutorial estn pensadas para alguien que quiere iniciarse y cuyos
conocimientos en estos temas son nulos, pero que quiera aprender. Y creemos que si nos sigues
conseguirs ese objetivo. En ello hemos puesto todo nuestro empeo.
2 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
http://arduino.cc/en/main/software
Y bajamos la versin ms reciente del IDE (Entorno de desarrollo de Arduino) Que a la fecha de
escribir los apuntes es la 1.6.9, suficientemente estable para usarla en condiciones normales.
Una vez finalizado, ejecuta el fichero que acabas de descargar y respondiendo a las opciones de
instalacin. Aceptar las opciones por defecto de instalacin es una opcin razonable en caso de
no estar seguro de las preguntas que nos hace.
Una vez instalado el IDE, vamos a comprobar que reconoce nuestra placa de Arduino
correctamente y que podemos programarlo. Para ello, Conecta tu Arduino a tu ordenador
mediante el cable USB.
Comprueba que las luces de la placa de Arduino se iluminan, esto indica que recibe alimentacin.
Al hacerlo nuestro PC debe detectar el nuevo dispositivo USB y montar el driver adecuado.
Y finalmente:
3 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Atencin, el puerto serie en que se instala en tu equipo puede variar del indicado en la imagen,
dependiendo de las caractersticas del equipo.
Ahora, ya podemos arrancar el programa desde el icono de Arduino que tenemos en el escritotio
de trabajo, configurar el modelo de placa de Arduino y el puerto serie al que est conecta la placa.
En Men\Herramientas\Placa deberemos elegir el modelo exacto de nuestra placa Arduino. En
nuestro caso elegimos un Arduino Uno:
Volquemos ahora un programa de ejemplo para comprobar que podemos comunicarnos con la
placa que acabamos de seleccionar:
4 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
5 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Este mensaje en color blanco indica que hemos volcado correctamente el programa y ya
deberamos ver una luz que parpadea en nuestra placa Arduino, tal como se indica en la figura
siguiente.
Si vemos el LED marcado como L parpadeando en nuestro Arduino, enhorabuena, el entorno est
instalado y configurado correctamente. Ya podemos pasar a la siguiente sesin.
6 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
2 NUESTRO PRIMER
PROGRAMA
Blinking LED.
2.1 OBJETIVOS.
Mientras que las personas somos razonablemente buenas interpretando las vagas instrucciones
de una receta de cocina, cuando programamos, quien debe entendernos es un ordenador que
espera instrucciones precisas respecto a lo que debe hacer y que por otro lado carece por
completo de la imaginacin o capacidad de improvisacin que posen los humanos.
Por ello se desarrollan los lenguajes de programacin de ordenador, para dar instrucciones a una
mquina de forma:
El Arduino se programa en una variante del lenguaje de programacin C++ , que es un lenguaje
muy extendido por sus caractersticas, aunque no es un lenguaje sencillo. C++, fija reglas estrictas
de cmo escribir estas instrucciones.
Un programa es una serie de instrucciones que se ejecutan en secuencia, salvo que indiquemos
expresamente condiciones precisas en las que esta secuencia se ve alterada.
Cuando el comprobador acepta nuestro programa, invoca a otro programa que traduce lo que
hemos escrito a instrucciones comprensibles para el procesador de nuestro Arduino. A este nuevo
programa se le llama compilador.
7 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Un programa diseado para ejecutarse sobre un Arduino (un sketch) siempre se compone de
tres secciones:
La primera seccin del sketch (que no tiene ningn tipo de smbolo delimitador de inicio o de final)
est reservada para escribir, tal como su nombre indica, las diferentes declaraciones de variables
que necesitemos. En un apartado posterior explicaremos ampliamente qu significa todo esto.
En el interior de las otras dos secciones (es decir, dentro de sus llaves) deberemos escribir las
instrucciones que deseemos ejecutar en nuestra placa, teniendo en cuenta lo siguiente:
Las instrucciones escritas dentro de la seccin void setup() se ejecutan una nica vez,
en el momento de encender (o resetear) la placa Arduino.
Las instrucciones escritas dentro de la seccin void loop() se ejecutan justo despus de
las de la seccin void setup() infinitas veces hasta que la placa se apague (o se resetee). Es
decir, el contenido de void loop() se ejecuta desde la primera instruccin hasta la ltima, para
seguidamente volver a ejecutarse desde la primera instruccin hasta la ltima, para
seguidamente ejecutarse desde la primera instruccin hasta la ltima, y as una y otra vez.
Por tanto, las instrucciones escritas en la seccin void setup() normalmente sirven para realizar
ciertas preconfiguraciones iniciales mientras que las instrucciones del interior de void loop() son,
de hecho, el programa en s que est funcionando continuamente.
8 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Ntese que el principio de cada funcin se indica mediante la apertura de llave { y el fin de la
misma corresponde al smbolo de cerrar llave } .
De hecho el conjunto de instrucciones contenidas entre una apertura y cierre de llaves se llama
bloque y es de capital importancia a la hora de que nuestro Arduino interprete de una u otra
manera las instrucciones que le damos. Es obligatorio que a cada apertura de una llave
corresponda un cierre de llave. En sucesivos captulos ampliaremos este concepto.
Por ahora resaltar las lneas que aparecen dentro de los bloques principales:
La primera lnea del sketch del ejemplo contiene un comentario (concretamente, son las dos
primeras lneas: desde los smbolos /* hasta los smbolos */). Un comentario es un texto escrito
intercalado con el cdigo del sketch que se utiliza para informar sobre cmo funciona ese cdigo a
la persona que en algn momento lo est leyendo. Es decir, los comentarios son texto de ayuda
para los seres humanos que explica el cdigo asociado y ayudan a entenderlo y recordar su
funcin. Los comentarios son completamente ignorados y desechados por el compilador, por lo
que no forman parte nunca del cdigo binario que ejecuta el microcontrolador (as que no ocupan
espacio en su memoria).
Comentarios compuestos por una lnea entera (o parte de ella): para aadirlos deberemos
escribir dos barras ( // ) al principio de cada lnea que queramos convertir en comentario.
Tambin podemos comentar solamente una parte de la lnea, si escribimos las barras en otro
punto que no sea el principio de esta; de esta manera solamente estaremos comentando lo
que aparece detrs de las barras hasta el final de la lnea, pero lo anterior no.
Una prctica bastante habitual en programacin es comentar en algn momento una (o ms)
partes del cdigo. De esta forma, se borran esas partes (es decir, se ignoran, y por tanto, ni se
compilan ni se ejecutan) sin borrarlas realmente. Normalmente, esto se hace para localizar
posibles errores en el cdigo observando el comportamiento del programa con esas determinadas
lneas comentadas. A lo largo de los ejemplos de este libro se ir viendo su utilidad.
Parece obligado en el mundo Arduino, que el primer programa que hagamos sea el blinking LED,
y est bien porque ilustra algunas ideas interesantes en cuanto a las posibilidades de la
programacin:
9 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
La capacidad de Arduino para interactuar con el mundo externo. Algo bastante inusual para
quienes estn acostumbrados a la informtica tradicional, donde la potencia de clculo ha
crecido de forma espectacular, pero sigue siendo imposible, influir en el mundo exterior.
La sencillez del entorno de trabajo. En contraposicin a un sistema tradicional de editor /
compilador / linker.
Arduino puede relacionarse de diferentes maneras con el mundo que le rodea, Empezaremos por
los pines digitales que pueden usarse de dos modos, como:
Las funciones que nos ofrece el lenguaje Arduino para trabajar con entradas y salidas digitales
son:
pinMode(): configura un pin digital (cuyo nmero se ha de especificar como primer parmetro)
como entrada o como salida de corriente, segn si el valor de su segundo parmetro es la
constante predefinida INPUT o bien OUTPUT, respectivamente. Esta funcin es necesaria
porque los pines digitales a priori pueden actuar como entrada o salida, pero en nuestro sketch
hay que definir previamente si queremos que acten de una forma u de otra. Es por ello que
esta funcin se suele escribir dentro de setup(). No tiene valor de retorno.
digitalWrite(): enva un valor ALTO (HIGH) o BAJO (LOW) a un pin digital; es decir, tan solo
es capaz de enviar dos valores posibles. Por eso, de hecho, hablamos de salida digital. El
pin al que se le enva la seal se especifica como primer parmetro (escribiendo su nmero) y
el valor concreto de esta seal se especifica como segundo parmetro (escribiendo la
constante predefinida HIGH o bien la constante predefinida LOW, ambas de tipo int).
digitalRead(): devuelve el valor ledo del pin digital (configurado como entrada mediante
pinMode()) cuyo nmero se haya especificado como parmetro. Este valor de retorno es de
tipo int y puede tener dos nicos valores (por eso, de hecho hablamos de entrada digital): la
constante HIGH (1) o LOW (0).
Arduino dispone de 14 pines que pueden ser usados de este modo, numerados del 0 al 13:
En la sesin anterior cargamos un programa de ejemplo que hacia parpadear un LED en la placa
con una cadencia definida. Veamos como podemos programar Arduino para que realice esto.
Primero configuraremos Arduino para que configure su pin 13 como de salida digital y despus
encenderemos y apagaremos la seal en esa salida, lo que har que el LED que tiene conectado
en serie se encienda o apague al ritmo que marquemos.
Para indicar al sistema que deseamos usar el pin 13 como salida digital utilizamos la instruccin:
10 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
El primer parmetro indica el pin a usar y el segundo OUTPUT es para usarlo como salida, y
tambin podramos usar como segundo parmetro INPUT, para indicar que usamos ese pin
como entrada, vamos a leer de este pin.
Estas definiciones se harn solo una vez al principio, en la funcin setup(). La nuestra quedar,
con una nica instruccin que declara que vamos a usar el pin 13 como salida digital:
void setup()
{
// initialize the digital pin as an output
pinMode( 13, OUTPUT) ;
}
Es importante que nos fijemos en que a pesar de ser una nica instruccin, hemos delimitado el
bloque de esta funcin mediante abrir y cerrar llaves.
Obsrvese que la instruccin finaliza con un ; . C++ obliga a terminar las instrucciones con un
punto y coma que delimite la orden. Si se omite generar un error al compilar.
digitalWrite( 13 , HIGH) ;
digitalWrite( 13 , LOW) ;
El primer parmetro 13 indica el pin a utilizar y segundo parmetro HIGH o LOW indican el valor
que deseamos poner en esa salida. En Arduino corresponden 5V para HIGH y 0V para LOW.
Si en la funcin loop() escribiramos estas dos instrucciones seguidas, Arduino cambiara estos
valores tan deprisa que no percibiramos cambios, as que necesitamos frenarle un poco para que
podamos percibir el cambio.
Por tanto para programar una luz que se enciende y se apaga, tendramos que generar una
secuencia de rdenes (Como en una receta de cocina) que hicieran:
1. Informar a Arduino de que vamos a utilizar el pin13 para escribir valores( en el Setup).
2. Encender el LED : Poner un valor alto ( 5V) en dicho pin.
3. Esperar un segundo.
4. Apagar el LED: Poner valor bajo (0V) en dicho pin.
5. Volver a esperar un segundo.
A. Si omitiramos este segundo retraso, apagara la luz y volvera a empezar encontrndose
la orden de volver a encender. No apreciaramos que se haba apagado. Comprobadlo.
B. El procesador de Arduino UNO es muy lento desde el punto de vista electrnico, pero es
capaz de conmutar la luz, pasar de encendido a apagado y vuelta a encender, unas 15.000
veces por segundo.
11 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
El primer concepto que tenis que recordar, es que los ordenadores procesan las ordenes en
secuencia, una instruccin despus de otra y en el orden en que se las dais. Nuestro programa
instruye al ordenador para que ejecute esas instrucciones y fija el orden en el que se ejecutan.
La forma de escribir un programa en Arduino C++ que haga lo anteriormente descrito es algo
parecido a esto:
void setup()
{
pinMode( 13 , OUTPUT); // Usaremos el pin 13 como salida
}
void loop()
{
digitalWrite(13 , HIGH); // Enciende el LED
delay(1000); // Esperar un segundo
digitalWrite(13 , LOW); // Apagar el LED
delay(1000); // Esperar otro segundo
}
Conviene aclarar ya pequeos detalles que deberemos tener en cuenta a la hora de escribir
nuestros sketches para evitarnos muchos dolores de cabeza. Por ejemplo, es necesario saber que
el lenguaje Arduino es case-sensitive. Esto quiere decir que es totalmente diferente escribir una
letra en mayscula que en minscula. Dicho de otra forma: para el lenguaje Arduino HolA y
hOLa son dos palabras distintas. Esto tiene una implicacin muy importante: no es lo mismo
escribir por ejemplo digitalWrite(13 , HIGH); que digitalwrite(13 , HIGH);;. En el primer caso la
instruccin estara correctamente escrita, pero en el segundo, en el momento de compilar el
cdigo el IDE se quejara porque para l write (con w minscula) no tiene ningn sentido. As
que hay que vigilar mucho con respetar esta distincin en los cdigos que escribamos.
Otro detalle: las tabulaciones de las instrucciones contenidas dentro de las secciones void
setup() y void loop() del sketch del ejemplo no son en absoluto necesarias para que la
compilacin del sketch se produzca con xito. Simplemente son una manera de escribir el cdigo
de forma ordenada, clara y cmoda para el programador, facilitndole la tarea de leer cdigo ya
escrito y mantener una cierta estructura a la hora de escribirlo. En los prximos ejemplos se ir
viendo mejor su utilidad.
Otro detalle: todas las instrucciones (incluyendo tambin las declaraciones de variables) acaban
con un punto y coma. Es indispensable aadir siempre este signo para no tener errores de
compilacin, ya que el compilador necesita localizarlo para poder detectar el final de cada
instruccin escrita en el sketch. Si se olvida, se mostrar un texto de error que puede ser obvio
(falta un punto y coma) o no. Si el texto del error es muy oscuro o sin lgica, es buena idea
comprobar que la causa no sea la falta de un punto y coma en las lneas justamente anteriores a
la marcada por el compilador como causante del problema.
Solo nos falta ya, comprobar si hay errores y para ello pulsamos el icono en amarillo, verificamos
y compilamos:
12 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Si todo va bien,( si no hay errores en rojo al final de la ventana) podemos compilar y volcar con
la flecha, En caso contrario ( y creedme que os pasar con frecuencia) habr que revisar los
posibles errores y corregirlos. Volveremos sobre esto en el futuro.
La flecha en amarillo volcara nuestro programa a la placa Arduino y comprobaremos que la luz
del pin 13 parpadea con una cadencia de un segundo.
Sugerencia: Si modificamos los valores del delay, modificaremos la cadencia del parpadeo.
Nota: Esto no funcionara con ningn otro Pin del Arduino UNO, porque solo el 13 tiene un LED
conectado.
2. 6 RESUMEN DE LA SESIN
13 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Arduino Uno o similar. Esta sesin acepta cualquier otro modelo de Arduino.
Un PC con el entorno de Arduino correctamente instalado y configurado.
Una Protoboard.
Un diodo LED
Una resistencia de 330 Ohmios.
Algunos cables de Protoboard.
En la sesin anterior programamos el LED conectado al pin 13 de nuestro Arduino. En esta sesin
vamos a duplicar este circuito en el exterior montndolo desde el principio con componentes
discretos. Su esquema elctrico sera.
Vemos a la izquierda el smbolo del diodo LED en serie una resistencia de 220.
A su vez vemos a la izquierda el smbolo GND para indicar que es el negativo. Por ltimo a la
derecha del smbolo de la resistencia tendremos el terminal que deberemos colocar a positivo
VCC o +5 V para conseguir que el LED se encienda.
14 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Es importante entender los esquemas, esto me permite comprender con rapidez cualquier circuito.
Vale la pena dedicarle un poco de esfuerzo porque son el lenguaje de la electrnica.
Una vez comprendido el esquema elctrico del circuito, veamos la conexin en la Protoboard:
Este esquema sigue una pauta de marcar los cables que van a positivo en rojo y los que van a
GND en azul (mejor negro). Recomendamos encarecidamente se siga esta norma en la prctica
porque ayuda a identificar posibles problemas y evita errores.
Podemos ahora volcar el programa que hicimos en la sesin 2 (o simplemente cargar el ejemplo
Blink), siguiendo el procedimiento que definimos all, y veremos cmo sta vez, adems del LED
propio en la placa de Arduino, nuestro LED exterior parpadea siguiendo el mismo ciclo de
encendido y apagado.
Hemos identificado dos componentes bsicos en electrnica, resistencias y los diodos LED.
Aprendimos a descifrar los primeros esquemas electrnicos.
Hemos montado nuestro primer circuito con estos componentes.
15 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Arduino Uno o similar. Esta sesin acepta cualquier otro modelo de Arduino.
Un PC con el entorno de Arduino correctamente instalado y configurado.
Una Protoboard.
7 x diodos LED.
7 x resistencia de 220 Ohmios.
Algunos cables de Protoboard.
En las sesiones anteriores vimos como gobernar un diodo LED externo. Si quisiramos montar un
circuito que tuviera 7 LEDs y en el que la luz se desplazara de uno a otro, una posibilidad sera
repetir varias veces las mismas secuencias de instrucciones que ya conocemos.
Por ejemplo si conectamos distintos LEDs a distintos pines digitales de Arduino, deberamos
declararlo en nuestra Funcin de setup() que podra ser:
void setup()
{
// initialize the digital pins as an output
pinMode( 10, OUTPUT) ;
pinMode( 9, OUTPUT) ;
pinMode( 8, OUTPUT) ;
pinMode( 4, OUTPUT) ;
}
Y a su vez nuestro loop() debera repetir tantas veces como LEDs tengamos el juego de encender
y apagar cada uno de los LEDs en secuencia desde el pin 10 hasta el 4.
Esta solucin es la que podramos describir como de fuerza bruta, pero no es muy elegante, es
trabajosa y probablemente cometeramos ms de un error al escribirla, porque las personas
tendemos a equivocarnos haciendo tareas repetitivas aburridas, y esta lo es mortalmente,
imaginad un circuito de 16 LEDs.
En cambio los ordenadores no se aburren y adems C++ nos ofrece un medio cmodo de
indicarle que debe repetir algo un nmero definido de veces. Este medio es la instruccin For
que podemos usar en combinacin con una variable.
16 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Una variable es un contenedor que puede tomar varios valores, en nuestro caso aceptar todos
los valores entre 4 y 10.
C++ nos exige declarar el tipo de las variables antes de usarlas. En nuestro caso usaremos el tipo
entero que se escribe int para indicar que esta variables es numrica y entera, sin decimales.
Iremos viendo que existen otros tipos de variables. Volveremos sobre este tema en prximas
sesiones.
As por ejemplo, para inicializar en nuestro setup() los pines desde el 10 hasta el 4 como salidas
(requerido por nuestro Arduino) podramos usar la instruccin for de la siguiente manera:
void setup()
{
int i = 0 ; // Inicializamos la variable i como un entero
for ( i = 4 ; i < 11 ; i++)
pinMode( i , OUTPUT) ;
}
Aunque la sintaxis parece complicada al principio, uno se acostumbra con rapidez. Aqu lo
importante es que for necesita 3 parmetros separados por un carcter de punto y coma.
valor_inicial_contador: una variable que ira tomando valores segn una cierta regla, y a la que
asignamos un valor inicial. En este caso: i = 4 .
condicion_final: el ciclo contina mientras se cumpla esta condicin. En nuestro caso mientras
la i sea menor que 11, o sea hasta el 10: i <11
incremento: como cambia la variable en cada iteracin. En nuestro caso i++ que es pedirle a
C++ que incremente en uno la variable i, al final de cada iteracin.
void loop()
{
int i = 0 ; // Inicializamos la variable i como un entero
for ( i = 4 ; i < 11 ; i++)
{
digitalWrite( i , HIGH) ;
delay (500) ;
digitalWrite( i , LOW);
delay (500) ;
}
}
En la sesin 3 el cdigo era muy similar excepto en que escribamos el valor 13 para el nico pin
que tena un LED conectado. Aqu asignamos el pin con una variable i , que va tomando los
valores de 4 hasta el 10 para el pin.
Ntese que la instruccin for no lleva un punto y coma al final. Esto es porque se aplica al bloque
de instrucciones que le siguen entre llaves, como es el caso del loop() La iteracin realiza las
cuatro instrucciones que siguen a la lnea del for, porque estn dentro de un bloque de
instrucciones.
17 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Las instrucciones que se aplican a bloques de cdigo, no llevan punto y coma al final.
En el caso de particular de que el bloque lleve una nica lnea de cdigo, las llaves pueden ser
omitidas, como en el caso de la instruccin for en la funcin setup() de arriba.
El esquema del circuito es muy similar al de la sesin 3, salvo por el hecho de que colocamos en
la Protoboard 7 LEDs.
Cuando nuestro programa coloque el pin correspondiente a valor HIGH, se cerrar el circuito
iluminndose el LED asociado a ese pin.
Con este circuito, y con el programa descrito en las pginas anteriores, tendremos un efecto de
luces similar al del coche fantstico.
18 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
En general, se considera buena costumbre, montar los circuitos que veamos a partir del esquema
electrnico del mismo, ms que a partir del diagrama de conexiones de la Protoboard.
La razn es que con el esquema, la comprensin del circuito es completa y se evita la tentacin
de copiar la prctica sin necesidad de entenderla.
Adems, el diagrama electrnico del circuito es su completa descripcin y suele resultar ms
sencillo comprender la funcin del mismo. En cambio a medida que los circuitos se hacen ms
complejos, comprender su funcin desde un esquema de Protoboard puede complicarse mucho, y
peor an llevar a una interpretacin errnea.
Este montaje nos permite jugar con las luces y se presta a varios programas diferentes para
conseguir distintos efectos.
Por ejemplo, con el programa anterior, el efecto no es exactamente el del coche fantstico porque
cuando acabamos de iterar el for, el programa vuelve a empezar desde el principio, lo que hace
que la luz salte desde el pin 4 hasta la del pin 10.
Desde luego que s, bastara con usar dos ciclos for, similar a lo siguiente:
void loop()
{
for ( int i = 4 ; i < 11 ; i++) // Definimos la variable i
sobre la marcha
{
digitalWrite( i , HIGH) ;
delay (500) ;
digitalWrite( i , LOW);
delay (500) ;
}
for ( int i = 9 ; i >4 ; i--) // Definimos la variable i
sobre la marcha
{
digitalWrite( i , HIGH) ;
delay (500) ;
digitalWrite( i , LOW);
delay (500) ;
}
}
El primer ciclo for hace que las luces se encienda en secuencia desde la 4 hasta la 10. El segundo
bucle entra a continuacin empezando con la luz 9 (para no repetir la 10) y finalizando con la
5(para no repetir la 4), y vuelta a empezar.
En el segundo bucle hemos hecho una cuenta atrs dicindole a la variable i que se decrementara
en uno en cada iteracin mediante la instruccin i - - .
Tambin nos hemos aprovechado de que C++ nos permite definir variables sobre la marcha
dentro de la propia instruccin for, sin necesidad de dedicarle una lnea completa a la declaracin
e inicializacin.
Otra variante seria, hacer un efecto de ola en al que las luces subieran dejando encendidos los
LEDs previos hasta alcanzar el mximo y ahora descender apagando los LEDs superiores. Os
recomendamos intentar resolver el problema como desafo.
19 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Programar es en parte aprender las instrucciones de un lenguaje, la parte fcil, y otra ms difcil
que es aprender a resolver los problemas de un modo que nos permita darle instrucciones a un
ordenador para que lo lleve a cabo.
Estos procedimientos secuenciales de cmo resolver un cierto tipo de problemas es lo que se
conoce como un algoritmo.
Segn el problema que abordemos el algoritmo ser ms o menos complicado pero aprender a
programar tiene ms que ver con desarrollar esta capacidad de resolver problemas lgicos en una
secuencia de pasos que podamos codificar en un ordenador.
Por cierto, cualquiera puede aprender a programar. No lo dudis. Solo que como en todo, a unos
les lleva ms tiempo que a otros desarrollar la habilidad necesaria. Al principio muchos dicen que
les duele la cabeza de pensar en este tipo de cosas, pero os animo a continuar, poco a poco si es
preciso, porque encontrareis que vale la pena.
La instruccin For, nos permite iterar un bloque de instrucciones tantas veces le indiquemos.
Hemos visto uno de los tipos de variables que C++ acepta: los enteros.
Hemos introducido el concepto de algoritmo, como un procedimiento secuencial para resolver un
problema concreto y lo hemos aplicado a varios ejemplos de programas sencillos con luces.
20 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
A este tipo de seales todo/nada, SI/NO, TRUE/FALSE, 1/0 u ON/OFF se les llama digitales, y
podemos manejarlas con los pines digitales del 0 al 13 de Arduino.
Muchos de los detectores, (sensores) y actuadores que vemos en el mundo real son digitales:
Como actuadores digitales, tenemos luces, alarmas, sirenas, apertura/bloqueo de puertas, etc.
Hemos visto que Arduino pueden usar los pines digitales como salidas todo o nada para encender
un LED. De la misma manera podemos leer valores, todo o
nada, del mundo exterior.
21 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
conectado al pin digital 2 de Arduino y ademas un segundo circuito con un pulsador S1 conectado
al pin 8 con una resistencia de 10K, tal como se muestra en el diagrama anterior.
En este esquema hemos seguido la prctica habitual de usar cables negros para conectar a masa
y cables rojos para conectar a tensin (+5V).
Obsrvese que el pulsador S1 tiene cuatro terminales. Esto es porque cada entrada del interruptor
tiene dos terminales conectados. En nuestro circuito simplemente ignoramos los terminales
secundarios. Ante cualquier duda del funcionamiento del pulsador utilizar un polmero para
comprobarlo.
22 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Empecemos haciendo un programa que haga que el LED se encienda cuando pulsamos el botn
y se apague cuando lo soltamos. Para ello pediremos a Arduino que configure el pin digital 2 (D2)
como salida para manejar el LED, y el pin digital 8 (D8) como entrada para leer el pulsador.
Normalmente en programas sencillos basta con poner el nmero de pin en las instrucciones. Pero
a medida que el programa se complica esto tiende a provocar errores difciles de detectar.
Por eso es costumbre definir variables con los nmeros de pin que usamos, de forma que
podamos modificarlos en un solo lugar del cdigo, y no teniendo que buscar a lo largo de todo el
programa. Vamos a escribir esto un poco ms elegantemente:
int LED = 2 ;
int boton = 8;
void setup()
{
pinMode( LED, OUTPUT) ; // LED como salida
pinMode( boton , INPUT) ;//botn como entrada
}
Atencin, recordar que, como vimos en la segunda sesin, C++ diferencia entre maysculas y
minsculas y por tanto LED, Led y led no son lo mismo. Del mismo modo, pinMode es correcto y
en cambio pinmode generar un error del compilador.
He usado la variable boton sin acento porque no es recomendable usarlos y tampoco la
cualquier otro smbolo en los nombres de variables, porque pueden pasar cosas extraas.
Vimos que para encender el LED bastaba usar digitalWrite( LED, HIGH). Para leer un botn se
puede hacer algo similar: digitalRead( boton). Veamos cmo podra ser nuestro loop:
void loop()
{
int valor = digitalRead(boton) ; // leemos el valor de boton
digitalWrite( LED, valor) ; //y lo almacenamos en valor
Fcil no? Comprobamos que el LED est apagado hasta que pulsamos el botn y se ilumina al
pulsar.
Cmo podramos hacer lo contrario sin modificar el montaje?, es decir que el LED se apague al
pulsar y se encienda si no pulsamos. Bastara con escribir en el LED lo contrario de lo que
leamos en el botn.
Existe un operador que hace eso exactamente, el operador negacin ! . Si una valor dado x es
HIGH, entonces !x es LOW y viceversa.
Un operador es un smbolo que relaciona varios valores entre s, o que modifica el valor de una
variable de un modo previsible.
Ejemplos de operadores en C++ son los matemticos como +,-,* , / ; y hay otros como la
negacin ! o el cambio de signo de una variable : x. Iremos viendo ms.
C++ incorpora un tipo de dato llamado bool o booleano que solo acepta dos valores TRUE (cierto)
y FALSE (falso) y son completamente equivalentes al 1 / 0, y al HIGH / LOW.
23 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
void loop()
{
bool valor = digitalRead(boton) ; // leemos el valor de boton y
//lo almacenamos en valor
digitalWrite( LED, !valor) ; //Escribimos lo contrario de valor en
// LED
}
Hemos definido valor como bool, porque podemos usar el valor de tensin alto como TRUE y el
valor bajo como FALSE.
SI el botn no est pulsado el D8 leer FALSE y por tanto pondr LED a TRUE. En caso contrario
apagar el LED.
De hecho podramos escribir una variante curiosa del blinking LED usando el operador negacin:
void loop()
{
bool valor = digitalRead (LED) ;
digitalWrite( LED, !valor) ;
delay ( 1000) ;
}
En este ltimo ejemplo observamos que, podemos leer la situacin actual de un pin ,nos devuelve
su estado actual, an cuando lo hayamos definido como salida. Por el contrario no podemos
escribir en un pin definido como entrada.
La primera linea lee la situacin del LED y la invierte en la segunda lnea, despus escribe esto
en LED. Y puestos a batir algn record, podemos escribir el blinking led en solo dos lneas:
void loop()
{
digitalWrite( LED , ! digitalRead( LED)) ;
delay ( 1000) ;
}
Las instrucciones dentro de los parntesis se ejecutan antes que las que estn fuera de ellos. Por
eso el digitalRead se ejecuta antes que el digitaWrite.
Hemos visto una forma de leer seales digitales del mundo exterior adems de poder enviarlas:
digitalRead( pin)
digitalWrite( pin , valor)
Hemos conocido un nuevo componente, el pulsador.
Conocemos un nuevo tipo en C++, el booleano y un nuevo operador el de negacin.
24 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
6 CONDICIONALES Y BOTONES
La instruccin if
6.1 OBJETIVOS
En la sesin anterior presentamos el tipo de variable booleano (bool) destacando que solo puede
tomar dos valores: TRUE o FALSE. Aunque para quienes no estn acostumbrados al lgebra
Booleana o binaria puede parecer excesivo dedicar un tipo a algo tan simple, en la prctica buena
parte de las instrucciones de programacin se apoyan o dependen de este tipo de variables.
La razn prctica es que con frecuencia hay que tomar decisiones para seguir un camino u otro en
funcin de que se cumpla una condicin dada. Esta condicin se debe evaluar necesariamente, a
TRUE o FALSE para tomar una decisin.
Por ejemplo, en las sesin 4 usamos la instruccin for y comentamos que la iteracin se
mantiene mientras se cumpla una cierta condicin. Esta condicin se evaluaba a TRUE o FALSE,
es decir es un booleano.
Existen otras muchas instrucciones que se apoyan en los valores booleanos, como los
condicionales if que veremos en esta sesin, pero de un modo muy explicito toda la computacin
actual se basa en la lgica digital de solo dos valores que solemos llamar 1 y 0, True y False.
Los ordenadores modernos funcionan mediante la aplicacin del lgebra de bool a variables
booleanas y contamos dentro de C++, con un juego completo de operadores lgicos como la
negacin, que vimos en la sesin anterior, algunos de estos operadores lgicos son AND (&&) y
OR (||).
6.4 LA INSTRUCCIN IF
En este captulo vamos a presentar unas instrucciones nuevas de C++, que nos permitan tomar
decisiones para tomar una decisin entre realizar una determinada cosa u otra.
tras el bloque if un bloque else (opcional), se ejecutarn las instrucciones escritas en el interior
de ese bloque else. Es decir, si solo escribimos el bloque if, el sketch tendr respuesta
solamente para cuando s se cumple la condicin; pero si adems escribimos un bloque else, el
sketch tendr respuesta para cuando s se cumple la condicin y para cuando no se cumple
tambin. En general, la sintaxis del bloque if/else es:
if (condicin) {
//Instrucciones una o ms que se ejecutan si la condicin es cierta
true,1 }else{
//Instrucciones una o ms que se ejecutan si la condicin es falsa false,0 }
Tanto si se ejecutan las sentencias del bloque if como si se ejecutan las sentencias del bloque
else, cuando se llega a la ltima lnea de esa seccin (una u otra), se salta a la lnea
inmediatamente posterior a su llave de cierre para continuar desde all la ejecucin del programa.
if (condicin) {
//Instrucciones una o ms que se ejecutan si la condicin es cierta
true,1
}
Tambin existe la posibilidad de incluir una o varias secciones else if, siendo en este caso
tambin opcional el bloque else final. Esta construccin tendra la siguiente sintaxis (puede haber
todos los else if que se deseen):
if (condicin) {
//Instrucciones una o ms que se ejecutan si la condicin es cierta
true,1 }
if (condicin) {
//Instrucciones una o ms que se ejecutan si la condicin es cierta
} else if (otra_condicin) {
/*Instrucciones una o ms que se ejecutan si la condicin
del anterior if es falsa pero la actual es cierta */ } else if (otra_condicin) {
/*Instrucciones una o ms que se ejecutan si la condicin del anterior if es falsa
pero la actual es cierta */
} else {
//Instruccin(es) que se ejecutan si todas las condiciones anteriores eran falsas
}
Es posible anidar bloques if uno dentro de otro sin ningn lmite (es decir, se pueden poner ms
bloques if dentro de otro bloque if o else, si as lo necesitamos).
Ahora que ya sabemos las diferentes sintaxis del bloque if, veamos qu tipo de condiciones
podemos definir entre los parntesis del if. Lo primero que debemos saber es que para escribir
correctamente en nuestro sketch estas condiciones necesitaremos utilizar alguno de los llamados
operadores de comparacin, que son los siguientes.
Operadores de comparacin
== Comparacin de igualdad
!= Comparacin de diferencia
26 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
int LED = 2 ;
int boton = 8;
void setup()
{
pinMode( LED, OUTPUT) ; // LED como salida
pinMode( boton , INPUT) ;//botn como entrada
}
void loop()
{
bool valor=digitalRead(boton);// leemos el estado del botn
if(valor) // s est pulsado
digitalWrite(LED,HIGH);// enciende LED
else // s no est pulsado
digitalWrite(LED,LOW); //apaga LED
}
Leemos primero el botn y almacenamos su valor en una variable de tipo bool y despus
decidimos si encendemos o apagamos el LED dependiendo de que su valor sea True o False.
Recordemos que un bloque es un conjunto de instrucciones encerrados entre llaves y que hay un
caso particular en el que se pueden omitir si y solo si, el bloque consta de una nica instruccin
como es nuestro caso.
Ejemplo 6.2: Vamos con un programa diferente. Queremos que el botn acte como un interruptor,
que al pulsarlo una vez se encienda, y la prxima vez lo apague. Podramos plantear algo as y os
recomiendo que lo probis en vuestro Arduino:
int LED=2;
int boton= 8;
bool estado=false;
void setup()
{
pinMode( LED , OUTPUT) ; //configura pin 2 como salida
pinMode(boton, INPUT); // configura pin 8 como entrada
digitalWrite(LED,LOW); // apaga el led
}
void loop()
{
bool valor=digitalRead(boton);//leemos el botn
if(valor == true)// s se ha pulsado el botn
{
estado=!estado; //cambiamos el estado
digitalWrite(LED,estado);//escribimos el nuevo valor
27 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
}
}
La idea es definir una variable llamada estado al principio para guardar la situacin del LED. El
loop comprueba si se ha pulsado el botn, y de ser as invierte su estado, y despus escribe el
valor de estado en el LED. Si estaba encendido lo apaga. Si estaba apagado se enciende.
Por eso, si lee un nmero par de veces dejara el LED como estaba y si lo lee un nmero impar de
veces lo invertir. En la prctica la situacin del LED se torna aleatoria, y si pulsis repetidamente
el botn veris que el resultado es impredecible.
Otra fuente de problemas es que en el mundo real un interruptor no cambia de un estado a otro de
forma perfecta, sino que suele rebotar y causar varios conexiones y desconexiones muy rpidas
antes de quedar en un valor estable. A esto se le llaman rebotes (bouncing) y al procedimiento
para eliminar estos rebotes se le llama debouncing en la jerga electrnica.
Ejemplo 6.3: El debouncing se puede hacer por hardware con un conjunto de resistencia y
condensador, o por software, mucho ms frecuentemente (por ms barato) y para esto una
solucin es nuevamente frenar a Arduino y hacerle esperar un tiempo entre 50 y 250 milisegundos
una vez que detecta que se ha pulsado el botn, de modo que nos d tiempo a liberar el pulsador:
void loop()
{
bool valor=digitalRead(boton);//leemos el botn
if(valor == true)// s se ha pulsado el botn
{
estado=!estado; //cambiamos el estado
digitalWrite(LED,estado);//escribimos el nuevo valor
delay(250);
}
}
Muy importante: Ntese que la condicin es (valor == false), con doble = . En C++ la comparacin
de dos valores usa ==, la asignacin de valor a una variable solo uno. Esto es fuente de errores
frecuentes al principio (entre programadores inexpertos).
Este lapso de 250 ms es suficiente para pulsar y liberar el botn cmodamente. Si probis esta
variante veris que ahora el LED invierte su valor cada vez que pulsas, siempre y cuando no te
demores demasiado en liberar el botn.
Pues sencillamente que el LED invierte su estado cada 250 ms (milisegundos) y tenemos otra
variante del blinking LED.
Ejemplo 6.4: Si queremos poder mantener pulsado sin que se produzca este efecto hay que
sofisticar un poco ms el programa:
int LED=2;
int boton= 8;
bool estado=false;
bool estadoAnterior = true;
void setup()
{
28 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
void loop()
{
estado=digitalRead(boton);
if(estado != estadoAnterior)//hay algn cambio, se ha pulsado o
soltado
{
if(estado==HIGH)//Al pulsar botn cambiar el estado del LED, pero
no al soltar
digitalWrite(LED,!digitalRead(LED));
estadoAnterior=estado; //recordamos el ltimo valor
}
}
Ya dijimos que para comprobar si dos valores son iguales usamos ==, Para comprobar si son
diferentes usamos !=.
Vale la pena comentar aqu que, a pesar de su aparente inocencia, los botones tienen una
sorprendente habilidad para complicarnos la vida, y que en la prctica la combinacin de rebotes y
la necesidad de corregirlos, junto al uso de pullups que garanticen la correcta lectura, pueden
hacer que su uso se pueda complicar mucho ms de lo que parece, sino se estudia el problema
con calma.
Por ltimo, una condicin lgica se puede construir mediante los operadores lgicos AND, OR, y
NOT cuyos smbolos son respectivamente: &&, || y !
Si usramos un circuito con dos pulsadores con pullups (True, si no se pulsa) y un LED,
dependiendo del comportamiento que se busque podemos especificar diferentes condiciones:
29 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
7 COMUNICACIN CON EL
EXTERIOR
El puerto serie en Arduino y los tipos String
7.1 OBJETIVOS
Antes o despus, necesitaremos comunicar nuestro Arduino con nuestro PC. Las razones son
varias, enviarle rdenes o recibir informacin de seales, por ejemplo.
Los PCs disponen de teclados, pantallas y adaptadores de red, pero con Arduino tenemos que
usar el puerto USB para establecer una conexin en serie con nuestro PC.
La comunicacin en serie es muy sencilla, bastan dos hilos para enviar una diferencia de tensin
entre ellos y poder marcar niveles alto (5V) y bajo(0V) y con esto podemos transmitir informacin
digital. Ahora solo nos falta pactar dos cosas entre quien enva y quien recibe:
El cdigo comn que vamos a usar con Arduino se llama cdigo ASCII y es estndar en todos los
PCs. Es una forma de codificar las letras mediante nmeros que representas estos caracteres.
Recordad que solo podemos transmitir unos y ceros.
Actualmente, en realidad, se suele usar una extensin del cdigo ASCII (llamada Unicode) que
permita el uso de caracteres no incluidos en la tabla original, y que permita representar
caracteres como las , o acentos para el espaol, pero tambin alfabetos distintos como el Kanji
chino o el alfabeto cirlico. Y este es el motivo por el que podis leer las letras chinas o rusas en
las pginas de internet de estos pases..
El otro factor a pactar para realizar una comunicacin serie es la velocidad. Dado que solo
disponemos de dos hilos para transmitir, necesitamos saber cundo hay que leer la lnea y esto se
30 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Buena parte de los errores de comunicacin serie programando con Arduino se suelen deber a
una diferencia de velocidad entre el emisor y el receptor.
Esta velocidad se mide en bits por segundo y vamos a ver que Arduino soporta diferentes
velocidades de comunicacin serie.
Arduino dispone de una librera serie incluida llamada Serial, que nos permite enva informacin al
PC y para usarla simplemente tenemos que pedirle en nuestro setup() que la incluya. La
instruccin que se encarga es:
Serial.begin( velocidad ) ;
Ntese que Serial tiene la S maysculas y que C++ diferencia entre maysculas y minsculas
La velocidad es una valor entre 300 y 115.200 bits por segundo. Y suele ser costumbre
establecerla en 9600 (el valor por defecto) pero no hay ninguna razn para ello y esta no es una
velocidad especialmente alta.
Para enviar un mensaje desde Arduino a nuestro PC podemos usar las funciones Serial.print() y
Serial.println().Veamos un Ejemplo 7.1:
void setup()
{
Serial.begin(9600) ;// Inicializa el Puerto seria 9600 bits por segundo
}
void loop()
{
int i = 54 ;
Serial.println( i );
}
El println() enviara el valor de i al puerto serie de Arduino. Para leerlo en nuestro PC necesitamos
un monitor de puerto serie. El IDE de Arduino incluye uno muy sencillo, pero suficiente que se
invoca con el botn del monitor:
31 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Normalmente la velocidad por defecto son los 9600 bits por segundo o baudios en los que hemos
programado nuestra puerto serie, y si lo desplegis, veris las diferentes velocidades aceptables
para Arduino.
Estrictamente hablando, bits por segundo y baudios no son exactamente lo mismo salvo bajo
ciertas condiciones particulares que en Arduino se cumplen, por lo que aqu podemos usarlos
como sinnimos.
En el mundo Arduino parece haber un acuerdo de usar velocidades bajas como 9600 en lugar
de ms altas como 115200, para evitar problemas. Esto es algo que hace aos estaba
justificado por problemas de transmisin, pero con la tecnologa actual no hay motivo para ello.
Es ms, en cuanto necesitemos utilizar dispositivos de comunicaciones como adaptadores
Ethernet o BlueTooth para comunicarnos, la velocidad tendr que subir necesariamente.
Ahora que sabemos enviar informacin y resultados al PC, vamos a ver cmo podemos operar
con enteros y mostrar el resultado en el puerto serie. En C++ los operadores numricos son los
normales en clculo y otros menos frecuentes:
Adicin: +
Resta:
Multiplicacin: *
Divisin entera: / Cociente sin decimales (puesto que operamos con enteros
Resto: % Devuelve el resto de una divisin.
En C++ tenemos que expresar las operaciones matemticas en una sola lnea y utilizar parntesis
para garantizar que se opera como necesitamos. Vamos con algunos ejemplos:
int i = 4 * 2 resultado = 8
int i = 4 * 2 / 3 resultado = 2 Porque desprecia los decimales al ser i entero
Dada una expresin, la precedencia de operadores indica que operaciones se realizaran antes y
cuales despus en funcin de su rango. Para los que se inician en C++ no es fcil saber que
operadores tienen preferencia, por lo que es ms seguro que ante la duda usis parntesis.
Los parntesis fuerzan las operaciones de una forma clara y conviene utilizarlos ante la duda
porque de otro modo, detectar los errores de operacin puede volverse muy difcil especialmente
cuando uno empieza a programar.
El operador resto es ms til de lo que parece a primera vista porque nos permite saber si un
numero es mltiplo de otro. Supongamos que queremos saber si un nmero dado es par.
void setup()
{
Serial.begin(9600) ; // Inicializa el Puerto serie
}
void loop()
32 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
{
int i = 27 ; //El nmero en cuestin
if ( i % 2 == 0)
Serial.println("Es par.") ;
else
Serial.println("Es impar");
}
Dando a i distintos valores podemos comprobar cmo funciona el operador resto %. Volveremos
sobre esto cuando veamos algunos ejemplos de cmo calcular nmeros primos.
En este programa hemos usado de un modo diferente el Serial.println() pasndole una String de
texto entrecomillada. Serial.print() enva el texto entrecomillado que le pongamos pero no realiza
el salto de lnea cuando termina. En cambio Serial.println() hace lo mismo pero incluye al final el
salto de lnea Ejemplo 7.3:
void setup()
{
Serial.begin(9600) ; // Inicializa el Puerto serie
}
void loop()
{
Serial.print("Buenos ") ;
Serial.print("Dias ") ;
Serial.println("a todos.") ;
}
C++ dispone de un tipo de variables llamadas Strings, capaces de contener textos. Podemos
operar con ellas simplemente definindolas como cualquier otro tipo de C++.Ejemplo 7.4:
void setup()
{
Serial.begin(9600); // Inicializa el puerto serie a 9600 bps
}
void loop()
{
int resultado = 25;
String s="El resultado es: "; // la S de String es mayscula
Serial.print(s);
Serial.println(resultado);
}
Un tipo String se define simplemente poniendo entre comillas dobles un texto, y se puede operar
con ellas de una forma similar a como operamos con enteros. Prueba Ejemplo 7.5:
void setup()
{
Serial.begin(9600); // Inicializa el puerto serie a 9600 bps
}
void loop()
{
String a = "hola " ;
String b = "a todos." ;
Serial.println( a + b);
}
33 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
void setup()
{
Serial.begin(9600); // Inicializa el puerto serie a 9600 bps
}
void loop()
{
int resultado = 25 ;
String s = "El resultado es: " ;
Serial.println( s + String( resultado ));
}
Hasta ahora solo hemos enviado mensajes desde Arduino hacia el PC, Pero como recibimos
mensajes en Arduino?
En primer lugar disponemos de una funcin llamada Serial.parseInt() que nos entrega lo que se
escribe en el monitor serie convertido a entero.Ejemplo 7.7:
void setup()
{
Serial.begin(9600); // Inicializa el puerto serie a 9600 bps
}
void loop()
{
if (Serial.available() > 0)
{
int x = Serial.parseInt();
Serial.println ( x) ;
}
}
Este programa simplemente recibe en x los nmeros que nos tecleen en la consola (cuando
pulsemos intro) y si es un texto, lo interpreta como cero.
Hemos utilizado otra funcin de Serial.available() que es un booleano. Conviene por costumbre
comprobar que antes de leer el puerto serie comprobemos si nos han enviado algo. Si lo hay
Serial.available() es True y en caso contrario es False.
Para leer un String del puerto serie tenemos que complicarnos un poco ms y hablar del tipo char.
char c = a ;
String s =a ;
34 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Para leer una cadena desde el puerto serie necesitamos leer un carcter cada vez y despus
montar un String a partir de ellos, pero antes, asegrate de seleccionar ambos NL & CR en la
parte inferior del monitor serie, para garantizar que se enva el carcter de fin de lnea:
Un programa para leer la consola sera algo as. Ejemplo 7.8:
void setup()
{ Serial.begin(9600); }
void loop ()
{
char c = ' ' ;
String mensaje ="" ;
if (Serial.available()) //Comprobamos si hay algo esperando
{
while( c != '\n') //Si lo hay, lo leemos hasta el intro
{
mensaje = mensaje + c ; // Aadimos lo ledo al mensaje
c = Serial.read(); //Leer 1 carcter
delay(25);
}
Serial.println( mensaje); //Al salir imprimir el mensaje
mensaje = "" ; //Brralo para la prxima vez
}
}
Aqu usamos otra instruccin de C++ llamada while. Es similar a if, Ejecuta repetidamente el
bloque que le sigue mientras se cumpla la condicin que le pasamos entre parntesis:
while ( condicin)
{ }
Cuando lee el intro final de lo que escribimos, La condicin c != \n se torna falso y sale del while.
Por lo dems, comprobamos si hay algo disponible en el puerto serie y de ser as montamos el
mensaje leyendo un char cada vez y sumndoselo a mensaje para construir un String que
podamos imprimir al salir.
El motivo del delay(25) es que a una velocidad tan lenta, enviar un char de 8 bits por el puerto
serie, tarda mucho ms de lo que tarda Arduino en ejecutar las instrucciones del while y volver a
empezar. Por eso si se suprime el delay (y os recomiendo la prueba) leer un carcter bueno
(de la palabra escrita y como 10 caracteres basura para un Arduino UNO o Mega).
Si subimos la velocidad de comunicacin a 115200 bits por segundo, comprobareis que no hay
este problema ya que al multiplicar la velocidad de envo por ms de 10 Arduino ya no tiene
tiempo de volver a por ms caracteres antes de que lleguen.
Hemos visto como establecer la comunicacin con el PC externo, tanto para enviar como para
recibir mensajes enteros y de texto.
Hemos presentado los tipos String y char.
Hemos visto las reglas bsicas para operar con enteros y con Strings.
Presentamos una nueva instruccin: while.
35 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
8. 2 MATERIAL NECESARIO.
Arduino Uno o similar. Esta sesin acepta cualquier otro modelo de Arduino
Una Protoboard.
Un diodo LED.
Un potencimetro de 10K
Una resistencia de 220 Ohmios.
Algunos cables de Protoboard.
8.3 EL POTENCIMETRO
Hasta ahora hemos usado siempre resistencias fijas, de un valor dado. Pero a veces es
conveniente disponer de un valor variable de resistencia o tensin, para controlar el circuito que
nos interesa.
Por eso un potencimetro siempre tiene 3 terminales. Los del extremo 1 y 3 se comportan como
una resistencia del valor de fondo de escala del potencimetro, y el pin central 2 va tomando
valores de resistencia en funcin del movimiento que hagamos con el ajuste.
Con Arduino hemos visto que podemos influir en el mundo exterior aplicando salidas todo / nada
en los pines digitales.
Tambin hemos visto cmo detectar pulsaciones de botones, definiendo como entradas los pines
digitales. Pero en muchas ocasiones los sensores que usamos para supervisar el mundo exterior,
nos entregan una seal analgica. Es el caso de los sensores de temperatura, intensidad
luminosa, de presin o de PH, de intensidad de corriente en un circuito, etc.
36 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Para leer este tipo de seales continuas necesitamos un convertidor analgico a digital (ADC) y
que nos permite leer el valor de una seal analgica en un instante dado y convertirla a digital.
Estos convertidores toman una muestra del valor actual de la seal y nos entregan su valor
instantneo, medido en Voltios.
Mediante la lectura repetida de muestras a lo largo del tiempo podemos reconstruir la seal
original con mayor o menor precisin, dependiendo de la exactitud de nuestra medida y de la
velocidad a la que pueda tomar esas muestras.
Veamos cmo usar las entradas analgicas con un circuito como este, en el que damos tensin a
los extremos 1 y 3 de un potencimetro y conectamos el pin central (2) a la entrada de la puerta
A5 de Arduino:
Los convertidores de Arduino UNO y Mega son de 10 bits de resolucin por lo que nos devolver
valores entre 0 y 210 0 y 1.024 para tensiones entre 0 y 5V. En cambio el Arduino DUE dispone de
convertidores de 12 bits por lo que el valor de sus lecturas estar entre 0 y 1012 o sea 4.096, es
decir tiene mejor resolucin(pero slo puede leer hasta 3,3V).
Asegrate de no usar sensores que puedan dar ms de 5V mximo (con Arduino UNO y Mega),
ya que daaras el chip principal de Arduino.
Vamos a escribir un programa que lea el valor del pin A5 y lo enve a la consola, puerto serie, para
que podamos visualizarlo.
void setup()
{
Serial.begin(9600); // Iniciamos la puerta serie
}
void loop()
{
int Lectura = analogRead(A5) ;
Serial.println( Lectura);
delay(200) ;
}
Cuando lo vuelques, arranca la consola y veras que a medida que giras el ajuste del
potencimetro, las lecturas varan de forma continua reflejando la posicin del potencimetro, las
lecturas reflejan la caida en voltios en el potencimetro.
Al no estar el A5 conectado a ninguna referencia vlida, est flotando y los valores que captura
son muestra de esa incoherencia.
Decamos en una seccin anterior, que la fidelidad con que podemos muestrear una seal
analgica dependa, bsicamente, de la resolucin de la muestra y de la velocidad a la que
podamos muestrear la seal (Sample Rate en ingls).
Ya dijimos que la familia Arduino, dispone de convertidores de 10 bits por lo que nuestra
resolucin es de 210 = 1.024 y en el caso del DUE de 212 = 4.096. Pero hasta ahora no hemos
visto a qu velocidad podemos tomar muestras con nuestro Arduino. Vamos a comprobarlo, con
este mismo circuito.
Tenemos una funcin llamada millis() que nos indica en milisegundos el tiempo transcurrido
desde que iniciamos Arduino y la podemos usar para ver cuantas muestras podemos tomar por
segundo. Ejemplo 8.2:
void setup()
{
Serial.begin(9600);
}
void loop()
{
unsigned long T ;
int n = 0 ;
T = millis();
while (millis() <= T + 1000)// Mientras no pase un Segundo = 1000 mS
{
analogRead( A5) ;
n++; // Contamos cada vez que leemos
}
Serial.println(n);
}
Hemos usado un unsigned long para guardar millis porque es el tipo que Arduino usa
internamente para su reloj. Sera un error manejar millis con un int porque su valor mximo es
32.767 y midiendo milisegundos el contador desbordara en poca ms de 32 segundos.
SI corris este programa en un Arduino UNO os dar, poco ms o menos, un resultado de 8.940
muestras o lecturas por segundo. No est mal.
Es adecuado para muestrear seales que no varen demasiado rpido con el tiempo, como son
casi todos los sensores habituales en la industria, pero que se quedar corto si queris muestrear
seales de audio.
Arduino Uno o similar. Esta sesin acepta cualquier otro modelo de Arduino
Una Protoboard.
Un diodo LED.
una resistencia de 220 Ohmios..
Algunos cables de Protoboard..
A esta clase de variables las llamamos analgicas y una representacin por contraposicin a lo
digital, sera algo como esto:
40 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
No es raro que queramos controlar algo del mundo exterior con una seal analgica de forma que
el comportamiento del sistema siga esa seal. Podemos por ejemplo querer variar la luminosidad
de un diodo lampara LED y no simplemente apagarla o encenderla.
En esta sesin aprenderemos a enviar seales analgicas a alguno de los pines de salida de
Arduino.
Hasta ahora hemos visto como activar las salidas digitales de Arduino, para encender y apagar un
LED por ejemplo. Pero no hemos visto como modificar la intensidad de brillo de ese LED. Para
ello, tenemos que modificar la tensin de salida de nuestro Arduino, o en otras palabras tenemos
que poder presentar un valor analgico de salida.
Para empezar tenemos que dejar claro que los Arduino carecen de salidas analgicas puras que
puedan hacer esto,con la notable excepcin del Arduino DUE.
Pero como los chicos de Arduino son listos, decidieron emplear un truco, para que con una salida
digital podamos conseguir que casi parezca una salida analgica.
A este truco se le llama PWM, siglas de Pulse Width Modulation, o modulacin de ancho de
pulsos. La idea bsica es poner salidas digitales que varan de forma muy rpida de modo que el
valor eficaz de la seal de salida sea equivalente a una seal analgica de menor voltaje.
Fijaros en la anchura del pulso cuadrado de arriba. Cuanto mas ancho es, mas tensin promedio
hay presente entre los pines, y esto en el mundo exterior es equivalente a un valor analgico de
tensin comprendido entre 0 y 5V. Al 50% es equivalente a una seal analogica del 50% de 5V,
es decir 2,5. Si mantenemos los 5V un 75% del tiempo, ser el equivalente a una seal analgica
de 75% de 5V = 3,75 V.
Para poder usar un pin digital de Arduino como salida analgica, lo declaramos en el Setup() igual
que si fuera digital:
41 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
pinMode( 9, OUTPUT) ;
analogWrite escribe en el pin de salida un valor entre 0 y 5V, dependiendo de V, que debe estar
comprendido entre 0 y 255.
De este modo si conectamos un LED a una de estas salidas PWM podemos modificar su brillo sin
ms que variar el valor que escribimos en el pin.
Pero hay una restriccin. No todos los pines digitales de Arduino aceptan poner valores PWM en
la salida. Solamente aquellos que tienen un smbolo ~ delante del nmero. Fijaros en la
numeracin de los pines de la imagen:
Si intentas hacer esto con un pin diferente, Arduino acepta la orden tranquilamente, sin error, pero
para valores de 0 a 127 entiende que es LOW y para el resto lo pone HIGH y sigue con su vida
satisfecho con el deber cumplido.
Vamos a hacer el tpico montaje de una resistencia y un diodo LED, similar al de la sesin 3, pero
asegurndonos de usar uno de los pines digitales que pueden dar seales PWM. En el ejemplo he
usado el pin 9.
Podemos escribir un programa parecido a esto:
void setup()
{
pinMode( 9, OUTPUT) ;
}
void loop()
{
for ( int i= 0 ; i<255 ; i++)
{
42 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
analogWrite (9, i) ;
delay( 10);
}
}
El LED va aumentando el brillo hasta un mximo y vuelve a empezar bruscamente. Podemos
modificar un poco el programa para que la transicin sea menos violenta:
void setup() //
{
pinMode( 9, OUTPUT) ;
}
void loop()
{
for ( int i= -255 ; i<255 ; i++)
{
analogWrite (9, abs(i)) ;
delay( 10);
}
}
Aqu aprovecho para hacer con un nico bucle for el ciclo de subir y bajar el brillo del LED. La
funcin abs(num), devuelve el valor absoluto o sin signo de un nmero num, y por eso mientras
que i va de -255 a 255, abs(i) va de 255 a 0 y vuelta a subir a 255.
43 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
10 DISPLAYS LCD
Usando displays de texto LCD 16x2 con Arduino
10.1 OBJETIVOS
Arduino Uno o similar. Esta sesin acepta cualquier otro modelo de Arduino.
Una Protoboard.
Cables de conexin.
Una resistencia ajustable de 10K.
Un display LCD, de 162 o 164.
Los displays LCD se utilizan para mostrar mensajes de texto sencillos. Son fciles de encontrar en
diversos formatos : 162 (16 caracteres x 2 lneas) o LCD 164 (16 caracteres x4 lneas). LCD
viene del ingls Liquid Crystal Display, o sea Pantalla de cristal liquido.
Son una opcin muy sencilla de usar, y adems, dan un toque muy profesional a nuestros
proyectos, y por eso, en los ltimos aos los displays LCD han ganado mucha aceptacin en
productos comerciales de todo tipo.
Bsicamente porque:
Son baratos.
Estn disponibles en varios tamaos y configuraciones.
Son de bajo consumo.
Muy prcticos si te basta con mostrar solo texto (y algunos caracteres especiales).
En esta sesin veremos cmo conectarlos a vuestro Arduino y cmo usarlos para sacar mensajes
por ellos, procedentes de Arduino.
44 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
La conexin no es complicada, pero requiere ser cuidadoso. As que vamos a ir paso a paso con
los diferentes cables. Empieza conectando tensin y GND a la protoboard.
45 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Paso 1
Aunque no aparece en el esquema, vamos a conectar la retro iluminacin del panel LCD. Conecta
el pin16 del LCD a GND y el 15 a 5V. Si conectas ahora el cable USB a tu ARDUINO, el LCD
debera iluminarse, si no, revisa tus cables antes de seguir.
Paso 2
Desconecta el USB y conecta ahora, el potencimetro de ajuste. Para ello conecta uno de los
extremos del potencimetro a GND y el otro a 5V. El centro al pin 3 del LCD. Aprovechemos
tambin para dar tensin al display LCD, El pin 1 va a GND y el 2 a 5V:
Paso 3
Si todo ha ido bien, ya podemos encender el display y probarlo. Conecta el USB a tu Arduino y
veamos. Si vas girando el potencimetro, en algn momento tienes que ver unos cuadraditos en la
pantalla, en caso contrario revisa las conexiones. No sigas, si no ves esto.
Paso 4
Vamos a conectar ya los pines de datos y control. Sin entrar en muchos detallas, no vamos a usar
todos los pines disponibles, porque no los necesitamos. Solo usaremos dos pines de control, RS y
EN y los 4 pines de datos D7, D6, D5, y D4 . No necesitamos mas por ahora.
Vamos a usar una librera para el control del panel LCD, que viene incluida en nuestro Arduino.
Pinchad en: \\Programa\Importar Libreria\LiquidCrystal. Y ahora podemos importar uno de los
ejemplos o escribir el nuestro, comentando el cdigo.
#include <LiquidCrystal.h>
Despus, hay que inicializar la librera. Creamos una instancia llamada lcd, de la clase
LiquidCrystal y le pasamos como parmetros los pines que hemos usado:
46 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // ( RS, EN, d4, d5, d6, d7)
Tened cuidado porque los pines que hemos usado, no corresponden a los ejemplos de Arduino,
as que podis cargarlos, pero aseguraros de cambiar la lnea de definicin de los pines, o no
funcionaran.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // ( RS, EN, d4, d5, d6, d7)
void setup()
{
lcd.begin(16, 2); // Fijar el numero de caracteres y de filas
}
void loop()
{
lcd.setCursor(0, 0); // coloca el cursor en la columna 0 lnea 0
lcd.print("Curso iDOM 16-17"); // Enviar el mensaje
lcd.setCursor(0, 1); // coloca el cursor en la columna 0 lnea 1
lcd.print(millis()/1000);//muestra el n de seg. desde el reset
}
Ejemplo 12.2: Otro ejemplo muy sencillo es el siguiente, que muestra en el LCD aquello que se
escribe en el Serial monitor en tiempo real (suponiendo que nuestra placa Arduino la tenemos
conectada a un computador va USB).
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int luzFondo = 13; //Defino el pin para la luz de fondo
void setup() {
pinMode(luzFondo, OUTPUT);
digitalWrite(luzFondo, HIGH); //Activo la luz de fondo
lcd.begin(16,2);
Serial.begin(115200);
}
void loop() {
if (Serial.available()>0) {
//Me espero un poco para que llegue el mensaje entero
delay(100);
lcd.clear();
//Leo todos los caracteres disponibles del buffer
while (Serial.available() > 0) {
//Muestro cada carcter en el LCD
lcd.write(Serial.read());
}
}
}
La librera LCD, viene con varios ejemplos muy interesantes, que os conviene probar. Recordad,
simplemente, que tenis que cambiar las definiciones de los pines para que funcionen en vuestro
montaje.
47 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Sin llegar a tanta sofisticacin, es muy interesante que veamos cmo definir algunos caracteres
especiales, porque en la tabla base del LCD, no estn incluidas , acentos, grados, o . As que
dependiendo del uso que le deis pude seros de inters saber cmo definir tus propios smbolos.
Lo primero que debemos hacer para poder utilizar pantallas LCD compatibles con la librera oficial
LiquidCrystal es declarar una variable global de tipo LiquidCrystal, la cual representar dentro de
nuestro sketch al objeto LCD que queremos controlar. La declaracin se ha de realizar usando la
siguiente sintaxis (suponiendo que llamamos milcd a dicha variable-objeto): LiquidCrystal
milcd(rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7); donde todos los parmetros especificados
entre parntesis en realidad son valores numricos que representan:
Por ejemplo, una posible declaracin para una LCD de 4 bits sin uso del pin rw podra ser:
Una vez creado el objeto lcd con la lnea anterior, lo primero que debemos hacer es establecer el
tamao de la pantalla para poder trabajar con ella. Esto se hace mediante la siguiente funcin:
A partir de aqu, ya podremos escribir caracteres en la pantalla con alguna de las tres funciones
siguientes:
lcd.write(): escribe un carcter en la pantalla. Como nico parmetro tiene ese carcter, el
cual se puede especificar explcitamente entre comillas simples o bien a travs de una variable
de tipo byte (cuyo valor puede haber sido obtenido de un sensor, o ledo del canal serie,
etc.). Su dato de retorno es de tipo byte y vale el nmero de bytes escritos (por tanto, si todo
es correcto, valdr 1, aunque no es obligatorio utilizarlo.
lcd.print(): escribe un dato (de cualquier tipo) en la pantalla. Como primer parmetro tiene ese
dato, que puede ser tanto un carcter de tipo char como una cadena de caracteres, pero
tambin puede ser numrico entero (int, long, etc.). Opcionalmente, se puede especificar un
segundo parmetro que indica, en el caso de que el dato a escribir sea entero, el formato con
el que se ver: puede valer la constante predefinida BIN (que indicar que el nmero se
visualizar en formato binario), HEX (en hexadecimal) y DEC (en decimal, que es su valor por
defecto). Su dato de retorno es de tipo byte y vale el nmero de bytes escritos, aunque no es
obligatorio utilizarlo.
49 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
10 FUNCIONES Y ENTEROS
Definiendo funciones y diferentes tipos de enteros
10.1 OBJETIVOS
Ya hemos comentado antes, que programar es un poco como andar en bici, se aprende
pedaleando y a programar se aprende programando. Hay que ir aprendiendo la sintaxis del
lenguaje, C++ en nuestro caso, pero tambin aprendiendo a resolver problemas lgicos y partirlos
en instrucciones.
Hacer cursos de programacin, o de andar en bici, est bien, pero al final hay que ponerse a
programar y tener problemas, porque tenindolos y resolviendo los problemas, solo o con ayuda
de alguien, se aprende. No se puede aprender a montar en bici slo estudiando.
Con un cierto temblor de manos, vamos a centrarnos en esta sesin en algunos ejemplos clsicos
de programacin, como son el clculo de nmeros primos para entrenar esta capacidad de
bsqueda de algoritmos prcticos para resolver problemas ms o menos abstractos y para
presentar algunos conceptos adicionales.
Es importante destacar que no existe una forma nica de resolver un problema concreto y que una
solucin no tiene porque ser mejor que otra, aunque con frecuencia se aplican criterios de
eficiencia o elegancia para seleccionar una solucin.
Esta sesin va a requerir un esfuerzo un poco mayor que las anteriores porque vamos a empezar
a entrenar un msculo poco usado, el cerebro, en una tarea poco frecuente, pensar. Y esto es
algo que exige un poco de esfuerzo, pero es necesario para avanzar.
Supongamos que queremos crear un programa que nos devuelva true o false segn que el
nmero que le pasamos sea primo o no y que podamos llamar varias veces sin copiar el cdigo
una y otra vez. La llamaremos Primo () y queremos utilizarla de la siguiente manera: Si el numero
n que le pasamos es primo nos tiene que devolver true y en caso contrario que devuelva false, o
sea queremos que nos devuelva un valor bool.
En realidad, ya hemos utilizado varias funciones que Arduino trae predefinidas como Serial.print()
o abs() , o Serial.available() y se las reconoce por esa apertura y cierre de parntesis.
C++ nos ofrece todas las herramientas para crear nuestras propias funciones y es algo muy til
porque nos ayuda a organizar un problema general en trozos o funciones ms pequeas y ms
fciles de manejar.
50 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Para definir una funcin as, tenemos que declararla primero y describirle a C++ que hacer:
Declaramos la funcin como bool Primo (int x), o sea va a devolver un valor bool y por eso en
algn punto de la funcin tendremos que usar la instruccin return( true) o return( false) para
devolver un resultado a quien la llame. Si devolviera un entero habra que definirla como int
Primo( int x).
Si una funcin no va a devolver ningn valor, sino que simplemente realiza su trabajo y finaliza sin
mas entonces hay que declararla como void (vaca). Ya conocemos dos funciones as : setup() y
loop().
Para saber si un nmero es o no primo basta con dividirlo por todos los nmeros positivos
menores que l y mayores que 1. En el ejemplo dividimos el nmero n empezando en 2 y
finalizando en n-1.
Para usar Primo hay que pasarle un entero. Recordad que al definir la funcin dijimos bool Primo
(int n) donde n representa el valor que queremos probar. As pues:
void loop()
{
int x =48; //el nmero a probar
bool p = Primo(x);
if (p)
Serial.println(String(x) + " Es primo.");
else
Serial.print(String(x) + " No es primo, el ");
}
51 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Veamos un ejemplo distinto, cuantos nmeros primos hay desde el 1 hasta el 1024:
void setup()
{
Serial.begin(9600); // Inicializa el pueto serie a 9600 bps
}
void loop()
{
if (control)// para que realice el lazo una sola vez
//y no lo repita indefindamente
{
Serial.println("Los nmero primos hasta el " +String(maximo));
for(int x=2;x<maximo;x++)
{
bool p = Primo(x);
if(p) Serial.println(x);
}
}
control=false;
}
bool Primo(int n)
{
for(int i=2;i<n;i++)
{
if(n%i ==0) // S el resto es cero es divisible.
return(false);
}
return(true);
}
Aunque el programa funciona correctamente la salida no es muy presentable( Recordad que nos
gusta ser elegantes). Vamos a formatearla. Para ello usaremos el carcter tabulador que se
representa como \t y una coma despus.
void setup()
{
Serial.begin(9600); // Inicializa el pueto serie a 9600 bps
}
void loop()
{
if (control)// para que realice el lazo una sola vez
//y no lo repita indefindamente
{
Serial.println("Los numeros primos hasta el " +String(maximo));
for(int x=2;x<maximo;x++)
{
if(Primo(x)) // mandamos ha imprimir el numero
{
52 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Ahora el programa formatea la salida de una forma un poco ms presentable y cmoda de leer.
Para conseguirlo, hemos aadido una coma y un tabulador a cada nmero excepto a uno de cada
8 que aadimos intro. Tambin tenemos una lnea que conviene comentar:
if ( contador++ % 8 == 0)
53 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Cuando a una variable se le aaden dos signos mas al nombre (++), significa que primero se use
su valor actual en la instruccin en curso, en este caso es en el if, y despus se incremente en 1
su valor.
Si hubiramos escrito:
if ( ++contador % 8 == 0)
Querra decir que queremos incrementar su valor antes de utilizarlo. Esta notacin es muy habitual
en C++ y conviene reconocerla. Tambin podemos usar contador- - y - - contador para
decrementar.
Este sera un buen momento para preguntarnos hasta donde podra crecer la variable mximo en
el programa anterior. Le asignamos un valor de 1024, pero Tiene un entero lmite de tamao?
La respuesta es afirmativa. Los enteros int en Arduino C++ utilizan 16 bits por lo que el mximo
seria en principio 216 = 65.536, Pero como el tipo int usa signo, su valor est comprendido entre
-32.768 y +32.767.
De hecho en Arduino C++ hay varios tipos distintos de tamaos para manejar enteros:
Todos estos tipos representan enteros con y sin signo y se pueden utilizar para trabajar con
nmeros realmente grandes pero no sin lmite.
De hecho C++ tiene la fea costumbre de esperar que nosotros llevemos el cuidado de no
pasarnos metiendo un valor que no cabe en una variable. Cuando esto ocurre se le llama
desbordamiento (overflow) y C++ ignora olmpicamente el asunto, dando lugar a problemas
difciles de detectar si uno no anda con tiento.
int i = 32767 ;
Serial.println ( i+1);
Enseguida veras que si i=32767 y le incrementamos en 1, para C++ el resultado es negativo. Eso
es porque sencillamente no controla el desbordamiento. Tambin es ilustrativo probar el resultado
de:
int i = 32767 ;
Serial.println (2* i + 1);
Hemos visto ya de pasada las dos funciones o rutinas principales de un sketch: setup() y loop().
Ambas se declaran de tipo void, lo cual significa que no retornan ningn valor. Arduino simplifica
muchas tareas proporcionando funciones que permiten controlar entradas y salidas tanto
analgicas como digitales, funciones matemticas y trigonomtricas, temporales, etc.
54 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Tu puedes tambin escribir tus propias funciones cuando necesites programar tareas o clculos
repetitivos que vas a usar varias veces en tu programa(o en futuros programas). La primera cosa
que tienes que hacer es declarar el tipo de funcin ,int si retorna un entero, float si es un nmero
en coma flotante, etc).
Te recomendamos dar a la funcin un nombre que tenga que ver con lo que hace para que te
resulte fcil recordarla, o identificarla cuando la veas escrita en uno de tus programas. A
continuacin del nombre de la funcin y sin dejar espacios, van los parmetros de la funcin
entre parntesis. Y ya slo queda lo ms difcil: escribir el cdigo de la funcin entre llaves:
type functionName(parameters)
{
// el cdigo de la funcin va aqu.
}
Recuerda que si la funcin no retorna un valor hay que definirla como de tipo void (vacio). Para
devolver el control al programa la funcin usa la instruccin return seguida por el nombre de la
variable que se quiere devolver y luego un punto y coma (;).
La siguiente rutina muestra una funcin que convierte una temperatura expresada en grados
Fahrenheit a Celsius o grados centgrados:
La funcin se declara de tipo float y se le pasa un parmetro, tambin de tipo float, que representa
los grados Fahrenheit medidos por un sensor. Dentro de la funcin se declara la variable Celsius
de tipo float que va a contener la medida de la temperatura pasada en Fahrenheit tras su
conversin a Celsius. La instruccin return devuelve el valor en Celsius de la temperatura pasada
en Farenheit. Esta funcin puede ser usada como parte de un sistema para registrar las
temperaturas captadas por un sensor a lo largo del tiempo.
Como puedes ver, el uso de funciones es la manera ideal de simplificar tu cdigo y abordar tareas
repetitivas.
55 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
Hemos visto en la sesin anterior, como definir funciones. En esta sesin vamos a ampliar el
programa que comprobaba si un nmero era primo, en ste nuevo programa introduciremos por
consola un nmero y el programa deber comprobar si es o no primo imprimiendo por consola el
resultado de la comprobacin.
Normalmente para resolver un problema complejo es buena poltica partirlo en otros problemas
ms pequeos que podamos resolver ms fcilmente. En este caso vamos a plantear al menos 2
funciones:
Primo() Calcula si un nmero dado es primo, devuelve true y en caso contrario false.
getLine() Vamos a definir una funcin genrica que recoja una cadena de texto de la puerta
serie, para procesarla a posteriori. En este caso recoger el nmero a probar.
La idea es, que nuestro programa empiece comprobando si un numero es primo. Y por ultimo
necesitamos una funcin que nos lea un numero de entrada desde la consola.
Fijaros que casi sin haber escrito una linea de programa, ya he decidido como partirlo en bloques
mas sencillos de manejar y programar. En otras palabras, he buscado una estrategia, de
resolucin
Un array es simplemente una coleccin de elementos organizados como una tabla, y pueden
definirse con varias dimensiones. Empecemos con un array de una sola dimensin. Para definirlo
podemos optar por dos maneras:
En el primer caso definimos un array de enteros, de una sola dimensin con 5 elementos, sin
asignarle valores.
56 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
En el segundo caso asignamos un array de enteros a los valores que le pasamos entre llaves, sin
especificar cuantos, porque le dejamos a C++ la tarea de contarlos. Decimos que definimos el
array por enumeracin.
Para asignar o leer los valores de un array se utiliza un ndice entre corchetes. Veamos este
programa:
El programa imprime el contenido del array recorriendo sus 5 posiciones, indicando posicin y
contenido.Esto lo hace de forma repetida cada 2 segundos.
Atencin: la primera posicin del un array es la 0 y la ltima el nmero de elementos del array 1.
As serie2 [0] devuelve el primer elemento 3, y serie2[4] el ltimo 23.
Uno esperara que C++ generase un error, ya que definimos un array de 5 elementos y hacemos
referencia a 100, pero no. Nuevamente C++ nos sorprende devolviendo correctamente los 5
primeros valores y luego sigue leyendo posiciones de memoria consecutivas tan tranquilo, como si
tuvieran sentido.C++ espera que seamos nosotros quienes controlemos esto, as que mucho
cuidado.
Int Tablero[8,8];
Imaginad que Tablero representa las posiciones de una partida de ajedrez y cada valor que
contiene esa posicin corresponde a una pieza que se encuentra en esa casilla.
Aunque ya comentamos que podemos usar una funcin parseInt () incluida en Arduino para
recoger un valor del puerto serie, tiene el inconveniente de que si no recibe una entrada salta al
cabo de un tiempo ( muy escasito) y devuelve 0, por lo que tendramos que controlar el valor
devuelto para que no se repitiese continuamente.
Por eso vamos a escribir una funcin de uso general que nos permita recoger una cadena de texto
de la puerta serie sin que salga hasta que reciba un String que vamos a hacer finalice en intro. De
hecho ya vimos este programa, aunque no como funcin en la sesin Comunicacin con el
exterior
57 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
String GetLine()
{
String S = "" ;
if (Serial.available())
{
char c = Serial.read(); ;
while ( c != '\n')//Hasta que el character sea intro
{
S = S + c ;
delay(25) ;
c = Serial.read();
}
return(S) ;
}
}
Definimos Getline() de tipo String, porque queremos que nos devuelva un texto. Comprobamos
que hay algo disponible en la puerta serie, y en caso afirmativo construimos un String S
aadindole cada uno de los caracteres que leemos del puerto serie, hasta que encontremos un
intro.
Al encontrar el intro, se cumple la condicin de salida del while y termina la funcin devolviendo la
cadena construida (sin el intro).
Normalmente convendr comprobar si hay algo disponible en la puerta serie antes de llamar a
GetLine(), y si es as, la comprobacin que hace GetLine() de tener algo disponible en el Serial
seria redundante.
Podemos ya escribir nuestra funcin principal loop(), que llame a las funciones que hemos
definido a lo largo de esta sesin, para determinar si un numero que le pasamos por la puerta
serie es primo o no y en caso negativo que nos muestre los divisores primos encontrados.
void setup()
{
Serial.begin(9600) ;
}
void loop()
{
if (Serial.available())
{
String s = GetLine();
int i = s.toInt() ;//Como esperamos un numero,
convertimos el texto a numero
if ( Primo(i))
Serial.println(String(i) + " Es primo.");
else
58 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
String GetLine()
{
String S = "" ;
if (Serial.available())
{
char c = Serial.read(); ;
while ( c != '\n')//Hasta que el character sea intro
{
S = S + c ;
delay(25) ;
c = Serial.read();
}
return(S) ;
}
}
bool Primo(int n)
{
for(int i=2;i<n;i++)
{
if(n%i ==0) // S el resto es cero es divisible.
return(false);
}
return(true);
}
Empezamos comprobando si hay algo sin leer en la puerta serie y si es asi llamamos a GetLine()
para que nos consiga lo que hay.
Como GetLine() nos devuelve un tipo String() usamos la funcin estndar de Arduino C++, s.toInt()
que convierte el contenido String a tipo numrico int.
Despus llamamos a Primo() para que compruebe este nmero. Y, simplemente imprime un
mensaje para confirmarlo.
59 de 60
2016-17 PRIMEROS PASOS CON ARDUINO
60 de 60