Arduino – Capítulo 10 – Reloj de arena digital

Hourglass

A ver, ¿cual puede ser nuestro siguiente proyecto? ¿Un reloj de arena digital? Eso está muy bien, de este modo aprenderemos a utilizar la función millis() la cual, nos permite contabilizar el tiempo que transcurre.

Hasta ahora, cuando queríamos que algo ocurriera al cabo de un intervalo específico de tiempo, recurríamos a la función delay(). Dicha función es útil pero un poco limitante. Cuando Arduino llama a la función delay(), este “congela” su estado actual tanto tiempo como indique dicho retardo. Esto quiere decir que mientras esté esperando no puede haber ninguna entrada ni salida de datos. El uso de este tipo de retraso no es muy útil para realizar un seguimiento del tiempo transcurrido. Si queremos llevar a cabo una tarea cada diez segundos, crear un retardo de dicho tiempo resulta bastante engorroso.

La función millis() nos ayuda a resolver estos problemas. Esta contabiliza en milisegundos el tiempo que nuestro Arduino está en marcha.

Hasta ahora, hemos creado variables de tipo int. Un int (entero o integer en inglés) es un número de 16 bits, que comprende los valores en un rango que va desde el -32.768 hasta el 32.767. Estos son números un tanto largos o grandes, como deseemos decirlo, pero si Arduino es capaz de contar mil veces en un solo segundo gracias a la función millis(), entonces habremos superado este límite en menos de un minuto. Por contra, el tipo de dato long contiene números de 32 bits, comprendidos en un rango que va desde el -2.147.483.648 hasta el 2.147.483.647. Como no podemos dar marcha atrás en el tiempo para usar los número negativos, la variable que usemos para almacenar el tiempo de la función millis() se denomina unsigned long (long sin signo). Cuando un tipo de variable es llamada unsigned, se la considera solamente positiva. Esto nos permite contar siempre hacia adelante. Un long sin signo puede contar hasta 4.294.967.295, esto es suficiente para que la función millis() almacene el tiempo transcurrido durante 50 días. Si comparamos el valor actual de millis() con un valor específico, podremos saber si ha transcurrido una cierta cantidad de tiempo.

Cuando le demos la vuelta a nuestro reloj de arena digital, un sensor de inclinación (tilt switch en inglés) cambiará su estado, haciendo que los leds que indican el tiempo transcurrido se apaguen para volver a contar un nuevo periodo de tiempo.

Un sensor de inclinación funciona igual que un interruptor, ya que tan solo es un componente con dos estados, es por ello que lo usaremos como elemento de entrada. El funcionamiento de nuestro sensor está basado en una pequeña cavidad, la cual, alberga una esfera metálica. Cuando el sensor de inclinación es girado, la bola rueda hacia un lado de la cavidad, conectando los dos terminales que posee. Existen dos modelos de este componente, los que están basados en una pequeña bola metálica y los que funcionan con mercurio.

 

Mercury switch

Sensor de inclinación basado en mercurio

 Tilt switchSensor de inclinación basado en esfera metálica

Montando el circuito

Para montar el circuito de este proyecto necesitamos los siguientes componentes:

– 1 sensor de inclinación.

– 6 leds rojos (o del color que queramos).

– 1 resistencia de 10KΩ.

– 6 resistencias de 220Ω.

Una vez tenemos los componentes necesarios, debemos seguir los siguientes pasos:

1 – Conectamos los cables de alimentación a la protoboard.

2 – Unimos el ánodo de cada uno de los seis leds a los pines del 2 al 7 del Arduino. El cátodo de los leds lo conectaremos a tierra mediante las resistencias de 220Ω.

3 – Ahora cogemos y unimos una de las patillas del sensor a la alimentación. La otra irá a tierra a través de la resistencia de 10KΩ.

4 – Finalmente colocaremos un cable que vaya desde el pin número 8 a la unión entre el sensor y la resistencia de 10KΩ.

Terminado de montar el circuito, deberíamos de tener algo parecido al mostrado en la siguiente figura.

Diseño de protoboard

 

El esquema eléctrico correspondiente sería:

Esquema de conexiones

 

El código

Comencemos por comentar paso a paso el código fuente con el que vamos a programar nuestro Arduino.

Vamos a necesitar unas cuantas variables globales en nuestro programa para que todo funcione. Así que para empezar, crearemos una constante llamada switchPin. Este será el nombre del pin en el que el sensor estará conectado.

const int switchPin = 8;

A continuación, creamos una variable de tipo unsigned long, la cual, almacenará el tiempo transcurrido desde la última vez que cambió el estado de un led.

unsigned long previousTime = 0;

Después, crearemos una variable para el estado actual del sensor y otra para su estado anterior. Estas variables nos servirán para comparar el estado del sensor desde el inicio de un ciclo hasta el siguiente.

int switchState = 0;
int prevSwitchState = 0;

Seguidamente, creamos una variable llamada led. Ésta nos servirá para contabilizar que led será el próximo en encenderse. El primero de ellos será el conectado al pin 2.

int led = 2;

La última variable en ser creada será aquella que almacene el valor del intervalo de tiempo entre el encendido de un led y el siguiente. Dicha variable será de tipo long. El tiempo transcurrido entre el encendido de un led y el siguiente será de 10 minutos, o lo que es lo mismo, 600.000 milisegundos. Si queremos que dicho intervalo de tiempo sea mayor, tendremos que cambiar dicho valor.

long interval = 600000;

Ahora vamos a entrar en la función setup(). En esta función debemos declarar los pins del 2 al 7 (los correspondientes a los leds) como salidas. Para realizar esto usaremos un bucle for(). Gracias a dicho bucle podremos declarar los seis pins como salidas en tan solo tres líneas de código. Por otra parte, también necesitamos declarar switchPin como entrada.

void setup() {

    for(int x = 2;x<8;x++){
        pinMode(x, OUTPUT);
    }

    pinMode(switchPin, INPUT);

}// Fin de la función setup.

Cuando la función loop() empieza, leeremos mediante la función millis() la cantidad de tiempo que ha lleva Arduino encendido y almacenaremos dicho valor en una variable local llamada currentTime.

void loop(){

    unsigned long currentTime = millis();

A continuación, utilizaremos la sentencia if() para comprobar si ha transcurrido tiempo suficiente para activar un led. Restaremos el tiempo actual (currentTime) del tiempo anterior (previousTime) y comprobamos si el resultado de dicha resta es mayor que el intervalo establecido anteriormente. Si han transcurrido 600.000 milisegundos (10 minutos), almacenaremos el valor de currentTime en la variable previousTime.

if(currentTime - previousTime > interval){
        previousTime = currentTime;

La variable previousTime indica la última vez que un led fue activado. Una vez que hayamos establecido el valor de previousTime, encenderemos un led e incrementaremos el valor de la variable led. La próxima vez que haya transcurrido el intervalo establecido, se encenderá el led siguiente.

digitalWrite(led, HIGH);
led++;

Seguidamente, añadiremos una sentencia if() más en el programa con el fin de determinar si el led conectado al pin 7 está activado. Si lo está, es que ha transcurrido una hora. En este momento, si dicha sentencia es cierta, no haremos nada. Que cada uno decida que debe ocurrir una vez haya pasado una hora.

        if(led == 7){
        }
 }

Ahora que hemos comprobado cuanto tiempo ha pasado, miraremos si el sensor ha cambiado su estado. Para ello leeremos el estado de dicho sensor y almacenaremos su valor en la variable switchState.

switchState = digitalRead(switchPin);

Mediante una sentencia if() comprobaremos si el estado actual del sensor difiere del estado anterior. El símbolo != sirve para evaluar si el valor de switchState no es igual que el valor de prevSwitchState. Si tienen valores diferentes, apagaremos los leds, le daremos a la variable led el valor del primer pin y resetearemos el temporizador de los leds dándole a la variable previousTime el valor de currentTime.

    if(switchState != prevSwitchState){
        for(int x = 2;x<8;x++){
            digitalWrite(x, LOW);
        }

        led = 2;
        previousTime = currentTime;
    }

Para acabar, al final de la función loop(), guardaremos el estado del sensor en la variable prevSwitchState, para que de esta manera podamos comprobar dicho estado con el que obtendremos en la variable switchState de la siguiente iteración de la función loop().

    prevSwitchState = switchState;

}// Fin de la función loop.

 

Puesta en marcha

Una vez que hayamos programado nuestro Arduino, comprobaremos la hora en un reloj. Tras haber transcurrido diez minutos, el primer led debería activarse. Después de esto, cada diez minutos se activará otro led. Después de una hora, los seis leds deberán estar encendidos. Cuando giremos la placa haciendo que el sensor cambie de estado, los leds se apagarán y el temporizador empezará a contar de cero.

Un elemento que podemos añadir a nuestro reloj de arena es algún tipo de alarma para cuando pase una hora. Podríamos hacer parpadear los leds o reproducir un sonido. Para ello, tendremos que comprobar la variable led para ver si todos los leds están encendidos y si dicha condición es cierta, activar nuestra alarma.

 

Conclusión

En este proyecto hemos aprendido a utilizar la función millis() para medir el tiempo y el tipo de variable unsigned long, la cual nos permite almacenar valores más grandes que los permitidos por su amigo el tipo de variable long. También hemos visto que es un sensor de inclinación y para que podemos usarlo. Pero…, tal y como hemos construido nuestro reloj de arena, los leds se encenderán en una sola dirección. ¿Cómo haríamos para que el sentido de su iluminación sea uno u otro en función de la posición del reloj?

 

Espero que os haya gustado.

Un saludo y muchas gracias por leer este artículo.  ^_^

 

Referencias

– Artículo basado en el capítulo “Project 08 – Digital Hourglass” del libro “Arduino Projects Book” distribuido por Arduino.cc junto con su “The Arduino Starter Kit“.

– Más información acerca de la función millis(): http://arduino.cc/en/Reference/Millis

– Más información acerca del tipo de variable unsigned long: http://arduino.cc/en/Reference/UnsignedLong

Anuncios

2 pensamientos en “Arduino – Capítulo 10 – Reloj de arena digital

  1. Pingback: Arduino – Capítulo 13 – Bola mágica | El gato inquieto

  2. Hola! gracias por tus tutoriales. Soy nuevo en esto, y hasta ahora ahí voy. Poco a poco. Tengo una curiosidad. para poner la alarma como dices. ¿En que linea debería de comprobar la condicion led? y ¿como tendria que hacerlo? Por mas que pruebo, no me sale nada.
    Muchas gracias!

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s