Está en la página 1de 237

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.
o 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).
o 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++.

MATERIAL REQUERIDO.

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


Un PC con el entorno de Arduino correctamente instalad

 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.

MATERIAL REQUERIDO.

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


entorno de Arduino correctamente instalado y configurad
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.

MATERIAL REQUERIDO.
 Arduino Uno o similar. Un PC con el entorno de Arduin
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.
MATERIAL REQUERIDO.

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


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 sin pulsar, 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.
MATERIAL REQUERIDO.

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


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 COMENTA

int i = 4 * 2 resultado =  8

int i = 4 * 2 / 3 resultado = 2 Porque desprecia los dec

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

Int i = 2 + 8 / 2 resultado = 6 Calcula primero

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


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.

MATERIAL REQUERIDO.
 Arduino Uno o similar. Un PC con el entorno de A
configurado.

DIBUJAR UNA GRÁFICA UTILIZANDO EL SERIAL PLOTTER


 

Ya hemos utilizado muchas veces el monitor serie del IDE para mostrar valores de las
variables de nuestro programa. Pero en ciertas ocasiones puede ser útil verlo en forma
de gráfica en vez de en datos numéricos, por ejemplo, para ver la tendencia de los datos de
una forma sencilla y clara.

Pues resulta que el IDE de Arduino incorpora desde la versión 1.6.6 una herramienta
llamada Serial Plotter que nos permite precisamente crear gráficas a partir de las variables
que le indiquemos. Es muy sencillita de usar y por el momento no ofrece muchas opciones,
pero seguramente vayan añadiendo características nuevas con nuevas versiones.

Para utilizarla no tenemos que aprender nada nuevo en cuanto a la programación.


Simplemente haremos un programa que muestre un valor por el puerto serie. Podéis utilizar
este programilla que genera números aleatorios cada cierto tiempo:

void setup()

Serial.begin(9600);

void loop()

int valor;
valor = random(0,100);

Serial.println(valor);

delay(250);

Ahora en vez de abrir el Monitor Serie, abriremos el Serial Plotter, que está en la barra de
herramientas, justo debajo.

Y cuando carguemos el programa en la placa, veremos cómo se va generando una gráfica a


partir de los valores aleatorios que va cogiendo la variable.

 
CÓMO INCLUIR MÁS VARIABLES
 

La herramienta también nos da la opción de mostrar varias variables a la vez en la misma


gráfica. La manera de hacerlo es también secillísima, simplemente tendremos que sacar las
mostrar las dos variables por el puerto serie pero utilizando un separador “,” entre ellos, y
automáticamente los dibujará en la misma gráfica con un color diferente.
Si añadimos otra variable que tome también valores aleatorios al programa anterior, el
programa quedaría de la siguiente forma: Grafica_2_variables.

void setup()

Serial.begin(9600);

void loop()

int valor1;

int valor2;

valor1 = random(0,100);

valor2 = random(0,100);

Serial.print(valor1);

Serial.print(",");

Serial.println(valor2);

delay(250);

}
RESUMEN DE LA SESIÓN
.
 
o Hemos descubierto una nueva herramienta que nos permite
hacer gráficas fácilmente desde el mismo IDE de Arduino.
o Sabemos incorporar varias variables a la gráfica.
o Ahora que sabemos que existe esta herramienta y cómo se utiliza, podéis
incorporarla a vuestros proyectos para realizar gráficas de las medidas de sensores, la
velocidad de un motor, o lo que se os pase por la cabeza.

MATERIAL REQUERIDO.

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


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

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

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

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

byte Entero sin signo, 8 bits 28 de 0 hasta


 

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

String Funcion2() Indica que va a devolver

unsigned long Funcion3() Indica que va a devolver un l

void Funcion4() No va a devolver valores e


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.
MATERIAL REQUERIDO.

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


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.
 
 

MATERIAL REQUERIDO.

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


 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.

MATERIAL REQUERIDO.

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

 Una Protoboard.
Un diodo LED RGB, independiente,  o bien, con montur

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.

MATERIAL REQUERIDO.

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

 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().

MATERIAL REQUERIDO.

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

Una Protoboard más cables.

Un diodo LED y una resistencia de 330Ω.


Un transistor 2N2222. Comprobad que lleva rotulada es
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 c


el transistor.
No es imprescindible, pero un transistor suele ser má
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.
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 referenc


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

MATERIAL REQUERIDO.

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

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, p
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.


 

MATERIAL REQUERIDO.
 Arduino Uno o similar.
Esta sesión acepta cualquier otro modelo de Ard
 

 Una Protoboard mas  cables.

Un Joystick.

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

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.

MATERIAL REQUERIDO.

 Arduino Uno o similar.


Esta sesión acepta cualquier otro modelo de Ard
 

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.
 

 
 

MATERIAL REQUERIDO.

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

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.

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.

MATERIAL REQUERIDO.

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

 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 P

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
 

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().

MATERIAL REQUERIDO.
 Paciencia y 20 minutos de

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

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:

PREFIJO VALOR DECIMAL

Kilo 103 Mil

Mega 106 Millón

Giga 109 Mil Millones

Tera 1012 Billón europeo

Peta 1015

Exa 1018

Zetta 1021
¿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

A 65 0100  0001

B 66 0100  0010

C 67 0100  0011

D 68 0100  0100
 

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.

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.

MATERIAL REQUERIDO.

Paciencia y 20 minutos de

 
 

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

Velocidad reloj 8.8 MHz 2.4 GHz

Memoria RAM 128 kB – 640 kB 4 Gb – 64 Gb

Disco duro 500 kB 4 Tb

Bus datos 8 64
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

Dynamic Random Access Memory,Son las memoria típicas de los PCs. Se construyen a b


DRAM integrar cantidades ingentes de ellas en un único chip de forma barata.A cambio tiene que
complica el diseño con mecanismos de refresco de la memoria ( Por supuesto fuera de los

SDRAM  Synchronous Dynamic Random Access MemoryComo las DRAM, pero el mecanismo de r

Double Data Rate Synchronous Dynamic Random Access Memory.Estas son las actuales


DDR
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 unos
PROM
prácticamente están en desuso

Electically Erasable Programable Read only MemorySon igual que las PROM, pero con la
EEPROM eléctricamente lo que evita el engorro de llevarlas a reprogramar a maquinas raras.A camb
número limitado de escrituras antes de morir.

Es un derivado de la EEPROM, con varias ventajas, la principal es que no pierde la inform


FLASH corriente y además pueden leerse y escribirse sobre la marcha.El inconveniente es que so
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

Procesador ATMEGA 328 ATmega2560

Anchura 8 bits 8 bits

Velocidad 16 MHz 16 MHz

Pines digitales 14 54

Pines PWM 6 16

Convertidores ADC 6 16

Convertidores DAC 0 0

Interrupciones 2 24

Memoria FLASH 32Kb 256Kb

SRAM 2Kb 8kb

EEPROM 1Kb 4kb

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 MOD

Arduino Leonardo.Es como un UNO


es el primer Arduino que incorpora ge
gestionado por un segundo procesad
permite presentarse al PC host como

Arduino Mini.Es como un UNO, el mi


montado pensando en el que ocupe l
prototipos, pero no incluye USB, deb
programarlo.

Arduino Micro.Es como un Leonardo,


incluido. Hasta un mini USB para pro
para incluir en la protoboard, porque

Arduino Yun.No sé muy bien qué dec


le  han puesto un copiloto que corre u
equipo Arduino ha desarrollado una l
procesador Arduino y el Linux, y apar
lleva incluido WIFI y lector de tarjetas
costar más que el Yun.Tengo uno po
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.
 

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.
 
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

MATERIAL REQUERIDO.

Arduino Uno o compatible y con el firmware para S4A

Un PC con el entorno S4A correctamente instalado y co

Una Protoboard.

Un diodo LED.

 Un sensor de sonido KY-038 o similar.

 Una resistencia de 330 Ohmios.


 
Algunos cables de Protoboard.

EL SENSOR DE SONYDO KY-038


 

Este tipo de sensor tiene montura Keyes para facilitarnos el montaje.

En la parte de la izquierda vemos lo pines de conexión:

 
 En el centro tenemos la conexión a 5V y a GND (+ y G).
 D0 es una salida digital que actúa a modo de comparador. Si el sonido captado por
el micrófono supera un determinado nivel se pone a HIGH.
 A0 es una salida analógica que nos da un valor entre 0 y 1023 en función del volumen
del sonido.[/fancy-ul] 
Además tenemos dos LEDs, uno que nos indica si hay alimentación en el sensor y otro que se
ilumina si D0 está a HIGH.

El ajuste de sensibilidad del micrófono lo hacemos mediante un potenciómetro que tendremos


que girar con un destornillador plano.

CIRCUITO DE ILUMINACIÓN ACTIVADO POR SONIDO


 

Primero vamos a usar la salida digital D0 como señal para encender un LED, de forma que
cuando demos una palmada, un silbido o hagamos algún ruido un poco alto, se encienda o se
apague un LED.

Sólo necesitamos conectar el pin D0 y los dos pines de alimentación, tal como se ve en el
diagrama electrónico y el montaje en la protoboard:
Si hemos conectado bien el sensor, se debería iluminar el LED de alimentación. El de salida
digital accionada puede o no estar encendido.

 
AJUSTANDO EL LÍMITE DE DISPARO
 

Esta es seguramente la parte más complicada de esta sesión. Para ajustar el límite de disparo
lo que hacemos es girar el potenciómetro con un destornillador. Tenemos que dejarlo de tal
forma que el LED que marca si está accionada la salida digital esté apagado, pero lo más
próximo posible al límite en el que se enciende.

 
 Si lo ajustamos mal y el LED se está encendido, no detectaremos ningún cambio y no
podremos reaccionar a ningún estímulo sonoro.
 Si lo ajustamos de forma que esté apagado pero demasiado lejos del límite en el que
se enciende, habrá que llamar al increíble Hulk para que dé una palmada por nosotros. 
 

PROGRAMANDO EL SENSOR
 

El programa para controlarlo es muy sencillo y es el mismo que hemos utilizado varias veces
para controlar un interruptor. La diferencia es que en vez de utilizar un pulsador, si el sensor
detecta un sonido por encima del límite enviará una señal que recogeremos en la entrada
digital 2.

int LED = 13 ;

int sensor = 6 ;

bool estado = false ;

void setup()

pinMode( LED, OUTPUT) ;

pinMode( sensor , INPUT_PULLUP) ;

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

}
void loop()

bool valor = digitalRead(sensor) ; //leemos el estado del sensor

if ( valor == true ) //Si está activada la salida D0

estado = ! estado ; // cambiamos el estado del LED

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

delay (1000);

 
 Si no sois capaces de encender el LED de una palmada, probad a pegar un silbido, un
soplido o a hablar cerca del micrófono. 
 
Podéis descargar el programa completo aquí: Sensor_sonido_D0.

UTILIZANDO EL PIN A0 PARA LEER LAS MEDIDAS DEL


SENSOR
 

Como hemos explicado al principio, el pin A0 nos devuelve un valor entre 0 y 1023 en función
del volumen del sonido que esté registrando.

Las conexiones serían las mismas pero conectando la salida A0 del sensor a cualquier
entrada analógica del Arduino. Podéis desconectar la salida D0 o dejarla conectada y seguir
usándola. El potenciómetro del sensor serviría en este caso para fijar la sensibilidad del
sensor.
El programa para mostrar las medidas del sensor en el monitor serie sería muy sencillito y ya
lo hemos utilizado varias veces:

void setup()

Serial.begin(9600); // Iniciamos la puerta serie

void loop()

{
int Lectura = analogRead(A5) ;

Serial.println( Lectura);

delay(200) ;

RESUMEN DE LA SESIÓN
 

En esta sesión hemos aprendido varias cosas importantes:

 
 Cómo funciona el sensor de sonido KY-038 y a utilizar tanto su salida digital como
analógica.
 Podemos interaccionar con nuestro Arduino a través del sonido.

MATERIAL REQUERIDO.

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


Una Protoboard más cables.

Un diodo LED y una resistencia de 330Ω.

Un transistor 2N2222. Comprobad que lleva rotulada es


temperatura es similar.

 Un ventilador de 5V o un motor de corriente continua.

Un Sensor de temperatura LM35DZ o similar.Comproba


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.
MATERIAL REQUERIDO.

 Arduino Uno o similar.

Esta sesión acepta cualquier otro modelo de Arduino.


 

 Una Protoboard.

 Cables  de protoboard

 Una resistencia.

 Un display de 1 dígito.


 

LOS DISPLAYS LED


 

En cuanto empecéis a plantearos hacer un circuito que realice alguna función práctica, hay un
50% de probabilidades de que acabéis necesitando enviar información al mundo exterior (y
claro no vais a dejar vuestro portátil pegado al invento).

Así que es el momento de ver que nos ofrece el mercado para mostrar información y para
empezar, nada mejor que un sencillo display LED de 1 digito.

Los diodos LED ya no guardan secretos para los que nos siguen, pero esto de un display
parece otra cosa.
Pues no. Es lo mismo pero en lugar de ser un punto luminoso como los familiares LED, tiene
forma de barra: 7 barras más 1 punto.

Estos displays nos son bastante familiares en despertadores y similares, están formados por 7
líneas, que a dependiendo de qué segmentos  se iluminan, muestran los dígitos del 0 al 9.

A cada uno de los 7 segmentos se les adjudica una letra para representarlos y suele ser a, b,
c, e, f, g y aparte un punto (o dos, o dos puntos según el fabricante) y es un buen momento
para echar un vistazo a las especificaciones de cada fabricante para estar seguros de que pin
es cual.

Todos los circuitos, los displays incluidos, llevan un código de fabricante rotulado. Es buena
política buscar en internet la hoja de especificaciones(o data sheet) y echarle un ojo. Si no
entendéis nada, es lo normal de momento, pero desde luego habrá un dibujo diciéndoos que
es cada pin. Yo he buscado el modelo que tengo delante, (un Kingbright SC08-11HWA ), pero
no os fieis, el vuestro puede ser distinto.
 
 Desde que existe Internet, localizar una hoja de características es algo trivial (No
como antes, que para conseguirlas había que pedir favores y mostrar las debidas muestras de
respeto y sumisión a quien disponía de catálogos de componentes).
 Probad a buscar en Google algo así como XXXXX data sheet, donde XXXXX son los
códigos que habéis encontrado rotulado en el display o componente que sea.  
Lo importante es que sepáis que es cada pin, y que veáis que segmento es cual. En realidad
es bastante más fácil de lo que parece, localizad primero un GND. En el de arriba son el 3, 5,
11 y 16.

Poned una resistencia (de 330Ω como siempre) de la salida del display a GND. Este es un
display de cátodo común, o sea que todos los LEDS comparten la masa, pero necesitamos
poner una resistencia de limitación o fundiréis el display, y este vale ya lo suficiente, como
para que os cueste verle la gracia al tema.
Una vez que hayáis conectado la masa común con una resistencia, empezad cableando solo
un LED, el a por ejemplo y conectadlo al pin 2 de Arduino. Escribid un programa en Arduino
para iluminar el LED en el pin 2 y veréis como se enciende el segmento a.

Podéis ir conectando y probando el resto de los pines poco a poco, asegurando las
conexiones. Es muy fácil equivocarse si no andáis con tiento.

Kit de Inicio Prometec.net 


Para los que uséis el nuevo kit de inicio de Prometec, el display que viene es un 5161AS que
tiene un patillaje y cuyo diagrama es este:

Para saber cual es el pin 1, poner el display de modo que viendo los numeros el punto decimal
quede abajo a vuestra derecha. El pin numero 1 es en la parte inferior el primero por la
izquierda, y luego ir contando en el sentido contrario a las agujas del reloj.
 

ESQUEMA ELÉCTRICO DEL CIRCUITO


 

El circuito no puede ser más sencillo, son como cuando hicimos un circuito con 8 diodos, solo
que esta vez los 8 diodos están en una cajita y con forma para dibujar números.
 
 Es importante que sigáis el esquema de aquí encima para que luego el programa
coincida con vuestras conexiones.
 Por eso no es importante que pin de vuestro display es el segmento C (Que
dependerá del fabricante y modelo), pero si que es importante que el segmento C vaya al pin
digital 4 de Arduino y lo mismo para los demás.  
No vamos a incluir el diagrama de protoboard, porque es difícil dejarlo más claro

PROGRAMA DE CONTROL
 

Tenemos que comprobar que las conexiones son correctas lo primero. Probad esto:

void setup()

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

pinMode(i, OUTPUT);

void loop()

for ( int j= 2; j<11 ; j++)   // Va encendiendo los segmentos

digitalWrite(j, HIGH);

delay(400) ;

for ( int j= 2; j<11 ; j++) //Apaga todos los segmentos

digitalWrite(j, LOW);

delay(400) ;
}

En el setup, inicializamos los 8 pines de salida con for (recordar que somos vagos) y en el
loop usamos una primera iteración que va iluminando los 8 segmentos con un delay, y en la
segunda los borra y vuelta a empezar. La idea es comprobar que las conexiones son
correctas.Vereis algo así:

Lo siguiente es mostrar los dígitos del 0 al 9.

Para ello, lo más rápido es hacerte una tabla para ver que segmentos tienes que iluminar para
cada digito decimal, y vas apuntando cuales son 1 (encendido) o 0 (apagado).

  DIGITO A B C D E

0 1 1 1 1 1

1 0 1 1 0 0

2 1 1 0 1 1

3 1 1 1 1 0

4 0 1 1 0 0

5 1 0 1 1 0

6 1 0 1 1 1

  7 1 1 1 0 0

8 1 1 1 1 1

9 1 1 1 0 0
 
 Aunque os damos los deberes hechos, haced la prueba con alguno de los dígitos,
simplemente, para aseguraros de que entendéis la idea
 
Ahora solo queda escribir el programa que dibuja los números en el display, así que vamos a
ello.

PROGRAMA QUE DIBUJA LOS DÍGITOS


 

La primera idea que se nos ocurre a todos es hacer una función por cada digito que queramos
representar. Por ejemplo podríamos hacer:
void Display7()

       digitalWrite(2, 1) ;        // Si, podemos decir 1 y 0 en lugar de HIGH y LOW

digitalWrite(3,1);

digitalWrite(4,1);

digitalWrite(5,0);

…………..

Es decir, encendemos los pines correspondientes a cada segmento a imagen de la tabla


previa.

El problema de este enfoque es que hay que hacer 10 funciones como esta y luego escribir en
el programa principal algo que llame a la función correspondiente según el número que
queramos mostrar.

Esta es, de nuevo, la solución de fuerza bruta y no, aquí no permitimos esas cosas, nos
gustan las soluciones elegantes (y porque, además, somos muy vagos y nos cansamos solo
de pensar en hacerlo así).

 
 Por cierto, para ser alguien en la comunidad freaky, hay que hablar de la elegancia de
tu código siempre que surja la ocasión, si queréis ser programadores es muy importante que
empecéis a adoptar las poses del gremio. 
 
Así que vamos a buscar otra solución más elegante. Para empezar, todos los que al ver  la
última tabla, con los segmentos que hay que iluminar, hayáis pensado que se parece
sospechosamente a un array de 10 x 8 podéis anotaros un punto por listos.
Porque por supuesto vamos a crear una array con todo eso (No, no tenemos comisiones por
vender los arrays) y veréis que el programa se simplifica mucho.

De nuevo, como con todo en la vida, es mucho más fácil de lo que parece. Vamos a empezar
definiendo el array de dos dimensiones (porque es una tabla, otra cosa son el número de
elementos por dimensión):

byte  Digit[10][8] =                // Arduino UNO va muy justo de memoria. Por eso lo

{ // definimos como byte y no como int

  { 1,1,1,1,1,1,0,0 },    // 0   


{ 0,1,1,0,0,0,0,0 },    // 1

{ 1,1,0,1,1,0,1,0 },    // 2

{ 1,1,1,1,0,0,1,0 },    // 3

{ 0,0,1,0,0,1,1,0 },    // 4

{ 1,0,1,1,0,1,1,0 },    // 5

{ 1,0,1,1,1,1,1,0 },    // 6

{ 1,1,1,0,0,0,0,0 },    // 7

{ 1,1,1,1,1,1,1,0 },    // 8

{ 1,1,1,0,0,1,1,0 }     // 9

};

Si os fijáis, he copiado directamente la tabla de mostrar los dígitos, pero en un array de 10


elementos, cada uno de los cuales es un array de 8(segmentos). La sintaxis es más o menos
complicada, pero no hay más y esto ya lo habíamos hecho antes.

Podemos ahora crear una función, que pasándole un número de 0 a 9, elija la fila del array en
función de ese mismo número y busque el array interno correspondiente.

void Display(int N)

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

{   int valor = Digit[N][i] ;

int pin = i+2;

digitalWrite(pin , valor) ;

}
Buscamos  valor en la tabla cuyo índice principal N apunta al array interno correspondiente.  El
for i, va leyendo los 8 elementos del array para escribirlos en el pin correspondiente de salida,
que lo calculamos como i +2, (Porque usamos los pines 2 al 10 para conectar los segmentos
del display y así unos valores de 1 de 0 a 8 se convierten en pines de 2 al 10).
void setup()

{   for (int i= 2; i<11; i++)

pinMode(i, OUTPUT);

void loop()

for ( int k=0 ; k<10 ; k++)    // Llama a Display para k de 0 a 9, los digitos

{  Display(k);

delay(1000);

void Display(int N)

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

{   int valor = Digit[N][i] ;

int pin = i+2; 

digitalWrite(pin , valor) ;    // digitalWrite(i+2 , Digit[N][i] ) ;

          }
}

Fijaros que podíamos haber escrito así (El código compacto también puntúa con los colegas):
void Display(int N)

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

digitalWrite(i+2 , Digit[N][i] ) ;

He aprovechado este ejemplo para insistir con los arrays, porque son muy útiles para resolver
problemas que de otro modo se pueden complicar bastante.

Un problema que a priori, era muy pesado, o complejo, se transforma en una nimiedad
recorriendo la tabla. He visto varios ejemplos por internet de este programa y la mayor parte
de ellos me ha dado dolor de cabeza (Con algunas muy honrosas excepciones).

La cosa ha ido bastante bien con un digito, pero… ¿Y si queremos mostrar 4 dígitos? ¿Vamos
a multiplicar 8 cables x 4 dígitos más tensión y GND = 34 pines?

En la próxima sesión veremos cómo manejar un display de 4 dígitos, porque para eso los
venden hechos, y no es necesario volvernos locos enchufando no sé cuántos cables para
hacer un reloj.

 
 Como esta sesión ya es suficientemente densa, no incluiré el ejemplo de conectar un
único digito a un shift register para gobernarlo, pero os recomiendo que lo hagáis como
práctica, y si es preciso, colgamos el ejemplo en la página web.
 
 

RESUMEN DE LA SESIÓN
 

 
o Hemos presentado los displays LED de 7 segmentos y un dígito.
o Son LEDs completamente normales, solo que en forma de líneas y no de
puntos.
o Algunas de las funciones que hemos definido nos seran útiles en los siguientes
capítulos para gobernar mas display

MATERIAL REQUERIDO.
Arduino Uno o similar. Esta sesión acepta cualquier ot

Una Protoboard .

Cables de protoboard

4 x resistencias de 330Ω.

Un display de 7 segmentos y 4 dígitos.

4 x Transistor 2N2222

LOS DISPLAYS LED DE 4 DÍGITOS


 

En la sesión anterior, la cosa ha ido bastante bien con un dígito, pero ahora que le hemos
cogido el puntillo, queremos poder usar 4 dígitos para, digamos dar la hora.

Y si queremos mostrar 4 dígitos… ¿Vamos a multiplicar 8 cables x 4 dígitos más tensión y


GND, en total 34 pines?
Para empezar, Arduino UNO no tiene tantos pines (Si, el Mega sí que los tiene, pero recordad,
elegancia, mucha elegancia), entonces si vosotros fabricarais estos displays ¿Cómo evitaríais
usar 34 pines? Pensadlo, ¿Qué solución daríais vosotros al problema?
Pues una fácil ( y barata que es lo que les gusta a los que fabrican) es la de mantener 8 pines
para iluminar los 7 segmentos más el punto, y poner otros 4 pines para indicar a cuál de los
dígitos  corresponde la información que ponéis en a, b, c, d, e, f, g, h.

La cosa va por ahí, pero para eso habría que poner unas memorias y latch como en el shift
register y alguien dijo: No, no, más barato aun. Y un ingeniero creativo dijo: pues si hacemos
que esos 4 pines para indicar la posición vayan a tierra pasando por un transistor cada uno
podemos hacer que se ilumine solo uno cada vez. Y si hacemos el ciclo lo bastante rápido,
pasando de uno a otro, ni se enteran. Ni que decir tiene que el ingeniero creativo pasó a jefe
de proyectos.

Y eso es todo. Simplemente seguimos utilizando 8 pines para iluminar los segmentos, pero
solo hay uno activo en un momento concreto. Y haciendo un ciclo rápido, iluminamos uno
cada vez rápidamente y pasamos al siguiente y luego al siguiente y problema resuelto.

Así que lo primero que vamos a hacer es conectar los 8 segmentos del display a los pines del
2 al 10 de nuestro Arduino, para probarlos. Conectad GND al cátodo del primer digito con una
resistencia y comprobad las conexiones.

CONEXIONES INICIALES
 

De nuevo, tengo que insistiros en que leáis la hoja de características de vuestro display y no
os fieis del diagrama de abajo, porque el vuestro puede ser distinto. Mirad el código de vuestro
display y bajaros la data sheet de Internet. Leedla, aunque solo sea para comprobar si
vuestros pines coinciden con el diagrama que os pongo debajo (Que es del manual de
Parallax).

Este diagrama es para el display que tengo entre manos (5461AS) y el vuestro no tiene por
qué usar los mismos pines ( Aunque la probabilidad de que sea así es alta, y en caso negativo
tampoco es grave porque basta con que conectéis los pines correctos al mismo orden de
vuestro Arduino).
Lo que yo he hecho (porque mi display solo tiene 12 pines), es conectar los 8 segmentos y
enviar el cátodo a masa mediante una resistencia, para probar el primer digito y ya me
preocupare del resto luego. Es imperativo que os aseguréis de conectar correctamente los
segmentos antes que nada.

Podeís correr un programa simple como este, para comprobar la conexión de los segmentos,
que los va encendiendo y apagando en secuencia: Prog_31_1

void setup()

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

pinMode( i, OUTPUT);

void loop()

for (int j=2; j<10 ; j++)

{    digitalWrite( j, HIGH);

delay(300);
digitalWrite( j, LOW) ;

delay(300);

Si todos se encienden, ya podemos pasar a la siguiente fase.

DIAGRAMA DE CONEXIÓN
 

Ahora que estamos seguros de que nuestros 7 segmentos están enchufados donde
corresponde viene la cuestión de  utilizar 4 pines de Arduino para elegir cual se ilumina.

Nuestra primera idea sería conectar esas salidas del display, 12, 9, 8 y 6  a 4 pines de nuestro
Arduino. Si mantenemos esos pines en HIGH excepto el que queremos iluminar, que
ponemos en LOW, parece que cerraría el circuito a GND y ya está.

Pero no. El consumo típico de cada segmento, (como de cada LED) es de entre 15 y 20mA.
Como son 8 segmentos cuando escribamos el 8 más el punto, el consumo será de 8 x 15 =
120 mA y pudiendo llegar a 160mA. Muy por encima de los 40 mA que un pin de nuestro
Arduino puede suministrar o drenar, así que mejor que pensemos otra cosa antes de que
huela a quemado.

Y la solución, queridos amigos, es, naturalmente, utilizar un transistor para permitir cerrar el
circuito de cada dígito.
El 2N2222 es ya un viejo conocido (No os olvidéis de la resistencia de la base, es
imprescindible), poniendo a LOW los pines 9, 10, 11, y 12 los transistores están al corte, y
ningún digito puede iluminarse. Si ponemos tensión en el pin 12, su transistor se satura y
permite la salida a Ground del primer digito que encenderá los segmentos que le indiquen los
pines 2 al 8.

Ahora ponemos en LOW el pin 12 y en HIGH el 11. Los valores de los segmentos iluminaran
ahora el segundo digito. Y luego el terceo y el cuarto. El único trucos es hacerlo rápido, y eso
se le da muy bien a nuestro Duino.

EL PROGRAMA DE CONTROL
 

Vamos a reaprovechar la función Display () que escribimos en la sesión anterior para dibujar
los dígitos en el display, que si recordáis se apoyaba en un array para saber que segmentos
encender: Prog_31_2

byte Digit[10][8] =


{ 1,1,1,1,1,1,0,0 },    // 0

{ 0,1,1,0,0,0,0,0 },    // 1

{ 1,1,0,1,1,0,1,0 },    // 2

{ 1,1,1,1,0,0,1,0 },    // 3

{ 0,0,1,0,0,1,1,0 },    // 4

{ 1,0,1,1,0,1,1,0 },    // 5

{ 1,0,1,1,1,1,1,0 },    // 6

{ 1,1,1,0,0,0,0,0 },    // 7

{ 1,1,1,1,1,1,1,0 },    // 8

{ 1,1,1,0,0,1,1,0 }     // 9

};

void setup()

{           for (int i= 2; i<13; i++)

pinMode(i, OUTPUT);

Pero vamos a extender Display para que escriba un digito en la posición que queramos,
donde la posición 0 son las unidades, 1 las decenas, 2 las centenas y 3 los miles.

void Display(int pos, int N)

digitalWrite(9 ,LOW);        // Apaga todos los digitos

digitalWrite(10,LOW);
digitalWrite(11,LOW);

digitalWrite(12,LOW);

for (int i= 0 ; i<8 ; i++)    // Esto no cambia de la session anterior

digitalWrite(i+2 , Digit[N][i]) ;

digitalWrite(pos + 9, HIGH);      // Enciende el digito pos

Como veis, es la misma función en la parte de iluminar segmentos, pero hemos hecho que al
entrar los apague todos, luego levanta los pines que queremos y solo luego activamos el
transistor de salida de la posición que queremos, lo que hace que ilumine la posición pedida
en pos.

Calculamos el pin de salida como pos + 9, porque a las posiciones 0, 1, 2, 3 les corresponden
los pines 9, 10, 11, 12, también aquí, la elección del orden de los pines juega a nuestro favor.

Una vez que tenemos resuelto dibujar el número buscado en la posición elegida tenemos que
escribir otra función que descomponga un número dado en unidades, decenas, centenas y
miles.

En un alarde de creatividad he bautizado a esta función como CalculaDigitos()

void CalculaDigitos( int Num)

int Digit0 = Num %10 ;

int Digit1 = (Num % 100) / 10 ;

int Digit2 = (Num % 1000) / 100 ;

int Digit3 = Num  / 1000)  ;

Display(3 , Digit3);
Display(2 , Digit2);

Display(1 , Digit1);

Display(0 , Digit0);

Por si acaso alguien faltó el día que hablamos de las operaciones con enteros haremos un
caso concreto. Supongamos un número como 2.386. ¿Cómo obtenemos sus dígitos
separados?

2386 % 10 = 6          Porque el %  nos devuelve el resto de dividir por 10, o sea 6.

2386 % 100 = 86        Ahora hacemos la división entera por 10 o sea 8,los decimales
se tiran

2386 % 1000 = 386      386 / 100 = 3

2386  / 1000 = 2       Directamente, para eso se inventó la división entera.

Y a continuación le pedimos directamente que nos  saque los dígitos al display.

Por ultimo para la función principal, empecemos pidiéndole que cuente décimas de segundo
(La cuenta atrás la hacemos, luego) 
void loop()

CalculaDigitos( millis() / 100);

¿Creías que iba a ser difícil? Pues lo siento. Es así de sencillo. Ya conocíamos millis(), el reloj
interno de nuestro Duino en milisegundos. Pues haciendo la división entera (otra vez) nos da
un contador de hasta 999 segundos.

¿Y si queremos hacer una cuenta atrás?  Venga pensad un momento antes de mirar la
solución.

 
 Muy fácil también. Como nuestro contador va hasta 9999 basta con restarle a esto el
cálculo de arriba, o simplemente poner en lugar del 9999 la cifra desde la que deseamos
descontar.
 
 
Más interesante, y práctico supone convertir esa cifra a minutos y segundos sexagesimales
para hacer un reloj.

void loop()

int n = millis() / 1000 ;       // Lo pasamos a segundos

int segundos = n % 60  ;

int minutos =  n / 60  ;

int k = minutos * 100 + segundos ;

CalculaDigitos(k) ;

De nuevo a partir del reloj interno de nuestro Duino, millis(),(que cuenta en milisegundos por lo
que lo dividimos por mil para pasarlo a segundos), calculamos los segundos y minutos, para
luego llamar a CalculaDigitos() que espera un numero centesimal y por eso multiplicamos por
100 los minutos para que cuadre el display.
 

Os dejo como ejercicio que hagáis un reloj que efectúa una cuenta atrás desde un número
dado.

 
 El circuito que hemos visto, es el correcto para garantizar que el display tenga una
vida larga y pacífica, de hecho es el que recomienda el fabricante.En internet encontrareis
bastantes ejemplos en los que, en vez de transistores usan resistencias de un cierto valor
para limitar la intensidad en los controles de salida. He preferido no hacerlo así, a sabiendas
de que el montaje que os he propuesto es bastante más pesado.
 
ALGUNOS COMENTARIOS FINALES
 

Cablear este montaje es un asco y si fuera un circuito comercial seria caro (Porque aunque los
componentes sean baratos, montarlos cuesta pasta, más que los componentes en este caso).

Así que en la práctica os desaconsejo que uséis estos displays de por si, en vuestros
proyectos. Hay demasiados cables y siempre hay alguno dando guerra. Lo normal es usar un
display tipo I2C o similar que lleven un circuito de control interno, o bien usar un integrado de
control BCD como el Max7219 (Volveremos a hablar del asunto en un futuro próximo).
Y ¿Por qué a pesar de todo hemos hecho esta práctica? Pues porque es importante que
entendáis cómo funcionan las cosas y el concepto de multiplexado es uno de los claves
básicas para entender la electrónica digital,

Por cierto, ¿Os habéis dado cuenta de que, al hacer un multiplexado de los dígitos basado en
que nuestro Duino recorra el ciclo completo en menos tiempo de lo que nuestro ojo percibe,
cualquier uso de un delay() dará al traste con el invento?. Meted uno por donde queráis y ved
lo que ocurre.

Aunque hasta ahora hemos usado y abusado de los delays, son algo poco práctico y
potencialmente muy peligroso a medida que los proyectos que presentemos se vayan
complicando, y este es uno de esos casos. Ya hablaremos de las soluciones.

RESUMEN DE LA SESIÓN
 
 

o Hemos presentado los displays LED de 7 segmentos y 4 digitos.


 Lo suficiente como para comprender, que como ejercicio está bien,
pero veremos otras maneras de incluir estos displays, menos trabajosas.
o Hemos mejorado nuestra función Display(), para que podamos usarla en
displays de digitos múltiples(Seria muy fácil extenderla a 8 digitos).
o Hemos resuelto una serie de problemas lógicos, en pasos más pequeños de
abordar para mejorar nuestra competencia en la búsqueda de algoritmos útiles.
o Hemos visto que podemos abordar problemas complejos mediante pequeños
pasos y funciones, que al combinarse resuelven problemas que inicialmente parecen
inabordables.

MATERIAL REQUERIDO.

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

Una Protoboard.
Cables  de protoboard

Un display de 7 segmentos y 4 dígitos.

LOS DISPLAYS LED DE 4 DÍGITOS


 

En la sesión anterior vimos cómo usar un display de 4 dígitos montando nosotros toda la
electrónica. Vimos que la cosa funcionaba bastante bien, y vimos que no se notaba el truco de
multiplexar los dígitos, porque en general los Duinos son lo suficientemente rápidos para que
no lo percibamos.

Pero lo que desde luego si que percibimos, fue lo pesado que es montar aquel circuito en una
protoboard, por la cantidad de cables que supone conectar y por lo fácil que es equivocarse o
soltar uno inadvertidamente.

En la práctica ese sistema solo es para los estudiantes (por aquello de que aprendan
sufriendo), pero en la realidad es mucho mejor utilizar un display con sistema anexo de
control, que son un poco más caros, pero no tienen ninguno de los problemas que vimos.

En realidad son tan sencillos que no suelen tener más allá de 4 pines y se controlan por
software directamente.

Hoy os voy a presentar un display chiquitín, pero muy resultón, que tengo rodando por la
mesa ya un tiempo y que me encanta.

Es un display de Catalex, un fabricante chino, de 4 dígitos que se gobierna con esos 4 pines
que decíamos (y dos son Vcc y GND), tiene una librería muy simple y funciona tanto a 5V como
a 3,3V.
 
 Espero recibir en breve uno de estos displays en versión I2C (Aaún no hemos hablado
del I2C, pero todo llegará) y entonces haremos un sesión sobre el tema..
 
 

DIAGRAMA DE CONEXIÓN
 

El cableado de uno de estos displays es insultantemente sencillo:


 

Conectamos tensión y Ground y solo nos quedan 2 hilos: DIO o Data Input Output y Clock,
que conectamos a los pinos 2 y 3 respectivamente. Y eso es todo.

EL PROGRAMA DE CONTROL
 

El fabricante del display nos proporciona una librería para que podamos olvidarnos del
multiplexado y demás historias:   DigitalTube 
La descargamos e instalamos como vimos en la sesión Conociendo los servos, Seleccionad
Programa – Añadir librería e indicadle el fichero que acabáis e descargar y se instalará.

Y en la lista de librerías que sale en el desplegable elegid DigitalTube . Veréis que os incluye
una línea como esta:

#include <TM1637.h>

Que es un nombre impresentable, pero que es lo que hay. Para usarla, definimos un par de
pines para la señal CLK y DIO:

#define CLK 3//pins definitions for TM1637 and can be changed to other ports

#define DIO 2

Ahora tenemos que crear una instancia del tipo TM1637 que llamaremos Display1 y le
pasamos los pines que controlan la comunicación:

TM1637 Display1(CLK,DIO);

Y ahora el fabricante nos pide que le pasemos los dígitos a representar en un array de 4
unsigned byte definidos con un tipo raro int8_t, del que no teneís que preocuparos:

int8_t  Digits[] = {3,2,1,2} ;

En este caso el display mostrara 3212. Y ahora hay que inicializar la librería y el display

void setup()

Display1.set();

Display1.init() ;

Y ahora ya solo queda pedirle que imprima Digits[]

Display1.display(Digits);

Y listo. Por pura vagancia os pongo el programa completo para que apreciéis la diferencia:
#include "TM1637.h"

#define CLK 3

#define DIO 2

TM1637 Display1(CLK,DIO);

int8_t Digits[] = {5,2,1,2};

void setup()

Display1.set();

Display1.init() ;

void loop()

Display1.display(Digits);

Vamos ahora a hacer el ejemplo del contador de la sesión anterior para que veamos cómo
queda. Vamos a empezar por las definiciones

#include "TM1637.h"

#define CLK 3
#define DIO 2

TM1637 Display1(CLK,DIO);

int8_t Digits[] = {7,6,5,4};            //Valor inicial

void setup()

Display1.set();

Display1.init() ;

Vamos a usar un contador para que veamos su valor en el display, así que vamos a necesitar
separar los dígitos del valor y meterlos en el array Digits. Para ello vamos a recuperar la
función CalculaDigitos () de la sesión anterior con alguna pequeña modificación:

void CalculaDigitos( int Num)

int8_t Digit0 = Num %10 ;

int8_t Digit1 = (Num % 100) / 10 ;

int8_t Digit2 = (Num % 1000) / 100 ;

int8_t Digit3 = Num  / 1000  ;

Digits[3] = Digit0 ;

Digits[2] = Digit1 ;

Digits[1] = Digit2 ;
Digits[0] = Digit3 ;

Display1.display(Digits);

Calculamos los dígitos y los metemos en el array, después basta con llamar al método display
(en minúsculas) del objeto Display (en mayúsculas). Y para calcular el número:

void loop()

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

CalculaDigitos(i);

delay(100);

RESUMEN DE LA SESIÓN
 
 

o Hemos presentado los displays LED de 7 segmentos y 4 dígitos de Catalex,


que utiliza un bus propio (y no documentado) pero que como funciona, casi puedo
perdonárselo.
o Hemos modificado nuestra función CalculaDigitos(), para que podamos usarla
con este display u otros que requieran que les pasamos los dígitos separados.
o La virtud de este tipo de display (Digital tubes para los ingleses) es la facilidad
de conexión y de gestión con la librería.

MATERIAL REQUERIDO.
Arduino Uno o similar. Esta sesión acepta cualquier ot

Una Protoboard.

Cables  de protoboard

Un Potenciómetro.

Un display LCD, de 16×2 o 16×4.

LOS DISPLAYS LCD


 

Los displays LEDs de 7 segmentos, que vimos en las sesiones anteriores, están muy bien,
son baratos y prácticos, pero tienen el inconveniente de que no pueden mostrar mensajes de
texto, sino solo números.

Se echa de menos algún sistema para mostrar mensajes de texto sencillos, y por eso se
comercializan los displays LCD. Son faciles de encontrar en diversos formatos :  16×2 (16
caracteres x 2 líneas) o LCD 16×4 (16 caracteres x4 lunes).

 
 LCD viene del inglés Liquid Crystal Display, o sea Pantalla de cristal liquido.
 
Son una opción muy sencilla de usar, y además, dan un toque muy pro a vuestros proyectos,
y por eso, en los últimos años los displays LCD han ganado mucha aceptación en productos
comerciales de todo tipo.
Básicamente porque:

 
 Son baratos.
 Están disponibles en varios tamaños y configuraciones.
 Son de bajo consumo.
 Muy prácticos si te basta con mostrar solo texto (y algunos caracteres especiales).
 
En esta sesión  veremos cómo conectarlos a vuestros Duinos y cómo usarlos para sacar
mensajes al exterior.

ANTES DE EMPEZAR
 

Aunque, últimamente, estos displays suelen venir con los pines soldados, todavía hay muchos
sitios que cuando compras uno de estos, te lo envían en kit, con los pines aparte para que los
sueldes

 
 En algún momento tendremos que hablar de cómo soldar componentes, pero ese día,
aún no ha llegado.
 

Lo primero que tienes que saber, es que tienes que soldarlos, y que no vale sujetar los pines
de algún modo más o menos extravagante. Los sueldas y punto. Hazte a la idea. Cualquier
otra solución acabara funcionando mal, o directoramente con el display quemado.
Cuando lo tengas listo, pincha el display en la protoboard, dejando sitio para el resto de
componentes y cables, recuerda que habrá muchos, así que se generoso con el espacio que
dejas.
 

DIAGRAMA DE CONEXIÓN
 

Aquí teneis el esquema de conexión:

Y este es el esquema para potoboard:


La conexión no es complicada, pero requiere ser cuidadoso. Asi que vamos a ir paso a paso
con los diferentes cables. Empieza conectando tensión y GND a la protoboard.
Vamos ahora a a conectar la alimentación el panel LCD. Conecta el pin16 del LCD a Ground y
el 15 a 5V

Si conectas ahora el cable USB a tu Duino, el LCD debería iluminarse, si no, revisa tus cables
antes de seguir.

Vamos a conectar ahora, el potenciómetro de ajuste. Para ello conecta uno de los extremos
del pot a GND y el otro a 5V. El centro al pin 3 del LCD.

Aprovechemos también para dar tensión al panel LCD, El pin 1 va a GND y el 2 a tensión:
Si todo ha ido bien, ya podemos encender el dispay y probarlo. Conecta el USB a tu Arduino y
veamos. Si vas girando el potenciómetro, en algún momento tienes que ver unos cuadraditos
en la pantalla, en caso contrario revisa las conexiones. No sigas, si no ves esto.

Si ya veis las matrices de puntos en la pantalla, podemos seguir.

Vamos a conectar ya los pines de datos y control. Sin entrar en muchos detallas, no vamos a
usar todos los pines disponibles, porque no los necesitamos. Solo usaremos dos pines de
control, RS y EN y los 4 pines de datos D7, D6, D5, y D4 . No necesitamos mas por ahora.

Vamos con las conexiones de control del display:

RW, LCD pin 5             GND

RS, LCD pin 4             Arduino pin 7

EN, LCD pin 6             Arduino pin 8

Y ya solo nos quedan los 4 cables de datos.

DB7, LCD pin 14          Arduino pin 12

DB6, LCD pin 13          Arduino pin 11


DB5, LCD pin 12          Arduino pin 10

DB4, LCD pin 11          Arduino pin 9

EL PROGRAMA DE CONTROL
 

Vamos a usar una librería de control del panel LCD, que viene incluida en nuestro Arduino.
Pinchad en:

\\Programa\Importar Libreria\LiquidCrystal

Y ahora podemos importar uno de los ejemplos o escribir el nuestro, comentando el código.Lo
primero es que al importar la librería nos ha escrito esto:

#include <LiquidCrystal.h>

Despues, hay que inicializar la librería. Creamos una instancia llamada lcd, de la clase
LiquidCrystal y le pasamos como parámetros los pines que hemos usado:

LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //    ( RS, EN, d4, d5, d6, d7)

 
 Tened cuidado porque los pines que hemos usado, no corresponden a los ejemplos
de Arduino, así que podéis cargarlos, peroaseguraros de cambiar la línea de definición de los
pines, o no correrán.
 
El resto es sencillo
void setup()

lcd.begin(16, 2); // Fijar el numero de caracteres y de filas

lcd.print("Prometec.net"); // Enviar el mensaje

void loop()

lcd.setCursor(0, 8);  // set the cursor to column 0, line 1

lcd.print(millis() / 1000);  // print the number of seconds since reset:

 
 Cuidado: Como siempre la primera linea, la superior, es la linea 0 y la segunda la linea
1.
 
Estos display son muy pesados de cablear, pero muy sencillos de utilizar.

Vamos a probar sacando un reloj (muy sencillo de momento). Si recordáis las funciones que
usamos en las ultimas sesiones, podemos recuperar alguna para presentar el valor de millis()
como un reloj

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup()

lcd.begin(16, 2);           // Fijamos el numero de caracteres y filas


lcd.print("Prometec.net");  // Aqi va el mensaje

void loop()

lcd.setCursor(6, 1);    // Ponte en la line 1, posicion 6

String s = reloj() ;

lcd.print(s) ;

String reloj()

int n = millis() / 1000 ;       // Lo pasamos a segundos

int segundos = n % 60  ;

int minutos =  n / 60  ;

String S = String(minutos) + ":" + String(segundos);

return (S);

Merece la pena, comentar algunas cosas de este código. En primer lugar en la función reloj,
calculamos los minutos y segundos a partir del reloj interno de Arduino en milisegundos, no
hay nada nuevo en esto. Pero fijaros que hemos definido reloj como String:

String reloj()

Eso significa que vamos a devolver un parámetro tipo String a quien nos haya llamado. En
algún punto de la función habrá que hacer un return( String).
Fijaros que definimos dentro de la función un string llamado s:

String S = String(minutos) + ":" + String(segundos);

En esta línea no hay que confundir (aunque se escriben exactamente igual), el tipo String para
definir S, con la función String(n) que convierte un numero n en un string de texto para que
pueda mezclar el número de los minutos y los segundos separados por un símbolo de “:”.

Al final le añadimos un par de espacios en blanco, para evitar arrastrar fantasmas en la


pantalla

 
 Quita los espacios y miro lo que pasa en el cambio de minuto. ¿Cómo lo arreglarías,
sin el truco de poner esos espacios al final? Piensalo.
 
En la función loop, hemos usado

lcd.print(s) ;

Para sacar el mensaje de texto. Todo lo que ya sabéis de Serial.print() se usa exactamente
igual con esta instrucción. Y por último, tenemos una línea como esta:

lcd.setCursor(6, 1);    // Ponte en la line 1, posicion 6

Que lo que hace es posicionar el cursor del panel, en la posición 6 de la segunda línea, para
escribir la hora centrada. Aquí os dejo un mini video con el resultado.

La librería LCD, viene con varios ejemplos muy interesantes, que os conviene probar.
Recordad, simplemente, que tenéis que cambiar las definiciones de los pines para que corran.

Un ejemplo particularmente interesante, es el de CustomCharacter, en el que define una serie


de símbolos especiales y los mueve por la pantalla en función de los valores que lee de un
potenciómetro.

Sin llegar a tanta sofisticación, es muy interesante que veamos cómo definir algunos
caracteres especiales, porque en la tabla base del LCD, no están incluidas ñ, acentos, grados,
o €. Así que dependiendo del uso que le deis pude seros de interés saber cómo definir tus
propios símbolos.

DEFINIENDO TUS PROPIOS CARACTERES


 

Vamos a definir un carácter propio, para digamos, el símbolo de grados centígrados,  por
ejemplo.
Lo primero que tenéis que saber, es que los caracteres se definen con un array ( si, de nuevo)
de 8×8, como si los dibujarais en una cuadricula de ese tamaño, y rellenando el cuadradito
completo.

Así por ejemplo para el símbolo del grado seria:

byte grado[8] =

0b00001100, // Los definimos como binarios 0bxxxxxxx

0b00010010,

0b00010010,

0b00001100,

0b00000000,

0b00000000,

0b00000000,

0b00000000

};

Para montar los caracteres definidos usamos:

lcd.createChar(0, euro);

lcd.createChar(1, grado);
Y ahora ya estan disponibles. Tened en cuenta que solo podemos definir 8 caracteres
especiales en un momento dado ( Aunque podemos definir 30 arrays, de caracteres y crearlos
y matarlos sobre la marcha).

Aqui tenemos un ejemplo del programa:

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

byte grado[8] =

0b00001100,

0b00010010,

0b00010010,

0b00001100,

0b00000000,

0b00000000,

0b00000000,

0b00000000

};

void setup()

lcd.begin(16, 2); // Hay que inicializar el LCD

lcd.createChar(1, grado);
lcd.setCursor(0, 0);

lcd.print("Estamos a 25");

lcd.write(1);

void loop()

Y aqui teneis una foto del resultado

Por último, y para cerrar ya la sesión (Todo llega en la vida), Deciros que de nuevo, hemos montado
este display a la brava, conectando un buen número de cables.
Esto solo se puede justificar, porque en su día piqué y me compre un display de estos ( en realidad,
dos. Tengo otro de 16×4), pero si vais a compraros un LCD, por Dios, compraros uno que sea I2C o
algo así, vuestra salud mental mejorará mucho y solo usa 4 cables.

En la próxima sesión montaremos uno para que veáis la diferencia.

RESUMEN DE LA SESIÓN
 
 

o Hemos visto los displays LCD de 16 caracteresy 2 líneas.


 Lo suficiente como para comprender, que como ejercicio está bien,
pero veremos otras maneras de incluir estos displays, menos trabajosas.
o Existen también, displays de 16 caracteres y 4 líneas, si necesitáis mas
espacio en pantalla.
o Son muy comodos de manejar porque podemos imprimir directamente, como
si fuera una puerta serie.
o Podemos ( y tendremos que hacerlo, seguro) definir caracteres y símbolos no
incluidos en el display.

También podría gustarte