Páginas

miércoles, 8 de enero de 2014

Reloj en tiempo real para Raspberry Pi

En una aplicación que desarrollé hace ya algún tiempo, en donde un miniPC Android al que le instalé Linux gestionaba las salidas de una tarjeta Arduino, eché en falta la existencia de un reloj en tiempo real. Aunque el equipo se pensó para estar en conexión permanente a Internet, la realidad se muestra a veces en toda su crudeza y deja de ser lo que uno idealiza o desea que sea. ¿Qué porqué digo esto? Pues muy sencillo. Cuando lo que se pretende con la aplicación es activar unas salidas digitales conforme a una secuencia que se activa a una determinada hora del día, es preciso que el reloj interno del sistema esté en hora, ya que si no es así la secuencia se activará a una hora dependiente de la hora de reinicio del equipo.
Cuando he rediseñado la aplicación (y el hardware del equipo) lo primero que hice fue implementar un reloj en tiempo real por hardware, que pudiese ser puesto en hora por el sistema operativo, obteniéndola de un servidor de Internet, y que, en el caso de un reinicio no tuviésemos acceso a Internet, leyese la fecha y hora desde reloj en tiempo real.

Diseño y Montaje del módulo Reloj en Tiempo Real

Por brevedad, a partir de ahora, nombraremos el Reloj en Tiempo Reloj por su acrónimo en inglés RTC (Real Time Clock).
Después de consultar al Gran Hermano, que es Google, me decidí por utilizar el circuito integrado DS1307, manejándolo mediante el bus serie i2c. Este módulo se conectará a la tarjeta Raspberri Pi v2 a través del conector GPIO 2x13.
El prototipo lo montaremos en una protoboard y utilizaremos el programa Fritzing en el diseño previo al montaje real.
En la imagen anterior se muestran los componentes que hemos utilizado y los puentes que hemos tendido entre los componentes. Así, los conductores rojos corresponden a la tensión positiva de 5V que tomamos del RaspPi, los conductores negros van a 0V que también va unido a la tierra del RaspPi. El conductor amarillo alimenta el integrado DS1307 con los 3V de la batería. Y los azules corresponden al bus i2c, el que nos permitirá que el RTC y la RaspPi se comuniquen. Mediante un cable plano de 26 conductores uniremos el conector situado en la protoboard con el conector situado en la RaspPi.
Los componentes que vamos a utilizar son:
  • circuito integrado DS1307 (RTC)
  • cristal de 32.768 kHz
  • batería CR2032 (3V)
  • zócalo para batería
  • tarjeta de expansión de 2x13 pines (ver en este mismo blog Conectando Raspberri Pi a una protoboard)
Una vez montado el circuito, de acuerdo al ejemplo de la imagen anterior y comprobando que los conductores unen las patillas de los componentes y de la protoboard convenientemente, pasamos a implementar la parte de software en la Raspberry Pi. CON EL EQUIPO DESCONECTADO, conectamos la protoboard a la tarjeta RaspPi uniendo los dos conectores de 2x13 pines mediante un cable plano de 26 conductores.

Librerías a instalar en la Raspberry Pi

Tal como indicaba en una entrada antigua de este blog (ver http://elfrikidiletante.blogspot.com.es/2013/11/el-prometedor-mundo-raspberry-pi.html) mi tarjeta RaspPi tiene instalado el sistema operativo Raspbian, una versión de linux basado en Debian. Para que el RaspPi pueda manejar el RTC, en el caso de que no lo estén, instalaremos las siguientes librerías:
sudo apt-get install python-smbus
sudo apt-get install i2c-tools
Seguidamente, indicaremos al sistema operativo que cargue ciertos módulos que no fueron integrados en su kernel, para ampliar las capacidades que queremos que tenga. Para ello, editaremos el fichero /etc/modules
sudo nano /etc/modules
para que contenga, al menos, las siguientes líneas:
Después, si existe el fichero /etc/modprobe.d/raspi-blacklist.conf lo editaremos como sigue
sudo nano /etc/modprobe.d/raspi-blacklist.conf
comentando las líneas que hacen mención a los dos protocolos de comunicación i2c y spi, insertando '#' al inicio de las líneas,  ya que estos protocolos podrían venir bloqueados por defecto:
Si el fichero no existe, no debemos preocuparnos de crearlo y editarlo.
Finalmente, reiniciamos el equipo
sudo shutdown -r now
y comprobamos que funciona el protocolo i2c. ¿De qué manera?
Mediante la instrucción i2cdetect -y 1. Al estar haciendo estas pruebas con la versión 2 de la tarjeta RaspPi, hemos puesto un '1' de parámetro. En el caso de que fuera la primera versión, pondríamos un '0', es decir, la instrucción sería i2cdetect -y 0.
Para evitar tener que ejecutar i2cdetect en modo root, vamos a añadir los usuarios que tengan estas facultades al grupo i2c. En este caso el usuario es pi. Reiniciamos el sistema y podremos comprobar que si ejecutamos i2cdetect sin sudo y sin ser root, se ejecutará correctamente.
sudo adduser pi i2c
sudo shutdown -r now

Manejando el Reloj DS1307 (hwclock)

Ahora viene la prueba de fuego:
- poner en (fecha y) hora el DS1307
- leer la (fecha y) hora almacenados en el DS1307
Para tal fin, el sistema Linux posee una instrucción para gestionar el RTC siempre que el hardware del sistema disponga del mismo. Esta utilidad es hwclock. Si tecleamos en un terminal (en este caso, desde un terminal remoto, invocado con la instrucción ssh) las siguientes instrucciones:
sudo hwclock -V
sudo hwclock -h
nos aparecerá en la misma ventana los siguientes resultados:
La primera instrucción nos muestra su versión. Y la segunda, todas las instrucciones (con sus correspondientes parámetros) que están implementados en esta versión. Para comprobar el buen funcionamiento del montaje realizado, ejecutaremos dos instrucciones:
sudo hwclock -w
sudo hwclock -r
En la primera instrucción, pondremos en hora el RTC. Y con la segunda, obtendremos la fecha y hora que contiene. Manos a la obra:
¡Error,Horror! ¿Qué ha sucedido? La instrucción no se ha llegado a ejecutar correctamente, dándonos un mensaje de error, que para mi, ha sido algo críptico. No importa. Recurrimos de nuevo al 'Gran Hermano', que es Google, introduciendo como búsqueda en un navegador, la primera línea de error. Y entre los 6.000 resultados que proporciona la búsqueda, encontraremos la solución.
En un principio, se puede llegar a pensar que es un problema de hardware, de que el montaje no está bien realizado, o de que el circuito integrado no responde. Pero no parece que sea éste el problema, ya que la instrucción i2cdetect funciona a la perfección. Debe ser algún problema de configuración al arranque, que es por lo que nos decantamos. Tecleamos lo siguiente:
sudo -s
echo ds1307 0x68> /sys/class/i2c-adapter/i2c-1/new_device
exit
y comprobamos lo qué sucede.
El periférico DS1307 es reconocido, pero con una sutil diferencia. En vez de aparecer con un 68 aparece con el código UU. ¡Sorprendente! Recuerdo que en otro equipo, que también aparecía con este código, hwclock funcionaba a la perfección. Ahora, utilicemos la instrucción hwclock.
/etc/rc.local, e incluyendo esta línea al final del fichero.
¡Por fin!. Lo hemos conseguido. Ya nos funciona.
Pero ahora, lo que tenemos que hacer es automatizarlo para que esta sentencia se ejecute al arranque del sistema. ¿Cómo? editando el fichero
sudo -s
nano /etc/rc.local
en la siguiente imagen podemos observar el fichero /etc/rc.local, con la línea insertada.
Reiniciamos el sistema, y comprobamos de nuevo que tecleando
sudo hwclock -w
sudo hwclock -r
funciona a la perfección.

Cambiando de timezone

Si nos fijamos con atención, probablemente observaremos que la hora que aparece es la UTC. Para que aparezca la hora de nuestra zona horaria podemos ejecutar la siguiente instrucción y seguir los pasos que nos vaya indicando.
sudo dpkg-reconfigure tzdata 

Montaje físico

En la siguiente imagen se muestra un montaje real del RTC en una protoboard, conectado a la RaspPi a través de un cable plano.

Ficheros utilizados en Fritzing

En el siguiente apartado de Enlaces se incluyen los ficheros del montaje y de los componentes para ser utilizados en Fritzing, por si alguien los quiere utilizar.

Enlaces

- DS1307 datasheet
- Conectando Raspberri Pi a una protoboard (en este mismo blog)
- DS1307 Real Time Clock Breakout Board Kit (ejemplo para Arduino)
- Configuring i2c
- hwclock (man)
- DS1307 hwclock -r problem
- WiringPi - GPIO Interface library for the Raspberry Pi
- How to use GPIOs on raspberry pi (Simple I/O, PWM and UART)
- WiringPi - Download and install
- RaspPi examples
- Quick2Wire - I2C & SPI
- I2C Installation for Raspberry Pi
- Raspberry Pi - I2C Tutorial
- Cambiando tu timezone en Linux
y a continuación el montaje y los componentes utilizados en el programa Fritzing
- RTC_DS1307.fzz
- RaspPi2 Header 13x2.fzpz
- Battery Holder + CR2032.fzpz
- cristal_kHz.fzpz
- Fritzing
- Inkscape

No hay comentarios:

Publicar un comentario