You are on page 1of 251

Primeros pasos en Arduino

Cuando uno empieza con Arduino, parece que la cantidad de cosas que hay que aprender es
inabordable. Necesitas conceptos de electricidad de electrónica de programación algo de ingeniería.
Y dependiendo de lo que quieras hacer, algo de matemáticas y mucha física (Ay Dios mío).

Hemos diseñado este itinerario pensando en la gente que como tú, amable lector, que si estás
leyendo esto, probablemente tengas que empezar desde el principio.

Por eso, estos primeros capítulos esta pensados para irte llevando de la mano, en los conceptos
básicos 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 electrónicos con la ley de Ohm e irán apareciendo las primeras
instrucciones de Arduino C++, con algunos programas y circuitos en los que haremos prácticas.

Las primeras sesiones de este tutorial están pensadas para alguien que quiere iniciarse y cuyos
conocimientos en estos temas son nulos, pero que quiera aprender. Y creemos que si nos sigues
conseguirás ese objetivo. En ello hemos puesto todo nuestro empeño.

1 – Instalación del entorno de trabajo Arduino.

Empecemos por el principio. Descargando e instalando el entorno de trabajo.

2 – Nuestro primer programa.

Siempre hay una primera vez. Un programa muy sencillo y algunas ideas básicas.

3 – Nuestro primer circuito.

Un circuito para quitar el miedo. Un diodo LED mas una resitencia.

4 – Circuito con múltiples LEDs.

Si funciona con un LED… ¿Porque no con 8?

5 – Las entradas digitales de Arduino.

Los sentidos de Arduino. Percibiendo el exterior en digital.


6 – Condicionales y botones.

Seguimos introduciendo instrucciones de C++ : Los condicionales

7 – Comunicación con el exterior.

Las puertas USB en Arduino y la comunicación serie.

8 – Funciones y enteros.

Seguimos trabajando vuestro conocimiento de C++ jugando con números primos como excusa.

9 – Un programa con varias funciones.

Sabemos que es cuesta arriba. Animo, como en la bici hay tramos así.

10 – Los pines cuasi analógicos.

Las salidas analógicas PWM

11 – Los diodos LED RGB.

Un capítulo divertido. O como mezclar colores con un LED RGB.

12 – Arduino y las puertas analógicas.

O de como usar las puertas analógicas para leer valores contínuos del exterior.
INSTALACIÓN DEL
ENTORNO DE TRABAJO
ARDUINO
Descargar y configurar el IDE

Objetivos

o Descargar del entorno de trabajo IDE de Arduino..

o Instalación del entorno..

o Comprobar su correcto funcionamiento .

Descarga e instalación del IDE Arduino.

Vamos s descargar e instalar el entorno de desarrollo de Arduino (IDE),y comprobar que está
correctamente configurado. Para ello vamos a la página de descarga:

http://arduino.cc/en/main/software

Y bajamos la versión más reciente del IDE (Entorno de desarrollo de Arduino) Que a la fecha de
escribir esto es la beta 1.6.48 es suficientemente estable para usarla en condiciones normales.

 Esta versión soporta las versiones DUE y Yun de Arduino y son obligadas para utilizar estos
modelos.

Elegir la versión correspondiente a nuestro sistema (En Windows recomendamos la versión Installer)
y tened paciencia porque es una descarga moderadamente grande

Una vez finalizado, ejecutad el fichero descargado, e ir respondiendo a las opciones de instalación.

 Aceptar las opciones por defecto de instalación es una opción razonable en caso de no estar
seguro de las preguntas que nos hace,
Al cabo de unos minutos finalizara la instalación, y en el área de trabajo del
equipo aparecerá el icono de Arduino

Comprobació de la instalación.

Una vez instalado el IDE, vamos a comprobar que reconoce nuestro Arduino correctamente y que
podemos programarlo. Para ello, Conecta tu Arduino a tu ordenador mediante el USB

 Comprueba que las luces del Arduino se iluminan indicando que tiene alimentación.

Al hacerlo nuestro PC debe detectar el nuevo dispositivo USB y montar el driver adecuado.

Y finalmente:

Atención, el puerto serie en que se instala puede variar del indicado en la imagen, dependiendo de
las características del equipo.

 En Linux además os creará una puerta \dev\ttyx y tendréis que daros de alta en el grupo de
usuarios de los USBs.
 Mac debería instalartelo a la primera, sin complicaciones.
Si nuestro modelo es un DCcduino UNO como el de la
foto, en muchos PCs necesitan un driver adicional que
puedes descargar desde aqui:

Driver DCcduino para windows

Driver DCcduino para Mac OSX

Descomprime e con Winrar, y ejecuta el programa incluido. Te instalará un controlador que resuelve
el problema.

Ahora, ya podemos arrancar el icono de Arduino del escritorio de trabajo y configurar el modelo de
Arduino y confirmar el puerto serie al que se conecta. En [Menú]\Herramientas\Placa Elegir el
modelo exacto de nuestro Arduino. En nuestro caso elegimos un Arduino Uno:

En [Menú]\Herramientas\Port es necesario comprobar que tenemos asignado un puerto y que tiene


la marca de selección.

Es importante asignar el puerto y el modelo de Arduino para garantizar el correcto funcionamiento


del IDE. La marca de selección debe estar con el tick. Vamos ahora a volcar un programa de
ejemplo:
Al pulsar [Menú]\Archivo\Ejemplos\01.Basics\Blink, aparecerá una serie de textos en el entorno de
trabajo, que ignoraremos por ahora. Pulsar el botón Marcado en amarillo, Veremos una línea de
progreso verde avanzando.

Si todo va correctamente veremos un mensaje en la parte inferior del IDE:

Este mensaje en color blanco indica que hemos volcado correctamente el programa y ya deberíamos
ver una luz que parpadea en nuestra placa Arduino, según indica la flecha roja:

Si vemos la luz parpadeando en nuestro Arduino, enhorabuena, el entorno está instalado y


configurado correctamente. Ya podemos pasar a la siguiente sesión.
NUESTRO PRIMER
PROGRAMA
Blinking LED

Objetivos

o Fijar algunas ideas básicas sobre programación.

o Comprender la estructura de un programa Arduino (Sketch).

o Definir las estructuras de bloques.

o Las primeras instrucciones.

Material requerido.

Arduino Uno o similar.

Esta sesión acepta cualquier otro modelo de Arduino.

Un cable USB adecuado al conector de tu Arduino.

Un PC con el entorno de Arduino correctamente instalado y


configurado..
Algunas ideas básicas sobre programación.

Un programa de ordenador es básicamente el equivalente a una receta de cocina… pero destinado


a un público distinto.

Mientras que las personas somos razonablemente buenas interpretando las instrucciones,
generalmente vagas, 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 además carece por
completo de la imaginación o capacidad de improvisación humana.

Por ello se desarrollan los lenguajes de ordenador, para dar instrucciones a una máquina de forma:

 Precisa: Sin ambigüedades inherentes a la comunicación humana.


 Univoca: Solo se puede interpretar de una manera.
 Concisa: Preferiblemente ordenes cortas.

El IDE de Arduino se programa en una variante de C++ , que es un lenguaje muy extendido por sus
características, aunque no es un lenguaje sencillo. C++, que fija reglas estrictas de cómo 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 altera).

Un programa interno comprueba que la sintaxis de nuestro programa es acorde a la norma de C++, y
si hay cualquier cosa que no le convence dará un error y finalizará la comprobación obligándonos a
revisar lo que hemos escrito.

Cuando el comprobador acepta nuestro programa, invoca 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.

Funcion del compilador


El compilador convierte nuestras instrucciones (código fuente) en instrucciones del procesador
(código ejecutable).

Estructura de un programa Arduino.

Un programa o sketch de Arduino consiste en dos secciones o funciones básicas:

 Setup: Sus instrucciones se ejecutan solo una vez, cuando se arranca el programa al
encender Arduino o cuando pulsamos el botón de reset. Generalmente incluye definiciones
e inicializaciones de ahí su nombre.
 Loop: Sus instrucciones se van ejecutando en secuencia hasta el final…. Y cuando acaba,
vuelve a empezar desde el principio haciendo un ciclo sin fin.

Cuando abrimos el IDE de Arduino (o hacemos [Menú]\Archivo\nuevo) él nos escribe ya estas dos
funciones (en color cobre):

Nótese que el principio de cada función es indicado por la apertura de llave “ { “ y el fin de la misma
corresponde al símbolo de cerrar llaves “ } “.

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 imperativo que a cada apertura de una llave corresponda un cierre de llave. En sucesivos
capítulos ampliaremos este concepto.

Por ahora resaltar las líneas que aparecen dentro de los bloques principales:

// put your setup code here, to run once

// put your main code here, to run repeatedly

Cualquier cosa que escribamos precedido por “ // “ son comentarios, y serán ignorados. Es decir
podemos dejarnos mensajes dentro del código,(que de otro modo darían errores). El compilador
ignorará cualquier cosa entre // y el fin de línea.

Primeras instrucciones en Arduino C++.

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 sus posibilidades:
 La capacidad de Arduino para interactuar con el mundo externo. Algo bastante inusitado para
quienes estén acostumbrados a la informática tradicional, donde la potencia de cálculo ha
crecido de forma espectacular, pero sigue siendo imposible (o casi), influir en el mundo exterior.
 La sencillez del entorno de trabajo. En contraposición 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 como:

 Entradas: Para leer información digital del mundo exterior.


 Salidas: Para activar una señal al mundo exterior.

Arduino dispone de 14 pines que pueden ser usados de este modo, numerados del 0 al 13:

pines del 0 al 13

En la sesión anterior cargamos un programa de ejemplo que hacia parpadear un LED en la placa con
una cadencia definida. Veamos como programar esto.

Pediremos a Arduino que active su pin 13 como de salida digital y después encenderemos y
apagaremos esta señal lo que hará que el LED que tiene conectado de serie se encienda o apague al
ritmo que marquemos.

Para indicar al sistema que deseamos usar el pin 13 como salida digital utilizamos la instrucción:

pinMode ( 13, OUTPUT ) ;

El primer parámetro indica el pin a usar y “OUTPUT” es para usarlo como salida, y también podría
usarse el valor “INPUT” para indicar que vamos a leer de este pin.
Estas definiciones se harán solo una vez al principio, en la función setup(). La nuestra quedará, con
una única instrucción 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 fijarse en que a pesar de ser una única instrucción, hemos delimitado el bloque de
esta función mediante abrir y cerrar llaves.
 Obsérvese que la instrucción finaliza en “ ;” . C++ obliga a acabar las instrucciones con un
punto y coma que delimite la orden. Si se omite generará un error.

Para encender el LED usaremos la instrucción:

digitalWrite( 13 , HIGH) ;

Y otra instrucción similar que le ordena apagarlo:

digitalWrite( 13 , LOW) ;

El 13 indica el pin a utilizar y HIGH, LOW indican el valor que deseamos poner en esa salida, que
en Arduino corresponden a 5V para HIGH y 0V para LOW.

 Si en la función loop() escribiéramos estas dos instrucciones seguidas, Arduino cambiaría


estos valores tan deprisa que no percibiríamos cambios, así que necesitamos frenarle un
poco para que podamos percibir el cambio.

Para hacer este retraso de, digamos, un segundo, utilizaremos:

delay(1000) ; // delay(n) “congela” Arduino n milisegundos

Por tanto para programar una luz que se enciende y se apaga, tendríamos que generar una secuencia
de órdenes (Como en una receta e 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 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.
 Si omitiéramos este segundo retraso, apagaría la luz y volvería a empezar
encontrándose la orden de volver a encender. No apreciaríamos que se había
apagado.(No espero que me creáis. Comprobadlo).
 El procesador de Arduino UNO es muy lento desde el punto de vista electrónico,
pero es capaz de conmutar la luz( pasar de encendido a apagado y vuelta a
encender) unas 15.000 veces por segundo.

El primer concepto que tenéis que fijar, es que los ordenadores procesan las ordenes en secuencia,
una instrucción después 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 Descargar:
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

 Nótese el sangrado de las líneas para destacar los bloques de código. Esto se considera
buena práctica y os lo recomendamos encarecidamente, porque facilita mucho la
comprensión del programa.
 Cuando os equivoquéis ( y creadme, os vais a equivocar) el sangrado ayuda,y mucho, a
visualizar el programa.
 Solo hay dos tipos de programadores. Los que se equivocan y los que se van a equivocar
Solo nos falta ya, comprobar si hay errores y para ello pulsamos el icono en amarillo:

Si todo va bien,( si no hay errores en rojo) podemos compilar y volcar con la siguiente 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 al Arduino y podremos comprobar que la luz del pin
13 parpadea con un retraso de un segundo entre encendido y apagado.

 Sugerencia: Si modificamos los valores del delay, modificaremos la cadencia del parpadeo.
 Nota: Esto no funcionara con ningún otro Pin del Arduino UNO, porque solo el 13 tiene un
LED conectado.

Resumen de la sesión

En esta sesión hemos aprendido varias cosas importantes:

o El concepto clave de un programa, como secuencia de instrucciones que se ejecuta


en el orden marcado.

o Hay dos funciones básicas en todo programa Arduino: Setup() y Loop()..

o Para delimitar un bloque de instrucciones usamos apertura y cierre de llaves..

o Todas las instrucciones acaban en punto y coma (Aunque hay excepciones)…

o Podemos usar comentarios usando // .

o Hemos aprendido algunas instrucciones iniciales del Arduino C++.


NUESTRO PRIMER
CIRCUITO
Arduino, primer circuito

Objetivos

o Fijar algunas ideas básicas sobre electrónica.

o Montar un circuito con LED y Resistencia comprender el esquema eléctrico..

o Aprender el manejo de la Protoboard..

o Instalar del blinking LED en la Protoboard.

Material requerido.

Arduino Uno o similar. Esta sesión 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.

Algunas ideas básicas sobre electrónica

Cuando dejamos fluir agua de un sitio alto a otro más bajo, el agua corre libremente mientras no se
lo impidamos, y siempre de arriba abajo. Decimos que las diferentes alturas suponen una diferencia
de potencial entre ambos puntos que puede ser transformada en trabajo útil.

Cuando existe una diferencia de tensión eléctrica (o diferencia de potencial) entre dos puntos con
conexión, la electricidad fluye del positivo (o de mas carga) hacia el negativo o menos, y también
podemos obtener trabajo útil de este principio.

Aunque la física detrás de estos dos ejemplos es diferente, conceptualmente son bastante parecidos y
por ello hablamos de:

 Corriente de agua / Corriente eléctrica.


 Caudal de agua / Intensidad de corriente.
 Resistencia al flujo / Resistencia eléctrica.
 Capacidad de una reserva de agua / Capacidad de un condensador.

La idea es que la corriente eléctrica fluye del positivo al negativo porque hay una diferencia de
tensión (que medimos en Voltios de símbolo V) pero esto no es una medida absoluta sino la
diferencia que hay entre los puntos en que lo medimos.

 De la misma manera, la diferencia de altura entre dos puntos solo representa eso, una
diferencia y no indica a qué altura se encuentran con respecto a una referencia más o
menos arbitraria.

Hay componentes que se oponen a a la libre circulación de la corriente. Los llamamos resistencias ,
su valor se mide en Ohmios y su símbolo es Ω .

La ley de Ohm, liga todos estos valores de una forma precisa:

V=RxI

Donde V es la tensión en voltios, R la resistencia e I la intensidad eléctrica que fluye.

 En el mundo de Arduino la tensión es casi siempre 5V, que es la tensión a que funciona y la
que es capaz de poner en sus salidas digitales.
Otra manera de escribir esta ley de Ohm es: I=V/R

Lo que implica que si la resistencia del circuito es nula (o casi, como en el caso de un cable de
cobre) la intensidad de la corriente se dispara y puede llegar a fundir el cable o componente que
encuentre.

 Esto se conoce como cortocircuito o corto simplemente y debe ser evitado decididamente ya
que suele acabar con olor a quemado y algún susto, en el mejor caso.

Nuestro primer circuito electrónico

En la sesión anterior programamos el LED conectado al pin 13 de nuestro Arduino. Hoy vamos a
duplicar este circuito en el exterior montándolo desde el principio con componentes discretos. Su
esquema eléctrico sería:

Vemos a la izquierda el símbolo del diodo LED que es emisor de luz y por eso tiene esas flechitas
salientes para indicarlo (LED viene del inglés Light Emitting Diode, o diodo emisor de luz).

La resistencia se representa por ese segundo símbolo indicando un nombre R1 y su valor 330Ω.

A su vez vemos a la izquierda las letras GND para indicar que es el negativo. Tiene muchos
nombres: Masa, El símbolo –, Tierra( aunque no es lo mismo), Ground, Negativo, cátodo.

Por último a la derecha el símbolo de +5V indica el extremo de tensión positiva o positivo y a veces
se representa como Vcc. Las líneas rectas y negras indican conexión eléctrica mediante cables
conductores.
 Un diodo, es un componente electrónico que solo permite pasar la
corriente en una dirección. En la dirección del positivo al negativo (la
parte ancha del triángulo) al negativo, la punta del triángulo (que
indica la dirección).
 Para indicar cuál de las patas de un diodo LED es el positivo, éste
suele ser de mayor longitud.
 Si se conecta a la inversa, cortará el flujo de corriente muy eficazmente y no se iluminará
en absoluto.

 Las resistencias en cambio no diferencian un extremos del otro, decimos que no tienen
polaridad.

Es importante entender los esquemas electrónicos porque permiten comprender con rapidez
cualquier circuito. Vale la pena dedicarle un poco de esfuerzo porque son el lenguaje de la
electrónica.

Una vez comprendido el esquema eléctrico del circuito, veamos la conexión 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 negro. Recomendamos encarecidamente se siga esta norma en la práctica porque ayuda a
identificar posibles problemas y evita errores.

 La Protoboard une los puntos de la línea azul entre si y los de encima de la línea roja entre
sí, (se les llama raíles), pero no conecta el raíl rojo positivo con el raíl negro negativo.

 A su vez existen dos zonas de líneas verticales en la Protoboard. Estas líneas verticales
están unidas entre sí internamente, para facilitar la conexión de los componentes, pero no
se unen las líneas paralelas.

Las claves para montar el circuito con éxito, son:

 Conectamos el pin 13 de Arduino a la línea roja de la Protoboard: Positivo.


 Conectamos el GND de Arduino a la línea azul de la Protoboard: Ground.
 Usamos el raíl positivo (los pines de la línea roja) para conectar a la resistencia.
 El otro extremo de la resistencia se conecta al positivo del LED porque están en la misma
vertical de la Protoboard (y esta los conecta eléctricamente).
 Nótese que el positivo del LED está claramente marcado como de mayor longitud mediante
un pequeño ángulo cerca de la base.
 Un diodo LED casi no presenta resistencia propia, por lo que siempre debe usarse una
resistencia adicional que limite el paso de corriente, y evite que se queme. (Una resistencia
entre 220 y 3300 Ω suele ser adecuada).
 El circuito se cierra con un cable desde el negativo del LED al raíl de GND.
 Cuando nuestro programa ponga un valor de HIGH (5V) en el pin 1,3 permitirá el flujo de
corriente por el circuito iluminando el LED. Con LOW sencillamente el circuito estará
apagado, sin tensión.

Podemos ahora volcar el programa que hicimos en la sesión 2 (o simplemente cargar el ejemplo
Blink), siguiendo el procedimiento que definimos allí, y veremos cómo ésta vez, además del LED
propio de Arduino, nuestro LED exterior parpadea siguiendo el mismo ciclo de encendido y
apagado.

Resumen de la sesión

En esta sesión hemos aprendido varias cosas importantes:

o Hemos visto algunos conceptos básicos de electrónica: la ley de Ohm, que


relaciona la tensión la resistencia.

o Hemos identificado dos componentes básicos en electrónica, resistencias y los


diodos.

o Aprendimos a descifrar los primeros esquemas electrónicos.

o Hemos montado nuestro primer circuito con estos componentes


CIRCUITO CON MÚLTIPLES
LEDS
Arduino com 8 LEDs, iteraciones

Objetivos

o Conocer las Iteraciones en C++, Instrucción for.

o Primeras variables en C++.

o Circuito con múltiples LEDs.

o Aprendiendo a programar…programando.

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo de Arduino.Un PC con el entorno de Arduino
correctamente instalado y configurado.

Una Protoboard.

8 x diodos LED.
Una resistencia de 330 Ohmios.

Algunos cables de Protoboard.

Un circuito con varios LED: Iteraciones For

En las sesiones anteriores vimos como gobernar que un diodo LED externo. Si quisiéramos montar
un circuito que tuviera 8 LEDs y en el que la luz se desplazara de uno a otro, una posibilidad sería
repetir varias veces las mismas secuencias de instrucciones que ya conocemos.

Por ejemplo si conectamos distintos LEDs a distintos pines digitales de Arduino, deberíamos
declararlo en nuestra Función de setup() que podría ser:

void setup()

// initialize the digital pins as an output

pinMode( 13, OUTPUT) ;

pinMode( 12, OUTPUT) ;

pinMode( 11, OUTPUT) ;

…………………………

pinMode( 6, OUTPUT) ;

Y a su vez nuestro loop() debería repetir tantas veces como LEDs tengamos el juego de encender y
apagar cada uno de los LEDs en secuencia desde el pin 13 hasta el 6.
Esta solución es la que podríamos describir como de fuerza bruta, pero no es muy elegante, es
trabajosa y probablemente cometeríamos más de un error al escribirla, porque las personas tendemos
a equivocarnos haciendo tareas repetitivas aburridas (y esta lo es mortalmente, imaginad un circuito
de de 16 LEDs).

En cambio los ordenadores no se aburren y además C++ nos ofrece un medio cómodo de indicarle
que debe repetir algo un número definido de veces. Este medio es la instrucción For que podemos
usar en combinación con una variable.

 Una variable es un contenedor que puede tomar varios valores, en nuestro caso aceptará
todos los valores entre 6 y 13.
 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 numérica y entera, sin
decimales.
 Iremos viendo que existen otros tipos de variables. Volveremos sobre este tema en próximas
sesiones.

Así por ejemplo, para inicializar en nuestro setup() los pines desde el 13 hasta el 6 como salidas
(requerido por nuestro Arduino) podríamos usar la instrucción for de la siguiente manera:

void setup()

int i = 0 ; // Inicializamos la variable i como un entero

for ( i = 6 ; i < 14 ; i++)

pinMode( i , OUTPUT) ;

Aunque la sintaxis parece complicada al principio, uno se acostumbra con rapidez. Aquí lo
importante es que for necesita 3 parámetros separados por un carácter de punto y coma.

Estos parámetros son y en éste orden:

 Una variable que ira tomando valores según una cierta regla, y a la que asignamos un valor
inicial. En este caso: i = 6 .
 El ciclo continúa mientras se cumpla esta condición. En nuestro caso mientras la i sea
menor que 14, o sea hasta el 13: i <14
 Como cambia la variable en cada iteración. En nuestro caso i++ que es pedirle a C++ que
incremente en uno la variable i, al final de cada iteración.

Con el mismo criterio podríamos escribir la función loop() así Descargar:


void loop()

int i = 0 ; // Inicializamos la variable i como un entero

for ( i = 6 ; i < 14 ; i++)

digitalWrite( i , HIGH) ;

delay (500) ;

digitalWrite( i , LOW);

delay (500) ;

En la sesión 3 el código era muy similar excepto en que escribíamos el valor 13 para el único pin que
tenía un LED conectado. Aquí asignamos el pin con una variable i , que va tomando los valores de 6
hasta el 13 para el pin.

 Nótese que la instrucción 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 iteración
realiza las cuatro instrucciones que siguen a la línea del for, porque están dentro de un
bloque de instrucciones.
 Las instrucciones que se aplican a bloques de código, no llevan punto y coma al final.
 En el caso de particular de que el bloque lleve una única línea de código, las llaves pueden
ser omitidas, como en el caso de la instrucción for en la función setup() de arriba.

Esquema electrónico del circuito

El esquema del circuito es muy similar al de la sesión 3, salvo por el hecho de que colocamos en la
Protoboard 8 LEDs.
La única novedad es que dado que la función de la resistencia es limitar la intensidad de la corriente
que circula por el circuito, y puesto que todos los diodos tienen masa común, basta una única
resistencia entre este punto y Ground.

Cuando nuestro programa levante el pin correspondiente a valor a HIGH, se cerrar el circuito
iluminándose el LED asociado.

Con este circuito, y con el programa 4.1 descrito en las páginas anteriores, tendremos un efecto de
luces similar al del “coche fantástico” (O de los Zylon para los aficionados a la ciencia ficción).

A continuación incluimos un esquema de conexión del circuito en una protoboard.

 En general, se considera buena


costumbre (la recomendamos), montar
los circuitos que veamos a partir del
esquema electrónico del mismo, más
que a partir del diagrama de conexiones
de la Protoboard.
 La razón es que con el esquema, la
comprensión del circuito es completa y
se evita la tentación de copiar la
práctica sin necesidad de entenderla.

 Además, el diagrama electrónico del circuito es su completa descripción y suele resultar


más sencillo comprender la función del mismo. En cambio a medida que los circuitos se
hacen más complejos, comprender su función desde un esquema de Protoboard puede
complicarse mucho, y peor aún llevar a una interpretación errónea.
Variantes del programa con el mismo circuito

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 4.1, el efecto no es exactamente el del coche fantástico
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 6 hasta la del pin 13.

Así pues ¿ Podríamos hacer que la luz rebotara ? Pensadlo un poco.

Desde luego que sí, bastaría con usar dos ciclos for, similar a lo siguiente Descargar:
void loop() // Prog_4_2

for ( int i = 6 ; i < 14 ; i++) // Definimos la variable i sobre la


marcha

digitalWrite( i , HIGH) ;

delay (500) ;

digitalWrite( i , LOW);

delay (500) ;

for ( int i = 12 ; i >6 ; 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 6 hasta la 13. El
segundo bucle entra a continuación empezando con la luz 12 (para no repetir la 13) y
finalizando con la 7(para no repetir la 6), y vuelta a empezar.
 En el segundo bucle hemos hecho una cuenta atrás diciéndole a la variable i que se
decrcmentara en uno en cada iteración mediante la instrucción i– .
 También nos hemos aprovechado de que C++ nos permite definir variables sobre la
marcha dentro de la propia instrucción for, sin necesidad de dedicarle una línea completa a
la declaración e inicialización.

Otra variante seria, hacer un efecto de ola en al que las luces subieran dejando encendidos los LEDs
previos hasta alcanzar el máximo y ahora descender apagando los LEDs superiores. Os
recomendamos intentar resolver el problema como desafío, antes de buscar una solución.

 Programar es en parte aprender las instrucciones de un lenguaje (la parte fácil), y otra más
difícil 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 cómo resolver un cierto tipo de problemas es lo que
se conoce como un algoritmo.
 Según el problema que abordemos el algoritmo será más o menos complicado pero
aprender a programar tiene más que ver con desarrollar esta capacidad de resolver
problemas lógicos en una secuencia de pasos que podamos codificar en un ordenador.
 Por cierto, cualquiera puede aprender a programar. No lo dudéis. Solo que como en todo, a
unos les lleva más tiempo que a otros desarrollar la habilidad necesaria. Al principio
muchos me 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 os encontrareis que vale la pena.

Resumen de la sesión

En esta sesión hemos aprendido varias cosas importantes:

 La instrucción 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.
LAS ENTRADAS DIGITALES
DE ARDUINO
Leyendo un pulsador con Arduino

Objetivos

o Conocer las entradas digitales.


o Leer el primer pulsador.
o Presentar los valores booleanos.
o Un operador: Negación.

Material requerido.

Arduino Uno o similar. Un PC con el entorno de Arduino


correctamente instalado y configurado.

Una Protoboard.

Un diodo LED.

Un pulsador.

Dos resistencias de 330 Ohmios.


Algunos cables de Protoboard.

Entradas digitales

Con frecuencia en electrónica necesitamos saber si una luz está encendida o apagada, si alguien ha
pulsado un botón o si una puerta ha quedado abierta o está cerrada.

A este tipo de señales todo / nada, SI / NO, TRUE /FALSE, 0/1 se les llama digitales, y podemos
manejarlas con los pines de 0 al 13 de Arduino y por eso hablamos de pines digitales.

Muchos de los sensores y actuadores que vemos en el mundo real son digitales:

 Como actuadores digitales, tenemos luces, alarmas, sirenas, desbloqueo de puertas, etc.
 Como sensores digitales podemos mencionar botones y pulsadores, Finales de carrera,
desbordamiento de nivel, sensores de llamas, humo o gases tóxicos.

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.

En esta sesión veremos que los pines digitales de Arduino pueden ser usados tanto de entrada como
de salida. Vamos a leer un botón o pulsador externo y vamos a encender o apagar un LED en
función de que el botón se pulse o no.

Esquema electrónico del circuito.

Montaremos un circuito con un diodo LED y resistencia conectado al pin digital 10 de Arduino, tal y
como vimos en las sesiones previas y ademas un segundo circuuito con un pulsador S1 conectado al
pin 6 con una resitencia como se muestra en el diagrama siguiente.
Obsérvese que mientras no pulsemos S1 el pin 6 de Arduino está conectado a 5V a través de la
resistencia R3 forzando una lectura de tensión alta (HIGH). En cambio cuando pulsemos S1
cerraremos el circuito del pin 6 a Ground con lo que leerá tensión baja, LOW. En ambos casos
tenemos un valor de tensión definido.

Si no pusiéramos la resistencia R3, al pulsar S1 leeríamos correctamente LOW en el pin 6. Pero al


dejar de pulsar S1 el pin 6 estaría en un estado flotante, que es ni HIGH ni LOW sino
indeterminado. Como esto es inaceptable en circuitos digitales forzamos una lectura alta con R3.

 A esta resistencia que fuerza el valor alto en vacio se le conoce como pullup Si la
conectáramos a masa para forzar una lectura a Ground se le llamaría pulldown resistor.
 Esta resistencia es clave para que las lecturas del pulsador sean consistentes. El circuito,
simplemente, no funcionará bien si se omite (volveremos sobre esto).

Y aquí tenemos el esquema para protoboard del circuito.

 En este esquema hemos seguido la


práctica habitual de usar cables negros
para conectar a masa y cables rojos
para conectar a tensión (5V).

Obsérvese que el pulsador S1 tiene cuatro pines


(el que está sobre la resistencia horizontal).
Esto es porque cada entrada del interruptor
tiene dos pines conectados. En nuestro circuito
simplemente ignoramos los pines secundarios

Leyendo los pulsadores

Empecemos haciendo un programa que haga que el LED se encienda cuando pulsamos el botón y se
apague cuando lo soltamos. Para ello pediremos a Arduino que configure el pin digital 10 (D10)
como salida para manejar el LED, y el pin digital 6 (D6) como entrada para leer el botón.

Normalmente en programas sencillos basta con poner el número de pin en las instrucciones. Pero a
medida que el programa se complica esto tiende a provocar errores difíciles de detectar.

Por eso es costumbre definir variables con los números de pin que usamos, de forma que podamos
modificarlos tocando en un solo lugar (y no teniendo que buscar a lo largo del programa). Vamos a
escribir esto un poco más elegantemente:
int LED = 10 ;

int boton = 6;

void setup()

pinMode( LED, OUTPUT) ; // LED como salida

pinMode( boton , INPUT) ; //botón como entrada

 Atención: C++ diferencia entre mayúsculas y minúsculas y por tanto LED, Led y led no son
lo mismo en absoluto. Del mismo modo, pinMode es correcto y en cambio pinmode
generará un error de compilador fulminante.

 He usado la variable boton sin acento porque no es recomendable usarlos ni la ñ en los


nombres de variables, porque pueden pasar cosas extrañas.

Vimos que para encender el LED bastaba usar digitalWrite( LED, HIGH). Para leer un botón se
puede hacer algo similar: digitalRead( botón). Veamos cómo podría ser nuestro loop:

void loop()

int valor = digitalRead(boton) ; // leemos el valor de boton


en valor

digitalWrite( LED, valor) ;

¿Fácil no? Aunque el LED está encendido hasta que pulsamos el botón y se apaga al pulsar.

¿Cómo podríamos hacer lo contrario, que el LED se encienda al pulsar y se apague si no? Bastaría
con escribir en LED lo contrario de lo que leamos en el botón.

Existe un operador que hace eso exactamente el operador negación “ ! “ . Si una valor dado x es
HIGH, entonces !x es LOW y viceversa.
 Un operador es un símbolo 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 matemáticos como +,-,* , / ; y hay otros como la
negación ! o el cambio de signo de una variable : – x. Iremos viendo más.

De hecho este tipo de operaciones son tan frecuentes que C++ incorpora un tipo llamado bool o
booleano que solo acepta dos valores TRUE (cierto) y FALSE y son completamente equivalentes al
1 / 0, y al HIGH / LOW

Este nuevo programa sería algo así:

void loop()

int valor = digitalRead(boton) ; // leemos el valor de boton en


valor

digitalWrite( LED, !valor) ; //Escribimos valor en LED

Hemos definido valor como bool, porque podemos usar el valor de tensión alto como TRUE y el
valor bajo como FALSE.

SI el botón no está pulsado el D6 leerá TRUE y por tanto pondrá LED a FALSE. En caso contrario
encenderá el LED.

De hecho podríamos escribir una variante curiosa del blinking LED usando el operador negación:

void loop()

bool valor = digitalRead (LED) ;

digitalWrite( LED, !valor) ;

delay ( 1000) ;

}
 Podemos leer la situación actual de un pin (nos devuelve su estado actual), aún cuando lo
hayamos definido como salida, En cambio no podemos escribir en un pin definido como
entrada.

La primera linea lee la situación del LED y la invierte en la segunda línea, después escribe esto en
LED. Y puestos a batir algún record, podemos escribir el blinking led en solo dos líneas:

void loop()

digitalWrite( LED , ! digitalRead( LED)) ;

delay ( 1000) ;

 Las instrucciones dentro de los paréntesis se ejecutan antes que las que están fuera de ellos.
Por eso el digitalRead se ejecuta antes que el digitaWrite..

Resumen de la sesión

o Hemos visto una forma de leer señales digitales del mundo exterior además de
poder enviarlas:
 digitalRead( pin)
 digitalWrite( pin , valor)
o Hemos conocido un nuevo componente: el pulsador.
o Conocemos un nuevo tipo en C++, el booleano y un nuevo operador de negación.
CONDICIONALES Y
BOTONES
La instruccion if

Objetivos

o Lógica digital y algebra de Bool.


o Los condicionales.Instrucción if.
o Botones, pulsadores y pullups.
o Debouncing.

Material requerido.

Arduino Uno o similar. Un PC con el entorno de Arduino


correctamente instalado y configurado.

Una Protoboard.

Un diodo LED.
Un pulsador.

Dos resistencias de 330 Ohmio.

Algunos cables de Protoboard..

Lógica digital y algebra de Bool

En la sesión anterior presentamos el tipo de variable bool destacando que solo puede tomar dos
valores: True o False. Aunque para quienes no estén acostumbrados al algebra booleana o binaria
puede parecer excesivo dedicar un tipo a algo tan simple, en la práctica buena parte de las
instrucciones de programación se apoyan o dependen de este tipo de variables.

La razón práctica es que con frecuencia hay que tomar decisiones para seguir un camino u otro en
función de que se cumpla una condición dada; Esta condición se debe evaluar necesariamente, a
True o False para tomar una decisión sin duda posible.

Por ejemplo, en las sesión 4 usamos la instrucción for y comentamos que la iteración se mantiene
mientras se cumpla una cierta condición. Esta condición debe ser evaluable 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 sesión) pero en un modo muy explicito toda la computación
actual se basa en la lógica digital de solo dos valores que solemos llamar 1 y 0, pero que con todo
derecho podemos llamar a estos valores True y False.

Los ordenadores modernos funcionan mediante la aplicación del algebra de bool a variables
booleanas y con un juego completo de operadores lógicos como la negación, que vimos en la
sesión anterior, mas operadores lógicos como AND, OR, + y – .
La instrucción if

En este capítulo vamos a presentar unas instrucciones nuevas de C++, que nos permitan tomar
decisiones para hacer una cosa u otra.

La instrucción if es muy sencilla de usar, basta con pasarle entre paréntesis una variable o condición
que se evalúe a true o false. Si el resultado es true se hace el bloque que viene a continuación y en
caso contrario se ejecuta el bloque que hay detrás del else si existe.

Si no existe la clausula del esle, entonces el bloque que sigue al if, se ejecuta o no, en función de la
condición y luego sigue con la secuencia de instrucciones a continuación.

if ( condición)

instrucción 1 ;

instrucción 2 ;

................

else

instruccion20 ;

instruccion21 ;

..............

Recordemos que en el circuito de la sesión anterior disponíamos de un pulsador y de un LED, en


esta sesión vamos a continuar con el mismo circuito y para conseguir que el LED se encienda o
apague al pulsar el botón. Para ello podríamos mantener la misma función setup() y escribir el
loop() diferente:
void loop()

bool valor = digitalRead(boton) ;

if ( valor)

digitalWrite( LED, HIGH) ;

else

digitalWrite( LED, LOW) ;

Leemos primero el botón a una variable bool y después decidimos si encender o apagar el LED
dependiendo de qué 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
instrucción como es nuestro caso.
 Se puede utilizar una instrucción if omitiendo la cláusula de else si se desea, pues esta es
opcional.

Volviendo con los botones

Vamos con un programa diferente. Queremos que el botón actúe como un interruptor, que al pulsarlo
una vez se encienda, y la próxima vez lo apague. Podríamos plantear algo así y os recomiendo que lo
probéis en vuestro Arduino:

int LED = 10 ; int boton = 6 ;

bool estado = false ;

void setup()

pinMode( LED, OUTPUT) ;

pinMode( boton , INPUT_PULLUP) ;

digitalWrite(LED , LOW) ; // Apagamos el LED al empezar


}

void loop()

bool valor = digitalRead(boton) ; //leemos el


botón: false = LOW

if ( valor == false ) // esto es que


han pulsado el botón

estado = ! estado ; // cambiamos el


estado

digitalWrite(LED, estado) ; // escribimos el


nuevo valor

La idea es definir una variable llamada estado al principio para guardar la situación del LED. El loop
comprueba si se ha pulsado el botón, y de ser así invierte su estado, y después escribe el valor de
estado en el LED. Si estaba encendido lo apaga. Si estaba apagado se enciende.

Aunque parece un plan perfecto, en la práctica no va a funcionar. En el tiempo que nosotros


tardamos entre pulsar y liberar el botón, nuestro humilde Arduino es capaz de leer unos cuantos
miles de veces el pulsador e invertir el valor del LED otras tantas.

Por eso, si lee un número par de veces dejara el LED como estaba y si lo lee un número impar de
veces lo invertirá. En la práctica la situación del LED se torna aleatoria, y si pulsáis repetidamente el
botón veréis 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 rápidas 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 electrónica.

El debouncing se puede hacer por hardware con un conjunto de resistencia y condensador, o por
software, mucho más frecuentemente (por más barato) y para esto una solución es nuevamente
frenar a Arduino y hacerle esperar un tiempo entre 50 y 250 mili-segundos una vez que detecta que
se ha pulsado el botón, de modo que nos dé tiempo a liberar el pulsador:

void loop()

bool valor = digitalRead(boton) ; //leemos el


botón: false = LOW

if ( valor == false ) // esto es que


han pulsado el botón

estado = ! estado ; // cambiamos el


estado

digitalWrite(LED, estado) ; // escribimos el nuevo


valor

delay(250) ;

 Muy importante: Nótese que la condición es (valor == false), con doble = . En C++ la
comparación de dos valores usa ==, la asignación de valor a una variable solo uno. Esto
es fuente de errores frecuentes al principio (entre novicios inexpertos).

Este lapso de 250 ms es suficiente para pulsar y liberar el botón cómodamente. Si probáis esta
variante veréis que ahora el LED invierte su valor cada vez que pulsas, siempre y cuando no te
demores demasiado en liberar el botón.

Pero… ¿Qué pasa cuando dejas el botón pulsado?

Pues sencillamente que el LED invierte su estado cada 250 ms (milisegundos) y tenemos otra
variante del blinking LED.

Si queremos poder mantener pulsado sin que se produzca este efecto hay que sofisticar un poco más
el programa:
int LED = 10 ; int boton = 6 ;

bool estado = true ;

bool estado_anterior = true ;

void setup()

pinMode(boton, INPUT_PULLUP); //Hemos eliminado R3

pinMode(LED, OUTPUT);

void loop()

estado = digitalRead(boton);

if (estado != estado_anterior) //hay cambio : Han pulsado o


soltado

if (estado == LOW) //Al pulsar botón cambiar LED,


pero no al soltar

digitalWrite(LED, !digitalRead(LED));

estado_anterior = estado ; // Para recordar el ultimo


valor

Ya dijimos que para comprobar si dos valores son iguales usamos ==, Para comprobar si son
diferentes usamos != , y existen otros operadores relacionales
 Igual que: ==
 Distinto de: !=
 Mayor que: >
 Mayor o igual: >=
 Menor que: <
 Menor o igual: <=

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 práctica la combinación 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 más de lo que parece, sino se estudia el problema con calma.

Por último, una condición lógica se puede construir mediante los operadores lógicos AND, OR, y
NOT cuyos símbolos son respectivamente: &&, || y !

Si usáramos un circuito dos pulsadores con pullups (True, si no se pulsa) y un LED, dependiendo del
comportamiento que se busque podemos especificar diferentes condiciones:

 If ( boton1 && boton2) Que ambos botones estén sin pulsar


 If ( !( boton1 && boton2)) Que ambos estén pulsados.
 If( boton1 || boton2 ) Que al menos uno este pulsado, o ambos.

Resumen de la sesión

o Hemos visto la instrucción if / else.


o Vimos varios programas con pulsadores y como hacer el debouncing.
o Hemos presentado los operadores lógicos de relación y comparación.
o Continuamos escribiendo pequeños programas para desarrollar la forma de pensar
necesaria para escribir nuestras propias aplicaciones.
COMUNICACIÓN CON EL
EXTERIOR
El puerto serie en Arduino y los tipos String

Objetivos

o Comprender la comunicación vía puerto serie.


o Utilizar la librería Serial.
o Operaciones con enteros.
o Los tipos String y char.
o Operando con Strings.
o La instrucción while.

Material requerido.

Arduino Uno o similar. Un PC con el entorno de Arduino


correctamente instalado y configurado.

Comunicación Serie con el mundo exterior

Más antes que después, vamos a necesitar comunicar nuestro Arduino con nuestro PC. Las razones
son varias, enviarle órdenes o recibir información o señales por ejemplo.

Los PCs disponen de teclados, pantallas y adaptadores de red, pero con Arduino tenemos que usar el
puerto USB que establecerá una conexión en serie con nuestro PC.
La comunicación en serie es muy sencilla, bastan dos hilos para enviar una diferencia de tensión
entre ellos y poder marcar niveles alto (5V) y bajo(0V) y con esto podemos transmitir información
digital. Ahora solo nos falta pactar dos cosas entre quien envía y quien recibe:

 Un código común para codificar los caracteres que enviamos.


 Un acuerdo de velocidad para saber a qué ritmo hay que leer los datos.

El código común que vamos a usar con Arduino se llama código ASCII y es estándar en todos los
PCs. Es una forma de codificar las letras mediantes números que representas estos caracteres.
Recordad que solo podemos transmitir unos y ceros.

Así por ejemplo la letra A se representa por el numero 65, la B el 66, C el 67… Prácticamente
todos los PCs actuales utilizan este código y eso incluye a Windows, Mac y Linux (y por eso
podemos leer emails enviados desde distintas plataformas), pero es importante comprender que esté
es uno más entre varios códigos de caracteres posibles (EBCDIC por ejemplo).

 Actualmente, en realidad, se suele usar una extensión del código 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 español, pero también alfabetos
distintos como el Kanji chino o el alfabeto cirílico. Y este es el motivo por el que podéis leer
las letras chinas o rusas en las páginas de internet de estos países..

El otro factor a pactar para realizar una comunicación serie es la velocidad. Dado que solo
disponemos de dos hilos para transmitir, necesitamos saber cuándo hay que leer la línea y esto se
hace estableciendo un acuerdo de velocidad. Si la velocidad de envío es distinta de la velocidad de
lectura, el mensaje final será irreconocible.

Buena parte de los errores de comunicación 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 comunicación serie.

Estableciendo la comunicación Serie

Arduino dispone de una librería serie incluida llamada Serial, que nos permite envía información al
PC y para usarla simplemente tenemos que pedirle en nuestro setup() que la incluya. La instrucción
que se encarga es:

Serial.begin( velocidad ) ;
 Nótese que Serial tiene la S mayúsculas y que C++ diferencia entre mayúsculas y
minúsculas

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 razón 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:

int LED = 10 ; int boton = 6 ;

bool estado = false ;

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 (repetidamente). 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 botón del monitor:
Necesitamos además asegurarnos de que la velocidad de conexión es la misma en ambos extremos.
Fíjate en la parte inferior derecha del monitor serie:

Normalmente la velocidad por defecto son los 9600 bits por segundo o baudios en los que hemos
programado nuestra puerta serie, y si lo desplegáis, veréis 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 sinónimos.
 En el mundo Arduino parece haber un acuerdo de usar velocidades bajas como 9600 en
lugar de más altas como 115200, para evitar problemas. Esto es algo que hace años estaba
justificado por problemas de transmisión, pero con la tecnología actual no hay motivo para
ello. Es más, en cuanto necesitemos utilizar dispositivos de comunicaciones como
adaptadores Ethernet o BlueTooth para comunicarnos, la velocidad tendrá que subir
necesariamente.

Ahora que sabemos enviar información y resultados al PC, vamos a ver cómo podemos operar con
enteros y mostrar el resultado en la puerta serie. En C++ los operadores numéricos son los normales
en cálculo (y algunos menos frecuentes):

 Adición: +
 Resta: –
 Multiplicación: *
 División entera: / Cociente sin decimales (puesto que operamos con enteros
 Resto: % Devuelve el resto de una división.

En C++ tenemos que expresar las operaciones matemáticas en una sola línea y utilizar paréntesis
para garantizar que se opera como necesitamos. Vamos con algunos ejemplos:

OPERACIÓN RESULTADO COMENTARIO

int i = 4 * 2 resultado = 8

int i = 4 * 2 / 3 resultado = 2 Porque desprecia los decimales al ser entero


OPERACIÓN RESULTADO COMENTARIO

int i = 14 % 3 resultado = 2 El resto de 14 entre 3

Int i = 2 + 8 / 2 resultado = 6 Calcula primero la división.

Int i = (2+8) / 2 resultado = 5 El paréntesis fuerza a que se realice primero la suma

Dada una expresión, la precedencia de operadores indica que operaciones se realizaran antes y
cuales después en función de su rango. Para los que se inician en C++ no es fácil saber que
operadores tienen preferencia, por lo que es más seguro que ante la duda uséis paréntesis.

Los paréntesis fuerzan las operaciones de una forma clara y conviene utilizarlos ante la duda porque
de otro modo, detectar los errores de operación puede volverse muy difícil especialmente cuando
uno empieza a programar.

El operador resto es más útil de lo que parece a primera vista porque nos permite saber si un numero
es múltiplo de otro. Supongamos que queremos saber si un número dado es par.

Podríamos escribir un programa como este:

void setup()

Serial.begin(9600) ; // Inicializa el Puerto serie

void loop()

int i = 27 ; //El número en cuestión

if ( i % 2 == 0)

Serial.println("Es par.") ;
else

Serial.println("Es impar");

Dando a i distintos valores podemos comprobar cómo funciona el operador resto %. Volveremos
sobre esto cuando veamos algunos ejemplos de cómo calcular números primos.

En este programa hemos usado de un modo diferente el Serial.println() pasándole una String de texto
entrecomillada. Serial.print() envía el texto ( entrecomillado) que le pongamos pero no da salto de
línea cuando termina. En cambio Serial.println() hace lo mismo e incluye al final ese salto de línea.

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 definiéndolas como cualquier otro tipo de C++:

void loop()

int resultado = 25 ;

String s = “ El resultado es: ” ; // Nótese que la S de string es


mayúscula.
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:

void loop()

String a = "hola " ;

String b = "a todos." ;

Serial.println( a + b);

Y también podemos construir un String sobre la marcha así:

void loop()

int resultado = 25 ;

String s = "El resultado es: " ;

Serial.println( s + String( resultado ));

Donde imprimimos el resultado de concatenar s String, y la conversión de un int a String (El


operador + añade un String al final de otro).

Recibiendo mensajes a través del puerto Serie

Hasta ahora solo hemos enviado mensajes desde Arduino hacia el PC, ¿Pero como recibimos
mensajes en Arduino?

En primer lugar disponemos de una función llamada Serial.parseInt() que nos entrega lo que se
escribe en el monitor serie convertido a entero:
void loop()

if (Serial.available() > 0)

int x = Serial.parseInt();

Serial.println ( x) ;

Este programa simplemente recibe en x los números que nos tecleen en la consola (cuando pulsemos
intro) y si es un texto, lo interpreta como cero.

Hemos utilizado otra función de Serial : Available() que es un booleano. Conviene por costumbre
comprobar que antes de leer el puerto serie hay algo que nos han enviado. Si lo hay Available() es
True y en caso contrario es False.

Para leer un String del puerto serie tenemos que complicarnos un poco más y hablar del tipo char.

Uno de de las mayores quebradero de cabeza al iniciarse en C++ es comprender la diferencia, anti-
intuitiva, entre char y String. char es un tipo que representa un único carácter y se define con
comillas simples, a diferencia de String que necesita comillas dobles:

char c = „a‟ ;

String s =”a” ;

Aunque parezca lo mismo para C++ son muy distintos.

Para leer una cadena desde el puerto serie necesitamos leer un carácter cada vez y después montar un
String a partir de ellos, pero antes, asegúrate de seleccionar ambos NL & CR en la parte inferior del
monitor serie, para garantizar que se envía el carácter de fin de línea:
Un programa para leer la consola sería algo así:

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 ; // Añadimos lo leído al mensaje

c = Serial.read(); //Leer 1 carácter

delay(25);

Serial.println( mensaje); //Al salir imprimir el mensaje

mensaje = "" ; //Bórralo para la próxima vez

Aquí usamos otra instrucción de C++ llamada while. Es similar a if, Ejecuta repetidamente el
bloque que le sigue mientras se cumpla la condición que le pasamos entre paréntesis:

while ( condición)

{ ……… }
Cuando lee el intro final de lo que escribimos, La condición c != „\n‟ se torna falso y sale del while.

Por lo demás, comprobamos si hay algo disponible en la puerta serie y de ser así montamos el
mensaje leyendo un char cada vez y sumándoselo 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 la
puerta serie, tarda mucho más 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 carácter bueno (de la palabra escrita y como 10 caracteres basura para un Arduino
UNO o Mega).

 Si subimos la velocidad de comunicación a 115200 bits por segundo, comprobareis que no


hay este problema ya que al multiplicar la velocidad de envío por más de 10 Arduino ya no
tiene tiempo de volver a por más caracteres antes de que lleguen.

Resumen de la sesión

o Hemos visto como establecer la comunicación con el PC externo, tanto para enviar
como para recibir mensajes enteros y de texto.
o Hemos presentado los tipos String y char.
o Hemos visto las reglas básicas para operar con enteros y con Strings.
o Presentamos una nueva instrucción: while.
FUNCIONES Y ENTEROS
Definiendo funciones y diferentes tipos de enteros

Objetivos

o Operar con enteros.


o Aprender a definir funciones en Arduino.
o Trabajar el pensamiento lógico ( y algorítmico)
o Diferentes tipos de enteros en C++.

Material requerido.

Arduino Uno o similar.Un PC con el entorno de Arduino


correctamente instalado y configurado.

La primera función: Calculando si un número es primo

Ya hemos comentado antes, que programar es un poco como andar en bici, se aprende pedaleando y
a programar… programando. Hay que ir aprendiendo la sintaxis del lenguaje, C++ en nuestro caso,
pero también aprendiendo a resolver problemas lógicos y partirlos en instrucciones.

Hacer cursos de programación (o de andar en bici) está bien, pero al final hay que ponerse a
programar y tener problemas, porque solo teniéndolos y resolviéndolos, solo o con ayuda, se
aprende. No se puede aprender a nadar sólo estudiando.

Con un cierto temblor de manos, vamos a centrarnos en esta sesión en algunos ejemplos clásicos de
programación, como son el cálculo de números primos para entrenar esta capacidad de búsqueda de
algoritmos prácticos para resolver problemas más 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 no tiene porque ser mejor que otra, aunque con frecuencia se aplican criterios de
eficiencia o elegancia para seleccionar una solución.

Esta sesion va a requerir un esfuerzo un poco mayor que las anteriores porque vamos a empezar a
entrenar un musculo poco usado,el cerebro, en una tarea poco frecuente, pensar. Y esto es algo que
exige un poco e esfuerzo, pero es necesario para avanzar.

Supongamos que queremos crear un programa que nos devuelva true o false según que el número
que le pasamos sea primo o no y a la que podamos llamar varias veces sin copiar el código 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.

Esto es lo que llamamos una función.

En realidad, ya hemos utilizado varias funciones que Arduino trae predefinidas como el Serial.print()
o abs() , o Serial.available() y se las reconoce por esa apertura y cierre de paréntesis.

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 más pequeñas y más
fáciles de manejar.

Para definir una función así, tenemos que declararla primero y describirle a C++ que hacer:

bool Primo( int x) // int x representa el parámetro que pasaremos a esta


función

Aquí va lo que tiene que hacer

…………

return( bool);

Declaramos la función Primo () como bool, o sea va a devolver un valor bool y por eso en algún
punto tendremos que usar la instrucción return( true) o return( false) para devolver un resultado a
quien la llame. Si devolviera un entero habría que definirla como int Primo( int x).
 Si una función no va a devolver ningún valor, sino que simplemente realiza su trabajo y
finaliza sin mas entonces hay que declararla como void (vacía). Ya cononocemos dos
funciones así : setup() y loop()

Veamos cómo podría ser el código de la función Primo():

bool Primo( int n)

for ( int i = 2 ; i <n ; i++)

if ( n % i == 0) // Si el resto es 0 entonces es divisible.

Serial.println ( String(n) +" es divisible por: " +


String(i)) ;

return(false) ;

return (true) ;

Para saber si un número es o no primo basta con dividirlo por todos los números positivos menores
que él y mayores que 1. En el ejemplo dividimos el número n empezando en 2 y finalizando en n-1.

Si encontramos un valor de i que devuelve resto 0, entonces es divisible (no es primo), devolvemos
false con return y volvemos a la intruccion que llamo a la función. Si no hallamos ningún divisor, al
finalizar el for devolvemos true y listo. Este es el método de fuerza bruta y sin duda es mejorable
pero de momento nos sirve.

Para usar Primo hay que pasarle un entero. Recordad que al definir la función dijimos bool Primo
(int n) donde n representa el valor que queremos probar. Así pues Descargar:
void loop() // Prog_8_1

int x = 427 ; // El número a probar

bool p = Primo(x);

if (p )

Serial.print( String(x) + " Es primo.") ;

else

Serial.print( String(x) + " No es primo." ) ;

Veamos cuantos primos hay hasta el, digamos 1024, Descargar:


bool control = true ; // Prog_8_2

int maximo = 1024 ;

void loop()

if ( control) // Solo es para que no repita una y otra vez lo mismo

Serial.println( "Los numeros primos hasta el " + String(


maximo)) ;

for ( int x = 2 ; x < maximo ; x++)

bool p = Primo(x);

if (p ) Serial.println( x) ; // No hay
inconveniente en escribirlo seguido
}

control = false ;

bool Primo( int n)

for ( int i = 2 ; i <n ; i++)

if ( n % i == 0) // Si el resto es 0 entonces es divisible.

return(false) ;

return (true) ; // Si llega aqui es que no ha encontrado ningun


divisor

Aunque el programa funciona correctamente la salida no es muy presentable( Recordad que nos
gusta ser elegantes). Vamos a formatearla. Para ello usaremos el carácter tabulador que se representa
como „\t‟ y una coma después. Descargar:

bool control = true ; //Prog_8.3

int maximo = 1024 ;

int contador = 1 ;

void loop()

{
if ( control) // Solo es para que no repita una y otra
vez lo mismo

Serial.println( "Los numeros primos hasta el " + String(


maximo)) ;

for ( int x = 2 ; x < maximo ; x++)

if (Primo(x) )

if ( contador++ % 8 == 0)

Serial.println( String(x)+"," ) ;

else

Serial.print( String(x) +","+ '\t') ;

control = false ;

Ahora el programa formatea la salida de una forma un poco más presentable y cómoda de leer.
Para conseguirlo, hemos añadido una coma y un tabulador a cada número excepto a uno de cada 8
que añadimos intro. También tenemosuna línea que conviene comentar:

if ( contador++ % 8 == 0)

Cuando a una variable se le añaden dos símbolos mas al nombre, significa que primero se use su
valor actual en la instrucción en curso, ene este caso en el if, y después se incremente en 1 su valor.

Si hubiéramos escrito:

if ( ++contador % 8 == 0)

Querría decir que queremos incrementar su valor antes de utilizarlo. Esta notación es muy habitual
en C++ y conviene reconocerla. También podemos usar contador- – y – -contador para decrementar.

El tipo entero

Este sería un buen momento para preguntarnos hasta donde podría crecer máximo en el programa
anterior. Le asignamos un valor de 1024, pero ¿Tiene un entero límite de tamaño?

La respuesta es afirmativa. Los enteros int en Arduino C++ utilizan 16 bits por lo que el máximo
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 de distintos tamaños para manejar enteros:

TIPO DESCRIPCIÓN VALOR

int Entero con signo, 16 bits entre -32,768 y 32,767

unsigned int Entero sin signo, 16 bits 216 – 1 ; de 0 hasta 65.535

long Entero con signo, 32 bits 232 – 1 ,Desde -2.147.483,648 hasta 2.147.483.647

unsigned long Entero sin signo, 32 bits Desde 232 – 1 ; 0 a 4.294.967.295


TIPO DESCRIPCIÓN VALOR

byte Entero sin signo, 8 bits 28 de 0 hasta 255

Todos estos tipos representan enteros con y sin signo y se pueden utilizar para trabajar con números
realmente grandes pero no sin límite.

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 olímpicamente el asunto, dando lugar a problemas difíciles de detectar si
uno no anda con tiento.

Prueba este a calcular esto en un programa:

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. También es ilustrativo probar el resultado de

int i = 32767 ;

Serial.println (2* i + 1);

Que según Arduino es -1.

 Esto no es un error, sino que se decidió así en su día y C++ no controla los desbordamientos,
así que mucho cuidado, porque este tipo de errores pueden ser muy complicados de detectar

Más sobre las funciones en C++

Cuando se declara una función se debe especificar que parámetro va a devolver. Así:
Instrucción Significa

int Funcion1() Indica que va a devolver un entero

String Funcion2() Indica que va a devolver un String.

unsigned long Funcion3() Indica que va a devolver un long sin signo

void Funcion4() No va a devolver valores en absoluto

Una función puede devolver cualquier tipo posible en C++, pero sólo puede devolver un único valor
mediante la instrucción return(). Expresamente se impide devolver más de un parámetro. Si se
requiere esto, existen otras soluciones que iremos viendo.

 Este problema se puede resolver usando variables globales o pasando valores por
referencia, y lo trataremos en futuras sesiones.

Lo que sí está permitido es pasar varios argumentos a una función:

int Funcion5 ( int x , String s , long y)

Aquí declaramos que vamos a pasar a Funcion5, tres argumentos en el orden definido, un entero un
String y por ultimo un long.

Resumen de la sesión

o Hemos definido una función propia para saber si un número es primo.


o Vimos que el tipo entero tiene un límite de tamaño.
o Conocimos tipos con mayor y menor capacidad para manejar números enteros mas
o menos grandes, pero que todos siguen teniendo un límite de tamaño.
o El efecto de desbordamiento de tipos es clave y debe ser tenido muy en cuanta
cuando operamos con enteros.
o Hemos ido jugando con problemas lógicos y hemos visto algunas soluciones que os
pueden ayudar a plantear las vuestras propias.
UN PROGRAMA CON VARIAS
FUNCIONES
Un programa un poco mas complicado

Objetivos

o Aprender a operar con Arrays .


o Como partir un problema en funciones especialistas.
o Operar con enteros y Strings.
o Entrenar y desarrollar algunas habilidades claves para programar.

Material requerido.

Arduino Uno o similar. Un PC con el entorno de Arduino


correctamente instalado y configurado.

Planteando un programa un poco más complicado.

Hemos visto ya como definir funciones. En esta sesión vamos a plantear un programa que acepte un
número desde la consola y compruebe si es o no primo. Y en caso de no serlo, nos calcule cuales son
los divisores primos de este.

Normalmente para resolver un problema complejo es buena política partirlo en otros problemas más
pequeños que podamos resolver más fácilmente. En este caso vamos a plantear al menos 3
funciones:

 Primo() – Calcula si un número dado es primo, devuelve true y en caso contrario false.
 Divisores() – Para un número dado nos devuelve sus divisores primos.
 GetLine() – Vamos a definir una función genérica que recoja una cadena de texto de la
puerta serie, para procesarla a posteriori. En este caso recogerá el número a probar.

La idea es, que nuestro programa empiece comprobando si un numero es primo. Si lo es, bien por el.
SI no llamaremos a una función que calcule cuales son sus divisores. Y por ultimo necesitamos de
algo que nos pueda dar un número desde la consola para probarlo y por eso escribimos otro
programa que nos permita recibir cómodamente este numero de entrada.

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 resolución

 Esto es un poco trampa. Parece que se me acaba de ocurrir instantáneamente pero no


(Aunque parezca increíble).
 Después de pensar un rato y pasar un rato mayor escribiendo y afinando el programa, da
gusto presentarlo como si fuera fácil. Que lo es, pero lo que no ves, es la de horas que hay
que estar haciendo pruebas hasta todo va encajando y queda afinado.
 Con tiempo y práctica ( No, no mucha) iréis mejorando con rapidez, en vuestra habilidad
de romper problemas en pedazos manejables, simplemente requiere tiempo y
entrenamiento, y esto es algo que os será útil no solo para programar.

Operando con Arrays.

Con la función Primo() que vimos en la sesión anterior, a medida que el tamaño del número a
probar, crece, el tiempo que tarda en determinar si es primo también, ya que dividimos por todos los
números que le preceden.

Una manera más eficaz de calcular si un número es primo, es dividirlo solo por los números primos
menores que el. Pero para esto necesitaríamos un modo de archivar estos primos.

Podríamos ejecutar primero el programa Prog_8.3 para hallar los N primeros números primos, y si
dispusiéramos de algún medio para guardarlos, tendríamos un sistema más eficaz para decidir si un
número es o no primo.

Una manera de archivar estos números es definir un array.

Un array es simplemente una colección de elementos organizados como una matriz, y pueden
definirse con varias dimensiones. Empecemos con un array de una sola dimensión. Para definirlo
podemos optar por dos maneras:

int serie1 [ 5] ; //Creamos una colección de 5 enteros


int serie2[] = { 3,5,6,12, 23} ;

En el primer caso definimos un array de enteros, de una sola dimensión con 5 elementos, sin asignar
valores de momento.

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 enumeración.

Para asignar o leer los valores de un array se utiliza un índice entre corchetes. Veamos este
programa Descargar:
int serie2[] = { 3,5,6,12, 23} ; // Prog_9_1

void setup()

Serial.begin(9600) ;

void loop()

for (int i=0 ; i<5 ; i++)

Serial.println("Posicion " + String(i)+ ": "+ String(serie2[i])) ;

El programa imprime el contenido del array recorriendo sus 5 posiciones.

 Atención: la primera posición del un array es la 0 y la última el número de elementos – 1.


Así serie2 [0] devuelve el primer elemento 3, y serie2[4] el último 23.

Un error muy peligroso, y difícil de detectar sería algo así (Prog_9.2):

int serie2[] = { 3,5,6,12, 23} ;

for (int i=0 ; i<99 ; i++)

Serial.println("Posicion " + String(i)+ ": "+ String(serie2[i])) ;


Uno esperaría 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

Por último, mencionar que podemos manejar arrays de varias dimensiones:

Int Tablero[ 8, 8 ] ;

Imaginad que Tablero representa las posiciones de una partida de ajedrez y cada valor que contiene
esa posición corresponde a una pieza que se encuentra en esa casilla.

Afinando la función Primo()

Si corremos el programa Prog_8.3 nos dará en el monitor una lista de primos hasta el 1024 (o hasta
el número que deseemos modificando el valor de máximo) y seleccionándolos con el ratón podremos
copiar esos valores y pegarlos en el IDE para crear un array con ellos (Prog_9.3):

int P[] =

{ 2, 3, 5, 7, 11, 13,
17, 19,

23, 29, 31, 37, 41, 43,


47, 53,

59, 61, 67, 71, 73, 79,


83, 89,

97, 101, 103, 107, 109, 113,


127, 131,

137, 139, 149, 151, 157, 163,


167, 173,

179, 181, 191, 193, 197, 199,


211, 223,

227, 229, 233, 239, 241, 251,


257, 263,
269, 271, 277, 281, 283, 293,
307, 311,

313, 317, 331, 337, 347, 349,


353, 359,

367, 373, 379, 383, 389, 397,


401, 409,

419, 421, 431, 433, 439, 443,


449, 457,

461, 463, 467, 479, 487, 491,


499, 503,

509, 521, 523, 541, 547, 557,


563, 569,

571, 577, 587, 593, 599, 601,


607, 613,

617, 619, 631, 641, 643, 647,


653, 659,

661, 673, 677, 683, 691, 701,


709, 719,

727, 733, 739, 743, 751, 757,


761, 769,

773, 787, 797, 809, 811, 821,


823, 827,

829, 839, 853, 857, 859, 863,


877, 881,

883, 887, 907, 911, 919, 929,


937, 941,

947, 953, 967, 971, 977, 983,


991, 997,

1009, 1013, 1019, 1021

} ;
Hemos definido un array enumerando sus elementos, entre llaves y separados por comas.

 Es importante percatarse de que después de copiar y pegar las salida de Prog_8.3 hemos
borrado la coma después del 1021, porque si no daría un error de sintaxis al definir el
array.
 Obsérvese que hay un punto y coma después de la llave de cierre del array. Aunque está
entre llaves es una instrucción de asignación y no una definición de función.
 Al definir el array por enumeración, si el número es alto podemos perder de vista cuantos
elementos contiene. Si necesitamos calcular el número de miembros podemos utilizar la
función sizeof():

int size = sizeof(P) / sizeof(int);

 Donde P es nuestro array y dividimos por sizeof(int) porque definimos P como int. Y para
este caso devuelve un valor de 172 elementos

Ahora bastaría dividir el número a probar por aquellos elementos del array P, menores que él:

bool Primo(int x)

int index = 0 ;

while ( P[index] < x)

{ if ( x % P[index++] == 0)

return(false);

return(true);

Recorremos los valores almacenados en el array P[] mediante index al que vamos incrementando en
cada iteración, hasta que nos toque probar un primo mayor que el valor que comprobamos.
Función Divisores ()

Esta función va a recorrer los elementos del array en tanto en cuanto sean menores (posibles
divisores) que el número que probamos. Si encontramos divisores primos los guardamos en un array
que hemos llamado Div[] al que le asignamos un máximo de 32 divisores:

int Div[32] ;

int Divisores(int x)

int index = 0 ; //Apunta a la posicion del array P[]

int pos = 0 ; //Para apuntar al array de divisores


Div[]

while ( P[index] < x)

int k = P[index++] ;

if ( x % k == 0)

Div[pos++]= k ; //Guardamos el divisor en en el array


Div[].

} // para uso posterior

return(pos); //Devolvemos el numero de divisores


encontrado

Cuando queramos imprimir los divisores, basta con recorrer Div[].

 Es importante entender que tanto la función Primo() como Divisores() recorren el array de
números primos hasta que sobrepasan el valor del numero a probar. Si el número que
probamos es mayor que el máximo primo que contiene P[], Podemos obtener resultados
extraños, ya que leeremos más elementos de los que hemos definido.

 Este método de buscar divisores es válido solo para números inferiores a 1024( o en su
caso, al máximo número hasta el que hayamos calculado primos), porque un número no
será primo si Primo() lo afirma, ya que encontrará divisores. Pero puede afirmar que un
numero es primo erróneamente si sus divisores son superiores al máximo primo en P[].

La función GetLine()

Aunque ya comentamos que podemos usar una función 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 tendríamos que controlar el valor devuelto para que
no se repitiese continuamente.

Por eso vamos a escribir una función 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 función en la sesión Comunicación con el exterior

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 añadiéndole
cada uno de los caracteres que leemos del puerto serie, hasta que encontremos un intro.

Al encontrar el intro, se cumple la condición de salida del while y termina la función 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 comprobación que hace GetLine() de tener algo
disponible en el Serial seria redundante.

 Pero si llamáramos a GetLine() sin comprobarlo y esta no lo controlase, quedaríamos


atrapados en esta función hasta que alguien escribiera algo finalizado con intro para poder
salir y podría no ser sencillo comprender el problema.

 Nuevamente hemos incluido un delay de 25 ms en el while para asegurarnos de que


Arduino no puede volver a leer mas caracteres antes de que a la velocidad de 9600 bps
haya llegado el próximo carácter. Si la velocidad de comunicación es de 115200 bits por
segundo o más, se puede suprimir este retraso.

El programa principal

Podemos ya escribir nuestra función principal loop(), que llame a las funciones que hemos definido a
lo largo de esta sesión, 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.

Podría ser algo así:Calculo de numeros primos en arduino:


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

Serial.println(String(i) + " No es primo.");

Serial.println("Sus divisores son: ");

int j = Divisores(i); //Recogemos el


numero de divisores encontrados

for (int n =0 ; n<j ; n++) //Imprimimos los


divisors del Div[]

Serial.print(String(Div[n]) + ",\t");

Serial.println(" "); // Al acabar salta


de linea

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 función estándar de Arduino C++, s.toInt()
que convierte el contenido String a tipo numérico int.

Después llamamos a Primo() para que compruebe este número. Si es primo, simplemente imprime
un mensaje para confirmarlo. En caso contrario llamamos a Divisores() que busca y almacena en el
array Div[] los divisores primos que encuentra.

Cuando divisores regresa, nos devuelve el número de divisores encontrados y podemos imprimirlos
con un sencillo bucle for.
Resumen de la sesión

o Hemos operado con arrays de una única dimensión tanto para leer su contenido
como para modificarlo.
o Hemos utilizado el programa de primos como excusa para mostrar cómo se pueden
resolver problemas complejos, dividiéndolos en otros más sencillos que podamos
resolver con funciones simples.
o Esta es, sin duda, una de las habilidades clave para ser un programador competente,
y como todo en la vida requiere practica e ir trabajando.
o También hemos definido una función de propósito general GetLine() que
utilizaremos más veces en el futuro.
LOS PINES CUASI
ANALÓGICOS
Los pines analógicos

Objetivos

o Comprender las diferencias entre analógico y digital.


o Conocer las salidas cuasi analógicas de Arduino.
o Modulación PWM

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo de Arduino

Una Protoboard.

Un diodo LED.

na resistencia de 330 Ohmios..


Algunos cables de Protoboard..

Analógico y digital

Todas las señales que hemos manejado hasta ahora con nuestro Arduino , de entrada o de salida,
comparten una característica común: Son digitales, es decir que pueden tomar un valor HIGH o
LOW pero no valores intermedios.

Si representamos una el valor de una señal digital a lo largo del tiempo veríamos algo así:

En la vida muchas cosas son así, apruebas o suspendes, enciendes la luz o la apagas, pero muchas
otras son variables mensurables continuas y pueden tomar cualquier valor que imaginemos, como el
ángulo del reloj o la temperatura, que aun dentro de valores finitos pueden tomar tantos valores
intermedios como podamos imaginar,

A esta clase de variables las llamamos analógicas y una representación por contraposición a lo
digital, sería algo como esto:

No es raro que queramos controlar algo del mundo exterior con una señal analógica de forma que el
comportamiento del sistema siga esa señal. Podemos por ejemplo querer variar la luminosidad de un
diodo LED y no simplemente apagarlo o encenderlo

En esta sesión aprenderemos a enviar señales analógicas a los pines de salida de Arduino.
Salidas cuasi analógicas

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 del brillo de ese LED. Para
ello, tenemos que modificar la tensión de salida de nuestro Arduino, o en otras palabras tenemos que
poder presentar un valor analógico de salida.

Para empezar tenemos que dejar claro que los Arduino carecen de salidas analógicas puras que
puedan hacer esto (con la notable excepción 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 analógica.

A este truco se le llama PWM, siglas de Pulse Width Modulation, o modulación de ancho de pulsos.
La idea básica es poner salidas digitales que varían de forma muy rápida de modo que el valor
eficaz de la señal de salida sea equivalente a una señal analógica de menor voltaje.

Lo sorprendente es que el truco funciona.

Fijaros en la anchura del pulso cuadrado de arriba. Cuanto mas ancho es, mas tensión promedio hay
presente entre los pines, y esto en el mundo exterior es equivalente a un valor analógico de tensión
comprendido entre 0 y 5V. Al 50% es equivalente a una señal analogica del 50% de 5V, es decir
2,5. Si mantenemos los 5V un 75% del tiempo, será el equivalente a una señal analógica de 75% de
5V = 3,75 V.
Para poder usar un pin digital de Arduino como salida analógica, lo declaramos en el Setup() igual
que si fuera digital:

pinMode( 9, OUTPUT) ;

La diferencia viene a la hora de escribir en el pin:

digitalWrite(9, HIGH); //Pone 5V en la salida

digitalWrite(9, LOW); //Pone 0V en la salida

analogWrite( 9, V) ;

analogWrite escribe en el pin de salida un valor entre 0 y 5V, dependiendo de V (que debe estar
entre 0 y 255).

De este modo si conectamos un LED a una de estas salidas PWM podemos modificar su brillo sin
más que variar el valor que escribimos en el pin.

Pero hay una restricción. No todos los pines digitales de Arduino aceptan poner valores PWM en la
salida. Solamente aquellos que tienen un símbolo ~ delante del número. Fijaros en la numeración de
los pines de la imagen:

solo los que llevan simbolo

 Solamente los pines 3, 5, 6, 9, 10 y 11 pueden hacer PWM y simular un valor analógico en


su salida.

 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 pone HIGH y sigue
con su vida satisfecho con el deber cumplido.
Modificando el brillo de un LED

Vamos a hacer el típico montaje de una resistencia y un diodo LED, similar al de la sesión 3, pero
asegurándonos de usar uno de los pines digitales que pueden dar señales PWM. En la imagen he
usado el pin 9.
Podemos escribir un programa parecido a esto:

void setup() //Prog_10_1

pinMode( 9, OUTPUT) ;

void loop()

for ( int i= 0 ; i<255 ; i++)

analogWrite (9, i) ;

delay( 10);

El LED va aumentando el brillo hasta un máximo y vuelve a empezar bruscamente. Podemos


modificar un poco el programa para que la transición sea menos violenta:

void setup() // Prog 10_2

pinMode( 9, OUTPUT) ;
}

void loop()

for ( int i= -255 ; i<255 ; i++)

analogWrite (9, abs(i)) ;

delay( 10);

Aquí aprovecho ( por pura vagancia) para hacer el ciclo de subir y bajar el brillo del LED con un
único bucle. La función abs(num), devuelve el valor absoluto o sin signo de un número num, y por
eso mientras que i viaja de -255 a 255, abs(i) va de 255 a 0 y vuelta a subir a 255. ¿Que os parece el
truco?

Resumen de la sesión

o Describimos a grandes rasgos la diferencia ente valores digitales y valores


analógicos.
o Hemos visto como simular valores analógicos en una salida digital de Arduino.
 Solo con las salidas que lo aceptan: pines 3, 5, 6, 9, 10 y 1.
 Podemos asignar valores entre 0 y 255.
LOS DIODOS LED RGB
Circuito con LED RGB

Objetivos

o Ampliar la experiencia con los pines PWM.


o Conocer los LED RGB.
o Presentar la función random().

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo de Arduino

Una Protoboard.

Un diodo LED RGB, independiente, o bien, con montura


keyes.

na resistencia de 330 Ohmios.

Algunos cables de Protoboard..


Los diodos RGB

Hasta ahora hemos usado varias combinaciones de LEDS, pero siempre de un color definido.
Habitualmente los rojos y amarillos son los más fáciles de conseguir, pero se pueden comprar
también en tonos azules, verdes y hasta blancos. No suele haber grandes diferencias entre ellos
excepto en el color.

Pero a veces es interesante disponer de una luz piloto que cambie de color según las condiciones. Por
ejemplo, todos identificamos el verde como una señal de OK, mientras que el rojo indica problemas
y el amarillo… bueno pues algo intermedio.

Poner varios diodos para hacer esto es engorroso y complica el diseño, así que estaría bien disponer
de un diodo al que podamos indicar que color queremos que muestre. Esto es un LED RGB.

Para quien este acostumbrado al diseño por ordenador ya está familiarizado con la idea de que
podemos generar cualquier color en la pantalla con la mezcla, en diferentes grados de tres colores
básicos:

Red : Rojo

Green: Verde

Blue: Azul

Es decir RGB, uno de esos acrónimos que surgen continuamente en imagen, TV, etc.
Un LED RGB es en realidad la unión de tres LEDs de los colores básicos, en un encapsulado común,
compartiendo el Ground (cátodo es otro nombre más para el negativo).

En función de la tensión que pongamos en cada pin podemos conseguir la mezcla de color que deseemos
con relativa sencillez

 Para quien haya dibujado con lápices de colores o acuarelas, las mezclas de colores de
arriba les resultará extraña. Esto es porque cuando pintamos en un papel blanco, la mezcla
de colores es substractiva: Si mezclamos los tres colores obtenemos negro, o por lo menos
algo oscuro
 En cambio cuando pintamos con luz directamente, la mezcla es aditiva y obtenemos blanco
al mezclar los tres colores básicos. Las reglas de mezcla de color en ambos casos son
opuestas.

Vamos a montar un pequeño circuito que nos permita gobernar el color que emite uno de éstos
LEDs de RGB.

Esquema del circuito

El montaje supone sencillamente conectar el negativo (el pin más largo) a Ground mediante una
resistencia que limite la intensidad, y luego identificar los pines de colores:

 El pin más largo en estos LED es el GND.


 Al lado de GND hay dos pines a un lado y uno solitario al otro. Por lo normal el solitario
es el rojo R.
 Así pues el pin out (patillaje) de un RGB LED suele ser R, GND, G, B.

De todos modos conviene asegurarse leyendo las especificaciones del fabricante, o bien
identificando cada PIN. Para identificarlos basta conectar el GND a nuestro Arduino e ir probando
cada una de las patas independientemente para ver qué color producen.

 Si tu RGB tiene una montura Keyes, no tendrás que hacer esto, porque los pines vienen
marcados y GND viene rotulado como -.

Atención, en contra de la norma habitual, en este caso el cable rojo no indica la tensionVcc, sino el
pin de gobierno del LED rojo.

En este esquema hemos utilizado los pines 9, 10 y 11. Podemos usar otros pero aseguraros de que
puedan hacer PWM(los que tienen ~) para poder poner distintas intensidades.

Programa de control RGB

Dado que nuestra idea es poder mezclar las tonalidades de los componentes RGB para generar
diferentes matices de colores, parece buena idea escribir una función que haga esta mezcla de
colores y a la que podamos recurrir de forma abstracta y práctica (además de para encapsular una
utilidad curiosa, a la que podremos recurrir en futuros ejemplos y de paso insistir en el concepto de
función).

Lo primero sería definir en el setup() los pines a usar:

void setup()

for (int i =9 ; i<12 ; i++)

pinMode(i, OUTPUT);

Y después podríamos escribir una función como esta

void Color(int R, int G, int B)

analogWrite(9 , R) ; // Red - Rojo

analogWrite(10, G) ; // Green - Verde

analogWrite(11, B) ; // Blue - Azul

De este modo tendríamos fácil llamar a Color ( 0, 255, 0) para el verde. De hecho vamos a empezar
asegurándonos de que tenemos identificados correctamente los pines, escribiendo un sketch como
este:

void loop()

{ Color(255 ,0 ,0) ;

delay(500);

Color(0,255 ,0) ;

delay(500);

Color(0 ,0 ,255) ;
delay(500);

Color(0,0,0);

delay(1000);

Este programa debería producir una secuencia de rojo, verde, azul, apagado y vuelta a empezar.

Conviene asegurarse de que hemos identificado correctamente los pines del RGB, porque de lo
contrario, las mezclas posteriores de colores no serán lo que esperamos.

Vamos a ver como averiguar qué mezcla de RGB necesitamos para conseguir un color determinado.
Para quienes uséis Windows disponéis del programa Paint incluido (en el menú de accesorios) y para
quienes uséis Mac o Linux tenéis programas similares.

Si arrancáis el Paint(o equivalente) suele tener un selector de colores:

Pulsándolo aparecerá algo parecido a esto:

Si vais pinchando en la zona de colores de la derecha, en la barra vertical aparecen los matices
próximos al que habéis pinchado y podéis elegir el que más os guste. Debajo podéis ver la
separación en RGB precisa para conseguir un tono determinado.

Así pues para conseguir ese tono de azulito de la imagen basta con que llaméis a

Color(13, 227, 201) ;

 Dado que Arduino nos permite escribir valores de 0 a 255 en los pines digitales, cuando
utilizamos analogWrite(), en la práctica tendremos 255 x 255 x 255 colores diferentes o lo
que es igual: 16.581.375 colores posibles.

La función Color() que hemos creado en esta sesión es muy sencilla pero se va añadiendo a otras que
hemos ido creando en sesiones anteriores con lo que vamos haciendo una pequeña colección de
ellas.

El grupo de desarrollo de Arduino ha ido creando también muchas funciones que están disponibles
para incorporar en nuestros programas y que por razones de espacio resultan imposibles de ver más
que muy por encima.

Solo como ejemplo introduciremos una de ellas. La función La función random( N ) devuelve un
valor al azar, comprendido entre 0 y N y en este caso, se presta especialmente bien para generar
colores aleatorios en nuestro LED RGB. Probad esto:

void setup() //Prog_11_3

for (int i =9 ; i<12 ; i++)

pinMode(i, OUTPUT);

void loop()

Color(random(255), random(255), random(255)) ;


delay(500);

void Color(int R, int G, int B)

analogWrite(9 , R) ; // Rojo

analogWrite(10, G) ; // Green - Verde

analogWrite(11, B) ; // Blue - Azul

Os generará un ciclo de colores aleatorios bastante psicodélico.

Resumen de la sesión

o Ya conocemos la utilidad y manejo de un LED RGB.


o Hemos insistido con la programación de los pines de Arduino como salidas
analogías (PWM).
o Hemos introducido la función random() que suele ser sorprendentemente útil en un
montón de situaciones diversas.
ARDUINO Y LAS PUERTAS
ANALÓGICAS
Convertidores Analógico a digital ADCs

Objetivos

o Conocer los potenciómetros.


o Comprender la conversión analógica a digital.
o Aprender a usar las puertas analógicas de Arduino.

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo de Arduino

Una Protoboard.

Un diodo LED.

Un potenciómetro de 10KΩ
na resistencia de 330 Ohmios.

Algunos cables de Protoboard..

Los potenciómetros

Hasta ahora hemos usado siempre resistencias fijas, de un valor dado. Pero a veces es conveniente
disponer de una señal variable para controlar el circuito que nos interesa. Imaginad el volumen de un
equipo de música, o el dial que sintoniza una emisora en una radio FM.

Un potenciómetro es, simplemente, un mecanismo para proporcionar una resistencia variable.

Hay potenciómetros de tantos tamaños, formas y colore,s como podáis imaginar, pero al final son
una resistencia fija de un valor dado (10 kΩ en nuestro caso actual) y un mecanismo que permita
deslizar un dial conductor sobre esa resistencia, que nos permita tomar una parte de ese valor.

Por eso un potenciómetro siempre tiene 3 pines en fila. Los del extremo se comportan como una
resistencia del valor de fondo de escala del potenciómetro, y un pin central que va tomando valores
de resistencia en función del movimiento que hagamos con el ajuste.

Vamos a montar un circuito como este (en el que el potenciómetro esta rotulado Pot1):
La idea es conectar 5V y GND a los extremos del Potenciómetro (no importa cual es uno y otro) y
luego conectar el pin central al positivo de un LED y el negativo a GND directo, pasando por una
resistencia de limitación.

De este modo cuando giremos el potenciómetro estaremos modificando la tensión que aplicamos a la
entrada del LED, que variara entre 0 y 5V (Aunque ahora parezca extraño es muy sencillo) y
habremos conseguido un regulador de intensidad del LED.

 Con una resistencia de 10k la intensidad en el circuito será de: 5V / 10.000Ω = 0,5 mA Muy
poco para conseguir iluminar el LED que requiere unos 20 mA. Así que durante la mayor
parte del giro del potenciómetro el LED estará apagado.

 Importante: No olvides la resistencia R1.Aunque el potenciómetro limite la intensidad, hay


un momento en que llegara a cero y ahí y tu LED fallecerá en acto de servicio.

Circuito para protoboard

El montaje en la protoboard sería similar a esto ya que vamos a utilizar el Arduino simplemente
para dar tensión al circuito y nada más, Veréis que la intensidad de la luz varia de forma continua al
girar el potenciómetro.

 Recuerda que debido al exceso de resistencia del potenciómetro de prueba, durante la


mayor parte del giro del ajuste el LED estará apagado.
 Nótese que en este caso utilizamos nuestro Arduino simplemente como fuente de
alimentación para dar tensión al circuito.
Arduino y las entradas analógicas

Con Arduino hemos visto que podemos influir en el mundo exterior aplicando salidas todo / nada en
los pines digitales y también que usando PWM podemos simular bastante satisfactoriamente señales
analógicas en algunos de esos pines.

También hemos visto cómo 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 señal analógica. Es el caso de los sensores de temperatura o distancia, de presión o PH,
de intensidad de corriente en un circuito o de caudal de agua en una tubería.

Para leer este tipo de señales continuas necesitamos un convertidor analógico a digital (o ADC por
sus siglas en ingles) y que nos permite leer el valor de una señal analógica en un momento dado.

Estos convertidores toman una muestra del valor actual de la señal y nos entregan su valor
instantáneo, medido en Voltios.

Mediante la lectura repetida de muestras a lo largo del tiempo podemos reconstruir la señal original
con mayor o menor precisión, dependiendo de la exactitud de nuestra medida y de la velocidad a la
que pueda tomar esas muestras.

Arduino UNO dispone de seis convertidores analógico a digital, nominados de A0 hasta A5,
rotuladas como ANALOG IN:
Veamos cómo usar las entradas analógicas con un circuito como este, en el que damos tensión a los
extremos de un potenciómetro y conectamos el pin central (el variable) a la entrada de la puerta A5
de Arduino:

 Parece buen momento para destacar que los convertidores ADC leen valores de tensión y no
resistencia, por lo tanto, lo que vamos a leer es la caída de tensión en el potenciómetro a
medida que giramos el ajuste.

La primera curiosidad es que no necesitamos declarar en el setup() que vamos a usar una puerta
analógica. Y la segunda es que para tomar una muestra (leer) del pin A5, usaremos la instrucción:

int Val = analogRead(A5) ;


 Los convertidores de Arduino UNO y Mega son de 10 bits de resolución por lo que nos
devolverá valores entre 0 y 210 = 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 resolución(pero sólo puede leer hasta 3,3V).
 Asegúrate de no usar sensores que puedan dar más de 5V máximo (con Arduino UNO y
Mega), ya que dañarías el chip principal de Arduino.

Vamos a escribir un programa que lea el valor del pin A5 y lo envíe a la consola para que podamos
visualizarlo.

Usando las puertas analógicas

Prueba este programa:

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 las lecturas varían de
forma continua reflejando la posición del potenciómetro, las lecturas reflejan la caida en voltios en
el.
No puedo resistirme a proponeros esta prueba: Desconecta el potenciómetro de la puerta A5 y
observa los resultados que arduino envía a la consola. ¿Porque salen esos valores?

 Al no estar el A5 conectado a ninguna referencia válida, está flotando y los valores que
captura son muestra de esa incoherencia. En realidad lo que está haciendo tu Duino es
captar ruido aleatorio de radiofrecuencia e intentar darle sentido, pero lo tiene mal, como
podeis ver.
 No obstante en condiciones normales los valores que leerá seran relativamente
bajos.¿Quieres que las oscilaciones crezcan en valor?. Fácil. Ponle una antena. Vale un
simple cable de protoboard conectado desde el A5 a nada (O si coges el otro extremo entre
los dedos, tu mismo haras de antena). Acabas de construir el receptor de Radio frecuencia
mas inutil del mundo

Un último comentario

Decíamos en una sección anterior, que la fidelidad con que podemos muestrear una señal analógica
dependía, básicamente, de la resolución de la muestra y de la velocidad a la que podíamos muestrear
la señal (Sample Rate en inglés).

Ya dijimos que la familia Arduino, dispone de convertidores de 10 bits por lo que nuestra resolución
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 función 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.
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. Sería un error manejar millis con un int porque su valor
máximo es 32.767 y midiendo milisegundos el contador desbordaría en poca más de 32
segundos.

SI corréis este programa en un Arduino UNO os dará, poco más o menos, un resultado de 8.940
muestras o lecturas por segundo. No está mal.

Es adecuado para muestrear señales que no varíen demasiado rápido con el tiempo, como son casi
todos los sensores habituales en la industria, pero que se quedará corto si queréis muestrear señales
de audio.

 Para jugar con audio es mejor usar un Arduino DUE. Tiene una velocidad de reloj 4 veces
más rápida(os hará falta), capacidad de muestreo a velocidad de audio (40Khz) y
auténticos convertidores DAC (digital to analog converters).
 De hecho no es complicado aumentar la velocidad de muestreo hasta unas 20.000
muestras por segundo con un Arduino UNO, pero para eso tenemos que puentear Arduino y
saltar a programar el chip interior Atmega 328. No es momento para ello, pero hay formas.

Resumen de la sesión

o Ya conocemos el uso del potenciómetro.


o Hemos presentado los conceptos básicos en la conversión analógica to digital.
o Aprendimos a leer las puertas analógicas de Arduino.
o Sabemos que podemos leer las puertas analógicas unas 8.900 veces por segundo
con una resolución de 10 bits, o sea entre 0 y 1.024.
o Conocimos la función millis().
TRANSISTORES
Arduino y los Transistores.

Objetivos

o Conocer el Transistor.
o El primer circuito con un transistor.
o Primer encuentro con un motor de continua.
o Como variar la velocidad del motor mediante PWM.

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo.

Una Protoboard más cables.

Un diodo LED y una resistencia de 330Ω.

Un transistor 2N2222. Comprobad que lleva rotulada esta


referencia, porque el sensor de temperatura es similar.

Un Motor de corriente continua.


Adaptándonos al mundo exterior

En las sesiones previas hasta ahora, hemos influido en el mundo exterior poniendo una orden en los
pines digitales de Arduino. Por ejemplo poniendo HIGH en un pin y confiando en que esto sea
suficiente para gobernar lo que haya detrás, que hasta ahora han sido diodos LEDs.

Pero la capacidad de Arduino para alimentar ese elemento externo es limitada, y con mucha
frecuencia insuficiente para excitar un actuador exterior.Por eso necesitamos elementos externos que
reciban la señal de control de nuestro Arduino y adapten este control a las necesidades del mundo
exterior.

Para ello vamos a tener que utilizar elementos como transistores, relés, servos y pequeños motores de
diferentes tipos.

 Los pines digitales de Arduino permiten un máximo de 40 mA o lo que es lo mismo 5V x


40mA = 0,2 Watt.
 Esto es suficiente para iluminar LEDs o incluso mover un pequeño servo pero es
insuficiente para mover un motorcito de corriente continua o de paso a paso.
 Es importante asegurarnos de que lo que conectemos a los pines no sobrepasen las
especificaciones de nuestros Arduinos, porque si los forzamos la cosa acabara oliendo a
plástico quemado y un viaje a la tienda de Arduinos a por otro.

A lo largo de las sesiones anteriores hemos ido conociendo componentes electrónicos de distintos
tipos: Diodos, LEDS, Resistencias, Potenciómetros… y ahora vamos a presentaros otro que es la
base fundamental de toda la electrónica moderna, incluyendo la informática, se llama transistor.

¡Que no cunda el pánico! Somos conscientes del terror reverencial que el transistor inspira entre
los aficionados novatos a la electrónica y los novicios de Arduino, pero tranquilos, es mucho más
fácil de lo que parece y es un componente muy agradecido en casi cualquier proyecto que podáis
imaginar.

Así que por favor seguid leyendo. Y confio en que acabareis cogiéndole gusto a los transistores.

El transistor

Según la Wikipedia un transistor es un dispositivo electrónico semiconductor utilizado para entregar


una señal de salida en respuesta a una señal de entrada, que cumple funciones de amplificador,
oscilador, conmutador o rectificador.

Guauuu, no me extraña el pánico. Vamos a traducir.


Siguiendo con las analogías que vimos en la sesión 3, entre el flujo de corriente eléctrica y flujo de
agua, resulta que con el agua tenemos una cosa muy similar al transistor. Se llama grifo.

Si, uno de esos grifos que abrimos y cerramos para ducharnos o lavarnos las manos y que cumplen
básicamente dos funciones:

 Permitir abrir o cortar el flujo de agua (digitalmente SI/NO).


 Regular la intensidad de dicho flujo, abriendo más o menos el paso.

Pues básicamente un transistor es exactamente lo mismo pero construido de otro modo, con
diferentes materiales y un poco más rápido de accionar. Un transistor puede trabajar de dos maneras:

 Permitir o cortar el flujo de corriente.


 Amplificando una señal de entrada (enseguida volvemos)

Cuando un transistor funciona de la primera manera, en modo pasa o no pasa, pero sin medias
tintas, decimos que funciona al corte (no pasa) o a saturación (pasa sin restricciones). Y esto es el
fundamento de toda tecnología digital moderna: Ordenadores, teléfonos, consolas, relojes digitales.
De hecho un transistor en corte es un 0 y en saturación es un 1, (o TRUE / FALSE si preferís).

Los grifos, tiene tres partes: entrada, salida y control. Los transistores igual, pero se llaman emisor,
colector y base (E, C, B).

Si hacemos funcionar un grifo y vamos moviendo sin parar el control en ambas direcciones, el flujo
de salida de agua es proporcional al Angulo del mando en cada momento. Y si la tubería fuese lo
bastante enorme estaríamos amplificando enormemente nuestro movimiento manual.

Cuando hacemos eso con un transistor poniendo en la Base una señal eléctrica variable, el flujo de
corriente entre el Emisor y el Colector sigue la señal de la base pero amplificándola. Se pueden
conseguir ganancias enormes con este sistema y es la base de todos los amplificadores electrónicos
modernos.

Cada vez que escuchas música, hay un transistor (o varios) amplificando una señal débil para que
puedas escucharla.

 Todos tenemos clara la idea de lo que es un conductor y un aislante. Los semiconductores


son un tipo de materiales que podemos convertir en conductores o aislantes a voluntad,
mediante una señal eléctrica. Y que presentan ciertas propiedades interesantes bajo las
condiciones adecuadas.
 Los semiconductores mas típicos y mas extendidos en la fabricación electrónica son el
Silicio y el arseniuro de Galio, pero son muchos los materiales, que en mayor o menor
medida, presenta un efecto semiconductor
 La mayor parte de los componentes que conocemos en electrónica, como LEDs, transistores
y diodos son semiconductores, y muchos otros menos conocidos como tiristores y hasta
láseres de estado solido

Nuestro primer circuito con un transistor

Vamos a empezar con un transistor de uso general, que podemos encontrar con facilidad en
cualquier sitio: P2N2222. Todos los circuitos que incluyen un transistor se suelen parecer a este:

 El transistor es Q1, y normalmente se suele representar inscrito en un círculo.

 La flecha del emisor indica la dirección de la corriente y que es un transistor NPN, si la


flecha tuviera la dirección contraria sería un transistor PNP, pero mejor lo dejamos de
momento

 M1 es cualquier cosa que vayamos a controlar (como un motor de CC por ejemplo).

 Pin9 representa uno de los pines de control de nuestro Arduino cuy señal gobernara el
circuito externo.

Un circuito así nos permite que la resistencia entre Emisor y Colector sea proporcional a la señal de
control que inyectamos en la Base. En este ejemplo un valor de 5V en la Base permite el paso de la
corriente sin restricciones. Y para tensiones que vayan decreciendo en la Base (mediante PWM) la
oposición al paso es cada vez mayor hasta que en 0V corta por completo el paso.

 Transistor es una acrónimo que deriva del inglés Transfer Resistor


Vamos a alimentar nuestra carga con 5V porque no tenemos otra. Pero podríamos conectar 12V,
24V o lo que necesitásemos e ir usando motores más potentes sin preocuparnos de si Arduino puede
alimentarlo o no. De hecho se venden transistores capaces de regular corriente alterna domestica a
220V.

Una ventaja de usar un transistor es que aísla eficazmente el circuito de control de la base de la carga
entre Emisor y Colector, haciendo casi imposible que queméis un Arduino con un circuito como
este.

 El número de transistores comerciales es ilimitado (y sus precios también) dependiendo de


su función y de su capacidad para soportar diferentes tensiones, mayores cargas, disipar
más calor o hacer poco ruido electrónico.
 No es buena idea buscar transistores raros y caros diseñados para tareas específicas.
Mientras no tengáis muy claro porque compráis un transistor caro, es mejor pegarse a los
modelos baratos de toda la vida.
 El P2N2222 lleva muchos años en el mercado por algo. Empezad con él y ya iremos
hablando de otros.

Circuito para protoboard

Vamos a utilizar un transistor para gobernar la velocidad de rotación de un pequeño motor de


corriente continua (CC)., pero este mismo circuito nos permitiría gobernar motores mayores sin más
que asegurarnos de que el transistor que empleemos resista la carga.

Para saber que es cada pin, Sostened el transistor


con las patas hacia abajo mirando a la cara plana,
donde esta rotulado el nombre. De izquierda a
derecha son Emisor, Base y Colector.
 Importante: Dado que el motor tiene carga inductiva
conviene añadir un diodo que proteja el transistor.
 No es imprescindible, pero un transistor suele ser más
caro que un diodo (aunque no mucho) y más difícil de
reemplazar.

El programa de control del motor

Vamos a empezar por lo sencillo, simplemente, arrancando y apagando el motor sin variar la
velocidad.

const int control = 9 ;

void setup()

pinMode(control, OUTPUT) ;

void loop()

digitalWrite(control, HIGH);

delay(2000);

digitalWrite(control, LOW);

delay(1000);

}
Ya va siendo hora de que empecemos a coger buenas costumbres, y por eso en la primera línea
definimos una constante de tipo entero llamada control, que usaremos en lugar el 9, cuando
queramos referirnos al pin de control.

 A medida que el tamaño de los programas crecen, un error en un numero de pin puede ser
muy difícil de detectar, pero en cambio dándole un nombre, no solo ayuda a que sea más
fácil de leer, sino que además, si por cualquier motivo queremos cambiar el pin de control,
basta con cambiarlo en un único sitio sin necesidad de recorrer el programa buscando un
número concreto.

Para ver como varía la velocidad podríamos hacer:

const int control = 9 ;

void setup()

{ pinMode(control, OUTPUT) ; }

void loop()

for ( int n = 0 ; n < 255 ; n++)

analogWrite (control, n) ;

delay(15) ;

Donde escucharemos como va aumentando la velocidad del motor hasta pararse y volver a empezar.
La razón es que al variar la tensión en la base del transistor, este limita la corriente que lo atraviesa
modificando así la velocidad del motor al que esta conectado. Sería bastante sencillo añadir al
ejemplo un potenciómetro, de modo que usemos su valor para variar la velocidad del motor. Animo
os lo dejo como ejercicio.
Resumen de la sesión

o Confío en que los transistores den un poco menos de miedo ahora. La imagen del
grifo es cómoda para imaginar la operación del transistor (aunque tiene sus
limitaciones).
o Hemos presentado el P2N2222 un transistor típico para aplicaciones en donde la
intensidad de la corriente a regular no pasa de medio amperio y la tensión de emisor
no es demasiado alta, hasta 40V.
o Hemos usado un circuito típico con un transistor para arrancar y parar un motor
DC. Pero que también os servirá para otras aplicaciones como manejar tiras de
LED de 12V por ejemplo.
o Cuidado: Una típica tira de LEDs suele moverse sobre 18 Watios con 12V de
alimentación, o sea 18W / 12V =1,5 Amperios, más que de sobra para freír nuestro
P2N2222. Para esto hace falta otro modelo de transistor (ya hablaremos).
o Usamos las salidas PWM de Arduino para variar la velocidad de giro del motor.
ARDUINO Y LOS RELÉS
Relés o Relaiys

Objetivos

o Conocer los Relés.


o El primer circuito con un relé.
o Los contactos normalmente abiertos y normalmente cerrados

Material requerido.

Arduino Uno o similar.

 Esta sesión acepta cualquier otro modelo.

Una Protoboard más cables.

2 x diodos LED y 2 x resistencias de 330Ω.

Un transistor 2N2222

 Comprobad que lleva rotulada esta referencia,


porque el sensor de temperatura es similar.

Un pequeño Relé.

Independiente o con montura keyes


Que es un relé y para qué sirve

Un relé es un interruptor que podemos activar mediante una señal eléctrica. En su versión más
simple es un pequeño electro-imán que cuando lo excitamos mueve la posición de un contacto
eléctrico de conectado a desconectado o viceversa.

El símbolo del relé muestra la bobina y en este caso, un accionador que conmuta entre dos contactos,
pero también existen relés de múltiples contactos. Mediante una señal de control de poca intensidad
que excite la bobina podemos conmutar grandes tensiones o intensidades.

Hemos visto cómo usar un transistor para hacer lo mismo, ¿Porque entonces usar relés?

 En primer lugar, los relés llevan entre nosotros desde finales del siglo 19 (y nadie ha sido
todavía capaz de convertirlos en obsoletos), es una tecnología muy probada y bien
establecida en la industria y además sirve para cosas que son problemáticas para los
transistores.
 Hay límites en la corriente que un transistor puede aceptar, pero un relé se puede diseñar
para que aguante cualquier carga, porque basta con los extremos metálicos de los contactos
lo soporten.
 Aísla completamente el circuito de control del de potencia, lo que tiene su importancia
especialmente en líneas de media y alta tensión.

Normalmente usaremos un relé cuando se requiera conmutar grandes picos de tensión o intensidad
como por ejemplo arrancando motores de corriente alterna de una cierta potencia. En cambio el
transistor es preferible como conmutador, para pequeñas cargas y cuando la velocidad de
conmutación sea una cuestión importante

 Un transistor conmuta varios millones de veces más rápido que un relé.


En la práctica, con Arduino es más sencillo utilizar un relé para encender una luz fluorescente o la
calefacción, que buscar un transistor de características adecuadas.

Aunque hay relés que necesitan muy poca potencia para excitar la bobina, por regla general Arduino
se quedará corto y vamos a tener que usar un transistor que nos resuelva la papeleta.

El ejemplo que veremos a continuación incluye un circuito de transistor / relé completo que nos
permitirá atacar cualquier proyecto casero que nos propongamos.

Circuito típico relé / transistor

Cuando ponemos un valor HIGH en el pin de control, El transistor pasa a saturación y la corriente
entre emisor y colector excita la bobina del relé, haciendo que el contacto cambie de posición (y
haciendo además un clic muy agradable).

Si ponemos LOW en el pin de control el transistor entra en corte e impide el flujo de corriente por lo
que la bobina cae y el contacto de salida vuelve a su posición de reposo.

La salida del relé consta de 3 pines y no de dos como se podría esperar. El motivo es que la
conexión entre los pines de salida 2 y 3 es de tipo normalmente abierto (circuito abierto sin excitar)
y entre los pines 2 y 4 es normalmente cerrado (circuito cerrado sin excitar la bobina).

Con un relé funcionando como normalmente abierto podemos hacer unas luces de emergencia.
Mientras hay corriente el relé esta excitado y el circuito abierto, pero si se va la luz, el contacto
normalmente abierto se cierra y si hay una batería se encenderán las luces de emergencia
automáticamente.
Para nuestro ejemplo podemos utilizar un LED rojo y otro verde para marcar la situación. Veremos
que se enciende uno u otro, pero nunca ambos (como corresponde a una señal de alarma).

Circuito para protoboard

Por una vez, y sin que sirva de precedente, no vamos a incluir un esquema de Protoboard para el
circuito porque el pinout (patillaje) de un relé depende del fabricante y del modelo y sería poco
práctico establecer múltiples diagramas de protoboard.

Además, el circuito básico del transistor de la sesión anterior es exactamente el mismo que este y
bastaría reemplazar el motor por los contactos de control del relé por una parte, y por la otra buscar
en el relé cual son los pines de normalmente abierto y normalmente cerrado, y conectar un LED a
cada uno con una resistencia común.

 Lo más recomendable seria buscar en internet la hoja de características del relé de que
dispongamos y ver en la descripción del fabricante que es cada pin.
 Si por cualquier motivo no pudiésemos conseguir las especificaciones, suele ser bastante
fácil determinar los pines de control (porque suelen estar próximos) y para saber cuál es
contacto NA o NC hay que hacer pruebas con los LEDs (suelen ser 3 pines próximos entre
sí, y el que esta solo es el común).
 Cuando un relé conmuta se oye un clic muy simpático, así que es fácil saber si lo has
excitado. Incluso algunos relés son transparentes para que puedas ver el mecanismo
interior y el movimiento del contacto.

El diagrama de la protoboard no haría sino complicar las cosas y ya va siendo hora de que tratemos
de montar el circuito a partir del esquema electrónico directamente. Animo

Programa de control del motor

Para probar que todo está correctamente conectado, bastaría con correr el mismo programa que para
el motor:
const int control = 9 ;

void setup()

pinMode(control, OUTPUT) ;

void loop()

digitalWrite(control, HIGH);

delay(1000);

digitalWrite(control, LOW);

delay(1000);

Este programa causará que el relé conmute cada segundo y los LEDs se encenderán
alternativamente.

Para convertir este circuito en unas luces de emergencia bastaría con poner una batería o pilas en el
común del relé en lugar de los 5V de Arduino. De ese modo al desconectar Arduino la luz de
emergencia se activaría sola.

Resumen de la sesión

o Ya conocemos los relés y porque tienen interés para nuestros proyectos


o Hemos visto lo que son los contactos normalmente abiertos NA y normalmente
cerrados NC.
o Normalmente los relés son muy interesantes para encender y apagar algo que tiene
un consumo relativamente alto de corriente
SENSOR DE TEMPERATURA
TMP36
Arduino y los Sensores de temperatura

Objetivos

o Calcular la temperatura con un tipo float.

o Construir una alarma de temperatura.

o Convertir la temperatura de Celsius a Fahrenheit.

Material requerido.

Arduino Uno o similar.Esta sesión acepta cualquier otro


modelo.

Una Protoboard más cables.

Un diodo LED y una resistencia de 330Ω.


Un Sensor de temperatura TMP36, o LM35DZ.

 Comprobad que lleva rotulada esta referencia,


porque es fácil confundirlo con un transistor.

Que es un sensor de temperatura

Un sensor de temperatura es simplemente un chip que nos devuelve un valor de tensión proporcional
a la temperatura a la que está sometido. En esta sesión vamos a utilizar unos modelos comerciales
muy extendidos y fáciles de encontrar por muy poco dinero: TMP36 o LM35DZ.

Vamos a ver como los usamos. Lo primero, tenéis que buscar la hoja de especificaciones del
fabricante. (Busca TMP36 o LM35DZ data sheet)Aunque al principio no es fácil acostumbrarse a
leer este tipo de documentación (y que encima vienen en inglés), en último término es a donde hay
que ir cuando queráis saber exactamente las características de su funcionamiento.

Pero el resumen podría ser más o menos así:

o Mide la temperatura en grados centígrados.


o Funciona entre -50º C y 125ºC para el TMP36.
o Funciona entre 0º C y 100ºC para el LM35DZ .
o No es especialmente preciso, ya que tiene ± 1ºC de incertidumbre, pero
normalmente nos sobra para proyectos sencillos y es muy barato.
o EL encapsulado es similar al de un transistor y también tiene tres patas, así que
mucho cuidado con confundirlos. Intentad leer las letras que lleva serigrafiadas (si
podéis, porque suelen ser tan pequeñas que a veces no se leen ni con lupa).

El pin central es el de señal, pero para saber cuál es GND y 5V, el encapsulado tiene una cara plana
y otra curva. Poniendo la cara plana mirando hacia vosotros con las patas hacia abajo(de modo que
podais leer el modelo), el pin de la izquierda es alimentación 5V y naturalmente el otro es GND.
 SI conectáis la tensión al revés, Tendréis tiempo de reaccionar y cambiarla, pero mucho
cuidado porque se calentará más que suficiente para haceros una quemadura dolorosa.
 Si veis que está caliente no tratéis de sacarlo con los dedos, simplemente desconectad el
Arduino y dadle un rato para que se enfríe.

Esquema electrónico del circuito.

Vamos a montar un pequeño circuito que lea la temperatura de un sensor, imprima el valor en la
consola y encienda un diodo cuando esta sobrepase un cierto umbral. Aquí tenemos el esquema
electrónico:

Y el circuito para protoboard sería muy sencillo también:

Calculando la temperatura.

El fabricante del TMP36 y del LM35DZ nos dice que la salida de tensión será de 10 mV (mili
voltios) por cada grado de temperatura y además sabemos que nuestro Arduino mide en las puertas
analógicas una máximo de 1.024 para 5V (y 0 para 0V), por tanto, para una lectura dada, el valor en
voltios de la medida será:

Y como cada voltio equivale a 100ºC ( 1V / 10mv = 100), la temperatura en grados Celsius es
resultado de multiplicar esto por 100.

Pero para que la cosa no sea tan fácil el fabricante del TMP36 nos dice que el 0V no es 0º sino -50º
(y así poder leer valores bajo cero), así que al total hay que restarle 50. En cambio com
el LM35DZ empieza en 0º, no hay que restarle nada, es más cómodo de manejar.

Resumiendo. Para calcular la temperatura en ºC a partir de la lectura de Arduino:

Recordad que el LM35DZ no empieza en -50º si no en 0º por lo que no es necesario restarle los los
50º de ajuste. Podéis encontrar cantidad de sensores similares a estos con diferentes rangos de
medida, tanto por arriba como por abajo, pero podéis usar este mismo método para calibrar la
medida.

Así pues, ya tenemos claro como calcular la temperatura, pero como vemos por ahí que tenemos
divisiones, nos conviene utilizar nuestra primera variable de tipo float, o sea que va a tener
decimales.

 Ya sé que la tendencia natural es usar int para todo, pero normalmente en cuanto haya una
división de por medio os conviene usar un float hasta que tengáis muy claro porque usáis
otro tipo.

Cada vez que tomemos una muestra de nuestra entrada analógica vamos a calcular la temperatura y
si sobrepasa el umbral definido, damos orden de activar la alarma, en caso contrario la apagamos.

Como la temperatura es algo que varía lentamente usaremos un delay para que solo nos dé una
medida por segundo.
El Programa de control.

En primer lugar vamos a definir un par de variables:

int Sensor = 0 ;

int umbral = 25 ;

Sensor es el pin analógico (A0) al que conectamos el sensor de temperatura y umbral el valor a partir
del cual disparamos la alarma de temperatura.

 El valor de umbral habrá que ajustarlo en función de la temperatura ambiente donde estéis
montando el circuito.
 En principio 25ºC son buenos para que si queréis subir la temperatura, lo podáis hacer
simplemente soplando o manteniendo entre los dedos el sensor. Otro sistema de subir la
temperatura rápido, es poner el sensor al lado de la salida de refrigeración de un portátil.

Y pasando los cálculos de la página anterior a C++ nos quedaría algo parecido a:
void loop ()

int lectura = analogRead(Sensor);

float voltaje = 5.0 /1024 * lectura ; // Atencion aqui

// Si usais un LM35DZ vuestra formula sera

//float temp = voltaje * 100 ;

float temp = voltaje * 100 -50 ;

Serial.println(temp) ; delay(1000); }

Importante: En la línea donde calculamos el voltaje hemos escrito 5.0 y no 5. Esto es para evitar
que C++ (que es un poco vago) intente hacer una división entre enteros y nos desprecie los
decimales.

 Haced la prueba de escribir en vuestro programa el 5 a secas y veréis que el resultado de


temperatura será siempre -50 ¿Porque?
 Pues sencillamente porque la parte entera de 5/1024 es 0 y punto. Así que por mucho que
después multipliquemos por lectura seguirá siendo 0. Y nuestro programa dice que para 0V
la temperatura es -50ºC.
 Hasta que comprendáis como entiende C++ las operaciones andad con piés de plomo y
comprobadlas sino queréis sorpresas. Una parte de esta sesión es provocar este tipo de
situaciones con las variables float.

Ya solo nos resta comprobar si la temperatura alcanza el umbral y encender el LED o


apagarlo. Descargar Prog_15_1
int Sensor = 0 ; // Prog_15_1

int umbral = 25 ;

void setup()

Serial.begin(9600);

pinMode(11,OUTPUT);

void loop()

int lectura = analogRead(Sensor);

float voltaje = 5.0 /1024 * lectura ; // Atencion aqui

// float temp = voltaje * 100 ; para el LM35DZ

float temp = voltaje * 100 -50 ; Serial.println(temp) ;

if (temp >= umbral)

digitalWrite(11, HIGH) ;

else digitalWrite(11,LOW);

delay(1000); }

Si disponéis de un pequeño ventilador de 5V, de los que suelen tener en las tiendas de informática (o
si desmontáis un equipo viejo), sería fácil cambiar el LED por ese ventilador y orientarlo hacia el
sensor.
Fijando un umbral superior y otro inferior podemos escribir un programa que arranque o pare el
ventilador cuando la temperatura se sale de los márgenes fijados. Habríais conseguido, de un modo
muy sencillo, una regulación de temperatura con un sensor y un ventilador.

Convirtiendo la temperatura a ºF.

En Europa estamos bastante acostumbrados a los grados Celsius desde pequeños, pero en América
las medidas de temperatura en grados Fahrenheit son habituales. Así que vamos a modificar nuestro
programa para que mida en ºF.

La forma de convertir una temperatura medida en Celsius a Fahrenheit es:

Os propongo que convirtáis el programa anterior para que dé medidas de temperatura en grados
Fahrenheit en lugar de Celsius (o mejor aún, que dé ambas en la misma línea).

Resumen de la sesión

 Hemos visto lo que son y cómo funciona un sensor de temperatura básico como el TMP35. Hay
muchos por ahí, pero suelen ser parecidos a este.
 Hemos aprovechado para meter el tipo float y ver como forzar las operaciones con ellos y lo que
es más importante prevenir posibles malas pasadas con ellos.
 Hemos desarrollado un circuito de medida de temperatura con alarma.

CONOCIENDO LOS SERVOS


Arduino con servo y potenciometro
Objetivos

o Que es un servo.
o Comprender la diferencia con un motor normal.
o Introducir el concepto de librería en C++.
o La función map().

Material requerido.

Arduino Uno o similar.

 Esta sesión acepta cualquier otro modelo de Arduino.

Una Protoboard más cables.

Una Potenciómetro.

Un Servo con sus horns,

Esas pequeñas piezas de plástico que se ponen en el eje

Que es un servo

Normalmente los motores habituales lo que hacen es transformar la energía eléctrica (O química) en
un giro continuo que podemos usar para desarrollar trabajo mecánico.
En la sesión 13 utilizamos un pequeño motor de corriente continua y regulamos la velocidad de giro
mediante una señal PWM de Arduino.

Los servos son también motores de corriente continua, pero en lugar de diseñarse para obtener un
giro continuo que podamos aprovechar (para mover una rueda por ejemplo), se diseñan para que se
muevan un angulo fijo en respuesta a una señal de control, y se mantengan fijos en esa posición.

Imaginad por ejemplo un timón de un avión o barco. No queremos un giro continuo, sino un motor
al que le pueda indicar el ángulo que deseamos en grados y que mantenga esa orientación hasta que
le demos una orden en contrario.

Estos servos o servomotores son muy frecuentes en Aero modelismo y en robótica, por la capacidad
que presentan para moverse a un ángulo concreto y mantenerse allí. De hecho se suelen diseñar para
que giren un ángulo proporcional a una señal PWM, de forma que su control es muy preciso. Un
servo suele estar formado por:

Un servo suele estar formado por:

 Una reductora.Un circuito de control..


 Un motor de CC.
 Un circuito de control

En la práctica se comporta como un bloque funcional que posiciona su eje en un ángulo preciso en
función de la señal de control

Habitualmente los servos tiene un margen de operación, es decir, pueden moverse entre 0º y ángulo
dado, que suele ser de 180º, pero existen modelos comerciales de todas la características imaginables
(incluyendo servos de 360º).

Normalmente estos pequeños servos funcionan sobre 5V y el control se realiza mediante una señal
de control PWM, en la que el ancho el pulso indica el ángulo que deseamos adopte el eje.

Un servo tiene un conector de 3 hilos, 5V (rojo), GND (negro o marrón) y el otro Control (amarillo
o blanco).
Podríamos escribir un pequeño programa en Arduino que controle estos pulsos y los relacione con el
ángulo buscado, pero antes de que nadie se asuste, los servos (y otras cosas) son tan habituales, que
ya ha habido gente que han escrito estos programas y los han puesto a nuestra disposición.

De este modo podemos manejar un servo sin preocuparnos para nada de cómo realizar el control de
las señales, o de la operación interna, basta con instalar estos programas en una forma especial
llamada librería.

 Una librería es un conjunto de definiciones y funciones escritas en C++ de Arduino, que


podemos utilizar en nuestros programas. Podemos ver el código de estos programas,
aunque normalmente se requiere un nivel medio alto en C++ para comprender su
funcionamiento.

La ventaja de trabajar con una plataforma tan bien establecida como Arduino, es que hay cantidad
de gente en el mundo desarrollando librerías, casi para cualquier cosa que podáis imaginar.

Y aún hay algo mejor: Son gratis.

Veréis que en las próximas sesiones vamos a utilizar librerías para cantidad de cosas, pero hoy
vamos a comenzar con la primera, la librería servo.

Usando nuestra primera librería: Servo

Servo es una librería estándar en Arduino. Eso quiere decir que viene incluida cuando instaláis el
IDE, a diferencia de otras librerías que debemos buscar, descargar de Internet e instalar para poder
usarlas.

Para usar una librería estándar, basta con pedirle al IDE que la incluya en nuestro programa. Id al
menú Programa \ Importar Librería y os saldrá un desplegable con todas las librerías que tenéis
instaladas en el IDE.

Por ahora solo nos interesa la librería Servo. Pinchad en ella. Arduino incluirá una línea al principio
de vuestro programa como esta:

#include <Servo.h>

A partir de ahora ya podemos utilizar las funciones disponibles en la librería.

 Normalmente para usar una librería hay que leer la documentación, en la que se detalla la
forma de usarla, que funciones tenemos disponibles, que parámetros pasarlas…etc.
 Como es vuestra primera librería, y nosotros ya nos hemos leído el manual, vamos a
llevaros de la mano. Veréis que es de lo más fácil.
Vamos a montar un circuito en el que hagamos moverse al servo de forma controlada, e iremos
viendo las instrucciones necesarias.

Esquema electrónico del circuito

Vamos a conectar el servo primero a GND y 5V y luego el pin de control, a un pin de Arduino que
permita PWM (Recordad esto o de lo contrario os costara ver el problema). Recordad que es el
ancho el pulso lo que controla el ángulo.

Vamos también a conectar un potenciómetro a la puerta A0 para jugar con el servo.

El diagrama de conexión para la protoboard es igual de sencillo:

El Programa de control

Vamos a empezar con una línea que ya conocíamos el include y otra nueva:
#include <Servo.h>

Servo servo1;

Para poder utilizar la librería debemos crear, lo que se conoce como un objeto tipo Servo que
llamamos servo1.

C++ es un lenguaje orientado a objetos, esto significa que podemos definir objetos tipo (como
servos) sin más que declarar un nuevo objeto del tipo que deseamos. En la jerga de la programación
se llama crear una instancia, o instanciar un nuevo objeto.

Así, esa segunda línea significa que vamos a crear una nueva instancia de tipo Servo que llamamos
servo1.

 Aunque ahora os pueda parecer una forma extraña de hacer las cosas, la programación
orientada a objetos (OOP por sus siglas en inglés), es una de las metodologías más
potentes de las ciencias de computación actuales y todos los lenguajes de programación
que se precien, han incorporado las ideas de la OOP.
 Entrar en la teoría del OOP, desborda con mucho las pretensiones de este humilde tutorial
de Arduino, por ahora nos limitaremos a mostraros como usar los objetos.

Una vez creada la instancia del objeto (y podemos crear tantas como necesitemos, para manejar
varios servos a la vez) tenemos que incluir una línea en la función setup() para informar a C++ que
vamos a conectar ese objeto abstracto que todavía es servo1 a un pin físico del Arduino para
controlarlo. En nuestro caso el pin 9:

servo1.attach(9);

Una vez cumplido el trámite para gobernar la posición del servo recurrimos a

servo1.write( angulo);

Donde Angulo es el valor en grados de la posición que deseamos. Fácil ¿No?

Vamos a escribir un programa que vaya barriendo un Angulo en grados y moviendo el servo a esa
posición.

#include <Servo.h> // Incluir la librería Servo

Servo servo1; // Crear un objeto tipo Servo llamado servo1


int angulo = 0 ;

void setup()

servo1.attach(9) ; // Conectar servo1 al pin 9

void loop()

for(angulo = 0; angulo <= 180; angulo += 1) //incrementa angulo 1


grado

servo1.write(angulo);

delay(25);

for(angulo = 180; angulo >=0; angulo -=1 ) //decrementa angulo 1


grado

servo1.write( angulo );

delay(25);

Veréis como el servo se va moviendo primero hacia adelante y luego retrocede para volver a
empezar.
Vamos ahora a hacer que el valor del potenciómetro represente la posición del servo de manera que
el servo se mueva siguiendo al potenciómetro. Para ello hay que entender que el valor que leamos en
la puerta A0 está comprendido entre 0 y 1024, y que estos valores tienen que distribuirse entre 0 y
180º. Así que para calcular el Angulo correspondiente basta con hacer:

Como la experiencia me ha demostrado, que los errores haciendo este tipo proporciones tienden a
infinito, voy a aprovechar para presentaros la función map(), que hace exactamente eso de un modo
cómodo, librándonos de los float ( aunque para aprender no os vendría mal hacer así el programa y
luego usar el map()).

angulo = map( analogRead(A0), 0, 1024, 0, 180);

Traducido quiere decir: Haz la proporción de los valores que leas en A0, entre 0 y 1024, en un valor
comprendido entre 0 y 180 y asignale ese valor al ángulo. //Prog_16_2

#include <Servo.h> // Incluir la librería Servo

Servo servo1; // Crear un objeto tipo Servo llamado servo1

int angulo = 0 ;

void setup()

servo1.attach(9) ; // Conectar servo1 al pin 9

void loop()

angulo = map( analogRead(A0), 0, 1024, 0, 180);


servo1.write(angulo);

delay(250);

Aqui teneis un peqeño video, mostrando el movimiento del servo

Resumen de la sesión

o Hemos presentado los servos y hemos vista una par de programas sencillos para
usarlos.
o Hemos introducido algún concepto básico de programación orientada a objetos para
que podáis utilizar las librerías.
o Hemos definido las librerías como conjuntos de funciones y objetos que podemos
utilizar sin preocuparnos de cómo funcionan internamente.
o Las librerías son un sistema excepcional de utilizar elementos electrónicos sin tener
que entrar en los detalles técnicos más o menos complicados. Esto nos abre un
potencial enorme de componentes a nuestra disposición.
o Introdujimos otra función más para nuestro arsenal: map().

CIRCUITO CON JOYSTICK Y


SERVO
Manejando joysticks con Arduino

Objetivos

o Presentando un pequeño joystick.


o Leyendo el joystick.
o Moviendo el servo mediante el stick.
o Filtrando las lecturas.

Material requerido.

Arduino Uno o similar.

 Esta sesión acepta cualquier otro modelo de Arduino.

Una Protoboard mas cables.

Un Joystick.

Un Servo con sus horns, esas pequeñas piezas de plástico que


se ponen en el eje.

Que es un joystick

Un joystick suele estar formado por dos potenciómetros a 90º que transforman el movimiento en X
e Y del mando en una señal eléctrica proporcional a su posición y que además suele incluir un botón.
Así pues, suelen tener 5 pines: X, Y, botón y 6V más GND.

En realidad ya usamos todos estos componentes previamente y la única curiosidad del joystick es
que resulta un elemento muy cómodo para posicionar algo, aunque no sea demasiado preciso.

Vamos a montar un circuito con un servo como en la sesión previa y usaremos uno de los ejes del
joystick para posicionar un servo, y si pulsamos el botón encendemos un LED. (Ignoraremos el otro
eje Y, aunque podríamos usarlo para posicionar un segundo servo).
El pin correspondiente al botón suele venir marcado como SW de Switch.

Aquí tenemos el diagrama eléctrico:

Y para la protoboard:

El Programa de control

Vamos con el programa (Prog_17_1):


#include <Servo.h> // Incluir la librería Servo

Servo servo1; // Crear un objeto tipo Servo llamado servo1

int angulo = 0 ;

int Eje_X = A1 ;

int Eje_Y = A2 ;

int boton = 4 , LED = 12 ;

void setup()

servo1.attach(6) ; // Conectar servo1 al pin 6

pinMode( boton, INPUT_PULLUP) ;

void loop()

angulo = map( analogRead(A1), 0, 1024, 0, 180);

servo1.write(angulo);

if ( ! digitalRead(boton))

digitalWrite(LED, HIGH);

else

digitalWrite(LED, LOW);

delay(250) ;

}
 La parte que corresponde al servo es exactamente lo mismo que en la sesión 16. Por lo
demás hemos incluido unas definiciones al principio indicando que hemos conectado el eje
X a la entrada analógica A1 y el eje Y a la entrada A2.
 El pulsador está conectado al pin digital 4 y el LED al 12, de forma que si queremos
cambiar de pines, por la razón que sea, bastara con actualizar esta lista al principio del
programa.

Insistir en que hemos definido la entrada correspondiente al boto del joystick


como INPUT_PULLUP y no como INPUT, porque de este modo no necesitamos incluir una
resistencia, sino que Arduino conecta un pullup internamente

Por eso leeremos LOW al pulsarlo y entre tanto será HIGH, por ese motivo invertimos la condición
en el if. Encenderemos el botón solo cuando pulsemos.

El servo sigue la posicion del joystick y cuando soltamos vuelve al centro.

Pero hay algo de epiléptico en el movimiento del servo (y más con uno barato como éste que estoy
usando). Recibe muchas interferencias y el movimiento es muy convulso, porque, aún si el servo
tuviera una cierta precisión (lo que es una suposición entre optimista y muy optimista) los
potenciómetros y los convertidores analógicos a digital siempre tienen un margen de ruido.

Seguro que se nos puede ocurrir una forma de mejorar ese movimiento. Pensadlo, ¿Que podemos
hacer para filtrar ese ruido?

No, en serio. Piénsalo primero antes de seguir.

Vale. En el mundo real, las cosas no son nunca blancas o negras, sino más bien en tonos grises (o
muy frecuentemente chocolates), por eso no es buena idea enviar las lecturas directamente al control
el servo, o de lo que sea que estamos moviendo.

Hay que filtrar un poco la señal. Sin entrar mucho en este tema (sobre el que hay
enciclopedias),vamos a usar una técnica muy básica, pero muy eficaz en muchas ocasiones y que os
conviene conocer.

Vamos a leer el potenciómetro para decidir si subimos o bajamos el valor del Angulo. No para
calcular Angulo directamente.

Como el potenciómetro nos da valores entre 0 y 10000, cuando está centrado o suelto, leerá sobre
500, poco más o menos (aunque bailará). Así que le vamos a dar un margen de tolerancia. Solo
aumentaremos el Angulo, un valor dado, si la lectura del potenciómetro sobrepasa el valor de 600 y
lo disminuiremos cuando baje de 400.

De este modo pequeñas oscilaciones alrededor del punto medio, no nos afectarán. Es decir las hemos
filtrado. Esto reflejado en el programa, podría ser algo así: Prog_17_2

#include <Servo.h> // Incluir la librería Servo

Servo servo1; // Crear un objeto tipo Servo llamado servo1

int angulo = 90 ; // Empezamos en el centro

int salto = 3 ; // Controla el salto por movimiento

int Eje_X = A1 ;

int Eje_Y = A2 ;

void setup()

servo1.attach(6) ; // Conectar servo1 al pin 6

pinMode( boton, INPUT_PULLUP) ;

void loop()

int p = analogRead(A1);

if ( p < 400 ) // Si la lectura es menor de 400

angulo = angulo - salto ; // disminuimos el angulo

else if (p>600) // Si mayor de 600

angulo = angulo + salto ; // Aumentamos el angulo


servo1.write(angulo); // Y este es el que mueve el servo

delay (50); // Este delay regula la velocidad del


movimiento

Creo que comprobareis que el movimiento es más fluido y uniforme, y que prácticamente elimina las
convulsiones del servo. Además usamos este método para dejar clavado al servo en la posición que
nos interesa (Aunque soltemos el mando), algo que del otro modo sería imposible.

Resumen de la sesión

o Hemos visto que un joystick son dos potenciómetros a 90º mas un pulsador, ambos
normales y corrientes.
o Aprovechamos el montaje anterior para mover el servo con el joystick y mapear su
valor entre 0 y 180º
o Hemos introducido el concepto de filtrado de señales, que de por si es una rama
específica de la electrónica y la computación, y una, que cada día es mas
importante en todos los ámbitos de la tecnología.

CIRCUITO CON SENSOR DE


DISTANCIA
Arduino y los sensores de distancia
Objetivos

o Sensor ultrasónico de distancia.


o Más sobre medir el tiempo: delayMicroseconds ().
o Más funciones disponibles: PulseIn ().
o Importando una librería externa.

Material requerido.

Arduino Uno o similar.

 Esta sesión acepta cualquier otro modelo de Arduino.

Una Protoboard mas cables.

Sensor de distancia HC-SR04

Un diodo LED y una resistencia.

Como funciona un sensor ultrasónicode distancia

Hemos visto, en los documentales, que los murciélagos son capaces de volar en completa oscuridad
y sin embargo, sortear obstáculos o atrapar insectos en vuelo. Sabemos que lo hacen, pero rara vez
pensamos como.
Tenemos una vaga idea de que se llama ecolocalización y que más o menos tiene que ver con unos
sonidos agudos que emiten y que después recogen con esas enormes orejas que Dios les ha dado,
pero rara vez nos planteamos cómo es esto posible.

Delfines y ballenas utilizan un sistema similar para atrapar a sus presas, y hasta hemos visto que, en
cualquier película de submarinos, en el momento álgido el capitán ordena emitir un pulso único de
sonar para localizar al enemigo.

El concepto básico, es siempre el mismo, sabiendo a qué velocidad viaja el sonido, si emitimos un
pulso sónico corto y escuchamos cuanto tiempo tarda en regresar el eco podemos calcular la
distancia a la que se encuentra el objeto en el que ha rebotado la señal.

 El radar funciona de modo similar aunque usando ondas de radio frecuencia muy cortasy
con una problemática propia descomunal. Un pulso de radiofrecuencia se emite desde la
antena y se recoge el eco que vuelve a la velocidad de la luz.

Lo que haremos en esta sesión es utilizar un sensor de distancia sencillo HC-SR04 (y muy parecido
a los sensores de aparcamiento de los coches modernos), que nos permite enviar estos pulsos
ultrasónicos y escuchar el eco de retorno. Midiendo este tiempo, podemos calcular la distancia hasta
el obstáculo.

 El oído humano no percibe sonidos por encima de 20kHz. Por eso, a las ondas de mayor
frecuencia las llamamos ultrasonidos ( mas allá del sonido). Los sensores de ultrasonidos
funcionan sobre los 40 kHz.
 No son perfectos, les influye la temperatura ambiente, la humedad y los materiales en los
que reflejan, lo que genera una cierta incertidumbre. Pero a cambio son baratos y efectivos
hasta un poco más de 3 metros en condiciones normales si la precisión no es un problema
determinante

Diagrama de conexión

Veamos como conectar uno de esto detectores a nuestros Duinos. Aquí está el esquema eléctrico y
de protoboard por cortesía de Fritzing:
Y de nuevo, el diagrama de conexión de la protoboard

El Programa de control

Vamos con el programa, empezamos definiendo algunos valores:

#define trigPin 13

#define echoPin 12

#define led 2

Hasta ahora habíamos visto que podíamos definir una variable como int, por ejemplo, y también
como una constante (const int pin). Aquí utilizamos otro método, el #define que es una directiva para
el compilador.

Esto solo significa que el compilador (en rigor el pre procesador) cambiará todas las ocurrencias de
estos #define en nuestro programa por su valor antes de compilar. Esta es la forma clásica de C de
hacer esto y tiene la virtud de que no ocupa memoria definiendo una variable (y con un Arduino
UNO, que va muy corto de memoria, esto puede ser crítico en ocasiones).

void setup()

Serial.begin (9600);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

pinMode(led, OUTPUT);

Ya estamos más que habituados a la función delay(milis), pero el reloj interno de Arduino mide en
microsegundos y tenemos otra función parecida delayMicroseconds(µs) que simplemente congela
Arduino el número especificado de microsegundos.

Para dar un pulso ultrasónico lo que hacemos es activar el pin Trigger durante unos microsegundos y
para ello lo ponemos en HIGH, antes de escuchar el eco:

digitalWrite(trigPin, LOW); // Nos aseguramos de que el trigger está


desactivado

delayMicroseconds(2); // Para estar seguros de que el trigger ya está LOW

digitalWrite(trigPin, HIGH); // Activamos el pulso de salida

delayMicroseconds(10); // Esperamos 10µs. El pulso sigue active este


tiempo

digitalWrite(trigPin, LOW); // Cortamos el pulso y a esperar el echo

Para escuchar el pulso vamos a usar otra función, pulseIn() ( Oh sí, hay muchas, muchísimas). Para
leer el manual de pulseIn() buscad en google Arduino pulseIn y vereis que pronto lo encontrais.

Básicamente lo que hace es escuchar el pin que le pasamos, buscando una señal que pase de LOW a
HIGH ( si le pasamos HIGH como parámetro) y cuenta el tiempo que tarda en volver a bajar desde
que sube.

long duracion, distancia ;


duracion = pulseIn(echoPin, HIGH) ;

Ahora ya sabemos el tiempo que tarda en volver el eco en µs. Como la velocidad del sonido es de
343 metros / segundo, Necesitamos 1/343 = 0,00291 segundos para recorrer un metro.

Para usar una medida más cómoda podemos pasar esto a microsegundos por centímetro:

Como nuestro eco mide el tiempo que tarda el pulso en ir y venir la distancia recorrida será la mitad:

Así que el programa queda parecido a esto ( Prog_18_1) : Descargar ejemplo 18_1:
#define trigPin 13

#define echoPin 12

#define led 2

void setup()

{ Serial.begin (9600);

pinMode(trigPin, OUTPUT);

pinMode(echoPin, INPUT);

pinMode(led, OUTPUT);

void loop()

{ long duracion, distancia ;


digitalWrite(trigPin, LOW); // Nos aseguramos de que el trigger
está desactivado

delayMicroseconds(2); // Para asegurarnos de que el


trigger esta LOW

digitalWrite(trigPin, HIGH); // Activamos el pulso de salida

delayMicroseconds(10); // Esperamos 10µs. El pulso sigue


active este tiempo

digitalWrite(trigPin, LOW); // Cortamos el pulso y a esperar el


echo

duracion = pulseIn(echoPin, HIGH) ;

distancia = duracion / 2 / 29.1 ;

Serial.println(String(distancia) + " cm.") ;

int Limite = 200 ; // Medida en vacío del sensor

if ( distancia < Limite)

digitalWrite ( led , HIGH) ;

else

digitalWrite( led , LOW) ;

delay (500) ; // Para limitar el número de mediciones

Para convertir esto en un detector de movimiento hemos creado una variable un poco menor de la
medida que el sensor recibe en vacio (en mi caso unos 200 cm). Si la distancia medida cae por
debajo este valor es que algo se ha interpuesto y por tanto encendemos una alarma, en nuestro caso
un humilde LED.

Después de este ejercicio de física y matemáticas, que sin duda causará furor entre los estudiantes
aplicados, vamos a hacer el mismo programa pero usando una librería externa, que alguien se ha
molestado en escribir, paras esas pocas personas que no disfrutan de los problemas de ciencias y que
así, podamos ver la diferencia.
Podeís descargar la librería de aquí, Descargar, o bien de la web del autor
en code.google.com/p/arduino-new-ping.

Para instalar una librería externa no incluida en el IDE de Arduino tenemos que importarla con el
menú Programa \ Importar librería\Añadir librería:

En la ventana que sale, buscad el fichero NewPing_v1.5.zip que habéis descargado y seleccionadlo.

Ya está. Arduino ha importado la librería y los ejemplos que incluye. Si ahora volvéis a
Programa\ImportarLibrería, veréis que al final de la lista ya está disponible como NewPing, y
además el zip incluye varios ejemplos de uso. Vamos a cargar el equivalente del programa anterior.
Haced :

Archivo \ Ejemplos \ NewPing \ NewPingExample

Arduino cargara un programa de ejemplo. Las instrucciones claves son primero inicializar la librería
con:

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE) ;

Y después medir la distancia:

unsigned int uS = sonar.ping() ;

Aqui os copio el ejemplo para vuestra referencia:

#include <NewPing.h>

#define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic


sensor.

#define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic


sensor.

#define MAX_DISTANCE 200


NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins
and maximum distance

void setup()

Serial.begin(115200); // Open serial monitor at 115200 baud to see ping


results.

void loop()

delay(50);

unsigned int uS = sonar.ping(); // Send ping, get ping time in


microseconds (uS)

Serial.print("Ping: ");

Serial.print(uS / US_ROUNDTRIP_CM);

Serial.println("cm");

Como veis la librería se encarga de inicializar los pines necesarios, enviar los pulsos, escuchar el eco
de retorno y de hacer los cálculos. No está mal.

 Fijaros, que el ejemplo, utiliza diferentes pines a los que nosotros hemos usado,así que
tendreís que modificarlos. Igualmente, el ejemplo inicializa la puerta serie a 115.200. Es
imprescindible igualar esta velocidad con la que recibe la consola o veréis muchas cosas
raras en pantalla.
 Los alumnos avispados se habrán dado cuenta de que Arduino viene forrado de ejemplos
que pueden cargar y usar. Os invito a que investiguéis y juguéis con estos ejemplos cuanto
queráis.

Resumen de la sesión

o Hemos conocido los sensores ultrasónicos de distancia.


 Sabemos que sirven para medir algo menos de 3 0 4 metros
 Sabemos que no son perfectos pero son útiles y baratos.

o Más sobre medir el tiempo: delayMicroseconds ().


o Más funciones disponibles: PulseIn ().
o Importando una librería externa, de nuevo,algo que en las próximas sesiones iremos
haciendo cada vez más, a medida que los elementos a usar se vayan sofisticando.

TECLADOS MATRICIALES
Arduino y los keypads de 4x4
Objetivos

o Familiarizarnos con un teclado matricial de 4×4.


o Usar otra librería externa: KeyPad.
o Volver a revisar los arrays, esta vez de dos dimensiones.

Material requerido.

Arduino Uno o similar.Esta sesión acepta cualquier otro


modelo de Arduino.

Una Protoboard más cables.

Un teclado matricial 4×4

Como funciona un teclado matricial

Un teclado no es más que una colección de botones, a cada uno de los cuales le asignamos un
símbolo o una función determinada. Pero botones al fin y al cabo.
Leer botones es algo que ya no tiene secretos para nosotros, pero si conectáramos cada tecla a un pin
digital de nuestro Arduino, pronto estaríamos en apuros.

El teclado de nuestro ordenador suele ser de alrededor de 106 teclas, así que el método de fuerza
bruta va a entrar en apuros rápidamente. Necesitamos otra solución.

Y como el mundo está lleno de gente ingeniosa se les ocurrió una solución de lo más elegante, una
matriz de teclas.

Vamos a ver un ejemplo con un pequeño teclado numérico de 16 teclas tipo los de los teléfonos
móviles o los de los cajeros automáticos.

Para que nuestro Arduino pueda saber que tecla se pulsa, basta con poner tensión en las filas de
forma secuencial y luego leer las columnas para ver cuál de ellas tiene HIGH.Los teclados
matriciales usan una combinación de filas y columnas para conocer el estado de los botones. Cada
tecla es un pulsador conectado a una fila y a una columna. Cuando se pulsa una de las teclas, se
cierra una conexión única entre una fila y una columna.

Por ejemplo, ponemos HIGH en la primera fila (hilo 8 en el diagrama de la derecha) y después
leemos sucesivamente los hilos correspondientes a las columnas (hilos 4, 3, 2,1). Si ninguno está en
HIGH es que no se ha pulsado ninguna tecla de la primera fila.

Pasamos a la segunda fila (hilo 7) y ponemos HIGH, si al leer los hilos 4, 3, 2,1 encontramos que el
hilo 1 está en HIGH, es que se ha pulsado la tecla correspondiente a la “B”.

De este modo, para leer un teclado matricial de 4×4 necesitamos 8 hilos en lugar de 16, aunque nos
dará un poco más de guerra a la hora de programar. Para un teclado de PC 106 teclas bastaría una
matriz de 10×11 o sea 21 hilos en vez de 106.

Diagrama de conexión
Lo más práctico es conectar el teclado a Arduino directamente, podemos usar cables de protoboard,
o bien con un peine de pines para que no se suelte nada.

Esta es otra de esas raras ocasiones en que un esquema electrónico tendría poco sentido, así que
pasaremos rápidamente a ver el tema del programa.

 Un apunte rápido: Por comodidad en el diagrama, y porque en los ejemplos que vienen con
Arduino utilizan estos mismos números de pines del 0 al 7, los hemos mantenido. Pero
conviene saber que Arduino usa los pines 0 y 1 para comunicarse a través del USB, por lo
que no es buena usarlos para otra cosa cuando vayamos a usar el puerto serie.

El Programa de lectura

Como ya dijimos, el programa ha de consistir en ir dando tensión consecutivamente a los pines de


las filas 8, 7, 6, 5 y después ir leyendo los valores de las columnas para detectar que teclas se han
pulsado.

No es un programa complicado, pero antes de que el pánico se apodere de los que siguen la sesión
con creciente temor (y recuerden que tienen algo urgente e ineludible que hacer) comentaremos que
alguien ha tenido este problema antes que nosotros y amablemente ha puesto a nuestra disposición
una librería llamada KeyPad ideal para leer este tipo de matrices sin complicaciones,.

 Lo que no quita para que podáis escribir un programa que lea directamente la matriz y
reconozcáis las pulsaciones. Animo, no es difícil y el ejercicio siempre es bueno.

Lo primero es descargar la librería e instalarla. La tenéis aquí Descargar, o bien en la página de


Arduino

http://playground.arduino.cc/Code/Keypad#Download
Id a la sección de “Download, install and import” donde encontrareis keypad.zip. Descargadlo y para
instalarla recordad que basta con hacer:

En la ventana que sale, buscad el fichero Keypad.zip que habéis descargado, seleccionadlo y listo.

Una vez instalada para usarla basta con que le indiquéis que deseáis usarla. SI hacéis
Programa\Importar Librería \ Keypad veréis que incluye la siguiente línea en vuestro programa:

#include <Keypad.h>

Vamos a ver como usamos esta librería. Lo primero es definir un par de contantes

const byte Filas = 4; //KeyPad de 4 filas

const byte Cols = 4; //y 4 columnas

Y ahora una par de arrays para indicarle a la librería que pines de Arduino corresponden a las filas y
cuales a las columnas del keypad:

byte Pins_Filas[] = {7, 6, 5, 4}; //Pines Arduino para las filas.

byte Pins_Cols[] = { 3, 2, 1, 0}; // Pines Arduino para las columnas.

Recordad que un array es una colección de elementos que pasamos entre llaves y separados por
comas. Es más cómodo que andar definiendo 8 variables.

Recordad lo que vimos en la sesión 9, que cuando definimos una array por enumeración de sus
elementos, como en este caso, no necesitamos pasar entre corchetes el número de elementos (Los
cuenta el mismo C++ solito).

Tendremos que definirle, además, que símbolos corresponden a cada posición de las teclas. Una
nueva oportunidad para disfrutar de los arrays, pero esta vez de 2 dimensiones en vez de una.

char Teclas [ Filas ][ Cols ] =

{
{'1','2','3','A'},

{'4','5','6','B'},

{'7','8','9','C'},

{'*','0','#','D'}

};

 Definimos el array de 4×4 pasándole las dimensiones entre corchetes. Sus miembros van a
ser 4 filas, cada una de las cuales es un array de 4 elementos, y después enumeramos los
cuatro arrays de 4 miembros.
 Fijaros en que cada array va entre llaves. Los elementos de un array se separan por comas,
pero al final de las llaves exteriores va un punto y coma porque toda el conjunto es una
asignación.
 Los arrays siempre parecen complicados hasta que te acostumbras pero no es para tanto y
este es un buen ejemplo para que comprendéis la idea de un array de 2 dimensiones.

Una de las curiosidades de leer una matriz de teclas y después asignar un carácter contenido en un
array es que podemos redefinir el valor de las teclas sin más que cambiar el contenido del array.

 Si por lo que sea hubiéramos conectado mal los pines del keypad al Arduino, podríamos
redefinir los valores del array para que coincidan con lo que pone en las teclas. Puede ser
más fácil que mover de sitio los cables.
 De hecho es esa capacidad de mapear la representación de un carácter a una posición en una
tabla, es lo que permite que podamos reconfigurar el mismo teclado a diferentes lenguas, sin
más que cambiar los valores del array (aunque también ayudará mucho luego cambiar los
símbolos rotulados en el teclado).

Por ultimo tendremos que crear una instancia de Keypad que llamaremos Teclado1
Keypad Teclado1 = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Fils,
Cols);

Que leído así asusta, pero que en realidad es una tontería. Traduciendo sería: Crea una instancia del
tipo Keypad que llamaras Teclado1 y al que asignarás las teclas que tenemos en el array Teclas, y le
decimos que hemos conectado las filas del keypad a los números de pines que te indico en el array
Pins_Filas y las columnas al array Pins_Cols.
 MakeKeymap (Teclas) es una función disponible en la librería y que nos permite asignar un
array de valores a una matriz. Se hace solo una vez al principio salvo que por lo que sea nos
interese cambiarlo sobre la marcha.

Por ultimo para leer el keypad hacemos una llamada a otra función de la librería:
char pulsacion = Teclado1.getKey() ;

Por ultimo enviamos a la consola el carácter pulsado. Aquí tenéis el programa en versión
completa:Descargar
#include <Keypad.h> // Prog_19_1

const byte Filas = 4; //Cuatro filas

const byte Cols = 4; //Cuatro columnas

byte Pins_Filas[] = {7, 6, 5, 4}; //Pines Arduino para las filas

byte Pins_Cols[] = { 3, 2, 1, 0}; // Pines Arduinopara las columnas

char Teclas [ Filas ][ Cols ] =

{'1','2','3','A'},

{'4','5','6','B'},

{'7','8','9','C'},

{'*','0','#','D'}

};

Keypad Teclado1 = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Filas,


Cols);

void setup()

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

{ char pulsacion = Teclado1.getKey() ;

if (pulsacion != 0) // Si el valor es 0 es que no se

Serial.println(pulsacion); // se ha pulsado ninguna tecla

Por cierto, en C++ y en otros lenguajes es muy frecuente escribir la instrucción:

if (pulsación != 0)

De esta otra manera (más elegante) completamente equivalente:

if (pulsación )

Porque la condición del if debe evaluarse a TRUE o FALSE y para los ordenadores un 0 es FALSE
sin remisión, pero cualquier otro valor que no sea 0 es TRUE, incluyendo un carácter.

Resumen de la sesión

o Hemos usado nuestro primer keypad hexadecimal


 Son prácticos y muy sencillos de usar en cuanto le pilléis el tranquillo.
 Están disponibles en múltiples formatos y tipos, Aquí hemos usado uno
típico de 4×4, pero también los hay 4×3 y en diferentes materiales y
acabados
 Un antiguo teléfono móvil roto se puede desmontar y usar su teclado
además de otras cosas, y se puede utilizar de la forma que hemos descrito.
o Hemos usado la excusa del teclado para volver sobre los arrays. Vale la pena de
que les dediquéis un poco de tiempo pues os ayudaran a resolver cómodamente más
de un problemas de programación, y no se merecen la fama de malotes que tienen.
o Hemos conocido otra librería externa, KeyPad. Os vendrá muy bien en vuestros
proyectos. Más adelante confío en que podamos hacer algún ejemplo más
sofisticado con un keypad como hacer que una cierta combinación abra una
cerradura de servo por ejemplo.

BUZZERS O ZUMBADORES
Sonido básico con Arduino
Objetivos

o Familiarizarnos con un buzzer piezoeléctrico.


o Las funciones tone() y notone().
o Primeros pasos con la música electrónica

Material requerido.

Arduino Uno o similar.

Esta sesión acepta cualquier otro modelo de Arduino.

Una Protoboard más Cables .

Un buzzer piezoeléctrico.

Piezoelectricidad

Según la Wikipedia, la piezoelectricidad es un fenómeno que ocurre en determinados cristales que,


al ser sometidos a tensiones mecánicas, adquieren una polarización eléctrica y aparece una diferencia
de potencial y cargas eléctricas en su superficie que generan una tensión eléctrica.
Este fenómeno también ocurre a la inversa: se deforman bajo la acción de fuerzas internas al ser
sometidos a un campo eléctrico. El efecto piezoeléctrico es normalmente reversible: al dejar de
someter los cristales a un voltaje exterior o campo eléctrico, recuperan su forma.

Es decir, que son materiales (el cuarzo es el más conocido) que si los sometemos a una tensión
eléctrica variable (como una señal PWM, que ya nos son familiares) vibran.

 Es un fenómeno bastante conocido y muchos encendedores domésticos de gas funcionan


bajo este principio. Un resorte golpea un cuarzo y como resultado tenemos la chispa que
enciende el gas o el calentador de agua con un característico click).
 En otro orden de cosas, los circuitos electrónicos digitales, suelen disponer de un reloj
interno que vibra a una velocidad patrón, basados en cristales de cuarzo piezoeléctrico.
 El cristal de Arduino late a 16Mhz por segundo y la flecha indica su posición.

 En una sesión próxima utilizaremos uno de estos cristales para sincronizar un circuito
discreto con el corazón de un Arduino, el ATmega 328.

Si conectamos un piezo con una señal digital, vibran a una frecuencia sigue bastante fielmente la
variación eléctrica con que los excita, y si vibran a la frecuencia audible, oiremos el sonido que
producen. A un componente que hace esto, le llamamos Buzzer o zumbador.

Naturalmente, la calidad del sonido que producen dista bastante de lo que podríamos denominar alta
fidelidad. Pero es suficiente para generar tonos audibles (como la típica alarma de los despertadores
digitales) e incluso tonos musicales reconocibles que podemos secuenciar, hasta en piezas musicales
(por más que uno quisiera estar en otro lugar cuando las oyes).

Como antes o después, disponer de una señal acústica en vuestros proyectos, acaba siendo útil,
vamos a ver cómo podemos montar estos elementos, y que tipo de opciones tenemos disponibles.

En esta sesión, montaremos un circuito muy sencillo con un zumbador.

Esquema electrónico
xx

La conexión es tan simple como conectar negativo a GND y positivo al pin 9. De todas maneras hay
que tener cuidado. Los piezos tienen polaridad y hay que asegurarse de conectarlos correctamente.

 Si los conectáis al revés, simplemente no sonará, y tendréis que dar la vuelta.


 Además para este primer montaje, necesitamos usar un pin PWM (como el 9) porque es la
alternancia entre HIGH y LOW lo que produce el efecto piezoeléctrico (recordad que una
señal PWM envía un tren de ondas cuadradas de amplitud variable), por lo que lo más
cómodo es usar un pin PWM en lugar de programar un efecto equivalente en un pin normal.

El Programa

Vamos a empezar creando una función, Beep(), que haga ruido simplemente:

void beep(unsigned char pausa)

analogWrite(9, 20);

delay(pausa); // Espera

analogWrite(9, 0); // Apaga

delay(pausa); // Espera

Y ahora prueba
void setup()

pinMode(9, OUTPUT);

beep(50);

beep(50);

beep(50);

delay(1000);

void loop()

{ beep(200);

Lo único que beep () hace es poner una señal PWM en el pin 9 de 20 sobre 255. Podéis varias el
valor, pero el tono de audio no cambiará gran cosa porque está controlado por la señal de base. Esto
es suficiente para generar una de las molestas señales acústicas de un despertador barato.

¿Qué pasa si quiero generar señales de tono variable para hacer una melodía? Bueno pues Arduino
dispone de la función tone() que genera una señal de la frecuencia indicada, y notone() que la corta:

void setup()

int pinOut = 8;

int freq = 440;

int duration = 1000;

tone(pinOut, freq, duration);

La función tone() genera un audio de la frecuencia y duración definidas.


Podemos definir una matriz con las frecuencias de las notas a utilizar y lee las correspondencias con
las notas musicales. Veamos cómo generar una escala con un zumbador:

int speakerPin = 9;

int numTones = 10;

int tones[ ] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440,466, 494};

// mid C C# D D# E F F# G G# A

void setup()

{ }

void loop()

for (int i = 0; i < numTones; i++)

tone(speakerPin, tones[i]);

delay(500);

noTone(speakerPin);

 Dada la afición reinante a la física recreativa, me aterra la idea de ponerme a perorar


sobre la relación entre las notas musicales y la frecuencia correspondiente, así como los
distintos métodos de calcularlas y no digamos ya pretender hablar de las escalas
temperadas.
 Así que vamos a mencionar simplemente que existe una relación directa entre la frecuencia
de una nota y su posición, en digamos el teclado de un piano.
 Para aquellos con formación musical e interés en como calcular la frecuencia de una nota
dada podeís hacer una búsqueda en Google, que enseguida encontrareis de todo.

Por último, y para cerrar esta sesión, os diré que internet está lleno de gente a quien le sobra tiempo
y lo dedica a las extravagancias más inverosímiles. Basta con indicaros aquí la página de alguien que
ha dedicado un número indecente de horas en transcribir la música de la guerra de las galaxias a
orquesta de cámara, compuesta por Arduino y zumbador.Descargar ejemplo:

Resumen de la sesión

o Hemos usado nuestro zumbador piezoeléctrico.


o Son muy sencillos de usar aunque su calidad es pobre.
o Son un sistema barato y rápido de añadir sonido a tus proyectos.
o Hemos planteado unos primeros pasos en generación electrónica de sonido.Si
tenemos ocasión dedicaremos algún otra sesión a la generación de sónidos
electrónico y MIDI.

ARDUINO Y FOTOSENSORES
LDRS
Fotoresistencias y divisores de tension

Objetivos

o Un componente simpático, el LDR.


o Los divisores de tensión.
o Un theremin sensible a la luz.

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo de Arduino.

Una Protoboard.

Cables de Protoboard.

Una resistencia de 330 Ohmios.

Una fotorresistencia o LDR

Los fotosensores

Una fotorresistencia o LDR (Light Depending Resistor, o resistencia dependiente de la luz) es un


componente fotoelectrónico cuya resistencia varía en función de la luz que incide en él. Esta
resistencia es muy baja, de unos pocos Ωs con una luz intensa incide en él y va creciendo
fuertemente a medida que esa luz decrece.

Se les suele utilizar como sensores de luz, para arrancar luces automáticamente cuando la oscuridad
sobrepasa un cierto umbral, o como detectores de movimiento próximo ( Cuando algo se interpone).

Vamos a utilizar en esta sesión un típico LDR, que es bastante fácil de conseguir y es sensible a los
cambios de luz ambiente. Montaremos un circuito con un LDR y el zumbador que vimos en la
última sesión, para construir un theremin rudimentario, que espero que os haga pasar un rato
entretenido.

Un theremin es un sintetizador rudimentario que genera audio variable de espectro continuo,


analógico, en función de una señal de control (No os asustéis, que es una tontería).

El circuito utiliza un LDR como señal de control y calcularemos una frecuencia en función de la
caída de tensión que leamos en nuestra fotorresistencia.

 Recordad que los convertidores ADC como los de Arduino no pueden leer resistencia sino
tensión.
 Los LDR no son precisamente rápidos en reaccionar a la luz, y puedan tardar hasta algunas
décimas de segundo en reaccionar. Esto no es importante para una alarma de luz, pero hace
imposible que se puedan utilizar para enviar información mediante la luz.

Pero antes de entrar en materia necesitamos hacer un inciso para conocer lo que es un divisor de
tensión.

Divisores de tensión

Hablamos en su momento de la ley e Ohm:

V=R*I

Pero no hablamos de cómo se combinan las resistencias y ha llegado el momento de hacerlo, para
desesperación de los que odian las mates.

Podemos combinar un par de resistencias R1 y R2 de dos maneras. En serie y en paralelo:

EN SERIE EN PARALELO
EN SERIE EN PARALELO

Cuando ponemos las dos resistencias en serie, la resistencia resultante es la suma de ambas:

Y cuando las ponemos en paralelo, podemos calcular la resitencia equivalente así:

Imaginemos ahora un circuito como este:

Como las resistencias están en serie el valor total es R1 + R2. Si Vin es de 5V la intensidad que

circulará por el circuito será:


La pregunta del millón ahora es ¿Si medimos entre las dos resistencias cuanto es Vout? Pues igual de
fácil :

Si todavía queda alguien despierto, se habrá dado cuenta que si R1 y R2 son iguales Vout será
exactamente la mitad de Vin pero si R1 o R2, fuese un potenciómetro (o un LDR) cualquier variación
en el ajuste, causaría una modificación en el valor de salida de tensión Vout.

Esto es lo que se conoce como un divisor de tensión y es un circuito de lo más práctico para rebajar
una señal de entrada, y podéis apostar a que lo usareis mas de una vez.

Por ejemplo, los convertidores analógicos de Arduino aceptan un máximo de 5V, pero muchas
señales industriales son de entre 0 y 12V.Si lo conectas sin más al A0, por ejemplo, freirás el chip de
largo.

Pero con el truco del divisor de tensión y calculando adecuadamente las resistencias (Que sí, que tú
puedes con lo que hay en la página anterior) puedes adaptarlo tranquilamente para que tu Arduino
viva feliz con una señal que originalmente le hubiera chamuscado.

Los divisores de tensión son un circuito muy sencillo y que conviene que sea parte de vuestro
arsenal electrónico. Resuelven cantidad de problemas con una resistencia y un potenciómetro y son
ideales para tratar señales, que por exceso de tensión, quedarían fuera del alcance de tu Arduino.

De hecho en esta práctica vamos a montar un divisor de tensión con una resistencia y un LDR y
leeremos la caída de tensión en él. Nos va a servir como ejemplo de los divisores de tensión y
además nos servirá como señal de control para calcular la frecuencia a la que haremos vibrar el
buzzer.

El circuito para un theremin óptico

Aunque el titulo impresiona, lo reconozco, el circuito no es para tanto:


Fíjate que el LDR R1, junto con R2 forma un divisor de tensión. La lectura de A0 dependerá de la
luz que incida en el LDR. El esquema de protoboard es igual de fácil:

Vamos con el programa.

El programa es muy sencillo. Leemos la caída de tensión en A0 y lo usamos para mapear una
frecuencia entre 20 y 5.000 Hz para llamar a la función tone() y eso es todo.

const int pinBuzzer = 13 ;

void setup()
{

pinMode (pinBuzzer , OUTPUT) ;

void loop()

int p = analogRead(A0) ;

int n = map (p, 0,1024, 20, 5000) ;

tone ( pinBuzzer, n) ;

 Para probar el circuito os recomiendo que pongáis un foco potente a 50 cm por encima del
LDR y probéis a mover la mano por delante y especialmente de arriba abajo y viceversa.
 Escuchareis un tono continuo más o menos agudo, que ira variando su frecuencia en función
de la luz que incida en el LDR.
 Se acepta que el oído humano se mueve ente 20 Hz y 20Khz (aunque esto es para algún
adolescente de oído muy fino) para los que peinan canas entre 40Hz y 10Khz ya es un rango
optimista. Por eso, mapeamos los valores del potenciómetro, que van de 0 a 1024, entre 20 y
5Khz, pero os recomiendo que cambiéis estos valores y veáis lo que pasa.

Aqui teneis un pequeño video con el resultado

Creo que convendréis conmigo, en que ha sido tan fácil, que no puedo dejaros marchar, sin poneros
antes algún otro problema. Veamos.

El sonido que obtenemos es de espectro continuo, es decir, que reproduce frecuencias continuas
en el margen que es capaz. Pero nuestro oído está acostumbrado a escuchar las notas en tonos y
semitonos de frecuencia dada, como veíamos en el programa de las sesión 20. ¿Cómo haríais
para conseguir que el resultado de este theremin, produjera, las notas que definimos allí?

Podrá ser algo asi:

const int pinLDR = 0 ;

const int pinBuzzer = 13 ;


int tono[ ] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440,466, 494};

// mid C C# D D# E F F# G G# A

void setup()

{ pinMode (pinBuzzer , OUTPUT) ;

void loop()

int p = analogRead(A0) ;

int n = map (p, 500,1024, 0, 12) ; // Ell array solo tiene 12 notas

tone(pinBuzzer, tono[n]);

delay(300);

He usado un array con las frecuencias temperadas de una octava. Después, mapeamos las
lectura de la puerta A0 a un entero entre 0 y 12, porque el array e arriba solo tiene 12 notas, y
usamos su valor para leer la frecuencia correspondiente.

En mi caso, además, A0 solo daba valores entre 500 y 1024, así que por eso he corregido la
escala. Por último el delay impide que el cambio de notas sea instantáneo, porque de lo
contrario no notaríamos mucho cambio el programa anterior.

Resumen de la sesión

o Hemos presentado las fotorresistencias o LDRs.


o Presentamos los divisores de tensión.
 Que utilizaréis más de una vez en vuestros circuitos.
 Los usamos para rebajar niveles de tensión en señales de entrada y como
adaptadores para leer caídas de tensión resistencias variables .

o Vimos como montar un theremin óptico


ARDUINO Y LOS SHIFT
REGISTERS
El registro de desplazamiento 74HC595

Objetivos

o Presentar los shift registers, o registros de desplazamiento.


o Mostrar como ampliar el número de salidas de Arduino.
o Conocer un chip muy práctico: el 74HC595.

Material requerido.

Arduino UNO o equivalente.

Una Protoboard más cables.

8 diodos LED y 8 resistencias de 330Ω.

Un chip 74HC595. Comprobad el rotulo del lomo.


El problema del número de pines de salida

Ya sabemos que Arduino UNO dispone de 14 pines digitales que podríamos usar para entrada y
salida y que además disponemos de 6 puertas de entrada analógicas de A0 hasta A5. Lo que no suele
ser muy conocido es que las puertas analógicas también se pueden usar como pines digitales en caso
necesario. Podemos leer y escribir valores digitales exactamente como lo hacemos con los pines
digitales normales:

pinMode (A1, OUTPUT) ;

Y después escribir tranquilamente:

digitalWrite(A1, HIGH) ;

Nuestras puertas analógicas se comportarán gentilmente como puertas digitales (Si, también
podemos hacer lo mismo para la lectura). Os animo a que hagáis el blinking LED con una puerta
analógica.

 Aqui teneis que hace el parpadeo de un LED con la puerta A1 Blinking LED y el
Prog_20_2 que lee en digital el pin A1 Lectura digital

Así pues, en realidad, disponemos de 20 puertas digitales para nuestras cosas. Pero en la vida de
toda persona, siempre hay un momento en que esto nos suficiente.

Podemos pasarnos a un Arduino Mega que con 54 pines digitales más 16 puertas analógicas hacen
el impresionante numero de 60 puertas disponibles. Pero al final, la combinación entre la ley de
Murphy y la segunda ley de la termodinámica (La de que todo tiende al caos) garantizan que
aparezca alguien que quiere un cuadro de luces con 64 LEDs (o 128 ya puestos) y la catástrofe nos
acecha porque no hay Arduinos con más pines.

Afortunadamente la industria electrónica nos provee con una forma sencilla de aumentar el número
de salidas digitales de nuestros Arduinos sin demasiada complicación. Unos pequeños chips
llamados Shift Registers fáciles de encontrar como el 74HC595.

El 74HC595 es un Shift Register de 8 bits serial-in, parallel-out, pertenece a una familia de chips
que aceptan una entrada de bits en serie y los sacan en 8 pines paralelos. Solo sirve para escribir
señales digitales y no para leerlas.

 Si lo que necesitas es aumentar los pines digitales de entrada, prueba a usar 74HC165 que
es un shift register de entrada
 Si lo que necesitas es aumentar los pines analógicos puedes usar un multiplexor /
demultiplexor como el 74HC4051.
Aunque ahora todo parezca un poco confuso (no me extraña) son bastante sencillos de manejar una
vez que entiendes lo que hacen y son sorprendentemente útiles en cantidad de situaciones.

Como funciona un Shift Register

En la Sesión 7 vimos que para comunicar dos puntos con una conexión serie necesitábamos pactar
una velocidad de envío para saber cuándo hay que leer los datos que llegan.

A este sistema le llamamos comunicación serie asíncrona porque la sincronía va implícita en la


velocidad. Un Shift Register funciona mediante la comunicación serie síncrona. Es decir que
usamos un pin para enviar los bits en serie (el Data pin) y usamos un segundo pin (el Clock pin)
para indicar cuando hay que leer el bit.

Cuando los 8 bits se han leído en el registro un tercer pin (Latch pin) escribe estos bits en los pines
de salida del chip y los mantiene hasta que se reciban nuevos datos.

Fíjate en el gráfico superior. Nuestro Arduino envía la señal de Clock Pin de modo regular para
indicar cuando hay que leer (Se lee en el flanco de subida, cuando Clock sube de 0 a 1).

A medida que Arduino va poniendo valores en el Data Pin(DS), el chip los va leyendo en el flanco
de subida del Clock pin y por eso va a ir leyendo 1 1 1 0 0 0 1 1 sucesivamente.

Cada uno de estos valores se van pasando en orden a los pines de salida de Q0 hasta Q7, pero aún no
se activan. Cuando el Latch Pin se activa (también por flanco de subida) los valores pasan a los pines
de salida y se memorizan.

Vamos a montar un circuito que use estas salidas para gobernar un conjunto de 8 LEDs, usando solo
3 pines de Arduino que corresponden a Clock, Data y Latch.
Diagramas del circuito

Vamos con el esquema por cortesía de Fritzing:

Y aquí tenemos el esquema de protoboard.

El Programa de escritura en el 74HC595

Vamos a empezar con las definiciones de pines lo primero: Descargar:


int latchPin = 8 ; //Pin conectado a ST_CP of 74HC595 (Verde)

int clockPin = 12; //Pin conectado a SH_CP of 74HC595 (Amarillo)

int dataPin = 11; //Pin connected to DS of 74HC595 (Azul)

Y despues el setup
void setup()

{ pinMode(latchPin, OUTPUT);

pinMode(clockPin, OUTPUT);

pinMode(dataPin, OUTPUT);

Las comunicaciones síncronas son tan frecuentes, que nuestro Arduino las soporta de fábrica con
una serie de funciones. La que nos interesa, se llama shiftOut(). (Podeis Goglear el manual) Para
iniciar la comunicación síncrona basta poner el Latch en LOW

DigitalWrite(latchPin, LOW);

Y ahora enviar los 8 bits llamando a shiftOut() y pasándole que pines usamos para Data y Clock
además indicándole el valor que queremos enviar a la salida:

shiftOut(dataPin, clockPin, MSBFIRST, Num) ;

 Lo de MSBFIRST significa Most Significant Bit First, o sea, enviar el número binario
empezando por la izquierda. También podría ser al revés como LSBFIRST (Least
Significant Bit First) . Solo es una forma de que los informáticos se hagan los interesantes y
en este caso nos da absolutamente lo mismo.

Y por último fijar los valores en la salida poniendo HIGH el Latch de nuevo.
void loop()

for (int Num = 0; Num < 256; Num++)

digitalWrite(latchPin, LOW) ; // Latch a LOW para que no varíe la


salida

shiftOut(dataPin, clockPin, MSBFIRST, Num); // Aqui va Num


digitalWrite(latchPin, HIGH) ; // Latch a HIGH fija valores en la
salida

delay(500);

Veremos que los LEDs irán contando mostrando los valores de Num en binario. Aquí tenéis otro
ejemplo con este mismo circuito en el que leemos la puerta serie para recibir un número entre 0 y 9 y
lo pasamos a los pines LEDs de salida: https://www.youtube.com/watch?v=7lk-gNXV1Y0

Más sobre los shift registers

Una curiosidad del 74HC595, es que si le metemos un tren de más bits de los 8 que puede
almacenar, sencillamente los va empujando hacia la salida por su pin 9 (que os habréis fijado no
hemos utilizado en el ejemplo anterior) y los va dejando caer al olvido.

Pero si conectamos este pin 9, al pin 14 de entrada de datos de un segundo chip 74HC595, y
compartimos entre ellos el Clock y el Latch, en lugar de caer en el olvido entrará en el siguiente
chip de la cadena y seguirá en el juego.

Hemos conseguido una ampliación de otras 8 salidas digitales sin utilizar pines adicionales de
nuestro Arduino. Y naturalmente una vez visto el truco, no hay límite en principio al número de
chips que podemos concatenar.

Si ese que quería un cuadro de luces de 128 LEDS vuelve, lo podríamos arreglar con 128/8 = 16
chips. O si preferís, también existen estos chips en 16 bits: SN74LS674, 74F675A que son 16-Bit
Serial-In, Serial/Parallel-Out Shift Register, y lo arreglaríamos con solo 8 chips.

Y ya que estamos ¿Existen Shift registers de 32 o de 64 bits? Pues sí.

Si buscáis en internet encontrareis que existe casi cualquier cosa que os imaginéis en chips digitales,
pero tomároslo con precaución porque mientras que un 74HC595 lo compras por 1€, el SN74LS674
de 16 bits se va a 4€ y los demás no he mirado pero me lo imagino.
Resumen de la sesión

o Hemos visto que los pines analógicos también se pueden usar como digitales.
o Hemos presentado nuestro primer chip comercial, el 74HC595, que es un shift
register serial-in, parallel-out de 8 bits, y que se puede conectar en cascada.
o Hemos apuntado muy brevemente a que existen otros chips en el mercado,
literalmente miles o decenas de miles.
o Vimos la diferencia entre comunicación serie asíncrona y síncrona y vimos un
ejemplo de cómo se sincronizan los datos.
o Hemos conocido otra función de Arduino shiftOut().
ALGUNAS IDEAS BÁSICAS
DE INFORMÁTICA
Los sitemas de numeración binariio, decimal y hexadecimal

Objetivos

o Presentar otros sistemas de numeración como el binario y el hexadecimal.


o Mostrar las razones que los soportan.
o Conocer de dónde viene la terminología informática.

Material requerido.

Paciencia y 20 minutos de sobra.

El problema

En la sesión anterior presentamos un circuito con un Shift Register para gobernar 8 salidas digitales
(o más) con solo 3 pines de Arduino y montamos un circuito de 8 LEDS y un primer programa en el
que iterábamos un número de 0 a 255 y cada vez lo enviábamos a la salida del registro.

Vagamente dijimos que los LED irían contando en binario y mostrando esos valores en el circuito.
Pero hasta ahora no hemos hablado en absoluto de que es el sistema binario o porque construimos
ordenadores basados en él. ¿Es que nuestro viejo y familiar sistema decimal no es lo bastante
bueno para los informáticos? ¿Se trata de una conspiración internacional para torturar a los
estudiantes de informática, o para defender, los inconfesables intereses de las universidades de
ciencias?

En mi experiencia, la gente que ha estudiado electrónica digital o informática, suele tener unas ideas
más o menos claras de estos temas, pero el resto de universitarios y de gente más joven, rara vez
tienen una comprensión mínima básica a pesar de que vivimos un mundo en el que a diario
manejamos tecnología y términos informáticos sin tener un mínimo de comprensión de la base en
que se apoya.

Como en estos tutoriales pretendemos no dar por supuesto ningún conocimiento previo, ha llegado el
momento de introducir algunos conceptos e ideas básicas sobre tecnología digital.

Somos muy conscientes de la desbandada que semejante pretensión puede producir entre los
esforzados seguidores de estos tutoriales, así que vamos a prometerles en primer lugar, que
trataremos de hacerlo fácil y hasta agradable y en segundo lugar que merece la pena, porque no se
puede entender la tecnología moderna sin unas nociones mínimas de sus fundamentos lógicos.

El sistema decimal

Estamos tan acostumbrados al sistema decimal, que cualquier idea de que se pueda usar otro, al
principio suena absurdo o hasta malintencionado. Y sin embargo este es solo uno más entre un
ilimitado número de posibilidades.

Desde pequeños, los colegios nos han entrenado en su uso y al final lo tenemos tan interiorizado que
sencillamente, hemos incluso olvidado las reglas básicas que aplicamos, simplemente lo hacemos y
ya está.

Vamos atener que recordar esas reglas. La primera es que se llama sistema decimal porque
utilizamos diez dígitos, del 0 al 9 (No señor, no usamos del 1 al 10). ¿Por qué?

Pues, probablemente, porque tenemos 10 dedos en las manos, y recordemos que las manos fueron la
primera calculadora. De hecho a la representación simbólica de un numero la llamamos digito que
viene del latín digitus (dedo), (y por eso tendemos a pensar que usamos del 1 al 10…dedos), porque,
aunque hemos asumido el sistema de numeración que nos enseñaron de niños, no es fácil
comprender el salto conceptual que significa representar nada con un 0. Y esta es la clave.

Los antiguos griegos y romanos, por ejemplo, tenían un sistema de numeración que funcionaba
malamente, y que era demencial porque no era posicional sino simbólico, y además no incluía ni la
noción ni la notación del 0. Sumar ya era complicado pero multiplicar o dividir era casi imposible.

Hizo falta que surgiera un matemático indio, allá por el siglo 3, que comprendió el concepto del 0 y
su importancia como digito, y estableció el primer sistema de numeración moderno.

Desde allí pasaron a los árabes, grandes comerciantes, que enseguida comprendieron la ventaja de
esta numeración para sus negocios( Pues cuando hay por el medio piastras o euros el ingenio se
agudiza mucho), y a través de los árabes llegaron a occidente en épocas muy posteriores y con la
notación actual que nos es familiar. Por eso quizás hayáis oído decir que en occidente usamos los
números arábigos.

¿Qué reglas aplicamos para contar? (Lo domináis, lo sé, pero recordemos el procedimiento). Pues
solamente dos:

 Primera: usamos los números en orden creciente 0, 1, 2,3,….9 y cuando se nos acaban los
dígitos de base volvemos a 0 e incrementamos en 1 el digito a la izquierda, aplicando la
misma regla.
 Segunda: Si no hay ningún digito a la izquierda entendemos que es un cero y aplicamos la
regla primera para incrementarlo.

Así pues, el siguiente al 9 va a ser un 0 a la derecha (ya que el siguiente al 9 es 0) y a la izquierda


como no hay nada lo consideramos un 0 que al incrementarlo deviene en un 1, o sea el 10. Lo
siguientes números son fáciles:
11, 12,13,….. 19

El siguiente a 19 se obtiene de volver a cero la posición del 9 y aplicar la regla al 1 à 2

20, 21,22…..29

……………

90, 91,92…..99

¿Qué ocurre ahora? Pues lo mismo. Aplicamos la regla primera al 9 de la derecha, 9 à 0, e


incrementamos el 9 a su derecha, 9 à 0 y aplicamos la regla al inexistente cero a la izquierda que
deviene en 0 à 1. Por tanto el siguiente número es el 100. Este es un procedimiento para crear
números ilimitadamente grandes y que simplifica enormemente el cálculo.

Pero la elección de 10 dígitos como sistema de numeración es una decisión arbitraria (que por cierto
no ha sido la única en la historia de la humanidad) y no está justificada por ninguna razón lógica. Es
simplemente una costumbre.

Y como los matemáticos son gente que odia las cosas sencillas, a la que les gusta complicarse la vida
y amargárnosla a los demás, empezaron a hacerse preguntas del tipo ¿Existe algún límite, superior o
inferior en el número de dígitos de un sistema de numeración? ¿Son equivalentes? ¿Se puede
traducir de un sistema de numeración a otro? Y aquí es donde se abrieron las puertas del infierno (o
del paraíso digital, según se mire).
El sistema binario

El sistema más sencillo de numeración que podemos organizar se llama binario y contiene solo dos
dígitos: 0 y 1. Con este sistema se puede escribir cualquier número por ilimitadamente grande que
sea y se puede además contar, calcular y hacer cualquier cosa que se pueda hacer es el sistema
decimal, sin excepción.

¿Cómo contamos con un sistema tan raro? Pues en realidad, aplicando exactamente las mismas
reglas que con el decimal, pero limitados a dos únicos dígitos:

Al cero le sigue el 1, y el siguiente al 1 es 0, y aplicábamos la regla al inexistente 0 a la izquierda

Así que los primeros números contados en binario serian:

0 - 0

1 - 1

10 - 2

11 - 3

100 - 4

101 - 5

110 - 6

111 - 7

1000 - 8

La notación binaria hace que la representación sea mucho más larga ¿y qué?, pero no tiene otro
inconveniente. Además las reglas para sumar y multiplicar harían las delicias de los escolares.

PARA SUMAR SOLO HAY: LAS TABLAS DE MULTIPLICAR SON:

0+0=0 0*0=0

0+1=1 0*1=0
PARA SUMAR SOLO HAY: LAS TABLAS DE MULTIPLICAR SON:

1+0=1 1*0=0

1 + 1 = 0 y me llevo una. 1*1=1

Y ahora viene la cuestión clave, ¿Por qué usar el sistema binario en los ordenadores en lugar del
familiar sistema decimal?

Pues sencillamente por una cuestión e tecnología: No disponemos de ningún material que presente
10 estados diferenciados estables que podamos utilizar como fundamento para la construcción de
ordenadores decimales.

Pero sin embargo, si disponemos de materiales (los semiconductores) que presentan dos estados
estables fácilmente diferenciables, los semiconductores nos permiten construir transistores que
mediante una señal de control en la Base, permiten la conducción entre emisor y colector( cuando
funciona en saturación) o la corta por completo ( cuando funciona al corte).Y es esto lo que
reconocemos como 0 y 1.

O lo que es lo mismo con un 1 en la base (HIGH o 5V) podemos leer la tensión de salida como un 1
o HIGH. Y para un LOW en la base leeremos un LOW en la salida del transistor. Construimos
computadores binarios porque disponemos de una tecnología estable que se presta a ello.

¿Es el sistema binario superior, o mejor que el decimal, en cualquier aspecto retorcido de la teoría
de algo? Para nada, son completamente equivalentes.

¿De disponer de una tecnología con 10 estados estables, que nos permitiera construir ordenadores
basados en el sistema decimal, seguiríamos usando el sistema binario? Ni hablar, y el binario se
relegaría a las escuelas de historia solamente (y a los matemáticos claro).

 Muy a principios del siglo 19, Charles Babbage ya construía maquinas mecánicas en
Inglaterra, que calculaban basados en una lógica parecida, pero la tecnología disponible
entonces solo permitía usar la mecánica y lamentablemente la velocidad de computo que se
obtenía era un asco comparado con la electrónica actual.
 De hecho es factible construir computadores con engranajes mecánicos, sistemas
neumáticos, relés y hasta grifos de agua, pero el coste y la velocidad de cómputo que se
obtiene no compensan el esfuerzo.
Aunque IBM ya construía computadoras e los años 40 del siglo 20, eran caras y problemáticas
porque se construían a base de válvulas termoiónicas de vacío ( las famosas lámparas, o válvulas de
la radio de la abuela). Fue con el advenimiento del transistor en 1947 (que supuso el Nobel de
física para sus descubridores) que empezó la carrera tecnológica actual.

Al principio los transistores se fabricaban de uno en uno, pero la gente (que no es tonta), en seguida
se dio cuenta de que podía fabricar varios transistores en una oblea de silicio, interconectados entre
sí, además de todos los componentes necesarios para integrar un circuito electrónico en un único
chip.

Y aquí empezó una carrera por ir metiendo más transistores y más componentes en un chip. Montar
las fábricas es caro pero lo que fabricas es casi gratis. (El Silicio sale de la arena de playa) así que
cuanto más componentes integras, más cosas hace el circuito y más caro se puede vender.

A finales de 2014, el circuito comercial que más transistores integra es un procesador de Intel con
alrededor de 4.300.000.000 transistores (Si, está bien, Unos cuatro mil trescientos millones).

Y para cerrar este capítulo mencionaremos que la famosa ley de Moore dice que el número de
transistores que somos capaces de integrar en un chip se dobla cada dos años (más o menos) y que se
ha cumplido bastante fielmente en los últimos 50 años, aunque parece haber dudas de que esto vaya
a seguir siendo así.

Otros sistemas de numeración

Si alguien pensaba que una vez establecido el sistema binario además del decimal, los matemáticos
nos iban a dejar en paz de una vez, se ve que es nuevo y no conoce a esa gente.

En computación se utiliza también la notación octal y la hexadecimal. En los que respectivamente


se utilizan 8 dígitos (del 0 al 7) y 16 respectivamente.

Un momento ¿16? ¡ Si no hay tantos números ! ¡Pues se inventan los que haga falta!

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

 Os acordáis de que cuando vimos la sesión del keypad matricial, contenía todos esos
símbolos? ¿Creíais que era casualidad?
 Vuestro humilde Duino, soporta todos estas notaciones de números, y ya buscaremos algun
ejemplo para ilustrarlo.
¿Porque usar otro par de sistemas de numeración tan extraños? Porque son potencias de 2, 23 y 24, y
son especialmente fáciles de pasar de uno al otro, especialmente al hexadecimal

Ignoraremos el octal, porque se usa más bien poco, pero el hexadecimal, sí que se usa bastante. Para
entender porque, tenemos que dar un rodeo.

En el sistema decimal, a llamamos dígitos a cada uno de los símbolos que representan los números
de la base aunque su nombre correcto sería digito decimal.

En el sistema binario llamamos dígitos binarios a cada uno de sus símbolos 0 y 1, en inglés se dice
BInary digiT, o sea bit, una de las palabras mágicas de la informática.

En el sistema decimal, de un numero como 4.327 decimos que tiene cuatro dígitos y en el sistema
binario de algo como 1100 0101 decimos que es de 8 dígitos, o sea de 8 bits.

En el mundo real, además de los diez dígitos usamos veintitantas letras mayúsculas y otras tantas
minúsculas, adema de símbolos especiales como +, -, *, /, € ….

Pero con la tecnología digital, sencillamente no hay más numero posibles,¿ Así que, como
representamos todo este caos? Pues solo hay una solución: Creando un código de representación de
caracteres, de forma que cada símbolo se represente por una combinación de bits en una tabla.

Algo que ya habíamos visto cuando hablamos en la sesión 7 del código ASCII. Lo que no dijimos
allí es que para poder representar todos los caracteres del alfabeto occidental (y reservar alguno para
sorpresas como el €) necesitamos utilizar paquetes de 8 bits porque con ello podemos codificar 28 =
256 caracteres.

Parecía que había que bautizar a los paquetes de 8 bits. Alguien dijo Byte, y mira, hasta hoy.

Así que un bit es un simple digito binario y la información que puede codificar es 0 o 1. Es difícil
codificar un elemento de información más pequeño.

 Si alguien piensa que solo con el 1, sería menor, se olvida de que no hay manera de librarse
del 0 y con un solo dígito, todos los números serian iguales, piénsalo, habríamos vuelto a las
cavernas, poniendo un palito por cada bisonte.
Un paquete de 8 bits, que puede llevar información de texto codificada se llama byte. Pero con la
tecnología moderna la capacidad de las memorias ha crecido tanto que necesitamos unidades
mayores así que tiramos del griego:

VALOR
PREFIJO VALOR EN BINARIO
DECIMAL

Kilo 103 Mil 210 = 1.024

Mega 106 Millón 220 = 1.048.576

Giga 109 Mil Millones 230 =

Tera 1012 Billón europeo 240 =

Peta 1015 250

Exa 1018 260

Zetta 1021 270

¿A que no os sabíais estos últimos?

Los prefijos decimales son las potencias de la base 10, pero por aprovechamiento, en un sistema
binario conviene usar las potencias de 2 y aprovecharnos de lo redonda que queda la numeración,
pero recordando que la Mega en binario son 1024×1024 aunque luego nadie recordemos cuanto
exactamente.

Ahora si podemos entender porque el sistema hexadecimal es útil en informática. Un carácter se


codifica con 8 bits y un número hexadecimal representa 4 bits exactamente por lo que cualquier
paquete de 8 bits se traduce en dos dígitos hexadecimales. La conversión es automática y el
empaquetado más conciso:
SÍMBOLO DECIMAL BINARIO HEXADECIMAL

A 65 0100 0001 41

B 66 0100 0010 42

C 67 0100 0011 43

D 68 0100 0100 44

Fíjate en la numeración e las primeras letras ( en ASCII). El binario corresponde a sus 8 bits y en
hexadecimal solo dos. Convertir de binario a ex consiste en tomar los números de 4 en 4 y asignar el
valor hex equivalente, para la D son dos cuatros.

 Creo que ya hemos abusado bastante de la buena voluntad de nuestros resignados lectores y
por tanto, evitaré entrar en cómo se pasa un número de un sistema a otro.

Todos los lenguajes de programación incluyen notación para introducir número binarios, decimales,
octales y hexadecimales y C++ no es la excepción. En las próximas sesiones tendremos ocasión de
verlo ( No, no es una amenaza).

Resumen de la sesión

o Hemos recordado los fundamentos del sistema decimal.


o Presentamos el sistema binario.
 Que no es mejor ni peor que el decimal, sino distinto..
 Que lo usamos porque se adapta brillantemente a la tecnología disponible.
o Para no aburrirnos, también hemos presentado el sistema hexadecimal, que se
emplea abunda mente en las ciencias de computación.
o Vimos de donde vienen los términos bit, byte, KiloByte o MegaByte.
SENSORES DE
TEMPERATURA DHT11
Sensor de temperatura y humedad

Objetivos

o Presentar los sensores DHT11.


o Mostrar como leerlos utilizando la librería de control.
o Escribir un programa básico de uso.

Material requerido.

Arduino UNO o equivalente.

Una Protoboard más cables.

Una resistencia de 330Ω.

Un sensor de temperatura DHT11.


Sensores de temperatura y humedad

En la sesion Sensor de temperatura TMP36, vimos cómo medir la temperatura con un sensor
TMP36. Es bastante sencillo y no presenta especiales problemas, mas allá de tener cuidado con las
operación con números float.

Pero en muchas ocasiones, y especialmente en la industria alimentaria, no basta con medir la


temperatura, sino que la humedad relativa es también un factor importante a tener en cuenta.

Por eso se desarrollaron los sensores de la familia DHT. Nos proporcionan de forma digital la
temperatura y la humedad, con diferente precisión según el modelo.

Básicamente hay dos variantes DHT11 y DHT22

Las características del DHT11 son:

 Muy barato, sobre 2€


 Funciona con 3,3 y 5V de alimentación
 Rango de temperatura: de 0º a 50º con 5% de precisión (pero solo mide por grados, no
fracciones)
 Rango de humedad: de 20% al 80% con 5% de precisión
 1 Muestra por segundo (No es el más rápido del oeste)
 Bajo consumo
 Devuelva la medida en ºC

En cuanto al DHT22:

 Barato, entre 4 y 5 €
 Funciona con 3,3 y %V de alimentación
 Rango de temperatura: de -40º a 125º ±0.5°C
 Rango de humedad: de 0% al 100% con 5% de precisión.
 Lee 2 veces por segundo.
 Bajo consumo.
 Devuelva la medida en ºC

En cuanto a la forma de conectarlos y programarlos es la misma para ambos modelos y veremos que
hay desarrolladas librerías para Arduino que soportan los dos de una forma sencilla.

Destacar que el chip incorpora electrónica para hacer internamente la conversión de temperatura y
humedad y nos da un valor de medida de forma digital, es decir, que no necesitamos un pin
analógico como en el caso del TMP36, sino que lo leeremos con un pin digital.
Diagramas del circuito

La conexión es trivial, pero cabe destacar que se vende en dos encapsulados, uno de tres pines que
son GND, Data y Vcc, y otro 4 pines y uno de ellos, sencillamente sobra y no se conecta.
Normalmente viene rotulado en el sensor el nombre de cada pin, y si no ya sabeis, a buscar el
manual en Google

Vamos con el esquema por cortesía de Fritzing:

Y aquí tenemos el esquema de protoboard.


El Programa de lectura del DHT11

En primer lugar, tenemos que descargar una librería para manejarlos cómodamente, DX11.zip e
importarla. Aquí teneís la librería DHT11.zip

Hacemos el importar la librería DHT11 que nos pondrá:

#include <DHT11.h>

Y definimos una instancia del sensor donde declaramos el pin al que esta conectado.

int pin=2;

DHT11 dht11(pin);

Leerlo ahora es muy sencillo:

int error ;

float temp, humi;

error = dht11.read(humi, temp)

Basta con hacer dht11.read pasandole las variables donde queremos el resultado, y comprobamos
que no haya errors (Siempre es buena idea comprobar que no hay error cuando hacemos una
llamda). El programa completo seria más o menos algo así: Prog_24_1

#include <DHT11.h>
int pin=2;

DHT11 dht11(pin);

void setup()

Serial.begin(9600);

void loop()

int err;

float temp, hum;

if((err = dht11.read(hum, temp)) == 0) // Si devuelve 0 es que ha leido


bien

Serial.print("Temperatura: ");

Serial.print(temp);

Serial.print(" Humedad: ");

Serial.print(hum);

Serial.println();

else

{
Serial.println();

Serial.print("Error Num :");

Serial.print(err);

Serial.println();

delay(1000); //Recordad que solo lee una vez por segundo

El resultado se envía a la consola y aquí podéis ver una muestra.

Para hacer variar os valores, de humedad y temperatura y comprobar que todo funciona
correctamente, podeis, sencillamente, enviar vuestro aliento al sensor, y salvo que estéis en el trópico
haréis subir tanto la temperatura como la humedad relativa.

Como vereris, son de lo mas sencillos de utilizar y un componente habitual de vuestro arsenal de
sensores

Resumen de la sesión

 Hemos visto los sensores DHT11, y montado un circuito de prueba con el


 Los DHT22, usan el mismo circuito y pines, pero su resolución y velocidad es bastante
mejor, aunque para muchas aplicaciones el DHT11 es mas que suficiente.
LOS MODELOS DE ARDUINO
Procesadores y tipos de memoria de Arduino

Objetivos

o Conocer los modelos básicos de Arduino y sus características.


o Comprender los PICs.
o Mostrar los diferentes tipos de memorias disponibles.
o Aprender a usar la memoria EEPROM interna sin miedo.

Material requerido.

Paciencia y 20 minutos de sobra.

De los modelos de Arduino y sus características.

Ya es hora de que empecemos a hablar de los diferentes modelos de Arduino disponibles, y en qué
consisten sus diferencias. Pero para comprenderlas correctamente, necesitamos conocer, además los
diferentes procesadores y lo que les diferencia, así como las memorias de que cada modelo dispone,
el tipo y su cantidad.

Y como este es un curso pensado para iniciarse desde cero, ha llegado el momento de hacer un
pequeño resumen de procesadores y memorias, sus diferencias y el porqué de unas y otras. Poneros
cómodos.

Haciendo un poco de historia (poco, tranquilos), el primer micro procesador con derecho a llamarse
así, fue el Intel 8080 allá por los finales de los años 70.

Fue el primer chip, que integraba todo lo necesario para construir una unidad central de proceso (o
CPU por sus siglas en ingles), en un único chip, y a su alrededor se construyeron los primeros
ordenadores personales sin más que añadir memoria y elementos de entrada /salida).
Para no ponerme pesado, diré simplemente, que aquel modelo basado en CPU, memoria e I/O (Input
Output) ha seguido vigente hasta hoy, en lo que conocemos como PCs.

Los números han crecido exponencialmente, claro, pero el modelo conceptual sigue siendo el
mismo, desde el 8080 hasta los modernos Intel I7.

MODELO IBM PC 1981 INTEL I7 MULTIPLICADOR

Velocidad reloj 8.8 MHz 2.4 GHz x300

Memoria RAM 128 kB – 640 kB 4 Gb – 64 Gb x2.000

Disco duro 500 kB 4 Tb x2.000.000

Bus datos 8 64 x8

Los procesadores han tenido un periodo de expansión infinita, pero siguen teniendo los mismos
problemas que el primer día:

 No tiene conexión, ni influencia en el mundo físico. ¿Te imaginas encender unos LEDs, o
mover un motor con tu PC? No es imposible, pero no sabríamos por dónde empezar.
 Podemos guardar datos en los cada día más enormes discos duros, pero los programas deben
ejecutarse desde memoria RAM, y esto ha sido un cuello de botella, con los modernos
sistemas operativos como Windows u OSX, que devoran ansiosamente, cuanta memoria
tengas instalada.
 En cuanto pierdes la alimentación, la RAM vuela y tus datos salen por el desagüe, si no has
tenido la precaución de salvar a disco periódicamente.
 Los microprocesadores modernos se han diseñado para ser rapidísimos haciendo cálculos
complejos, y han alcanzado una capacidad tal, que sencillamente hace mucho que se
sobrepasó lo que un usuario normal necesita, y les ha costado algunos años darse cuenta.

Entre tanto y en paralelo, pequeños fabricantes, a los que difícilmente conoce el público, han ido
generando pequeños procesadores, menos ambiciosos, pero más dirigidos a resolver un tipo de
problemas que Intel, AMD y alguno otro ignoraban. (Evito conscientemente el tema de los
procesadores de teléfonos móviles, porque abriríamos una puerta que se sale de lo que nos atañe
ahora mismo)

Es lo que se ha dado en llamar la computación física, en la que el resultado del cálculo no es solo un
resultado numérico, sino una operación física que se traslada al mundo real.

Uno de esos fabricantes es ATMega, y nuestros Arduinos están construidos a partir de uno de sus
procesadores: UN AT328 para el Arduino UNO. Y que se vende en dos encapsulados:

Podéis encontrar Arduinos UNO con ambos modelos y su única diferencia es el encapsulado plástico
que los recubre, aunque el del primer tipo se suele montar en un zócalo, para poderlo reemplazar
cuando le hagáis algo que no deberías.

 En una sesión futura tengo previsto que montemos un Arduino en una protoboard, para que
veáis lo sencillo que es.

Sus especificaciones técnicas son en principio modestas, comparándolos con los últimos
procesadores de Intel,

Un procesador de 8 bits,16 MHz de reloj,32k de memoria FLASH y algo de memoria SRAM, 2K


mas 1.024 posiciones de memoria EEPROM (Ahora entendéis porque vamos a tener que hablar de
los tipos de memoria).

Pero tienen la curiosidad de incorporar pines digitales que pueden sentir y comandar el mundo
exterior, (a los que los seguidores de estas sesiones están ya más que habituados) además de
convertidores analógicos a digital (ADC)

Es la mezcla de estas características la que le dan a los procesadores como el de nuestro Arduino
(a los que por cierto se les llama PICs), la capacidad que muestran. Son ordenadores completos,
con procesamiento, memoria y entrada y salida. No demasiado potentes pero que pueden hacer
trabajos periféricos, para los que las grandes estrellas de Intel o AMD, no disponen de recursos.
Enseguida hablaremos de los diferentes procesadores de nuestros modelos de Arduino, pero antes
tenemos que hablar de memoria.

Tipos de memoria de ordenador

Es un modelo útil imaginar la memoria del ordenador, como en una hilera de cajas o cajones, todos
del mismo tamaño que están numerados de 0 a la n, donde n es el tamaño de nuestra RAM. Cuando
enciendes el ordenador lo primero que hace nuestra CPU en cuanto se despierta es salir corriendo al
cajón 0, ver que instrucción tiene allí y ejecutarla. Después con el deber cumplido salta al siguiente
cajón, el 1, lee la orden y la ejecuta, después salta al cajón 2 y……

Las primeras instrucciones que tiene en el cajón 0, se llaman boot strap (que es algo así como el
cordón de arranque de un motor), en nuestro caso son las instrucciones que le enseñan a interpretar
el modelo Arduino, para aceptar nuestros programas. Cuando termina con esto, el boot strap le dirige
directamente a nuestras instrucciones y por eso los ordenadores ejecutan las órdenes en secuencia,
porque sencillamente no saben hacerlo de otro modo, a no ser que nosotros les ordenemos saltar a
otros cajones en función de las condiciones que les especifiquemos.

En los primeros ordenadores, solo había dos tipos de memoria: RAM y ROM, pero ya sabéis que las
cosas tienden al caos y las todo se han ido complicando desde entonces.

Todo lo que ejecutamos en nuestros PCs debe estar almacenado en memoria RAM o Random
Access Memory. Se suele traducir por memorias de acceso aleatorio. . Se pueden leer y escribir (lo
ideal, vamos) pero tienen la mala costumbre de borrase cuando les quitan la corriente.

Cuando arrancas tu PC ya sabe hacer algunas, como leer el boot strap y por tanto, esto no puede
estar en RAM (Se habría perdido al apagar), eso está en ROM.

Las memorias ROM, o Read Only Memories, como su nombre indica son de solo lectura y no se
pueden escribir más que por el fabricante cuando las construye.

Tradicionalmente una sabia combinación de memorias RAM y ROM han permitido todo el
desarrollo de la microinformática, pero pronto empezaron las variedades:

MEMORIA CARACTERÍSTICAS

RAM Se pueden leer y escribir pero son volátiles


MEMORIA CARACTERÍSTICAS

Dynamic Random Access Memory,Son las memoria típicas de los PCs. Se construyen
a base de condensadores y se pueden integrar cantidades ingentes de ellas en un único
DRAM chip de forma barata.A cambio tiene que ser refrescadas cada poco, lo que complica
el diseño con mecanismos de refresco de la memoria ( Por supuesto fuera de los ojos
del orgullosos propietario)

Synchronous Dynamic Random Access MemoryComo las DRAM, pero el


SDRAM
mecanismo de refresco es síncrono

Double Data Rate Synchronous Dynamic Random Access Memory.Estas son las
DDR actuales memorias utilizadas en los PCS de sobremesa. Actualmente están en la
versión DDR4

ROM Read Only Memory, son no volátiles, pero solo se pueden leer, no escribir.

Programable Read Only MemoryNo son volátiles y se pueden escribir y reescribir en


PROM
unos equipos especiales. Hoy prácticamente están en desuso

Electically Erasable Programable Read only MemorySon igual que las PROM, pero
con la curiosidad que se pueden reescribir eléctricamente lo que evita el engorro de
EEPROM
llevarlas a reprogramar a maquinas raras.A cambio son lentas de escribir y tienen un
número limitado de escrituras antes de morir.

Es un derivado de la EEPROM, con varias ventajas, la principal es que no pierde la


información cuando le quitamos la corriente y además pueden leerse y escribirse
FLASH
sobre la marcha.El inconveniente es que son lentas. Es la clase de memoria que se
utiliza para fabricar las memorias USBs pendrives y demás

Después de esta ensalada de siglas, ya podemos volver al tema de modelos y características de


nuestros Arduinos.
ARDUINO UNO MEGA DUE

Procesador ATMEGA 328 ATmega2560 Atmel SAM3X8E

Anchura 8 bits 8 bits 32 bits

Velocidad 16 MHz 16 MHz 84 MHz

Pines digitales 14 54 54

Pines PWM 6 16 12

Convertidores ADC 6 16 12

Convertidores DAC 0 0 2

Interrupciones 2 24

Memoria FLASH 32Kb 256Kb 512Kb

SRAM 2Kb 8kb 96Kb

EEPROM 1Kb 4kb 0


ARDUINO UNO MEGA DUE

Tenéis que saber que nuestros programas se graban en la memoria Flash (que es bastante lentora de
escribir), pero las variables que definamos en nuestro programa se guardan en memoria SRAM (que
es mucho más rápida para escribir en ella)

Por eso, nuestro familiar Arduino UNO, se os va a quedar corto enseguida porque va muy escaso de
memoria. En cuanto empecéis a incluir librerías en vuestros programas el margen de memoria flash
se reducirá peligrosamente y entre tanto, la parte de SRAM dedicada a manejar las variables se
puede llenar con facilidad, sino controláis los tamaños de estas o de los arrays que creéis.

De hecho, quizás no os hayáis fijado, pero cada vez que compiláis y volcáis un programa vuestro
Arduino, el IDE os informa de como andáis de memoria, de uno y otro tipo:

Así que, a medida que vuestros programas y proyectos vayan creciendo es interesante que tengáis
en reserva un Arduino Mega para lo que sea menester. Que desde luego, es el siguiente Arduino que
os interesa añadir a vuestra colección.

¿Por qué un Mega y no un DUE?

Porque el DUE es una bestia de carga muy sexy, pero el inconveniente de que funcione a 3,3V le
coloca en un una especie de tierra de nadie y no es fácil de recomendar sin saber exactamente su
destino, porque si no, puede tener más inconvenientes que ventajas.
Si necesitas potencia de cálculo, para procesar audio, hacer transformadas de Fourier FFT, o filtros
digitales, en los que lo que prima es la potencia y la velocidad, el DUE es tu candidato, sin duda.

Pero si quieres ponerle algún shield (ya hablaremos) o enganchar con integrados TTL y similares,
los 3 voltios del DUE te van a complicar la vida, en seguida. Si quieres un Arduino UNO a lo bestia
para lo que haga falta, compra el Mega (que además es bastante más barato) y estarás encantado.

Además con la evolución de precios que todo esto esta teniendo (a la baja) es probable que te acabes
comprando uno de cada.

Hay más modelos de Arduino por ahí:

IMAGEN MODELO

Arduino Leonardo.Es como un UNO y con las


mismas prestaciones, pero es el primer Arduino
que incorpora gestión interna del USB (Y no
gestionado por un segundo procesador como en
el UNO), lo que le permite presentarse al PC
host como si fuera un ratón o un teclado.

Arduino Mini.Es como un UNO, el mismo


procesador, pero en minúsculo, montado
pensando en el que ocupe lo mínimo.Es ideal
para incluir en prototipos, pero no incluye USB,
debes comprar otro cacharrito para
programarlo.

Arduino Micro.Es como un Leonardo, pero en


miniatura y con todo incluido. Hasta un mini
USB para programarlo cómodamente.Es ideal
para incluir en la protoboard, porque viene con
los pines adecuados.
IMAGEN MODELO

Arduino Yun.No sé muy bien qué decir del


Yun. Es un Leonardo, al que le han puesto un
copiloto que corre un Linux chiquito pero
matón.El equipo Arduino ha desarrollado una
librería para interactuar entre el procesador
Arduino y el Linux, y aparentemente es muy
sencillo.Además lleva incluido WIFI y lector de
tarjetas, y solo la tarjeta WIFI ya suele costar
más que el Yun.Tengo uno por aquí, así que si
tengo ocasión montaremos una sesión con él.

Hay mas modelos en camino, pero de momento no conviene complicarnos mas.

Usando la EEPROM de Arduino

No quiero dejar pasar esta ocasión de hablar de la EEPROM interna de Arduino.

¿Porque tiene EEPROM Arduino?, pues sencillamente porque aunque guardamos el programa en
FLASH y por tanto, no se pierde al apagar, no ocurre lo mismo con las variables que se guardan en
SDRAM y su valor e pierde cada vez que apagamos.

Por eso hay ocasiones, en las que es interesante poder conservar opciones de configuración del
usuario, sin tener que preguntarle lo mismo cada vez que reinicia.

Imagínate un reloj digital, en el que le preguntamos usuario si prefiere e formato de 12 0 24h, o a


qué hora poner el despertador.

Vamos a escribir un pequeño programa que muestre como almacenar valores en la EEPROM, de
forma que podamos recuperarlos aun cuando se vaya la luz.

Para escribir en la memoria EEPROM, tenemos que incluir la librería correspondiente:

#include <EEPROM.h>

for (int i = 0; i < 255; i++)


EEPROM.write(i, i);

Y para leer de la EEPROM

#include <EEPROM.h>

value = EEPROM.read(pos);

Donde pos, es la posición de EEPROM que queremos escribir. Para un UNO pos puede llegar hasta
un máximo de 1.024, que es la longitud de EEPROM disponible. Para un Mega puede alcanzar 4k =
4.096

Y poco más se puede decir de este asunto. Que está disponible una especie de mini disco duro
secuencial, dentro de vuestro Arduino, y que es bueno que sepáis que podéis usarlo cuando lo
necesitéis.

 En cuanto al tema de que esta memoria se degrada con el uso y acaba volviéndose
inservible, vale la pena revisar la documentación del fabricante (Si, el dichoso manual que
hay que leerse siempre) confirma este punto y dicen que solo aguanta 100.000 reescrituras
antes de degradarse.
 Así que si grabas 4 datos diarios, se estropeara al cabo de, veamos, 100.000/4 /365 = algo
más de 68 años, así que ya sabéis, mucho cuidado al escribir la EEPROM, no vayáis a
gastarla.
 Parece existir un absurdo temor a usar las EEPROM en la comunidad Arduino. Os
recomiendo que las escribais sin miedo. Hay muchas posiciones y si alguna se estropea,
siempre podéis escribir en otras posiciones. El UNO tiene 1024 diferentes.

Resumen de la sesión

 Hemos hablado un poco de los diferentes tipos de memoria y de sus motivos de ser.
 Hemos visto las características de diferentes procesadores, al redor de donde se con
construyen los modelos de Arduino.
 Hemos presentado varios modelos diferentes de Arduino.
ARDUINO Y EL SENSOR DE
AGUA
Arduino y el sensor de agua

Objetivos

o Conocer los sensores de nivel de agua, lluvia o condensación.


o Montar un circuito de prueba.

Material requerido.

Arduino UNO o similar.

Algunos cables de protoboard macho hembra.

Un sensor de agua
Sensores de Agua

Por diferentes razones, no es raro necesitar detectar si hay presencia de agua en un lugar. Puede ser
porque queremos saber si ha habido un escape de agua, o para saber si hay condensación en una
cierta zona, y muy frecuentemente nos viene bien conocer el nivel de un líquido en un depósito

En el mundo Arduino se comercializan unos detectores de agua muy baratos y simpáticos, que nos
pueden servir para todas estas cosas, siempre y cuando seáis conscientes de que la calidad de estos
detectores baratos es limitada.

En concreto, tengo dudas serias de su durabilidad a medio plazo si los mantenéis en exteriores como
detector de lluvia, o si los sumerges en líquido para tener un medidor de nivel. No dudo de su
utilidad sino de su duración.

En cualquier caso como son bastante baratos, he pensado en incluir un ejemplo sencillo de su uso, y
quien sabe, quizás puedan seros útiles.

Son muy simples y lo único que hay que hacer es conectar a tensión y GND y el tercer pin es una
señal analógica, proporcional a la cantidad de agua que detecta.

Eso es todo. Veamos las conexiones

Diagrama de conexión

El conexionado es de lo más sencillo. Simplemente conectar Tensión y GND y el pin restante es la


señal.
 En este diagrama he pintado unos cables cortos por necesidad, pero cuando montéis este
ejemplo, os recomiendo que pongáis los cables más largos que tengáis, porque la electrónica
y el agua no se llevan bien.
 Tened cuidado de no volcar agua en vuestro Arduino, o morirá en acto de servicio.
 Si insertáis el sensor en agua, para usarlo como medidor de nivel, tened mucho cuidado de
no sumergir los pines de conexión a Arduino, o provocareis un corto.
 No hay suficiente tensión como para provocar un accidente, pero siempre es recomendable
impedir un cortocircuito.

Programama de control

El programa es de lo más simple y sabrá a poco después de las últimas sesiones que hemos tenido.

Vamos a leer la señal del sensor con nuestro A0 y enviaremos la lectura a la consola serie para ver la
medida. Jugando a mojar más o menos el sensor veremos cómo los valores van cambiando a más
cuanto mayor sea la cantidad de agua que detecta.

void setup()

Serial.begin(9600);

void loop()

Serial.println(analogRead(A0));

Es tan facil que da asco.

Como no he sido capaz de grabar un vídeo decente del sensor, el agua, y la salida serie de la consola
Arduino, he optado, por incluir un display en el vídeo, que nos permita ver la lectura de la puerta
A0.

No he incluido el programa con el display, porque aun, no hemos hablado de estos componentes,
pero tranquilos, que enseguida empezaremos con ellos.
 Como a pesar de todo alguno me seguis pidiendo el programa con el display os lo pongo
aqui por si quereis echarle una ojeada: Prog_26_1

El vídeo pretende simplemente, mostraros la utilidad del sensor de agua y no del display. Así que
aquí tenemos ese mini video con el resultado:

Resumen de la sesión

o Hemos presentado un sensor muy sencillo de agua, muy útil si quereis detectar
inundación o simplemente gotas de lluvia.
o No es un sensor de humedad, que es un tipo diferente de sensor.
o Se puede utilizar como un sensor de nivel de agua relativamente pobre.
DETECTOR DE LLAMA
Arduino y los sensores de fuego

Objetivos

o Presentar los sensores de llama.


o Montar un circuito de ejemplo.
o Ver sus características.

Material requerido.

Arduino UNO o similar.

Algunos cables de protoboard macho hembra.

Un buzzer piezoeléctrico

Un sensor de llama
Sensores de llama

No resulta extraño que los sensores de llamas se encuentren entre los más vendidos. La industria los
suministra de todos los tipos, tamaños y precios, porque la idea de que se te queme la casa o la
empresa es algo que ayuda mucho a sacar la cartera y buscar un detector que sea capaz de avisarte
con tiempo de que hay llamas cerca de tus cosas.

En realidad, es muy probable que tengas varios de estos detectores en tu casa. Imagínate, por
ejemplo, los calentadores de gas, los hornos domésticos de gas, o un sencillo calentador de agua y
calefacción.

Todos ellos requieren una llama quemando gas. Si por cualquier motivo, la llama se extingue y no lo
detectases, el gas seguiría fluyendo y causando un embalsamiento, listo para causar un disgusto
explosivo.

Por eso, todos estos electrodomésticos, y sus equivalentes industriales, incorporan por ley, un
detector de llama, que pueda cortar el gas en cuanto detecte falta de llama.

Lo sensores más sencillos (y baratos), suelen ser del tipo de detectores de ultravioletas, o sensores de
infrarrojos.

 El mercado ofrece, también, un amplio espectro de sensores del tipo de detectores de humo
y de gases nocivos como monóxido de Carbono (CO) típico de la combustión,Dioxido de
Carbono (CO2), detectores de humo, o de gases peligrosos libres, como
hidrocarburos (Propano, Butano y demás).
 Si tenemos ocasión en el futuro hablaremos de ellos.

En un entorno normal, la ignición de una llama provoca una ionización potente de gases comunes
(En realidad un plasma ionizado, similar al que ilumina una lámpara halógena), que generan un
patrón típico de frecuencia en el rango del ultravioleta. El detector es un semiconductor sensible a
este rango de frecuencias.

Cuando la llama se estabiliza, es relativamente sencillo detectar su espectro infrarrojo, con una
fotorresistencia LDR, pero diseñada para ser específicamente sensible a un rango característico.

Nosotros vamos a usar un sensor muy sencillo y fácil de manejar que es un sensor infrarrojo de
llamas. Funcionan detectando una longitud de onda especifica (de unos 760 nm) que son
características de las llamas, aunque son relativamente fáciles de engañar y pueden dar falsos
positivos con ciertas luces.

Como todo en la vida, es cuestión de precio, y el nuestro es barato, así que nos tendremos que
apañar, pero a pesar de todo, confio, en que el resultado de la sesión, sea satisfactorio.
Este sensor se encuentra muy frecuentemente encapsulado con un soporte y un potenciómetro para
ajustar la sensibilidad, por poco dinero. Incluso se vende en formato múltiple, con varias cabezas
apuntando en distintas direcciones

En principio siempre es recomendable usar uno montado (Porque dan menos trabajo y a la hora de la
verdad no se suelta un cable), pero como me sobraba un detector independiente, por la mesa voy a
montarlo en circuito de protoboard para ver qué pasa.

Esquema de conexión

Lo normal para leer este sensor de llamas, seria usar un divisor de tensión como este:

Donde R1 debería tomar valores sobre 500k y como no tenía nada parecido, he usado 4 resistencias
de 100k en serie, para tener lecturas claras en la puerta A0 de Arduino. EL esquema eléctrico es algo
así:
Y aquí tenemos el esquema de la protoboard:

Programa de control

El programa es de lo más simple. Solo tenemos que leer la caída de tensión en el divisor y mandar
una señal acústica con el buzzer en cuanto el valor de la lectura en A0 sobrepase un cierto umbral.

Vamos a recuperar, además, la función Beep () que escribimos en la sesion Buzzers o zumbadores,
para dar el tono de alarma cuando se detecte una llama
void setup()

pinMode(9, OUTPUT);

void loop()

int v = analogRead(A0) ;

if ( v > 10)

beep(200) ;

void beep(unsigned char pausa)

analogWrite(9, 20);

delay(pausa); // Espera

analogWrite(9, 0); // Apaga

delay(pausa); // Espera

Lo que hace el programa es leer el pin A0 y si su valor sobrepasa un mínimo (para evitar los falsos
positivos) llama a la función beep() para dar la alarma.
 Nota: Normalmente hay que calibrar la sensibilidad del sensor. Para ello hay que ver que
valores te devuelve en tu caso concreto y afinar este valor umbral, para que no esté pitando
continuamente.
 Los sensores en placa, suelen venir con un potenciómetro, que hay que ajustar para calibrar
la sensibilidad el detector.
 Tambien convendría modificar el programa, para que el tono de la señal se hiciese mas
agudo cuanto mas alto sea el valor de lectura en A0

Aquí os dejo un mini video con un ejemplo:

Resumen de la sesión

o Hemos visto que estos pequeños sensores de llamas son simples y razonablemente
eficaces.
o Dan bastante falsos positivos especialmente si les acercáis una luz potente.
o Os recomiendo la versión con montura por la comodidad de uso.
o Hemos creado una pequeña alarma de incendios con unos materiales de muy poco
coste
SENSOR DE INCLINACIÓN
(TILT SWITCH)
Inclinometro rudimentario y sensor de choque

Objetivos

o Presentar un sensor de inclinación.


o Montar un circuito de ejemplo.
o Es una sesión de descanso, para que nos relajemos
o Muestra un Debouncing sin delay.

Material requerido.

Arduino Uno o similar.

Una Protoboard.

Un diodo LED.

Un sensor de inclinacion o tilt switch.


Una resistencia de 330 Ohmios.

Algunos cables de Protoboard.

Sensores de inclinación (Tilt Sensors)

Para los que hace ya unos años jugábamos a las maquinas, entones llamadas de Petacos y hoy
llamadas Pinball (Como cambian las cosas y los nombres) nos acostumbrábamos enseguida a que si
te dejabas llevar por la emoción y le metías un empujón a la máquina, rápidamente marcaba Tilt y te
impedía seguir jugando.

Así que acabamos pensando que Tilt era algo así como falta, pero no. En ingles Tilt es inclinar o
ladear y se refiere a inclinar el plano de referencia sobre el que se asienta nuestro sistema de
coordenadas (Movimiento que de no impedirse, nos aseguraríamos de que la bola nunca llegara
abajo del Pinball, ya que bastaría con levantar de las patas más próximas al jugador).

Creo recordar que en aquellas antiguas maquinas se realizaba mediante un péndulo, pero que podría
haberse realizado mediante uno de los sensores que nos ocupan en esta sesión: Los sensores de
inclinación o Tilt Sensors.

Son sensores de unos pocos milímetros de longitud, que llevan en su interior una o dos pequeñas
bolas conductoras, capaces de cerrar el circuito con los pines metálicos inferiores del cilindro..

Cuando hacen contacto permiten el paso de la corriente y cierran el contacto exactamente igual que
si fueran un interruptor (Y de hecho se manejan igual) pero que a partir de un cierto Angulo de
inclinación dejan de hacer contacto y abren el contacto.
No es una tecnología reciente, pues llevan en uso mucho tiempo, pero antes se hacían con una gotita
de mercurio líquido, que es conductor y que al desplazarse por el interior del cilindro acababa por
cerrar el circuito entre un par de contactos en el fondo.

Pero dado que el mercurio es sumamente toxico para el entorno y para las personas que lo manejan,
hace ya bastante tiempo que se han reemplazado por el modelo que vamos a usar, aunque aún es
fácil encontrarnos con que se siguen llamando interruptores de mercurio.

A todas luces se comportan igual que un interruptor sencillo y de hecho vamos a tener que hacer el
debouncing igual que estos, porque si aquí rebotaban los contactos, podéis imaginaros los rebotes
que van plantear las bolitas de poca masa.

Veamos el circuito de prueba que vamos a usar

Esquema de conexión

Vamos a usar el mismo esquema de conexión que con un interruptor normal. Por ello necesitamos
usar una resistencia de pullup, y según el valor que leamos encendemos o apagamos un LED
conectado al pin 13.

 Por una vez, y sin que sirva de precedente conectaremos el LED al pin 13 sin resistencia,
porque este pin ya lleva una en serie. Para cualquier otro pin deberíamos poner una
resistencia de limitación o veremos un bonito plof con el LED.
 Vamos a usar lógica negativa. Esto es una manera complicada de decir que puesto que en
condiciones normales, el interruptor está cerrado, la señal de disparo será cuando leamos
un LOW en el pin 2.

El diagrama de conexión será:


Y aquí tenemos el esquema de protoboard

Programa de control

El programa va a ser muy similar al que usamos en la sesión previa, condicionales y botones. Pero
por aquello de variar un poco, vamos a usar un debouncing de tiempo variable (que si no, nos
aburrimos).

Aquí tenéis el programa: Prog_28_1

int inPin = 2;

int outPin = 13;

int lectura;

int previo = LOW;


long time = 0; // Para guardar la hora de la inversion de valor

long debounce = 50; // Tiempo de rebote

void setup()

{ pinMode(inPin, INPUT_PULLUP);

pinMode(outPin, OUTPUT);

void loop()

{ lectura = digitalRead(inPin);

if (lectura != previo) // Si hay cambio en la lectura

time = millis();

if ((millis() - time) > debounce)

digitalWrite(outPin, lectura);

previo = lectura ;

No hay nada Nuevo en el programa. Con lectura vamos leyendo el pin 2 hasta que es diferente del
último valor leído. A partir de esto comprobamos que ha transcurrido el tiempo de debouncing para
filtrar los rebotes y escribimos en el pin de salida lo que leemos.

En la practica son bastante fáciles de manejar y os permiten detectar un movimiento brusco del
sensor y también detectan una inclinacion superior a un cierto angulo.

No es difícil imaginárselo en un circuito que detecta si una puerta de garaje esta levantada o no, por
ejemplo, o en un sensor de impacto. Por alguna razón que se me escapa estos sensores parecen ser
muy populares entre nuestros Arduinos.
Aquí os dejo un minivideo con el resultado:

Resumen de la sesión

o Hemos visto que estos pequeños sensores de inclinación son simples y


razonablemente eficaces.
o Se comportan exactamente igual que un interruptor de contacto, pero con mas
rebote.
o Hemos visto que se pueden usar como un sensor de movimiento brusco o
inclinación.
SENSOR DE TEMPERATURA
Y VENTILADOR
Ejemplo sencillo de control de temperatura

Objetivos

o Unir un sensor de temperatura y un ventilador.


o Calculando la temperatura con float.
o Usando el ventilador para disminuir la temperatura.
o Ilustrar la idea de un buffer circular

Material requerido.

Arduino Uno o similar. Esta sesión acepta cualquier otro


modelo.

Una Protoboard más cables.

Un diodo LED y una resistencia de 330Ω.

Un transistor 2N2222. Comprobad que lleva rotulada esta


referencia, porque el sensor de temperatura es similar.
Un ventilador de 5V o un motor de corriente continua.

Un Sensor de temperatura LM35DZ o similar.Comprobad que


lleva rotulada esta referencia, porque es fácil confundirlo con
un transistor.

Un circuito con sensor y actuador

Hemos ido viendo hasta ahora como utilizar un sensor de temperatura y también como usar un
pequeño transistor para mover un motor de CC, pero no los habíamos mezclado.

En esta sesión haremos un pequeño ejemplo de control, usando un sensor LM35DZ para determinar
la temperatura y un ventilador de 5V, para que cuando la primera alcance un valor crítico, usemos el
segundo a fin refrigerar el circuito.

Como no disponemos de ningún sistema a refrigerar, nos conformaremos con enfriar el propio
sensor, lo que no resulta especialmente provechoso, pero sin duda, nos servirá para mostraros un
ejemplo de control y reacción, en el mejor espíritu de un sistema automático, tal como un regulador
de temperatura con nuestros Duinos.

Veremos que la regulación de un sistema tan sencillo no tiene grandes problemas y por eso esta
sesión esta mas pensada como un ejercicio de control sencillo y que como una regulación en toda
regla.

Además el parámetro que buscamos controlar, la temperatura, tiene la virtud de variar con lentitud,
lo que nos deja mucho tiempo para reaccionar y no tener que preocuparnos por cuestión de
reaccionar con precisión en tiempo real.

 Hace mucho tiempo, cuando empecé a trabajar en cosas de estas, y alguien preguntaba qué
era eso de trabajar en tiempo real, definíamos el tiempo real como el margen que tenías
para reaccionar y controlar el parámetro díscolo antes de que algo caro se fuera al guano.
 Cuando estás en un marrón así, las técnicas que vamos a aplicar aquí no valdrían y
tendríamos que empezar a hablar de cosas como el control PID, pero por ahora es pronto,
así que mejor lo dejamos aquí.

Vamos por tanto a montar un circuito sencillo con el sensor de temperatura y otro independiente
con un transistor para controlar el motor del ventilador en la misma protoboard.

Esquema electrónico del circuito.

Vamos a montar un pequeño circuito que lea la temperatura de un sensor, imprima el valor en la
consola y encienda un diodo cuando esta sobrepase un cierto umbral.

Para conectar el sensor de temperatura LM35DZ y el transistor 2N2222, os incluyo el detalle de sus
pines aquí

Aquí tenemos el esquema electrónico del circuito:

Y el circuito para protoboard sería muy sencillo también:


Probando el sensor de temperatura.

Ya hemos visto en sesiones previas como usar un sensor LM35DZ, pero si alguno queréis revisarlo
podéis hacerlo aquí: Sensor de temperatura.

Vamos a empezar probando el sensor para comprobar que funciona correctamente, y para ello vamos
a usar este programa:

const int Sensor = 0 ; // Pin que lee la temperatura

void setup()

{ Serial.begin(115200); }

void loop()

{ int lectura = analogRead(Sensor);

float voltaje = 5.0 /1024 * lectura ;

float temp = voltaje * 100 ;

Serial.println(temp) ;

delay(200);

Usamos la puerta Analog0 que definimos como una constante sensor, y en el loop leemos la puerta y
convertimos el valor de la lectura a grados centígrados (Recordad que la razón de hacerlo así la
vimos en la sesión de los sensores de temperatura) e imprimimos sin más el valor de la temperatura.
Deberías ver algo parecido a esto:

El sensor LM35DZ tiene un margen de error de alrededor de ± 0,5 grados y por eso las
lecturas tienen oscilación, dando diferencias de hasta un grado.

Para los que van a por nota

El baile de las lecturas se debe a que el mundo real nunca es perfecto y hay cosas que van desde la
incertidumbre de la medida causada por el propio sensor hasta los errores en los convertidores de
nuestro Arduino (Que no son los mejores del mundo) e incluso interferencias electromagnéticas
espurias.

Todo ello se confabula para que tengamos ese molesto baile de cifras en la medida y aunque en este
caso no tiene importancia puede convenirnos filtrar este tipo de errores y para ello podemos
promediar las n ultimas lecturas y presentar esto como el valor de la temperatura.

Para ello podemos guardarlas digamos 8 últimas lecturas y promediarlas, con lo que aplanaremos
fuertemente los errores, y la manera más sencilla es usar un buffer circular (O Ring Buffer)

La forma de apuntar a la posición a escribir es una variable llamada Índex que empieza en 0 y cada
vez que escribe en la posición correspondiente se incrementa en 1 ¿Y cómo evitamos que pase del
valor máximo aceptable? Pues tomando el resto del valor de Índex con respecto al número de
posiciones del array.
Buffer[ index] = temp ;

index = ++index % 8 ;

Una vez que apuntamos correctamente a la posición a escribir y después de los N valores iniciales en
los que la temperatura promedio será falsa (Porque aún no hemos leído N valores) tendremos en
Buffer las ultimas N lecturas y el resto es aritmética:

int index = 0 ; // Posicion a escribir

const int N = 16 ; // Numero de muestras a considerar

float Buffer[N] ; // Array donde guardamos las lecturas

Buffer[ index] = temp ;

index = ++index % N ;

float Tmedia = 0 ;

for (int i=0 ; I < N ; i++)

Tmedia = Tmedia + Buffer[i] ;

Serial.println( Tmedia / N) ;

Aquí os dejo el programa complete, por si quieres jugar con el: Prog_130_2. Para N = 32 podéis ver
algo así:

Podéis ver que la temperatura baila mucho menos y el baile desciende a medida que aumentáis el
número de muestras que promediáis, pero cuidado, cuanto más crece N también crece el tiempo que
tardáis en responder a los cambios ( Para N = 32 a 5 muestras por segundo hay más de 6 segundos
de tiempo de reacción).
 Aunque con una temperatura ambiente eso no es grave, puede haber ocasiones en que lo
sea, por ejemplo porque un quemador arranca, y en 6 segundos le sobra tiempo para
chamuscar lo que sea que estemos controlando, así que ojo.

Incluyendo el ventilador.

Ya tenemos montado el sensor de temperatura y ahora vamos a programar el control de arranque y


apagado del motor / Ventilador, definiendo un valor umbral a partir del cual queremos ventilar el
sensor. Veamos un posible programa: Prog_130_1

int Sensor = 0 ; // Pin que lee la temperatura

int umbral = 30 ; // Temparatura que arranca el ventilador

const int control = 9 ; // Gobierna el ventilador

void setup()

{ Serial.begin(115200);

pinMode(control, OUTPUT) ;

void loop()

{ int lectura = analogRead(Sensor);

float voltaje = 5.0 /1024 * lectura ;

float temp = voltaje * 100 -5 ;

Serial.println(temp) ;

if (temp >= umbral)

digitalWrite(control, HIGH);
else

digitalWrite(control, LOW);

delay(200);

La única novedad es que comprobamos que la temperatura medida es inferior al umbral prefijado y
si no es así, arrancamos el ventilador para refrescar el sensor.

 Fijaros que al alcanzar el umbral, disparamos el ventilador a tope de modo digital. Es


decir todo o nada. En una situación real probablemente convendría hacer un control
proporcional de la velocidad del ventilador en función de lo lejos que esta del punto que
buscamos ( Aquí es donde entran las cuestiones de control PID)
 Os propongo que hagáis un ejemplo en el que la velocidad del ventilador sea proporcional
a la diferencia entre la temperatura umbral y la temperatura medida.

Aquí tenéis un pequeño vídeo mostrando el montaje:

Resumen de la sesión

o Mezclamos en un único proyecto un sensor y un actuador para conseguir control.


o Presentamos la idea de buffer circular para promediar las lecturas instantáneas.
o Vimos un principio de regulación de temperatura.
JUGANDO CON EL HLK-
RM04
MOntando un servidor web entre otras cosas

Objetivos

o Una vez presentado el WIFI HLK-RM04., empezamos el juego.


o Veremos cómo enviar instrucciones a través de una página Web para realizar
acciones en nuestro Arduino
o Usaremos Putty para enviar y recibir información del módulo y nuestro Arduino.
o De nuevo, montaremos un pequeño servidor web para ver las posibilidades del
módulo.
o Veremos un par de soportes adicionales muy curiosos para el HLK-RM04.

Material requerido.

Arduino UNO o MEGA.

Un módulo WIFI HLK-RM04,

Algunos cables de protoboard, preferiblemente


Dupont macho/hembra más una protoboard

Acceso bidireccional a través de una consola


En la sesión previa dejamos configurado el módulo HLK-RM04 para que aceptara peticiones de
servicio Web, y vimos que en cuanto alguien se conectaba por el puerto previamente definido, el
8080, recibíamos un aviso puntual de ello en la consola:

Pero tal y como vimos en las sesiones previas con el módulo WIFI ESP8266, esto no nos permite la
comunicación bidireccional, porque solo podemos pasarle mensajes al servidor, pero no al revés.

Podemos usar esto para pasar parámetros al servidor Web y que encienda unos LEDs por ejemplo
sin más que en la dirección que le pasamos el navegador, añadir los parámetros:

http://192.168.1.254:8080/P13=1

Que podemos rastrear en lo que recibimos por la consola, tal y como vimos en “Usando el módulo
WIFI ESP8266” y que hará que recibamos algo así:

Del mismo modo, es igual de sencillo establecer una comunicación bidireccional desde un terminal
como Putty
Donde cualquier cosa que tecleemos se envía a la consola de Arduino y de esta a Putty

De nuevo podemos usar este sistema, como un modo de control desde nuestro pc de cualquier
proyecto que incluya WIFI.

No hay diferencia entre el programa para este módulo y los programas que usamos con el ESP8266,
ya que la comunicación es vía puerta serie exactamente igual, con una excepción importante: Los
comandos AT son diferentes y por eso vamos a verlos un poco ahora.

Comandos AT en el WIFI HLK-RM04

Cuando iniciamos el módulo, este arranca en lo que el fabricante llama modo transparente, es decir,
que todo lo que viene vía TCPIP lo envía limpio de polvo y paja a la puerta serie y viceversa.
Para poner el módulo HLk-RM04 en modo comando AT, parce que hay dos modos. Uno que se
menciona en el manual, mantener el pin de Reset, el número 10, que ya conocemos, más del tiempo
Tes de 100 mili segundos y menos del tiempo de Reset que es de 6 segundos (Si no hemos cambiado
la configuración)

Podríamos usar esto con el mismo circuito y programa que usamos para Resetear el módulo a sus
valores de fábrica cambiando la configuración del delay, pero parece que hay otro sistema de enviar
ciertos textos con unos tiempos predefinidos, con lo que entraríamos directamente en modo de
comandos AT.

 Encontré este método y función en algún sitio de Internet que he perdido, pero no tengo ni
idea de donde sale, porque en mi manual no habla de ello, en absoluto, pero parece que
funciona.

Aquí tenéis la función que hace entrar al módulo HLK-RM04 en modo AT:
void exitTransparentMode()

{ Serial.println("Exiting Transparent Mode...");

delay(500);

Serial3.write("+");

delay(20);

Serial3.write("+");

delay(20);

Serial3.write("+");

delay(500);

Serial3.write(0x1b);
delay(20);

Serial3.write(0x1b);

delay(20);

Serial3.write(0x1b);

delay(20);

Serial3.write(0x0d);//not documented, but seems to need CR here

delay(500);

Serial3.write("at+ver=?\r");

Vamos a repetir el diagrama de conexión de la sesión anterior para los más vagos (Yo incluido):

Y aquí tenéis un programa que ejecuta esa función y abre la comunicación entre el módulo y nuestro
Arduino, reenviando los mensajes de la puerta del módulo a las puertas de Arduino y viceversa.
Prog_78_1 , Una vez que lo volquéis al Mega, deberíamos estar en modo AT.

Tened en cuenta en primer lugar que en estos módulos los comandos AT se deben escribir en
minúsculas (¿Qué pasa? ¿Vosotros no tenéis ninguna manía?)

El primero para ver la versión de Firmware instalada:

at+ver=?

Y si queréis saber el modo de trabajo:


at+netmode=?

Donde en la respuesta, 0 es el default setup, 1 modo Ethernet y 2 modo client WIFI y 3 punto de
acceso. Para conocer la configuración del TCPIP, usamos

at+net_ip=?

Podemos usar estos comandos AT para fijar el valor de los parámetros en lugar de consultarlos,
cambiando la interrogación de las instrucciones anteriores por los parámetros a fijar en el módulo.
Por ejemplo:

at+netmode=2

Hay un montón de comandos AT y no es cuestión de probarlos aquí, pero si descargáis el manual del
módulo, encontrareis una lista extensiva de ellos: HLK-RM04-user-manual

Servidor Web con el módulo WIFI HLK-RM04

Vamos a ver como montar un pequeño servidor Web para publicar las lecturas de las puertas
analógicas. Partiremos del programa que escribimos en la sesión previa “Servidor Web con WIFI
ESP8266” y lo modificaremos un poco para adaptarnos al nuevo módulo.
La principal diferencia es que mientras el ESP8266 necesitaba un comando AT+IPSEND para enviar
un puñetero String a la puerta serie, el Modulo WIFI HLK-RM04 actual es transparente y enviara
por TCPIP cualquier cosa que reciba.

Así que vamos a simplificar un rato el programa del ESP8266, porque no se requiere la mitad de la
complicación que tuvimos que montar. Aquí tenéis el programa servidor, al que le hemos quitado,
todo el envío de comandos previos: HLK-RM04

El mismo esquema para detectar en Serial3, movimiento, cuando llega algo, llamamos a webserver:

void setup()

{ Serial3.begin(57600);

delay (1000);

void loop()

{ while (Serial3.available() >0 )

{ char c = Serial3.read();

if (c == 71)

{ webserver();

delay(500);

Y en cuanto a webserver:

void webserver(void)

{ Serial3.println("<!DOCTYPE HTML>");

Serial3.println("<html>");
Serial3.println("<head><title>LECTURAS ANALOGICAS.</title>");

Serial3.println("<meta Serial3.println-equiv=\"refresh\"
content=\"15\"></head>");

Serial3.println("<body><h1> Situacion Ambiente</h1>");

for (int analogChannel = 0; analogChannel < 6; analogChannel++)

{ int sensorReading = analogRead(analogChannel);

Serial3.println("analog input ");

Serial3.println( String(analogChannel));

Serial3.println(" is ");

Serial3.println(String(sensorReading));

Serial3.println("<br />");

Serial3.println("<p><em> La página se actualiza cada 15


segundos.</em></p></body></html>");

En la que simplemente enviamos a través del Serial3, los textos que corresponden a generar la
página Web que describimos allí.

Al final es aún más fácil, porque eliminamos toda la complicación para enviar textos a través del
WIFI y resulta trivial de nuevo. Aquí tenéis un volcado del resultado:
Más modos del WIFI HLK-RM04

Al principio de la configuración del módulo, os pedí que seleccionarais como NetMode WIFI
Client, y si volvéis allí (Poniendo 192.168.1.254) y desplegáis los modos disponibles, veréis algo
así:

Podéis ver el modo ya conocido de cliente WIFI, pero ¿Qué es eso de ETH+Serial?

Pues básicamente, que si usáis un soporte externo adicional para este modulito os podéis configurar
un Ethernet a Serie como su nombre indica, y lo que es más, dispone de dos puertas Ethernet que
parece indicar que nos permitirían configurar un Router Ethernet más conexión WIFI al mismo.

No he tenido mucho tiempo aun para jugar con ello, porque acabo de recibir uno de estos chismes,
pero espero que si hay ocasión volveremos a hablar del asunto.
El único problema que le veo a este módulo, es que anda escaso de documentación y de ejemplos
de posibilidades. Por lo demás, la única limitación que le encuentro es que una puerta Ethernet es de
100 Gbits hoy día como mínimo y nosotros estamos usando una puerta seria 57.600 bits, así que no
vais a descargar pelis por aquí.

Si queréis usar este módulo en serio, es imprescindible que uséis un Mega, que tiene puertas
hardware y que subáis la velocidad al menos hasta 115.200 ( A los que el uno llegara muy
joiamente) pero el Mega lo tengo probado hasta el doble sin problemas.

 Sí señor, el Mega alcanza sin problemas velocidades de 230.400 bits por segundo, que es la
velocidad a la que suelen ir las impresoras 3D del tipo RepRap que se basan en él.

Y por si aún os parece poco lo de este modulito dispone también de un Shield para ponerlo a la
espada de nuestros Arduinos y dotarlos de conexión WIFI (Lentorra, eso sí)
En resumen una sorprendente pieza de hardware, con unas capacidades camaleónicas, a la espera de
encontrar utilidad y por si fuera poco a un precio muy bajo tanto el modulo como los soportes
adicionales. Tengo mucha curiosidad por ir viendo lo que hace la peña con ellos

Resumen de la sesión

o Vimos como montar la comunicación con el módulo HLK.-RM04, tanto


unidireccional como bidireccional.
o Vimos cómo poner el modulo en modo comandos AT, y jugamos con un par de
ellos.
o Montamos de nuevo un pequeño servidor web para ver las posibilidades del
módulo.
o Presentamos varias opciones disponibles de soportes para este sorprendente módulo
LOS MÓDULOS DE RADIO
NRF2401
Usando radios para comunicar nuestros Arduinos

Objetivos

o Presentar los módulos de radio NRF2401.


o Describir la forma de conectarlos a nuestros Arduinos o similares.
o Presentar un par de programas sencillos que nos permitan usarlos en nuestros
proyectos para enviar y recibir órdenes o datos.
o En este primer ejemplo de programa la comunicación será unidireccional..

Material requerido.

Arduino UNO o equivalente.

Un par de módulos de radio NRF2401,

Algunos cables de protoboard, preferiblemente Dupont


macho/hembra más una protoboard
Las conexiones de radio

Hemos visto en anteriores sesiones, que poder usar conexiones inalámbricas nos ofrece unas
posibilidades a las que resulta difícil renunciar cuando te acostumbras, y hemos hecho pruebas de
conexiones tanto WIFI como Bluetooth.

Las WIFI nos permiten conectarnos a Internet con facilidad y podemos publicar páginas Web con
valores de nuestros sensores y Arduinos o simplemente acceder a estos Duinos y pasarles
parámetros u órdenes. EL BlueTooth es ideal si queremos controlar nuestros Arduinos sin más
controlador que un móvil que ya llevamos habitualmente en el bolsillo.

Pero tanto el BT como el WIFI tienen unas limitaciones considerables en lo que se refiere a la
distancia a la que podemos usarlo. No pasa más allá de 20 metros y eso en condiciones óptimas, pero
no es raro que necesitemos más distancia, digamos 50 m, 0 200 m, y porque no un kilómetro.

Como siempre, cuando hay una necesidad en el mercado, surge alguien dispuesto a ofrecer una
solución en forma de electrónica, y en esta ocasión vamos a presentar una solución magnifica para el
tipo de problema que planteamos. Un medio de dar órdenes a un Arduino o similar, a una distancia
que puede variar entre 50 metros y hasta digamos un kilómetro.

En esta sesión vamos a presentar y dar los primeros pasos con unos magníficos dispositivos de radio
basados en el chip de Nordic semiconductor NRF24, y que podemos encontrar en multitud de
módulos de diferentes fabricantes, compatibles entre sí, por muy poco dinero, que es lo que nos
gusta en esta casa.

Este dispositivo NRF2401, integra en un único chip, toda la electrónica y bloques funcionales
precisos, para establecer comunicaciones RF (Radio Frecuencia) entre dos o más puntos a
diferentes velocidades, (Hasta 2 Mb/seg) con corrección de errores y protocolo de reenvió cuando es
necesario, sin intervención del control externo, lo que nos permite aislarnos de tobo el trabajo sucio
y complicado relacionado con la transmisión física.

Las características más destacadas son:

 Muy baratos, unos pocos dólares.


 Operan en la banda de 2.4Ghz, que es de libre uso a nivel mundial.
 Velocidad configurable de 250kb, 1 Mb o 2Mb por segundo.
 Muy bajo consumo en Stand By (Cuando no se usan).
 El alcance depende de si hay visión directa entre los nodos, o por el contrario hay
obstáculos, pero nos ofrece un mínimo de unos 20 m hasta un máximo e 80m en óptimas
circunstancias, en el modelo básico con la antena integrada.
 Podemos encontrar modelos con antenas más eficaces por un coste un poco superior (no
mucho no os asustéis) que aumentan de forma importante el alcance hasta casi un km.
 Si no queremos complicarnos la vida son muy fáciles de usar y configurar y además son los
enlaces más baratos que podemos encontrar para vincular nuestros Arduinos.
 Compatibles con todo un rango de modelos de diferentes tipos y fabricantes.

Las ondas de radio

A finales del siglo XIX, James C. Maxwell estableció las leyes del electromagnetismo que
describen la propagación de las ondas electromagnéticas y la relación que existe entre los campos
magnéticos y la electricidad (de ahí el nombre) estableciendo una de las teorías básicas que regulan
el funcionamiento del mundo moderno.

Todas la ubicuas emisiones de RF que nos rodean actualmente, fueron descritas por Maxwell y sus
ecuaciones hace ya más de 100 años, y eso incluye las emisiones de radio en AM y FM, las de
televisiones, tanto analógicas como digitales, la conexión de tu teléfono móvil y hasta las
conexiones WIFI y Bluetooth de las que hemos hablado previamente.

Las primeras emisiones de radio viables se atribuyen en 1901 Guillermo Marconi y son el
precedente de toda la tecnología de radio actual apoyándose en los trabajos de Maxwell y Heinrich
Hertz de quien deriva la unidad de medida de la frecuencia Hercios en español (Hertz en inglés)

 La descripción de una onda de RF se realiza por su frecuencia, en Hercios, que indica el


número de pulsos por segundo a los que bate la señal, y por su amplitud que indica la
intensidad.

Ya hemos hablado antes del espectro de frecuencia y vamos a destacar que en la práctica llamamos
RF a las señales de frecuencia inferior a los 300Ghz
Como podéis ver, el espectro de radiofrecuencias parece el camarote de los hermanos Marx, con los
servicios de radio, TV, telefonía y demás por lo que es importante que los dispositivos que usemos
emitan en el rango de frecuencias libres, es decir, en las que se permite que cualquiera emita y
reciba, sin interferir con la operación normal de emisiones que operan los servicios sometidos a
regulación.

Nuestros humildes módulos NRF2401 emiten a 2.4 GHz, lo que es banda libre y no requieren de
ningún permiso para usarse en ninguna parte del mundo (Por mucho que os quieran meter miedo con
esto). Pero a cambio, no tenemos garantía de que no haya alguien más emitiendo en esta banda en las
cercanías, lo que puede producir interferencias con nuestra emisiones.

 Cuando sintonizas tu emisora FM en el dial, digamos 103.4, es porque la emisora paga a la


administración para ser la única que pueda emitir legalmente en esa frecuencia y de ese
modo impida la interferencia de otros servicios comerciales.
 Por eso el espectro de radiofrecuencias está sometido a un estricto control administrativo,
en todos los países, para evitar que señales en competencia interfieran entre si anulando la
posibilidad de transmitir información valida.

Diagrama de conexión de un módulo NRF2401

Estos módulos usan el bus SPI para acelerar la conexión con el micro controlador por lo que vamos
a ver la descripción de los pines necesarios para su conexión, en vista superior:
Hay dos librerías básicas para el manejo de los NRF2401s en Arduino, la NRF24 que es la que
vamos a usar aquí (Porque me parece más sencilla) y la librería MIRF.

PIN NRF2401 ARDUINO UNO MEGA

GND 1 GND GND

VCC 2 3.3 3.3

CE 3 9 9

CSN 4 10 53

SCK 5 13 52

MOSI 6 11 51

MISO 7 12 50

IRQ 8 2 –
 Es importante recalcar que estos módulos funcionan a 3.3V; EL fabricante previene contra
conectarles a 5V so pena de achicharrarlos.
 La librería MIRF espera que hagas unas conexiones de pines diferentes, así que no te
conviene usar este diagrama de conexión si pretendes utilizarla.
 Tenéis que comprender que los modelos UNO y MEGA usan diferentes pines para el
control del bus SPI y luego para rematar la faena, según la librería cambian de nuevo.

Vamos con el esquema de conexión de protoboard:

Para poder emitir y recibir con estos módulos vamos a necesitar dos Arduinos configurados con
estas conexiones a los que llamaremos emisor y receptor, porque inicialmente los programas van a
ser distintos.

Empezaremos haciendo la prueba más sencilla posible. Uno de ellos, el emisor, radia una serie de
números y el otro, el receptor, los recibe y muestra en la consola serie.

 Aunque estos módulos consumen muy poco en uso o en Stand by, pueden absorber en el
arranque más de lo que la fuente de 3.3V de Arduino puede proporcionar, lo que impide
que arranque correctamente o que tenga un funcionamiento errático, especialmente en el
caso del emisor.
 Si buceáis en Internet, veréis cantidad de páginas recomendándoos usar unos
condensadores entre los pines tal y cual.
 Aunque tomar precauciones nunca sobra, los vagos somos incapaces de hacer algo así,
mientras no se demuestre que es imprescindible.
 En mi caso he comprobado que la manera más sencilla de evitar problemas (Que los he
tenido) ha sido asegurarme de que el emisor tiene una alimentación correcta y abundante,
mediante un alimentador externo de los típicos. Esta sencilla precaución ha hecho que en
mi caso los problemas se reduzcan hasta desaparecer.

Programando las radios

Vamos a montar un primer ejemplo en el que crearemos dos programas diferentes que corren en dos
Arduino diferentes. El primero será el programa emisor, que radiará números en secuencia desde 0
hasta el 255, y el segundo el programa receptor, que nos permitirá comunicarnos en una única
dirección inicialmente.

Vamos con el programa emisor y para ello necesitamos la librería RF24-master, cuya última versión
siempre podéis encontrar en https://github.com/maniacbug/RF24. Empezamos con unos cuantos
includes, necesarios para el NRF2401 y para el bus SPI:

#include <nRF24L01.h>

#include <RF24.h>

#include <RF24_config.h>

#include <SPI.h>

Después tenemos que crear una instancia de la radio, indicándole los pins de control, y la siguiente
línea indica el pipe a utilizar, que podemos imaginar como uno de los diferentes canales en los que la
radio puede operar.

RF24 radio(9,10);

const uint64_t pipe = 0xE8E8F0F0E1LL;


 El pipe es un numero de 64 bits, lo que indicamos con el tipo uint64_t , entero sin signo de
64 bits, y por si no estuviera suficientemente claro, le indicamos al compilador que se trata
de un LL al final del número, o sea LongLong = 64 bits.

Y ahora basta con inicializarla en el setup:

void setup(void)

{ Serial.begin(9600);

radio.begin();

radio.openWritingPipe(pipe);

En el programa principal, simplemente vamos incrementando una variable para luego transmitirla
por la radio

int msg[1] ;

void loop(void)

{ for (int x=0;x<2255;x++)

{ msg[0] = x ;

radio.write(msg, 1);

Aqui os dejo el programa completo Prog_79_1_Emisor

En cuanto al programa receptor Prog_79_1_Receptor, tenemos que empezar incluyendo las mismas
librerías, y un array mínimo para el entero a recibir, e instanciamos la radio como radio

#include <nRF24L01.h>

#include <RF24.h>
#include <RF24_config.h>

#include <SPI.h>

RF24 radio(9,10);

const uint64_t pipe = 0xE8E8F0F0E1LL;

int msg[1];

El setup es casi el mismo.

void setup(void)

{ Serial.begin(9600);

radio.begin();

radio.openReadingPipe(1,pipe);

radio.startListening();

Pero en vez de usar radio radio.openWritingPipe(pipe) para escribir, usamos


radio.openReadingPipe(1,pipe) para poder leer y después radio.startListening() nos permite
comenzar la escucha. Y ya solo falta el setup con el programa que recibe:

void loop(void)

{ if (radio.available())

{ int done = radio.read(msg, 1);

Serial.println(msg[0]);

Se nos ha vuelto a perder la parte difícil, porque no me digáis que no es sencillo y elegante. El tema
no da para más. Si corréis los programas en Arduinos diferentes, la salida del receptor debería ser
algo así:
Programa por el que no ganaremos ningún premio, pero que ilustra a la perfección como emitir datos
numéricos uno a uno entre emisor y receptor mediante radio frecuencia. Si habéis llegado hasta aquí,
enhorabuena acabáis de emitir por radio, vuestro primer mensaje.

Bueno, está bien. Enviar un carácter esta chupado, pero ¿Que pasa si hay que enviar un String
completo, seguro que la cosa se complica?

Pues sí. Para enviar un mensaje de texto tenemos que cambiar un par de cosas. Primero definir un
array de char suficiente para que quepa el mensaje:

char msg[16]="Prometec.net.\n" ;

Y después cambiar el loop para que envié los 16 caracteres

void loop(void)

radio.write(msg, 16);

Y por supuesto hay que cambiar el programa del receptor

void loop(void)

{ if (radio.available())

{ int done = radio.read(msg, 16);

Serial.println(msg);

}
}

Basta con llamar a radio.write o radio.read con el array como parámetro y pasarle el número de
caracteres que queremos enviar o recibir. Aquí tenéis el emisor y el receptor modificados.

Emisor_String

Receptor_String

He visto en Internet un programa que me encantó, porque lo que hace es colocar un LED rojo y uno
Verde en los pines 3 y 5 de Arduino y después emite números entre 0 y 255 en el emisor mientras
en el receptor corre un programa que controla que los números se reciban en el orden adecuado.

Cuando es así, ilumina brevemente la luz verde, en caso contrario la roja. Lo bueno de esto es que os
sirve como ejemplo de si tenéis una buena recepción o no, ya que según el baile de los LEDs tenéis
una idea bastante aproximada de los errores de trasmisión que tenéis en vuestra zona.

Usad el programa Prog_79_1_Emisor para el emisor y este programa en el receptor Prog_79_4.

Resumen de la sesión

o Presentamos las unidades de radio NRF2401, que son ideales para muchos
proyectos, porque son buenas, bonitas y baratas.
o Vimos como conectarlas a nuestros Arduinos con confianza usando el SPI y un par
de pines.
o Descargamos y usamos la librería RF24 para el manejo de las radios y vimos los
comandos básicos para enviar y recibir.
o Hicimos un montaje de prueba con una comunicación en una única dirección.
COMUNICACIÓN DÚPLEX
CON NRF2401
Enviando y recibiendo datos por RF con nuestros Arduinos

Objetivos

o Seguimos probando los módulos de radio NRF2401.


o Vemos porque no podemos enviar y recibir a la vez con ellos.
o Presentar un par de programas sencillos que nos permitan usarlos en nuestros
proyectos para enviar y recibir órdenes o datos en ambas direcciones y en ambos
módulos.

Material requerido.

Arduino UNO o equivalente.

Un par de módulos de radio NRF2401,

Algunos cables de protoboard, preferiblemente Dupont


macho/hembra más una protoboard
Las conexiones de radio

En la sesión anterior establecimos una comunicación RF muy básica entre un emisor y un receptor
de radio controlado con nuestros Arduinos.

Era un ejemplo muy sencillo, de hecho, procuramos que fuera la mínima expresión para facilitar la
comprensión del ejemplo y para combatir el miedo irracional que las comunicaciones de radio
parece producir en muchos aficionados competentes.

Nunca entendí porqué. Parece que esa aura fantasmal que impregnaba las comunicaciones de
radiofrecuencia a principios del siglo XX sigue vivo en el XXI.

Pero en realidad, gracias a ingenieros anónimos, como los que nos ofrecen las NRF24L01, son muy
fáciles de utilizar sin más que un pequeño empujón de ayuda, algo que por cierto estaría bien que
nos dieran los ejemplos que vienen con la librería (Que hace falta ser egiptólogo para descifrarlos)

Y es una pena, porque estos modulitos cumplen la regla de las 3 Bs, Bueno, bonito y Barato y esto
no es frecuente.

Por eso vamos a seguir incluyendo tutoriales de uso de estos módulos RF, y como no podía ser de
otra manera, teníamos que ampliar el tutorial a un ejemplo que hiciera comunicación bidireccional
(Dúplex) de modo que un emisor envíe una secuencia de datos, que se reciben en un segundo nodo y
nos responde para saber que ha llegado el mensaje.

Pero antes de empezar con el ejemplo tenéis que saber que el módulo NRF24L01 es un transceptor
y no un emisor receptor.

Un equipo emisor receptor puede enviar mensajes de radio y recibirlos simultáneamente porque
ambos circuitos, aunque muy similares, están aislados uno del otro y pueden operarse
independientemente.

Estos equipos se venden y están disponibles en el mercado, ¿Pero sabéis que? Cuestan pasta. Por eso
cuando alguien quiere ahorrar unos euritos en la radio y dado que el emisor y el receptor son
bastante similares, se monta un circuito con partes comunes. De este modo podemos emitir o
recibir (Observad el uso de la disyuntiva no copulativa) pero, y este es el truco, no a la vez.

 No confundir con transponder o tranpondedor que es una cosa diferente. Aunque también
es un sistema de radio, el transponder emite una señal y espera una respuesta, que
dependiendo de la que sea puede poner o no en marcha una serie de acciones automáticas,
como abrir la puerta de tu coche, o reclamar la identificar un avión en vuelo con su
posición.
Por eso nuestros módulos NRF2401, pueden estar en modo recepción o en modo emisión, pero no
en ambos. Aunque eso sí, podemos cambiar de uno a otro a voluntad, muy al estilo de las radios de
aficionados que indican con un “corto” la intención de cambiar de modo.

Las instrucciones básicas

Aunque ya vimos algunas en la pasada sesión, vamos a insistir con ellas. Lo primero es
incluir algunas librerías:

#include <SPI.h>

#include "nRF24L01.h"

#include "RF24.h"

Y después inicializamos los pines de control del módulo (Además, claro, de los de control SPI, de
los que se encarga la librería):

RF24 radio(9,10);

En la última sesión dijimos que los pipes se pueden entender más o menos como canales de
comunicación que no se interfieren unos con otros y definimos uno para enviar nuestros mensajes.

Como lo que queremos ahora es generar una comunicación en ambos sentidos, vamos a necesitar dos
canales o pipes, por el primero hablará uno y escuchará el otro, y por el segundo funcionará al revés.
Pero recordad que no podemos hacerlo a la vez.

const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

Son un par de enteros de 64 bits y no os preocupéis mucho por ellos. Para iniciar la radio hacemos:

radio.begin();

Normalmente cuando envías un mensaje por radio, uno espera que llegue bien a la primera, pero la
realidad suele tener su propia opinión y hacer de las suyas. Por eso es buena idea que si no recibimos
un mensaje correctamente, se reenvíe para garantizar la entrega.

 Hay una relación muy estrecha entre las señales de radio frecuencia, la electricidad y el
electromagnetismo y generalmente cuando se produce una, también aparecen las otras.
 Hay cantidad de fenómenos naturales que generan señales de RF espurias, como tormentas
y rayos o tormentas solares incidiendo en las capas superiores de la atmosfera, pero
también se generan por la actividades humanas tales como arrancar cualquier cosa
eléctrica, como motores o lámparas fluorescentes.
 Hay todo un muestrario de fenómenos que te producirán interferencias RF, antes o después
y es mejor prevenirlo.

El problema es cuantas veces hacemos este reenvío y cada cuanto tiempo. Por ese tenemos una
instrucción como esta:
radio.setRetries(15,15);

Fija en el primer parámetro la pausa entre reintentos, en múltiplos de 250µS, por eso 0 son 250µS y
15 son 400µS.(La radio funciona a velocidad de vértigo)

El segundo parámetro indica cuantos reintentos se deben hacer hasta dejarlo, con un máximo de 15.

 Si bajamos estos valores, la velocidad de comunicación sube, pero también los errores y
pueden perderse datos. Por eso si la velocidad no es una cuestión decisiva (Y con Arduino
rara vez lo será) es preferible dejarlo en 15,15 y listo.

También te interesa saber que independientemente de la longitud del mensaje que tú quieras enviar,
el módulo lo partirá en paquetes de una longitud dada. Si no especificas un tamaño, el modulo usara
32 Bytes.

A esta longitud se le llama carga útil del paquete o PayLoad, y en caso de que haya un error en
cualquiera de los bits de la transmisión, todo el paquete debe ser reenviado de nuevo (Pero no te
preocupes que el NRF2401 lo gestione en automático por ti).

setPayloadSize (número de Bytes)

 Si tienes muchos errores de transmisión, puedes bajar este número para evitar reintentos,
pero ten en cuenta que el paquete conlleva una carga propia entre las radios y psi lo bajas
mucho, puedes estar enviando muchos más datos de control que de mensajes y esto es un
desperdicio.

Por ultimo tendremos que abrir los canales de comunicación o pipes, uno para emitir y el otro para
recibir
radio.openWritingPipe(pipes[0]);

radio.openReadingPipe(1,pipes[1]);
Y a partir de ahora, ya podemos empezar a escribir lineas de código.

Prgramando la comunicación de un par de módulos NRF2401

Montaremos de nuevo un par de Arduinos conectados mediante los NRF2401, con el mismo
esquema que en la sesión anterior y que repito aquí para vagos y gente con muchas cosas que hacer:

De nuevo tendremos dos roles diferenciados. Uno será el emisor y el otro el receptor. Comencemos
con el programa del emisor Prog_79B_Emisor:

#include <SPI.h>

#include "nRF24L01.h"

#include "RF24.h"

RF24 radio(9,10);

const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

void setup(void)

{ pinMode(10, OUTPUT);

Serial.begin(9600);

radio.begin();
radio.setRetries(15,15); // Maximos reintentos

//radio.setPayloadSize(8); // Reduce el payload de 32 si tienes problemas

radio.openWritingPipe(pipes[0]);

radio.openReadingPipe(1,pipes[1]);

Nada nuevo en el setup. Veamos el loop:

void loop(void)

radio.stopListening(); // Paramos la escucha para poder hablar

unsigned long time = millis();

Serial.print("Enviando ") ; Serial.println(time) ;

bool ok = radio.write( &time, sizeof(unsigned long) );

if (ok)

Serial.println("ok...");

else

Serial.println("failed");

radio.startListening(); //Volvemos a la escucha

Dejamos de escuchar en la radio para poder emitir. Leemos el valor de millis (O de cualquier otro
parámetro que queramos enviar, como una temperatura) y lo enviamos para después testear si la
emisión ha sido o no correcta.

unsigned long started_waiting_at = millis();


bool timeout = false;

while ( ! radio.available() && ! timeout ) // Esperamos 200ms

if (millis() - started_waiting_at > 200 )

timeout = true;

Esperamos la confirmación de que han recibido el mensaje en destino, durante 200 ms. Y al salir
comprobamos si se acabó el tiempo, o hemos recibido un mensaje.

Si ha disparado el timeout imprimimos un mensaje de error, y en caso contrario procesamos el


mensaje recibido.

if ( timeout )

Serial.println("Error, No ha habido respuesta a tiempo");

else

{ // Leemos el mensaje recibido

unsigned long got_time;

radio.read( &got_time, sizeof(unsigned long) );

Serial.print("Respuesta = ");

Serial.println(got_time);

delay(500);

Creo que no tendréis problemas con este programa. Vamos con el receptor Prog_79_B_receptor.

El setup es exactamente igual que en el emisor con una pequeña diferencia clave, los pipes de
comunicación se invierten, ya que si el emisor escucha por un canal, el receptor necesariamente tiene
que hablar por él y viceversa, para que se puedan poner de acuerdo.

Por eso, el receptor empieza a escuchar en el setup y define los pipes de lectura y escritura invertidos
con relación al emisor:
radio.begin();

radio.startListening();

radio.openWritingPipe(pipes[1]);

radio.openReadingPipe(1,pipes[0]);

Y para el loop del receptor tenemos:

if ( radio.available() ) // Si hay datos disponibles

unsigned long got_time;

bool done = false;

while (!done) // Espera aqui hasta recibir algo

done = radio.read( &got_time, sizeof(unsigned long) );

Serial.print("Dato Recibido =");

Serial.println(got_time);

delay(20); // Para dar tiempo al emisor

radio.stopListening(); // Dejamos d escuchar para poder hablar

radio.write( &got_time, sizeof(unsigned long) );

Serial.println("Enviando Respuesta");

// Volvemos a la escucha para recibir mas paquetes

radio.startListening();
}

Aquí os pongo un pequeño video mostrando el resultado de la comunicación:

He hecho una prueba usando estos programas dejando el emisor en mi PC y colocando el receptor en
mi portátil, para ver moviéndome por casa, hasta donde me he podido alejar sin perder la señal.

El resultado ha sido bastante pobre, ya que en cuanto colocas paredes de por medio la comunicaron
se pierde con rapidez a partir de 10 metros, lo que no resulta extraño dado que estoy usando módulos
con antena integrada.

Normalmente a estos módulos se les asigna un alcance de 20 o 25 m sin obstáculos y esta distancia
disminuye rápidamente a medidas que la señal encuentra obstáculos, ya que la potencia de emisión
es muy baja y por tanto, el resultado de la prueba concuerda con esta idea.

Si queremos ampliar el radio de cobertura tendremos que pasar a usar antenas amplificadas,
similares a estas:

Estos módulos incluyen, no solo un adaptador de antena, además llevan integrado un


amplificador de señal para potenciar la emisión y recepción de señal, con lo que la distancia útil de
transmisión crece hasta unos 100 metros (Según he visto en Internet).

En las pruebas que hemos hecho nosotros usando un par de estos módulos, puedes conectar
cualquier punto de una casa de tamaño medio sin problemas, pero no los hemos podido probar en el
campo.
Por último y para cerrar esta sesión, comentar que también existe disponibles adaptadores USB con
NRF2401 incluido, lo que nos permite enviar y recibir mensajes desde nuestro PC a estos módulos.

De hecho tengo uno de un fabricante chino, pero me temo que Windows se niega tercamente a
reconocerlo y la página del fabricante es un desastre en el que soy incapaz de encontrar ningún
driver para él.

Pero vale la pena comentar, que disponer de un medio de interactuar con estas radios desde nuestros
portátiles es una utilidad que amplia enormemente las posibilidades de comunicación y control de
nuestros Arduinos.

Seguiré insistiendo con él y si consigo arrancarlo, os lo hare saber.

Resumen de la sesión

o Seguimos profundizando en los módulos NRF24L01.


o Hemos visto más comandos disponibles en la librería que nos ayudaran a minimizar
los problemas de interferencias y reenvíos.
o Escribimos unos programa básicos para comunicar dos de estos módulos y
establecer un canal de ida y vuelta
CONTROL REMOTO RF
SENCILLO
Controlando a distancia con un mando sencillo

Objetivos

o Presentar unos módulos de control remoto por RF.


o Introducir los integrados 2262 / 2272, encoder decoder.
o Un control sencillo mediante mando a distancia simple.

Material requerido.

2 x Arduino UNO o equivalente.

1 x Protoboard .

Algunos cables de protoboard, Dupont macho-hembra

Un emisor receptor de 315MHz con 2262/2272


Los módulos RF

Hasta la fecha hemos ido dedicando toda una serie de sesiones a hablar de módulos de Radio
Frecuencia RF, basados en diferentes normas y estándares que nos permitían comunicar nuestros
humildes Arduinos con un mundo exterior que suele ser más o menos confuso.

Así hemos visto como enviar mensajes vía TCPIP mediante módulos WIFI del tipo del ESP8266 en
sus distintas variantes y también usar el Bluetooth de nuestros teléfonos para comunicarnos con
nuestros proyectos.

A más bajo nivel, presentamos los módulos de radio NRF24L01 que tienen la enorme virtud de tener
un muy largo alcance si usamos la antena adecuada, mucho más que el WIFI o el Bluetooth y suelen
ser más baratos.

Pero todos estos sistemas adolecen de un problema común: Que tenemos que construirnos el mando
a distancia. Cierto que tenemos todo lo necesario, pero al final nuestro mando acaba pareciendo un
cacharro salido de la pesadilla de un científico loco, por no hablar de la probabilidad de que algo se
suelte en el peor momento (Por la ley de Murphy, ya sabes).

En muchas de esas ocasiones, en que necesitamos simplemente un control remoto sin


complicaciones y con mucha frecuencia, de un alcance inferior a 15 metros, el tema de conseguir un
mando a distancia cómodo y barato puede convertirse en el principal problema.

Por eso me ha parecido que podía ser interesante presentaros algunos componentes muy sencillos
que por unos poco euros te resuelven la papeleta de conseguir un mando remoto práctico y un
circuito sencillo que te permita manipular algo a no demasiada distancia.

La idea de esta sesión es presentaros una pareja de mando a distancia de 4 canales con su receptor
correspondiente que podemos manejar en nuestros proyectos con la menor complicación, y para eso
os tengo que hables de un par de chips que el mercado nos ofrece y en los que se basan los productos
de esta sesión.

Los integrados 2262/2272

En las comunicaciones a distancia siempre tenemos un problema parecido. Necesitamos un emisor y


un receptor y tener claro si la comunicación es unidireccional: Solo uno envía y el resto recibe, o si
por el contrario la comunicación es bidireccional: Uno envía, pero el que recibe tiene que responder
y por tanto ser también emisor.
Todas las sesiones previas que hemos presentado anteriormente, correspondían a módulos de
comunicación que permitían establecer una comunicación bidireccional, y naturalmente nos parece
lo normal y que no tendría sentido otra cosa.

Pero lo cierto es que hay muchas ocasiones en las que no se requiere la comunicación
bidireccional. Imagínate el mando a distancia de la tele o de la puerta de un garaje. Basta con que el
emisor envíe la orden y que el receptor demuestre que no estaba sordo haciendo la operación
requerida.

No es necesario que la puerta del garaje nos informe de que nos ha oído. Basta con que inicie la
apertura. Si trascurrido un par de segundos no vemos que nos haga caso, pulsamos de nuevo el
mando y punto. La bi direccionalidad de la comunicación es superflua.

La ventaja de establecer comunicación unidireccional es que los circuitos de control son mucho más
sencillos y baratos y nos solemos ahorrar cantidad de complicaciones.

Por ello el mercado, siempre atento a la oportunidad de olfatear negocio, vio una ocasión para
proveernos con un par de chips que pretende esto exactamente, la pareja 2262 / 2272.

2262

2272
Estos son un par de chips de tecnología CMOS, tipo encoder / decoder, pensados para establecer
una comunicación sencilla entre dos puntos en modo unidireccional y tienen la virtud de ser muy
sencillos y baratos, y por eso hay cantidad de productos que se apoyan ellos.

Desde mandos a distancia de infrarrojos hasta pequeños módulos inalámbricos para puertas de garaje
y similares. De hecho hay bastantes posibilidades de que tengáis alguno en casa o en la puerta del
garaje, pero no os asustéis. Solo quería presentároslos y hablar de su utilidad.

Como el objetivo de estas páginas no es entrar en la electrónica de los integrados salvo que sea muy
interesante, vamos a pasar directamente a ver algún producto que los usan para enviar señales
sencillas que podamos usar en nuestros proyectos.

Control remoto a 315 MHz

Uno de los productos más divertidos y sencillos que podéis encontrar son esta pareja de emisor
receptor por RF, que son de lo más molones para cualquier chapuza que os planteéis que necesite
un control sencillo del tipo enciende apaga, son esta pareja:

Son básicamente un emisor de 4 canales con formato llavero y con antena retráctil, y un sencillo
receptor basado en nuestro chip 2272, que activa uno de 4 pines en función del botón que se pulse en
el mando remoto. ¿Fácil no?

Vamos a ver cómo se comporta el modulo receptor que podemos conectar a nuestros Arduinos para
controlar lo que os parezca, empecemos describiendo los pines:
Las conexiones son triviales. Conectar tensión y Ground y después cuando se pulsa un botón el
mando remoto, si la comunicación es correcta levanta el pin VT para indicar que ha detectado una
transmisión valida (Valid Trans).

Por otra parte, los pines D0, D1, D2, D3 se activan con un HIGH, cuando se pulsa el botón A, B, C,
D respectivamente, por lo que vamos a conectarlos a los pines digitales de Arduino 8, 9, 10, y 11. Y
eso es todo, no tiene más complicación.

La conexión que vamos a usar en el programa será así de sencilla:

ALIMENTACIÓN VALIDO DATOS

MODULO
GND Vcc VT D3 D2 D1 D0
RF

ARDUINO GND 5V 7 11 10 9 8

Fijaros que además el receptor requiere que le conectéis una antena sencilla si os vais a alejar unos
cuantos metros. Para eso basta con que soldéis un cable arrollado en espiral a la conexión de antena
que veis en la esquina superior izquierda.

 En el vídeo de demostración yo no voy a usar antena porque voy a emitir a 15 cm del


receptor y para ese viaje no se necesitan alforjas.

Podéis hacerlo simplemente arrollando un cable conductor alrededor de un lápiz tal y como indica
Jesús en este proyecto.
Esto es la electrónica que me gusta sin complicaciones superfluas. Hace lo que tiene que hacer y
punto.

El programa de control

Como la señal que nos entregan los módulos son muy simples el programa es igual de sencillo y
rápido de poner en marcha, no requiere librerías ni otras zarandajas, simplemente leer y escribir
pines digitales de Arduino. Sesion_129__1

Empezamos inicializando pines y puerta serie:

void setup()

{ Serial.begin (9600);

pinMode (13, OUTPUT) ;

pinMode (12, OUTPUT) ;

for (int i = 7 ; i < 12 ; i++)

pinMode(i, INPUT) ;

Y ahora leemos los pines sin más:


void loop()

if (digitalRead(7) ) // Si hay dato valido

{ Serial.print("Valid trans. \t");

if (digitalRead(8))

Serial.print( "Boton A, pulsado");

if (digitalRead(9))

Serial.print( "Boton B, pulsado");

if (digitalRead(10))

Serial.print( "Boton C, pulsado");

digitalWrite (12, ! digitalRead(12)) ;

delay (500) ;

if (digitalRead(11))

Serial.print( "Boton D, pulsado");

digitalWrite (13, ! digitalRead(13)) ;

delay (500) ;

Serial.println("\t");

}
Comprobamos con el pin digital 7 si hay una entrada valida de datos, es decir, si se ha pulsado un
botón en el mando e imprimimos un mensaje de código valido recibido.

Cuando es así, sacamos un mensaje simple indicando que botón se ha pulsado y poco más. Si el
botón pulsado es el D o B, levantamos el pin 13 o 12, para excitar lo que tengamos conectado, en mi
caso un relé sencillo.

Además saca por la consola información sobre el botón pulsado (No está muy pulido que digamos).

Y para cerra aquí va un pequeño vídeo de muestra:

https://youtu.be/yEIbaicANQM

Resumen de la sesión

o Hemos introducido muy por encima una pareja de chips 2262/ 2272 como encoder
y decoder pareados.
o Presentamos los mandos a distancia sencillos basados en estos chips.
o Vimos como utilizarlos en nuestros propios proyectos.
o Presentamos ejemplo de programacion con ellos.

You might also like