Documente Academic
Documente Profesional
Documente Cultură
programas Arduino.
IF
Comprueba si cierta condicin se cumple y puede ser usado en conjunto con uno o ms
operadores de comparacin (==igual, != distinto, < menor, > mayor):
if (a == b)
{
cdigo
}
IF y ELSE
Permite agrupar mltiples comprobaciones.
if (a < b)
{
cdigo 1
}
else
{
cdigo 2
}
WHILE
Se ejecuta un bloque hasta que la condicin deje de cumplirse.
while(a > b)
{
cdigo
}
DO y WHILE
Trabaja de la misma manera que el bucle while, con la excepcion de que la condicin se
comprueba al final del bucle, por lo que este bucle se ejecuta "siempre" al menos una vez.
do
{
cdigo
} while (a > b)
BREAK
Es usado para salir de los bucles do, for, o while, pasando por alto la condicin normal del
bucle. Es usado tambin para salir de una estructura de control switch.
while (a > b)
{
cdigo
if(a == 5) {
break
}
}
FOR
Repite un bloque de cdigo hasta que se cumpla una condicin. Se inicializa una variable, se
comprueba una condicin y ejecuta un bloque, luego se comprueba nuevamente la condicin y
asi sucesivamente hasta que la condicin ya no sea vlida.
for (int a = 0; a < 10; a++)
{
cdigo
}
Este cdigo es equivalente al siguiente
int a = 0;
while (a < 10)
{
cdigo
a++
}
SWITCH
Compara el valor de una variable con el valor especificado en las sentencias "case". Cuando se
encuentra una sentencia cuyo valor coincide con dicha variable, el cdigo de esa sentencia se
ejecuta.
switch (variable) {
case 1:
cdigo cuando "variable" es igual a 1
break;
case 2:
cdigo cuando "variable" es igual a 2
break;
default:
cdigo ejecutado cuando ninguna de las sentencias se cumple (es opcional)
}
pinMode:
Configura el pin especificado para comportarse como una entrada o una salida.
pinMode(pin, OUTPUT/INPUT)
digitalWrite:
Pone en 1 o 0 un pin de salida (output)
digitalWrite(pin, HIGH/LOW)
digitalRead:
pinMode( 6, OUTPUT) ;
}
Y a su vez nuestro loop() debera repetir tantas veces como LEDs tengamos el juego de
encender y apagar cada uno de los LEDs en secuencia desde el pin 13 hasta el 6.
Esta solucin es la que podramos describir como de fuerza bruta, pero no es muy elegante, es
trabajosa y probablemente cometeramos ms de un error al escribirla, porque las personas
tendemos a equivocarnos haciendo tareas repetitivas aburridas (y esta lo es mortalmente,
imaginad un circuito de de 16 LEDs).
En cambio los ordenadores no se aburren y adems C++ nos ofrece un medio cmodo de
indicarle que debe repetir algo un nmero definido de veces. Este medio es la instruccin For
que podemos usar en combinacin con una variable.
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 numrica y
entera, sin decimales.
Iremos viendo que existen otros tipos de variables. Volveremos sobre este tema en
prximas sesiones.
As por ejemplo, para inicializar en nuestro setup() los pines desde el 13 hasta el 6 como
salidas (requerido por nuestro Arduino) podramos usar la instruccin for de la siguiente
manera:
void setup()
{
int i = 0 ; // Inicializamos la variable i como un entero
for ( i = 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 parmetros separados por un carcter de punto y coma.
Una variable que ira tomando valores segn una cierta regla, y a la que asignamos un
valor inicial. En este caso: i = 6 .
El ciclo contina mientras se cumpla esta condicin. En nuestro caso mientras la i sea
menor que 14, o sea hasta el 13: i <14
Como cambia la variable en cada iteracin. En nuestro caso i++ que es pedirle a C++
que incremente en uno la variable i, al final de cada iteracin.
Con el mismo criterio podramos escribir la funcin 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 sesin 3 el cdigo era muy similar excepto en que escribamos el valor 13 para el nico
pin que tena un LED conectado. Aqu asignamos el pin con una variable i , que va tomando los
valores de 6 hasta el 13 para el pin.
Ntese que la instruccin for no lleva un punto y coma al final. Esto es porque se aplica
al bloque de instrucciones que le siguen entre llaves, como es el caso del loop() La iteracin
realiza las cuatro instrucciones que siguen a la lnea del for, porque estn dentro de un bloque
de instrucciones.
Las instrucciones que se aplican a bloques de cdigo, no llevan punto y coma al final.
En el caso de particular de que el bloque lleve una nica lnea de cdigo, las llaves
pueden ser omitidas, como en el caso de la instruccin for en la funcin setup() de arriba.
El esquema del circuito es muy similar al de la sesin 3, salvo por el hecho de que colocamos
en la Protoboard 8 LEDs.
La nica novedad es que dado que la funcin de la resistencia es limitar la intensidad de la
corriente que circula por el circuito, y puesto que todos los diodos tienen masa comn, basta
una nica resistencia entre este punto y Ground.
Cuando nuestro programa levante el pin correspondiente a valor a HIGH, se cerrar el circuito
iluminndose el LED asociado.
Con este circuito, y con el programa 4.1 descrito en las pginas anteriores, tendremos un
efecto de luces similar al del coche fantstico (O de los Zylon para los aficionados a la ciencia
ficcin).
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 fantstico
porque cuando acabamos de iterar el for, el programa vuelve a empezar desde el principio, lo
que hace que la luz salte desde el pin 6 hasta la del pin 13.
As pues Podramos hacer que la luz rebotara ? Pensadlo un poco.
Desde luego que s, bastara 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 continuacin 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 atrs dicindole a la variable i que
se decrcmentara en uno en cada iteracin mediante la instruccin i .
Tambin nos hemos aprovechado de que C++ nos permite definir variables sobre la
marcha dentro de la propia instruccin for, sin necesidad de dedicarle una lnea completa a la
declaracin e inicializacin.
Otra variante seria, hacer un efecto de ola en al que las luces subieran dejando encendidos los
LEDs previos hasta alcanzar el mximo y ahora descender apagando los LEDs superiores. Os
recomendamos intentar resolver el problema como desafo, antes de buscar una solucin.
Programar es en parte aprender las instrucciones de un lenguaje (la parte fcil), y otra
ms difcil que es aprender a resolver los problemas de un modo que nos permita darle
instrucciones a un ordenador para que lo lleve a cabo.
Estos procedimientos secuenciales de cmo resolver un cierto tipo de problemas es lo
que se conoce como un algoritmo.
Segn el problema que abordemos el algoritmo ser ms o menos complicado pero
aprender a programar tiene ms que ver con desarrollar esta capacidad de resolver problemas
lgicos en una secuencia de pasos que podamos codificar en un ordenador.
Por cierto, cualquiera puede aprender a programar. No lo dudis. Solo que como en
todo, a unos les lleva ms tiempo que a otros desarrollar la habilidad necesaria. Al principio
muchos 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 SESIN
.
Hemos visto uno de los tipos de variables que C++ acepta: los enteros.
Con frecuencia en electrnica necesitamos saber si una luz est encendida o apagada, si
alguien ha pulsado un botn o si una puerta ha quedado abierta o est cerrada.
A este tipo de seales 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:
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.
A esta resistencia que fuerza el valor alto en vacio se le conoce como pullup Si la
conectramos a masa para forzar una lectura a Ground se le llamara 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 prctica habitual de usar cables negros para
conectar a masa y cables rojos para conectar a tensin (5V).
Obsrvese que el pulsador S1 tiene cuatro 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.
Empecemos haciendo un programa que haga que el LED se encienda cuando pulsamos el
botn y se apague cuando lo soltamos. Para ello pediremos a Arduino que configure el pin
digital 10 (D10) como salida para manejar el LED, y el pin digital 6 (D6) como entrada para leer
el botn.
Normalmente en programas sencillos basta con poner el nmero de pin en las instrucciones.
Pero a medida que el programa se complica esto tiende a provocar errores difciles de detectar.
Por eso es costumbre definir variables con los nmeros de pin que usamos, de forma que
podamos modificarlos tocando en un solo lugar (y no teniendo que buscar a lo largo del
programa). Vamos a escribir esto un poco ms elegantemente:
int LED = 10 ;
int boton = 6;
void setup()
{
pinMode( LED, OUTPUT) ; // LED como salida
pinMode( boton , INPUT) ;
Atencin: C++ diferencia entre maysculas y minsculas 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 extraas.
Vimos que para encender el LED bastaba usar digitalWrite( LED, HIGH). Para leer un botn se
puede hacer algo similar: digitalRead( botn). Veamos cmo podra ser nuestro loop:
void loop()
{
int valor = digitalRead(boton) ;
Cmo podramos hacer lo contrario, que el LED se encienda al pulsar y se apague si no?
Bastara con escribir en LED lo contrario de lo que leamos en el botn.
Existe un operador que hace eso exactamente el operador negacin ! . Si una valor dado x
es HIGH, entonces !x es LOW y viceversa.
}
Hemos definido valor como bool, porque podemos usar el valor de tensin alto como TRUE y el
valor bajo como FALSE.
SI el botn no est pulsado el D6 leer TRUE y por tanto pondr LED a FALSE. En caso
contrario encender el LED.
De hecho podramos escribir una variante curiosa del blinking LED usando el operador
negacin:
void loop()
{
bool valor = digitalRead (LED) ;
Las instrucciones dentro de los parntesis se ejecutan antes que las que estn fuera
de ellos. Por eso el digitalRead se ejecuta antes que el digitaWrite..
RESUMEN DE LA SESIN
.
Hemos visto una forma de leer seales digitales del mundo exterior adems de poder
enviarlas:
digitalRead( pin)
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 tambin aprendiendo a resolver problemas lgicos y
partirlos en instrucciones.
Hacer cursos de programacin (o de andar en bici) est bien, pero al final hay que ponerse
a programar y tener problemas, porque solo tenindolos y resolvindolos, solo o con
ayuda, se aprende. No se puede aprender a nadar slo estudiando.
Con un cierto temblor de manos, vamos a centrarnos en esta sesin en algunos ejemplos
clsicos de programacin, como son el clculo de nmeros primos para entrenar esta
capacidad de bsqueda de algoritmos prcticos para resolver problemas ms o menos
abstractos y para presentar algunos conceptos adicionales.
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 segn que el
nmero que le pasamos sea primo o no y a la que podamos llamar varias veces sin copiar
el cdigo una y otra vez. La llamaremos Primo () y queremos utilizarla de la siguiente
manera: Si el numero n que le pasamos es primo nos tiene que devolver true y en caso
contrario que devuelva false, o sea queremos que nos devuelva un valor bool.
Esto es lo que llamamos una funcin.
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
parntesis.
C++ nos ofrece todas las herramientas para crear nuestras propias funciones y es algo
muy til porque nos ayuda a organizar un problema general en trozos o funciones ms
pequeas y ms fciles de manejar.
Para definir una funcin as, tenemos que declararla primero y describirle a C++ que hacer:
bool Primo( int x) // int x representa el parmetro que pasaremos a esta
funcin
{
Aqu va lo que tiene que hacer
return( bool);
}
Declaramos la funcin Primo () como bool, o sea va a devolver un valor bool y por eso en
algn punto tendremos que usar la instruccin return( true) o return( false) para devolver
un resultado a quien la llame. Si devolviera un entero habra que definirla como int
Primo( int x).
Para saber si un nmero es o no primo basta con dividirlo por todos los nmeros positivos
menores que l y mayores que 1. En el ejemplo dividimos el nmero n empezando en 2 y
finalizando en n-1.
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 funcin. Si no
hallamos ningn divisor, al finalizar el for devolvemos true y listo. Este es el mtodo 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 funcin 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 nmero a probar
bool p = Primo(x);
if (p )
Serial.print( String(x) + " Es primo.") ;
else
Serial.print( String(x) + " No es primo." ) ;
}
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 ;
}
void loop()
{
if ( control)
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 ;
}
Para conseguirlo, hemos aadido una coma y un tabulador a cada nmero excepto a uno
de cada 8 que aadimos intro. Tambin tenemosuna lnea que conviene comentar:
if ( contador++ % 8 == 0)
Cuando a una variable se le aaden dos smbolos mas al nombre, significa que primero se
use su valor actual en la instruccin en curso, ene este caso en el if, y despus se
incremente en 1 su valor.
Si hubiramos escrito:
if ( ++contador % 8 == 0)
Querra decir que queremos incrementar su valor antes de utilizarlo. Esta notacin es muy
habitual en C++ y conviene reconocerla. Tambin podemos usar contador- y -contador
para decrementar.
EL TIPO ENTERO
.
Este sera un buen momento para preguntarnos hasta donde podra crecer mximo en el
programa anterior. Le asignamos un valor de 1024, pero Tiene un entero lmite de
tamao?
La respuesta es afirmativa. Los enteros int en Arduino C++ utilizan 16 bits por lo que el
mximo seria en principio 216 = 65.536, Pero como el tipo int usa signo, su valor est
comprendido entre
-32.768 y +32.767.
De hecho en Arduino C++ hay varios tipos de distintos tamaos para manejar enteros:
TIPO
DESCRIPCIN
VALO
int
entre -32,768
unsigned int
216 1 ; de 0 h
long
unsigned long
byte
Todos estos tipos representan enteros con y sin signo y se pueden utilizar para trabajar
con nmeros realmente grandes pero no sin lmite.
Desde 232 1 ; 0
28 de 0 ha
De hecho C++ tiene la fea costumbre de esperar que nosotros llevemos el cuidado de no
pasarnos metiendo un valor que no cabe en una variable. Cuando esto ocurre se le
llama desbordamiento (overflow) y C++ ignora olmpicamente el asunto, dando lugar a
problemas difciles de detectar si uno no anda con tiento.
Prueba este a calcular esto en un programa:
int i = 32767 ;
Serial.println ( i+1);
i + 1);
Cuando se declara una funcin se debe especificar que parmetro va a devolver. As:
Instruccin
Significa
int Funcion1()
String Funcion2()
void Funcion4()
No va a devolver valore
Una funcin puede devolver cualquier tipo posible en C++, pero slo puede devolver un
nico valor mediante la instruccin return(). Expresamente se impide devolver ms de un
parmetro. 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.
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 SESIN
.
Conocimos tipos con mayor y menor capacidad para manejar nmeros enteros
mas o menos grandes, pero que todos siguen teniendo un lmite de tamao.
LOS POTENCIMETROS
Hasta ahora hemos usado siempre resistencias fijas, de un valor dado. Pero a veces es
conveniente disponer de una seal variable para controlar el circuito que nos interesa.
Imaginad el volumen de un equipo de msica, o el dial que sintoniza una emisora en una
radio FM.
Un potencimetro es, simplemente, un mecanismo para proporcionar una resistencia
variable.
Hay potencimetros de tantos tamaos, formas y colore,s como podis 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 potencimetro siempre tiene 3 pines en fila. Los del extremo se comportan
como una resistencia del valor de fondo de escala del potencimetro, y un pin central que
va tomando valores de resistencia en funcin del movimiento que hagamos con el ajuste.
Vamos a montar un circuito como este (en el que el potencimetro esta rotulado Pot1):
La idea es conectar 5V y GND a los extremos del Potencimetro (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 limitacin.
De este modo cuando giremos el potencimetro estaremos modificando la tensin que
aplicamos a la entrada del LED, que variara entre 0 y 5V (Aunque ahora parezca extrao
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 potencimetro el LED estar apagado.
Importante: No olvides la resistencia R1.Aunque el potencimetro limite la
intensidad, hay un momento en que llegara a cero y ah y tu LED fallecer en acto de
servicio.
Con Arduino hemos visto que podemos influir en el mundo exterior aplicando salidas todo /
nada en los pines digitales y tambin que usando PWM podemos simular bastante
satisfactoriamente seales analgicas en algunos de esos pines.
Tambin hemos visto cmo detectar pulsaciones de botones, definiendo como entradas los
pines digitales. Pero en muchas ocasiones los sensores que usamos para supervisar el
mundo exterior, nos entregan una seal analgica. Es el caso de los sensores de
temperatura o distancia, de presin o PH, de intensidad de corriente en un circuito o de
caudal de agua en una tubera.
Para leer este tipo de seales continuas necesitamos un convertidor analgico a digital (o
ADC por sus siglas en ingles) y que nos permite leer el valor de una seal analgica en un
momento dado.
Estos convertidores toman una muestra del valor actual de la seal y nos entregan
su valor instantneo, medido en Voltios.
Mediante la lectura repetida de muestras a lo largo del tiempo podemos reconstruir la
seal original con mayor o menor precisin, dependiendo de la exactitud de nuestra
medida y de la velocidad a la que pueda tomar esas muestras.
Arduino UNO dispone de seis convertidores analgico a digital, nominados de A0 hasta A5,
rotuladas como ANALOG IN:
Veamos cmo usar las entradas analgicas con un circuito como este, en el que damos
tensin a los extremos de un potencimetro 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
tensin y no resistencia, por lo tanto, lo que vamos a leer es la cada de tensin en el
potencimetro a medida que giramos el ajuste.
La primera curiosidad es que no necesitamos declarar en el setup() que vamos a usar una
puerta analgica. Y la segunda es que para tomar una muestra (leer) del pin A5, usaremos
la instruccin:
int Val = analogRead(A5) ;
Los convertidores de Arduino UNO y Mega son de 10 bits de resolucin 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 resolucin(pero slo puede leer hasta
3,3V).
Asegrate de no usar sensores que puedan dar ms de 5V mximo (con Arduino
UNO y Mega), ya que daaras el chip principal de Arduino.
Vamos a escribir un programa que lea el valor del pin A5 y lo enve a la consola para que
podamos visualizarlo.
}
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 varan de forma continua reflejando la posicin del potencimetro, las lecturas
reflejan la caida en voltios en el.
UN LTIMO COMENTARIO
Decamos en una seccin anterior, que la fidelidad con que podemos muestrear una seal
analgica dependa, bsicamente, de la resolucin de la muestra y de la velocidad a la que
podamos muestrear la seal (Sample Rate en ingls).
Ya dijimos que la familia Arduino, dispone de convertidores de 10 bits por lo que nuestra
resolucin es de 210 = 1.024 y en el caso del DUE de 212 = 4.096. Pero hasta ahora no
hemos visto a qu velocidad podemos tomar muestras con nuestro Arduino. Vamos a
comprobarlo, con este mismo circuito.
Tenemos una funcin llamada millis() que nos indica en milisegundos el tiempo
transcurrido desde que iniciamos Arduino y la podemos usar para ver cuantas muestras
podemos tomar por segundo.
void setup()
{
Serial.begin(9600); }
void loop()
{
unsigned long T ;
int n = 0 ;
T = millis();
1000 mS
{
analogRead( A5) ;
n++ ;
}
Serial.println(n);
}
Hemos usado un unsigned long para guardar millis porque es el tipo que Arduino
usa internamente para su reloj. Sera un error manejar millis con un int porque su valor
mximo es 32.767 y midiendo milisegundos el contador desbordara en poca ms de 32
segundos.
Para jugar con audio es mejor usar un Arduino DUE. Tiene una velocidad de reloj 4
veces ms rpida(os har falta), capacidad de muestreo a velocidad de audio (40Khz) y
autnticos 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 SESIN
Sabemos que podemos leer las puertas analgicas unas 8.900 veces por segundo
con una resolucin de 10 bits, o sea entre 0 y 1.024.
Conocimos la funcin millis().
Un rel es un interruptor que podemos activar mediante una seal elctrica. En su versin ms simple es
un pequeo electro-imn que cuando lo excitamos mueve la posicin de un contacto elctrico de
conectado a desconectado o viceversa.
El smbolo del rel muestra la bobina y en este caso, un accionador que conmuta entre dos contactos,
pero tambin existen rels de mltiples contactos. Mediante una seal de control de poca intensidad que
excite la bobina podemos conmutar grandes tensiones o intensidades.
Hemos visto cmo usar un transistor para hacer lo mismo, Porque entonces usar rels?
En primer lugar, los rels llevan entre nosotros desde finales del siglo 19 (y nadie
ha sido todava capaz de convertirlos en obsoletos), es una tecnologa muy probada y bien
establecida en la industria y adems sirve para cosas que son problemticas para los
transistores.
Hay lmites en la corriente que un transistor puede aceptar, pero un rel se puede
disear para que aguante cualquier carga, porque basta con los extremos metlicos de los
contactos lo soporten.
En la prctica, con Arduino es ms sencillo utilizar un rel para encender una luz
fluorescente o la calefaccin, que buscar un transistor de caractersticas adecuadas.
Aunque hay rels 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 continuacin incluye un circuito de transistor / rel completo que
nos permitir atacar cualquier proyecto casero que nos propongamos.
Cuando ponemos un valor HIGH en el pin de control, El transistor pasa a saturacin y la corriente entre
emisor y colector excita la bobina del rel, haciendo que el contacto cambie de posicin (y haciendo
adems 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 posicin de reposo.
La salida del rel consta de 3 pines y no de dos como se podra esperar. El motivo es que la conexin
entre los pines de salida 2 y 3 es de tiponormalmente abierto (circuito abierto sin excitar) y entre los pines
2 y 4es 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 batera se encendern las luces de emergencia automticamente.
Para nuestro ejemplo podemos utilizar un LED rojo y otro verde para marcar la situacin.
Veremos que se enciende uno u otro, pero nunca ambos (como corresponde a una seal
de alarma).
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
sera poco prctico establecer mltiples diagramas de protoboard.
Adems, el circuito bsico del transistor de la sesin anterior es exactamente el mismo que
este y bastara 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 comn.
El diagrama de la protoboard no hara sino complicar las cosas y ya va siendo hora de que
tratemos de montar el circuito a partir del esquema electrnico directamente. Animo
Para probar que todo est correctamente conectado, bastara 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 encendern
alternativamente.
Para convertir este circuito en unas luces de emergencia bastara con poner una batera o
pilas en el comn del rel en lugar de los 5V de Arduino. De ese modo al desconectar
Arduino la luz de emergencia se activara sola.
RESUMEN DE LA SESIN
Normalmente los rels son muy interesantes para encender y apagar algo que
tiene un consumo relativamente alto de corriente
PIEZOELECTRICIDAD
posicin.
Si conectamos un piezo con una seal digital, vibran a una frecuencia sigue bastante
fielmente la variacin elctrica 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 podramos
denominar alta fidelidad. Pero es suficiente para generar tonos audibles (como la tpica
alarma de los despertadores digitales) e incluso tonos musicales reconocibles que
podemos secuenciar, hasta en piezas musicales (por ms que uno quisiera estar en otro
lugar cuando las oyes).
Como antes o despus, disponer de una seal acstica en vuestros proyectos, acaba
siendo til, vamos a ver cmo podemos montar estos elementos, y que tipo de opciones
tenemos disponibles.
En esta sesin, montaremos un circuito muy sencillo con un zumbador.
ESQUEMA ELECTRNICO
xx
La conexin 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.
Adems 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 piezoelctrico
(recordad que una seal PWM enva un tren de ondas cuadradas de amplitud variable),
por lo que lo ms cmodo es usar un pin PWM en lugar de programar un efecto
equivalente en un pin normal.
EL PROGRAMA
Vamos a empezar creando una funcin, 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 seal PWM en el pin 9 de 20 sobre 255. Podis
varias el valor, pero el tono de audio no cambiar gran cosa porque est controlado por la
seal de base. Esto es suficiente para generar una de las molestas seales acsticas de
un despertador barato.
Qu pasa si quiero generar seales de tono variable para hacer una meloda? Bueno
pues Arduino dispone de la funcin tone() que genera una seal de la frecuencia indicada,
y notone() que la corta:
void setup()
{
int pinOut = 8;
int freq = 440;
int duration = 1000;
tone(pinOut, freq, duration);
}
void setup()
{ }
void loop()
{
for (int i = 0; i < numTones; i++)
{
tone(speakerPin, tones[i]);
delay(500);
}
noTone(speakerPin);
}
Por ltimo, y para cerrar esta sesin, os dir que internet est lleno de gente a quien le
sobra tiempo y lo dedica a las extravagancias ms inverosmiles. Basta con indicaros aqu
la pgina de alguien que ha dedicado un nmero indecente de horas en transcribir la
msica de la guerra de las galaxias a orquesta de cmara, compuesta por Arduino y
zumbador.Descargar ejemplo:
RESUMEN DE LA SESIN
Fotoresistencias o LDR
LOS FOTOSENSORES
Recordad que los convertidores ADC como los de Arduino no pueden leer
resistencia sino tensin.
Pero antes de entrar en materia necesitamos hacer un inciso para conocer lo que es
un divisor de tensin.
DIVISORES DE TENSIN
EN SERIE
Como las resistencias estn en serie el valor total es R1 + R2. Si Vin es de 5V la intensidad que circular
EN
Si todava 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 potencimetro (o un
LDR) cualquier variacin en el ajuste, causara una modificacin en el valor de salida de
tensin Vout.
Esto es lo que se conoce como un divisor de tensin y es un circuito de lo ms prctico
para rebajar una seal de entrada, y podis apostar a que lo usareis mas de una vez.
Por ejemplo, los convertidores analgicos de Arduino aceptan un mximo de 5V, pero
muchas seales industriales son de entre 0 y 12V.Si lo conectas sin ms al A0, por
ejemplo, freirs el chip de largo.
Pero con el truco del divisor de tensin y calculando adecuadamente las resistencias (Que
s, que t puedes con lo que hay en la pgina anterior) puedes adaptarlo tranquilamente
para que tu Arduino viva feliz con una seal que originalmente le hubiera chamuscado.
Los divisores de tensin son un circuito muy sencillo y que conviene que sea parte de
vuestro arsenal electrnico. Resuelven cantidad de problemas con una resistencia y un
potencimetro y son ideales para tratar seales, que por exceso de tensin, quedaran
fuera del alcance de tu Arduino.
De hecho en esta prctica vamos a montar un divisor de tensin con una resistencia y
un LDR y leeremos la cada de tensin en l. Nos va a servir como ejemplo de los
divisores de tensin y adems nos servir como seal de control para calcular la
frecuencia a la que haremos vibrar el buzzer.
Fjate que
el LDR R1, junto con R2 forma un divisor de tensin. La lectura de A0 depender de la
luz que incida en el LDR. El esquema de protoboard es igual de fcil:
Se acepta que el odo humano se mueve ente 20 Hz y 20Khz (aunque esto es para
algn adolescente de odo muy fino) para los que peinan canas entre 40Hz y 10Khz ya es
un rango optimista. Por eso, mapeamos los valores del potencimetro, que van de 0 a
1024, entre 20 y 5Khz, pero os recomiendo que cambiis estos valores y veis lo que
pasa.
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. Despus, 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, adems, 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 instantneo, porque de lo
contrario no notaramos mucho cambio el programa anterior.
RESUMEN DE LA SESIN
Bajo consumo
Devuelva la medida en C
En cuanto al DHT22:
Barato, entre 4 y 5
Bajo consumo.
Devuelva la medida en C
La conexin 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
En primer lugar, tenemos que descargar una librera para manejarlos cmodamente,
DX11.zip e importarla. Aqu tenes la librera DHT11.zip
Hacemos el importar la librera 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);
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 ms 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)
bien
{
Serial.print("Temperatura: ");
Serial.print(temp);
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 estis
en el trpico haris 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 SESIN
Uso de Servomotores
QUE ES UN SERVO
.
Servos
Normalmente los motores habituales lo que hacen es transformar la energa elctrica
(O qumica) en un giro continuo que podemos usar para desarrollar trabajo mecnico.
En la sesin 13 utilizamos un pequeo motor de corriente continua y regulamos la
velocidad de giro mediante una seal PWM de Arduino.
Los servos son tambin motores de corriente continua, pero en lugar de disearse para
obtener un giro continuo que podamos aprovechar (para mover una rueda por ejemplo), se
disean para que se muevan un angulo fijo en respuesta a una seal de control, y se
mantengan fijos en esa posicin.
Imaginad por ejemplo un timn de un avin o barco. No queremos un giro continuo, sino
un motor al que le pueda indicar el ngulo que deseamos en grados y que mantenga esa
orientacin hasta que le demos una orden en contrario.
Estos servos o servomotores son muy frecuentes en Aero modelismo y en robtica, por la
capacidad que presentan para moverse a un ngulo concreto y mantenerse all. De hecho
se suelen disear para que giren un ngulo proporcional a una seal PWM, de forma que
su control es muy preciso. Un servo suele estar formado por:
Un motor de CC.
Un circuito de control
En la prctica se comporta como un bloque funcional que posiciona su eje en un ngulo preciso en
funcin de la seal de control
Habitualmente los servos tiene un margen de operacin, es decir, pueden moverse entre
0 y ngulo dado, que suele ser de 180, pero existen modelos comerciales de todas la
caractersticas imaginables (incluyendo servos de 360).
Normalmente estos pequeos servos funcionan sobre 5V y el control se realiza mediante
una seal de control PWM, en la que el ancho el pulso indica el ngulo que deseamos
adopte el eje.
Un servo tiene un conector de 3 hilos, 5V (rojo), GND (negro o marrn) y el otro Control
(amarillo o blanco).
Podramos escribir un pequeo programa en Arduino que controle estos pulsos y los
relacione con el ngulo buscado, pero antes de que nadie se asuste, los servos (y otras
cosas) son tan habituales, que ya ha habido gente que han escrito estos programas y los
han puesto a nuestra disposicin.
De este modo podemos manejar un servo sin preocuparnos para nada de cmo realizar el
control de las seales, o de la operacin interna, basta con instalar estos programas en
una forma especial llamada librera.
Servo es una librera estndar en Arduino. Eso quiere decir que viene incluida cuando
instalis el IDE, a diferencia de otras libreras que debemos buscar, descargar de Internet
e instalar para poder usarlas.
Para usar una librera estndar, basta con pedirle al IDE que la incluya en nuestro
programa. Id al men Programa \ Importar Librera y os saldr un desplegable con todas
las libreras que tenis instaladas en el IDE.
Por ahora solo nos interesa la librera Servo. Pinchad en ella. Arduino incluir una lnea al
principio de vuestro programa como esta:
#include <Servo.h>
Normalmente para usar una librera hay que leer la documentacin, en la que se
detalla la forma de usarla, que funciones tenemos disponibles, que parmetros pasarlas
etc.
Como es vuestra primera librera, y nosotros ya nos hemos ledo el manual, vamos
a llevaros de la mano. Veris que es de lo ms fcil.
Vamos a montar un circuito en el que hagamos moverse al servo de forma controlada, e
iremos viendo las instrucciones necesarias.
EL PROGRAMA DE CONTROL
Vamos a empezar con una lnea que ya conocamos el include y otra nueva:
#include <Servo.h>
Servo servo1;
Para poder utilizar la librera debemos crear, lo que se conoce como un objeto tipo
Servo que llamamos servo1.
C++ es un lenguaje orientado a objetos, esto significa que podemos definir objetos tipo
(como servos) sin ms que declarar un nuevo objeto del tipo que deseamos. En la jerga de
la programacin se llama crear una instancia, o instanciar un nuevo objeto.
As, esa segunda lnea significa que vamos a crear una nueva instancia de tipo Servo que
llamamos servo1.
Aunque ahora os pueda parecer una forma extraa de hacer las cosas, la
programacin orientada a objetos (OOP por sus siglas en ingls), es una de las
metodologas ms potentes de las ciencias de computacin actuales y todos los lenguajes
de programacin que se precien, han incorporado las ideas de la OOP.
Entrar en la teora del OOP, desborda con mucho las pretensiones de este humilde
tutorial de Arduino, por ahora nos limitaremos a mostraros como usar los objetos.
Una vez creada la instancia del objeto (y podemos crear tantas como necesitemos, para
manejar varios servos a la vez) tenemos que incluir una lnea en la funcin setup() para
informar a C++ que vamos a conectar ese objeto abstracto que todava es servo1 a un pin
fsico del Arduino para controlarlo. En nuestro caso el pin 9:
servo1.attach(9);
Una vez cumplido el trmite para gobernar la posicin del servo recurrimos a
servo1.write( angulo);
Servo servo1;
int angulo = 0 ;
void setup()
{
servo1.attach(9) ;
}
void loop()
{
for(angulo
= 0; angulo
+= 1)
//incrementa angulo 1
grado
{
servo1.write(angulo);
delay(25);
}
for(angulo
= 180; angulo
>=0; angulo
-=1 )
//decrementa angulo 1
grado
{
servo1.write( angulo );
delay(25);
}
}
Veris como el servo se va moviendo primero hacia adelante y luego retrocede para volver
a empezar.
Vamos ahora a hacer que el valor del potencimetro represente la posicin del servo de
manera que el servo se mueva siguiendo al potencimetro. Para ello hay que entender que
el valor que leamos en la puerta A0 est comprendido entre 0 y 1024, y que estos valores
tienen que distribuirse entre 0 y 180. As que para calcular el Angulo correspondiente
basta con hacer:
Como la experiencia me ha
demostrado, que los errores haciendo este tipo proporciones tienden a infinito, voy a
aprovechar para presentaros la funcin map(), que hace exactamente eso de un modo
cmodo, librndonos de los float ( aunque para aprender no os vendra mal hacer as el
programa y luego usar el map()).
angulo
Traducido quiere decir: Haz la proporcin de los valores que leas en A0, entre 0 y 1024, en
un valor comprendido entre 0 y 180 y asignale ese valor al ngulo. //Prog_16_2
#include <Servo.h>
Servo servo1;
int angulo = 0 ;
void setup()
{
servo1.attach(9) ;
void loop()
{
angulo
servo1.write(angulo);
delay(250);
}
RESUMEN DE LA SESIN
Hemos presentado los servos y hemos vista una par de programas sencillos para
usarlos.
Hemos definido las libreras como conjuntos de funciones y objetos que podemos
utilizar sin preocuparnos de cmo funcionan internamente.
Hemos visto, en los documentales, que los murcilagos son capaces de volar en completa
oscuridad y sin embargo, sortear obstculos o atrapar insectos en vuelo. Sabemos que lo
hacen, pero rara vez pensamos como.
Tenemos una vaga idea de que se llama ecolocalizacin y que ms o menos tiene que ver
con unos sonidos agudos que emiten y que despus recogen con esas enormes orejas
que Dios les ha dado, pero rara vez nos planteamos cmo es esto posible.
Delfines y ballenas utilizan un sistema similar para atrapar a sus presas, y hasta hemos
visto que, en cualquier pelcula de submarinos, en el momento lgido el capitn ordena
emitir un pulso nico de sonar para localizar al enemigo.
El concepto bsico, es siempre el mismo, sabiendo a qu velocidad viaja el sonido, si
emitimos un pulso snico 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
seal.
El radar funciona de modo similar aunque usando ondas de radio frecuencia muy
cortasy con una problemtica 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 sesin 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 ultrasnicos y escuchar el eco de retorno. Midiendo este tiempo, podemos
calcular la distancia hasta el obstculo.
El odo 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 ms de 3 metros en condiciones normales si la precisin no es un
problema determinante
DIAGRAMA DE CONEXIN
Veamos como conectar uno de esto detectores a nuestros Duinos. Aqu est el esquema
elctrico y de protoboard por cortesa de Fritzing:
EL PROGRAMA DE CONTROL
Hasta ahora habamos visto que podamos definir una variable como int, por ejemplo, y
tambin como una constante (const int pin). Aqu utilizamos otro mtodo, 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 valorantes de compilar. Esta es
la forma clsica 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 crtico
en ocasiones).
void setup()
{
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(led, OUTPUT);
}
digitalWrite(trigPin, LOW);
desactivado
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
tiempo
digitalWrite(trigPin, LOW);
Para escuchar el pulso vamos a usar otra funcin, pulseIn() ( Oh s, hay muchas,
muchsimas). Para leer el manual de pulseIn() buscad en google Arduino pulseIn y vereis
que pronto lo encontrais.
Bsicamente lo que hace es escuchar el pin que le pasamos, buscando una seal que
pase de LOW a HIGH ( si le pasamos HIGH como parmetro) 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 ms cmoda podemos pasar esto a microsegundos por centmetro:
Como nuestro eco mide el tiempo que tarda el pulso en ir y venir la distancia recorrida ser
la mitad:
#define echoPin 12
#define led 2
void setup()
{
Serial.begin (9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(led, OUTPUT);
void loop()
{
est desactivado
delayMicroseconds(2);
delayMicroseconds(10);
echo
duracion = pulseIn(echoPin, HIGH) ;
distancia = duracion / 2 / 29.1
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.
Despus de este ejercicio de fsica y matemticas, que sin duda causar furor entre los
estudiantes aplicados, vamos a hacer el mismo programa pero usando una librera
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.
Podes descargar la librera de aqu, Descargar, o bien de la web del autor en
code.google.com/p/arduino-new-ping.
Para instalar una librera externa no incluida en el IDE de Arduino tenemos que importarla
con el men Programa \ Importar librera\Aadir librera:
sensor.
#define MAX_DISTANCE 200
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 librera se encarga de inicializar los pines necesarios, enviar los pulsos,
escuchar el eco de retorno y de hacer los clculos. No est mal.
Fijaros, que el ejemplo, utiliza diferentes pines a los que nosotros hemos usado,as
que tendres que modificarlos. Igualmente, el ejemplo inicializa la puerta serie a 115.200.
Es imprescindible igualar esta velocidad con la que recibe la consola o veris muchas
cosas raras en pantalla.
Los alumnos avispados se habrn dado cuenta de que Arduino viene forrado de
ejemplos que pueden cargar y usar. Os invito a que investiguis y juguis con estos
ejemplos cuanto queris.
RESUMEN DE LA SESIN
Teclados Matriciales
Para que nuestro Arduino pueda saber que tecla se pulsa, basta con poner tensin en las
filas de forma secuencial y luego leer las columnas para ver cul de ellas tiene
HIGH.Los teclados matriciales usan una combinacin 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 conexin nica entre una fila y una
columna.
Por ejemplo, ponemos HIGH en la primera fila (hilo 8 en el diagrama de la derecha) y
despus 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 44 necesitamos 8 hilos en lugar de 16,
aunque nos dar un poco ms de guerra a la hora de programar. Para un teclado de PC
106 teclas bastara una matriz de 1011 o sea 21 hilos en vez de 106.
DIAGRAMA DE CONEXIN
Esta es otra de esas raras ocasiones en que un esquema electrnico tendra poco sentido,
as que pasaremos rpidamente a ver el tema del programa.
EL PROGRAMA DE LECTURA
comentaremos que alguien ha tenido este problema antes que nosotros y amablemente ha
puesto a nuestra disposicin una librera llamada KeyPad ideal para leer este tipo de
matrices sin complicaciones,.
Lo que no quita para que podis escribir un programa que lea directamente la
matriz y reconozcis las pulsaciones. Animo, no es difcil y el ejercicio siempre es bueno.
Vamos a ver como usamos esta librera. Lo primero es definir un par de contantes
const byte Filas = 4;
//KeyPad de 4 filas
//y 4 columnas
Y ahora una par de arrays para indicarle a la librera que pines de Arduino corresponden a
las filas y cuales a las columnas del keypad:
byte Pins_Filas[] = {7, 6, 5, 4};
Recordad que un array es una coleccin de elementos que pasamos entre llaves y
separados por comas. Es ms cmodo que andar definiendo 8 variables.
Recordad lo que vimos en la sesin 9, que cuando definimos una array por enumeracin
de sus elementos, como en este caso, no necesitamos pasar entre corchetes el nmero de
elementos (Los cuenta el mismo C++ solito).
Tendremos que definirle, adems, que smbolos corresponden a cada posicin 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'}
};
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 asignacin.
Una de las curiosidades de leer una matriz de teclas y despus asignar un carcter
contenido en un array es que podemos redefinir el valor de las teclas sin ms que cambiar
el contenido del array.
Si por lo que sea hubiramos conectado mal los pines del keypad al Arduino,
podramos redefinir los valores del array para que coincidan con lo que pone en las teclas.
Puede ser ms fcil que mover de sitio los cables.
Por ultimo tendremos que crear una instancia de Keypad que llamaremos Teclado1
Keypad Teclado1 = Keypad(makeKeymap(Teclas), Pins_Filas, Pins_Cols, Fils,
Cols);
Que ledo as asusta, pero que en realidad es una tontera. Traduciendo sera: Crea una
instancia del tipo Keypad que llamaras Teclado1 y al que asignars las teclas que tenemos
en el array Teclas, y le decimos que hemos conectado las filas del keypad a los nmeros
de pines que te indico en el array Pins_Filas y las columnas al array Pins_Cols.
Por ultimo para leer el keypad hacemos una llamada a otra funcin de la librera:
char pulsacion = Teclado1.getKey() ;
Por ultimo enviamos a la consola el carcter pulsado. Aqu tenis el programa en versin
completa:Descargar
#include <Keypad.h>
// Prog_19_1
//Cuatro filas
//Cuatro columnas
void setup()
{
Serial.begin(9600) ; }
void loop()
{
// Si el valor es 0 es que no se
// se ha pulsado ninguna tecla
Porque la condicin del if debe evaluarse a TRUE o FALSE y para los ordenadores un 0 es
FALSE sin remisin, pero cualquier otro valor que no sea 0 es TRUE, incluyendo un
carcter.
RESUMEN DE LA SESIN
Hemos conocido otra librera externa, KeyPad. Os vendr muy bien en vuestros
proyectos. Ms adelante confo en que podamos hacer algn ejemplo ms sofisticado con
un keypad como hacer que una cierta combinacin abra una cerradura de servo por
ejemplo.
QUE ES UN JOYSTICK
Joystick
Un joystick suele estar formado por dos potencimetros a 90 que transforman el
movimiento en X e Y del mando en una seal elctrica proporcional a su posicin y que
adems suele incluir un botn.
As pues, suelen tener 5 pines: X, Y, botn y 6V ms GND.
En realidad ya usamos todos estos componentes previamente y la nica curiosidad del
joystick es que resulta un elemento muy cmodo para posicionar algo, aunque no sea
demasiado preciso.
Vamos a montar un circuito con un servo como en la sesin previa y usaremos uno de los
ejes del joystick para posicionar un servo, y si pulsamos el botn encendemos un LED.
(Ignoraremos el otro eje Y, aunque podramos usarlo para posicionar un segundo servo).
El pin correspondiente al botn suele venir marcado como SW de Switch.
Aqu tenemos el diagrama elctrico:
Y para
la protoboard:
EL PROGRAMA DE CONTROL
Servo servo1;
int angulo = 0 ;
int Eje_X = A1 ;
int Eje_Y = A2 ;
int boton = 4
, LED = 12 ;
void setup()
{
servo1.attach(6) ;
void loop()
{
angulo
servo1.write(angulo);
if ( ! digitalRead(boton))
digitalWrite(LED, HIGH);
else
digitalWrite(LED, LOW);
delay(250) ;
}
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
condicin en el if. Encenderemos el botn solo cuando pulsemos.
El servo sigue la posicion del joystick y cuando soltamos vuelve al centro.
Pero hay algo de epilptico en el movimiento del servo (y ms con uno barato como ste
que estoy usando). Recibe muchas interferencias y el movimiento es muy convulso,
porque, an si el servo tuviera una cierta precisin (lo que es una suposicin entre
optimista y muy optimista) los potencimetros y los convertidores analgicos 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. Pinsalo primero antes de seguir.
Vale. En el mundo real, las cosas no son nunca blancas o negras, sino ms 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 seal. Sin entrar mucho en este tema (sobre el que hay
enciclopedias),vamos a usar una tcnica muy bsica, pero muy eficaz en muchas
ocasiones y que os conviene conocer.
Vamos a leer el potencimetro para decidir si subimos o bajamos el valor del Angulo. No
para calcular Angulo directamente.
Como el potencimetro nos da valores entre 0 y 10000, cuando est centrado o suelto,
leer sobre 500, poco ms 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 potencimetro
sobrepasa el valor de 600 y lo disminuiremos cuando baje de 400.
De este modo pequeas oscilaciones alrededor del punto medio, no nos afectarn. Es
decir las hemos filtrado. Esto reflejado en el programa, podra ser algo as: Prog_17_2
#include <Servo.h>
Servo servo1;
int angulo = 90 ;
// Empezamos en el centro
int salto = 3 ;
int Eje_X = A1 ;
int Eje_Y = A2 ;
void setup()
{
servo1.attach(6) ;
void loop()
{
int p = analogRead(A1);
if ( p < 400 )
angulo = angulo - salto ;
else if (p>600)
angulo = angulo + salto ;
servo1.write(angulo);
delay (50);
movimiento
}
RESUMEN DE LA SESIN
Hemos visto que un joystick son dos potencimetros a 90 mas un pulsador, ambos
normales y corrientes.
Parece un poco ms complicado que los sensores que hemos usado hasta ahora, pero la
verdad es que se trata de una tecnologa muy fiable y que cuenta con la ventaja adicional
de ser baratos y mltiples fuentes de suministro disponibles.
El propio sensor PIR se puede comprar independientemente:
ESQUEMA DE CONEXIN
Antes de que vayis a buscar vuestros Arduinos, debis saber que estos sensores
PIR pueden disparar directamente una alarma con una seal de 3.3V y son capaces de
excitar pequeos rels, de modo que no necesitis micro controladores, si lo nico que
queris es encender una luz o dispara una alarma.
Por eso vamos a hacer, en primer lugar, un pequeo circuito de prueba como este, de
modo que nos sirva para probar el sensor, y veais que se puede usar directamente.
Vamos a montar un circuito sencillo de deteccin de movimiento que encienda una
LED cuando perciba algo:
Fijaros que hay 3 pines en el lateral, que usaremos para pinchar el sensor PIR HCSR501 a nuestra protoboard, y aqu debajo os pongo el esquema de conexiones:
Como podis ver enseguida, hay un par de potencimetros que podemos usar para
ajustarlo adems de un jumper para elegir modo. Vamos con ello.
AJUSTANDO EL SENSOR
Empezad por colocar el sensor en la misma posicin que la imagen de arriba porque mi
modelo no trae rotulado ningn nombre (Lo que me hizo poner nervioso al principio pero
despus vi que era completamente estndar).
He visto en Internet que recomiendan poner el jumper en la posicin H para las primeras
pruebas que arriba est rotulado como Auto Reset, pero en mi caso me ha resultado ms
fiable sacar el jumper y dejarlo al aire.
Fijaros que el modelo de la imagen este jumper no existe, pero la mayor parte de
los modelos que encontris por ah podris seleccionar H o L, conectando el jumper entre
el pin central y la seleccin deseada o bien dejarlo sin conectar.
Cuando colocamos el sensor en la posicin L, al detectar algo el LED se encender, y al
poco se apagar y har una cadencia tipo blinking LED dependiendo de lo que detecte. A
este modo se le llama no retriggering y no suele demasiado interesante.
Si lo ponemos en H, cuando detecte movimiento se encender y mantendr as durante un
tiempo (Llamado retrigger mode) y suele ser ms conveniente en buena parte de los
circuitos practicos .
Para ajustar la sensibilidad podemos usar uno de los potencimetros que incluye el sensor,
fijaras en la imagen de arriba. (Girando a favor del reloj aumentamos la sensibilidad)
El segundo potencimetro ajusta el tiempo que estar activa la seal de deteccin
despus de que esta haya desaparecido. Pero parece que tambin afecta al retraso con
que inicia la alarma, as que es cuestin de que vayis jugando para encontrar un punto
adecuado para vuestra alarma.
Aqu os dejo un mini video con una demostracin prctica
PROGRAMA DE CONTROL
Si queris usar estos sensores en conjuncin con vuestro Arduino, por ejemplo para
montar un detector con varios puntos controlados, como una habitacin con
mltiples puertas, basta con tomar la seal del sensor y la leis directamente en los pines
digitales de Arduino.
La seal que os entrega el sensor HC-SR501 es digital todo o nada en cuanto detecta
movimiento de una fuente de calor. Podeis leer el sensor directamente sin mucha
complicacin, con un programa similar a este:
const int led = 6 ;
const int sensor = 7 ;
void setup()
{
void loop()
{
if (digitalRead( sensor))
digitalWrite( led , HIGH);
else
digitalWrite( led , LOW);
RESUMEN DE LA SESIN
Ms sobre el PUENTE H
Hemos visto por encima las caractersticas bsicas de los motores de corriente continua
con escobillas (Porque hay varios tipos adems de este), pero vamos a entrar un poco
ms en detalle de que cosas debes considerar cuando vayas a elegir uno de estos
motores.
Cuando compres un motor de corriente continua debes fijarte en tres cosas bsicamente:
Voltaje de funcionamiento: Que especifica los rangos de tensin entre los que el
motor funcionar correctamente. Por ejemplo el que yo estoy usando se mueve entre 3 y
6V, pero no es raro encontrarlos de 9, 12 y 24V
Revoluciones por minuto: Que indica la velocidad que puede alcanzar a las
distintas tensiones y que se suele consignar como Rpm. Tpicamente en motores de
Hobby andaremos entre 200 y 2.000 rpm
Par motor: O potencia que el motor puede desarrollar y que indica la carga til
que puede mover. En ingls se llama Torque.
En la sesin anterior vimos como como conectar uno de estos motores a
nuestro Arduino y como variar la velocidad de giro modificando la tensin que le
Mucho cuidado de no superar la tensin mxima que el fabricante nos indica como
seguras o encontrareis que el olor de un motor quemado es muy caracterstico y
particularmente desagradable.
Pero una cosa que no hicimos en la sesin previa fue invertir el sentido de rotacin del
motor, porque este es un tema espinoso, ya que para ello necesitamos invertir la
polaridad de la tensin en bornes, y esto, queridos amigos, no podemos hacerlo usando
solamente nuestros Arduinos(Porque Arduino puede proporcionar +5V pero no -5V).
Para resolver este problema tenemos que usar un poco ms de ingenio y disear un
circuito que se llama puente en H ( H-bridge). Para comprenderlo, imaginaros el siguiente
montaje a base de interruptores:
Olvdate por ahora de los diodos, que son para proteccin de la descarga inductiva del
motor y proteger los transistores. Jugando con la tensin en los pines A; B; C; D podemos
conseguir que los transistores entren en corte o saturacin y disponemos de un medio
electrnico para abrir o cerrar el equivalente a los interruptores mediante transistores.
Observa que dos transistores son unos PNP y otros dos NPN para jugar con la
polaridad de la tensin.
El campo magntico del rotor almacena energa, que puede ser importante, y que
cuando cortamos la alimentacin debe ser liberada en forma de corriente elctrica, y
adecuadamente dirigida por los diodos para impedir daos en los transistores o en la
fuente de alimentacin
Que no se asuste nadie. No voy a pediros que montis ese circuito (aunque no sera
demasiado complicado). Recordad que cuando hay una necesidad en el mercado, siempre
hay alguien dispuesto a fabricar un integrado que hace eso y ms.
Y como esta no iba a ser la excepcin, nos encontramos que disponemos de varias
versiones de circuitos H-bridge dependiendo de la tensin y la intensidad que se debe
conmutar.
Nosotros hoy vamos a utiliza un integrado barato, probado y fcil de encontrar que incluye
dos H-bridge y que nos sirve para pequeos motores de corriente continua. Se
llama L293D.
EL H BRIDGE L293D
El L293D, es un pequeo integrado que incluye dos puentes H-Bridge que podemos usar
para gobernar simultneamente dos motores CC.
Si buscis el manual del L293D, veris que aunque el funciona a 5V internamente, puede
conmutar tensiones de hasta 36V para tus motores.
El pin 16, Vss, son los 5V con los que alimentamos el chip y el pin 8, Vs, es la
tensin con la que alimentamos el motor.
Los pines del 1 al 7 controlan el primer motor y los pines 9 a 15 controlan el
segundo motor.
El pin 1, Enable1, Activa el uso del motor 1. Con un valor HIGH, el motor puede
girar dependiendo del valor de I1 e I2. Si es LOW se para independientemente de los
valores del resto de pines
Los pines 2 y 7 son los pines de control para el motor 1, e irn conectados a
nuestros Arduino para controlar el sentido de giro.
Los pines 3 y 6 son la salida a la que se conecta el motor 1, cuya polaridad se
invierte en funcin los valores de 2 y 7.
En el diagrama de arriba veis que hay pines equivalentes para el motor 2 y cuales
son.
Los pines 4, 5,12 y 13 van a GND.
Podemos hacer una tabla para mostrar la lgica que sigue el giro del motor en funcin de
los tres pines:
ENABLE
CONTROL PIN 2
CONTROL PIN 7
LOW
HIGH
HIGH
LOW
ENABLE
CONTROL PIN 2
CONTROL PIN 7
HIGH
LOW
HIGH
HIGH
HIGH
HIGH
HIGH
LOW
LOW
Por tanto tenemos que activar el pin enable para que el motor gire y despus usamos los
pines Input1 e Input2 con valore opuestos para hacer girar el motor en una direccin o en
la contraria. Fcil no? Veamos cmo hacer el montaje con nuestros Arduinos.
Hagamos un resumen de conexiones
PIN L293D
PIN ARDUINO
10
Ena
Inp
Moto
4,5, 12,13
GND
Moto
Inp
Vin
Alimentaci
16
5V
Alimentaci
ESQUEMA DE PROTOBOARD
Una vez que tenemos claras las conexiones, el diagrama de protoboard del chip L293D a
nuestro Duino ser algo as:
DESCR
GN
Veamos el programa que vamos a usar para controlar este motor. Vamos a usar los 3
pines de la tabla anterior. Arduino Pin 10 es el enable del Motor 1 y usamos los pines 8 y 9
para controlar el sentido de giro. Por tanto
#define E1 10
#define I1 8
#define I2 9
void setup()
{
for (int i = 8 ; i<11 ; i++)
pinMode( i, OUTPUT);
}
void loop()
{
digitalWrite(E1, HIGH);
// Activamos Motor1
digitalWrite(I1, HIGH);
// Arrancamos
digitalWrite(I2, LOW);
delay(3000);
digitalWrite(E1, LOW);
// Paramos Motor 1
delay(1000);
digitalWrite(E1, HIGH);
// Activamos Motor1
digitalWrite(I1, LOW);
digitalWrite(I2, HIGH);
delay(3000);
digitalWrite(E1, LOW);
// Paramos Motor 1
delay(1000);
}
Pero el truco est en que hemos conectado el pin Enable1 al pin Arduino 10 que es PWM
(As, como sin querer) y los L293D vienen diseados para variar la velocidad de giro de los
motores correspondientes con la tensin aplicada a este pin, por lo que resulta trivial variar
la velocidad del motor, sin ms darle valores analgicos.
Si por ejemplo aadimos un potencimetro de nuevo conectado al A1, podemos escribir
este valor directamente (dividido por 4, claro) al pin 10 como analgico, sustituyendo la
lnea
digitalWrite(E1, HIGH);
// Activamos Motor1
Fijaremos la velocidad de giro del motor en funcin del valor del potencimetro. El
programa corregido, quedara poco ms o menos as:
#define E1 10
#define I1 8
#define I2 9
void setup()
{
for (int i = 8 ; i<11 ; i++)
pinMode( i, OUTPUT);
}
void loop()
{
// Arrancamos
// Activamos Motor1
delay(3000);
digitalWrite(E1, LOW);
// Paramos Motor 1
delay(1000);
analogWrite(E1, analogRead(A1) / 4);
digitalWrite(I1, LOW);
// Activamos Motor1
digitalWrite(I2, HIGH);
delay(3000);
digitalWrite(E1, LOW);
// Paramos Motor 1
delay(1000);
}
Y eso es todo.
RESUMEN DE LA SESIN
Los displays LEDs de 7 segmentos, que vimos en las sesiones anteriores, estn muy bien,
son baratos y prcticos, pero tienen el inconveniente de que no pueden mostrar mensajes
de texto, sino solo nmeros.
Se echa de menos algn sistema para mostrar mensajes de texto sencillos, y por eso se
comercializan los displays LCD. Son faciles de encontrar en diversos formatos : 162 (16
caracteres x 2 lneas) o LCD 164 (16 caracteres x4 lunes).
LCD viene del ingls Liquid Crystal Display, o sea Pantalla de cristal liquido.
Son una opcin muy sencilla de usar, y adems, dan un toque muy pro a vuestros
proyectos, y por eso, en los ltimos aos los displays LCD han ganado mucha aceptacin
en productos comerciales de todo tipo.
Bsicamente porque:
Son baratos.
Muy prcticos si te basta con mostrar solo texto (y algunos caracteres especiales).
En esta sesin veremos cmo conectarlos a vuestros Duinos y cmo usarlos para sacar
mensajes al exterior.
ANTES DE EMPEZAR
Aunque, ltimamente, estos displays suelen venir con los pines soldados, todava hay
muchos sitios que cuando compras uno de estos, te lo envan en kit, con los pines aparte
para que los sueldes
En algn momento tendremos que hablar de cmo soldar componentes, pero ese
da, an no ha llegado.
Lo primero que tienes que saber, es que tienes que soldarlos, y que no vale sujetar los
pines de algn modo ms o menos extravagante. Los sueldas y punto. Hazte a la idea.
Cualquier otra solucin 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 CONEXIN
La conexin no es complicada, pero requiere ser cuidadoso. Asi que vamos a ir paso a
paso con los diferentes cables. Empieza conectando tensin y GND a la protoboard.
Vamos ahora a a conectar la alimentacin 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 debera iluminarse, si no, revisa tus
cables antes de seguir.
Vamos a conectar ahora, el potencimetro 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 tambin para dar tensin al panel LCD, El pin 1 va a GND y el 2 a tensin:
GND
Arduino pin 7
Arduino pin 8
Arduino pin 12
Arduino pin 11
Arduino pin 10
Arduino pin
EL PROGRAMA DE CONTROL
Vamos a usar una librera de control del panel LCD, que viene incluida en nuestro Arduino.
Pinchad en:
\\Programa\Importar Libreria\LiquidCrystal
Despues, hay que inicializar la librera. Creamos una instancia llamada lcd, de la clase
LiquidCrystal y le pasamos como parmetros los pines que hemos usado:
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //
Tened cuidado porque los pines que hemos usado, no corresponden a los
ejemplos de Arduino, as que podis cargarlos, peroaseguraros de cambiar la lnea de
definicin de los pines, o no corrern.
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);
lcd.print(millis() / 1000);
void setup()
{
lcd.begin(16, 2);
lcd.print("Prometec.net");
// Aqi va el mensaje
void loop()
{
lcd.setCursor(6, 1);
String s = reloj() ;
lcd.print(s) ;
}
String reloj()
{
int n = millis() / 1000 ;
int segundos = n % 60
int minutos =
n / 60
// Lo pasamos a segundos
Merece la pena, comentar algunas cosas de este cdigo. En primer lugar en la funcin
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 parmetro tipo String a quien nos haya llamado. En
algn punto de la funcin habr que hacer un return( String).
Fijaros que definimos dentro de la funcin un string llamado s:
String S = String(minutos) + ":" + String(segundos);
En esta lnea no hay que confundir (aunque se escriben exactamente igual), el tipo String
para definir S, con la funcin String(n) que convierte un numero n en un string de texto
para que pueda mezclar el nmero de los minutos y los segundos separados por un
smbolo de :.
Al final le aadimos un par de espacios en blanco, para evitar arrastrar fantasmas en la
pantalla
Para sacar el mensaje de texto. Todo lo que ya sabis de Serial.print() se usa exactamente
igual con esta instruccin. Y por ltimo, tenemos una lnea como esta:
lcd.setCursor(6, 1);
Que lo que hace es posicionar el cursor del panel, en la posicin 6 de la segunda lnea,
para escribir la hora centrada. Aqu os dejo un mini video con el resultado.
La librera LCD, viene con varios ejemplos muy interesantes, que os conviene probar.
Recordad, simplemente, que tenis que cambiar las definiciones de los pines para que
corran.
Un ejemplo particularmente interesante, es el de CustomCharacter, en el que define una
serie de smbolos especiales y los mueve por la pantalla en funcin de los valores que lee
de un potencimetro.
Sin llegar a tanta sofisticacin, es muy interesante que veamos cmo definir algunos
caracteres especiales, porque en la tabla base del LCD, no estn incluidas , acentos,
grados, o . As que dependiendo del uso que le deis pude seros de inters saber cmo
definir tus propios smbolos.
Vamos a definir un carcter propio, para digamos, el smbolo de grados centgrados, por
ejemplo.
Lo primero que tenis que saber, es que los caracteres se definen con un array ( si, de
nuevo) de 88, como si los dibujarais en una cuadricula de ese tamao, y rellenando el
cuadradito completo.
As por ejemplo para el smbolo del grado seria:
byte grado[8] =
{
0b00001100,
0b00010010,
0b00010010,
0b00001100,
0b00000000,
0b00000000,
0b00000000,
0b00000000
};
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()
{
}
Por ltimo, y para cerrar ya la sesin (Todo llega en la vida), Deciros que de nuevo, hemos
montado este display a la brava, conectando un buen nmero de cables.
Esto solo se puede justificar, porque en su da piqu y me compre un display de estos ( en
realidad, dos. Tengo otro de 164), 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 prxima sesin montaremos uno para que veis la diferencia.
RESUMEN DE LA SESIN
Hemos ido viendo hasta ahora como utilizar un sensor de temperatura y tambin como
usar un pequeo transistor para mover un motor de CC, pero no los habamos mezclado.
En esta sesin haremos un pequeo ejemplo de control, usando un sensor LM35DZ para
determinar la temperatura y un ventilador de 5V, para que cuando la primera alcance un
valor crtico, usemos el segundo a fin refrigerar el circuito.
Como no disponemos de ningn 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 reaccin, en el mejor espritu de un sistema automtico,
tal como un regulador de temperatura con nuestros Duinos.
Veremos que la regulacin de un sistema tan sencillo no tiene grandes problemas y por
eso esta sesin esta mas pensada como un ejercicio de control sencillo y que como una
regulacin en toda regla.
Adems el parmetro 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
cuestin de reaccionar con precisin en tiempo real.
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.
Vamos a montar un pequeo 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
Ya hemos visto en sesiones previas como usar un sensor LM35DZ, pero si alguno queris
revisarlo podis 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 ;
void setup()
{
Serial.begin(115200);
void loop()
{
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 centgrados (Recordad que la razn
de hacerlo as la vimos en la sesin de los sensores de temperatura) e imprimimos sin ms
el valor de la temperatura. Deberas 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 oscilacin, dando diferencias de hasta un grado.
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 electromagnticas 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 ms sencilla es usar un buffer
circular (O Ring Buffer)
La forma de apuntar a la posicin a escribir es una variable llamada ndex que empieza en
0 y cada vez que escribe en la posicin correspondiente se incrementa en 1 Y cmo
evitamos que pase del valor mximo aceptable? Pues tomando el resto del valor de ndex
con respecto al nmero de posiciones del array.
Buffer[ index] = temp ;
index = ++index % 8
Una vez que apuntamos correctamente a la posicin a escribir y despus de los N valores
iniciales en los que la temperatura promedio ser falsa (Porque an no hemos ledo N
valores) tendremos en Buffer las ultimas N lecturas y el resto es aritmtica:
int index = 0 ;
// Posicion a escribir
const int N = 16 ;
float Buffer[N] ;
% 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
podis ver algo as:
Podis ver que la temperatura baila mucho menos y el baile desciende a medida que
aumentis el nmero de muestras que promediis, pero cuidado, cuanto ms crece N
tambin crece el tiempo que tardis en responder a los cambios ( Para N = 32 a 5
muestras por segundo hay ms de 6 segundos de tiempo de reaccin).
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.
int umbral = 30 ;
// Gobierna el ventilador
void setup()
{
Serial.begin(115200);
pinMode(control,
OUTPUT) ;
void loop()
{
delay(200);
RESUMEN DE LA SESIN