viernes, 6 de mayo de 2016

Instalar y configurar reloj RTC DS3231 en Raspberry Pi con Raspbian Jessie

El módulo RTC DS3231 es un reloj en tiempo real bastante preciso, que puede ser usado con el Raspberry Pi para mantener la hora en forma independiente de no estar el computador prendido o de contar con acceso a internet al momento de prenderse.

El módulo que compré es un SoundFounder, pero se parece mucho a este en dx.com, que básicamente contiene el chip Maxim y un par de resistencias para el I2C.

Según las especificaciones del chip Maxim DS3231, este tiene una exactitud de ±2 minutos por año,  que es mejor que el típico DS1307 (dependiendo del cristal utilizado puede ser ±1 minuto por mes). La precisión la obtiene al incorporar dentro del chip un cristal con baja dispersión (±2ppm entre 0°C y 40°C y ±3,5ppm entre 40°C y 85°C), junto con tener compensación según la temperatura. Utiliza interfaz I2C, con posibilidad de usar velocidad rápida (400khz).

Configuración del módulo en Raspbian Jessie

Esta sección es una mezcla de información de varios sitios, pues con Raspbian Jessie al usar overlays las instrucciones antiguas quedan algo desactualizadas.

1) Uso de Overlays

Lo primero es editar el archivo /boot/config.txt:
$ sudo nano /boot/config.txt
añadiendo las líneas siguientes al final del archivo:
dtparam=i2c_arm=on
dtoverlay=i2c-rtc,ds3231
La primera línea habilita el canal i2c en los pines GPIO2 y GPIO3.
La segunda línea es la declaración para cargar el módulo RTC, especificando el uso del DS3231.

Lo siguiente es revisar que no esté restringido el driver, revisando el archivo /etc/modprobe.d/raspi-blacklist.conf:
$ sudo nano /etc/modprobe.d/raspi-blacklist.conf
El archivo debería estar en blanco, o tener comentado el driver, en una línea como:
#blacklist i2c-bcm2708 

 Finalmente se debe resetear el Raspi, con el comando:
$ sudo shutdown -r now

Opcional: uso de bus más rápido para i2c

Como este dispositivo se puede utilizar con una velocidad mayor de bus (400kHz), esto también se puede habilitar con los overlays, agregando otro parámetro al archivo /boot/config.txt:
dtparam=i2c_arm=on
dtparam=i2c_arm_baudrate=400000
dtoverlay=i2c-rtc,ds3231

El parámetro i2c_arm_baudrate especifica la velocidad del bus, siendo las comunes 100kHz, 400kHz y 1.2MHz, aunque hay que ver según las posibles para cada dispositivo.

2) Instalación del módulo

Teniendo la precaución de tener el Raspi apagado, el módulo se instala en los pines correspondientes a +3.3V, SDA1 (GPIO2), SCL1 (GPIO3) y GND.
Fuente: http://elinux.org/RPi_Low-level_peripherals

3) Verificación de funcionamiento

 Luego de reiniciado el Raspi, probar los siguientes comandos para revisar que todo funcione:
$ dmesg | grep i2c
[    5.523637] i2c /dev entries driver
[   14.631118] bcm2708_i2c 20804000.i2c: BSC1 Controller at 0x20804000 (irq 79) (baudrate 100000)

Esto muestra que se cargó el driver del i2c con velocidad 100kHz (baudrate).

$ dmesg | grep rtc
[   14.733399] rtc-ds1307 1-0068: rtc core: registered ds3231 as rtc0

Esto muestra que el driver del RTC se cargó exitosamente, como DS3231 y se registró como dispositivo rtc0 en uso por el kernel como reloj en tiempo real. Lo curioso es que el módulo del kernel se llama rtc-ds1307, aunque soporta ese modelo y el del DS3231.

$ lsmod | grep rtc
rtc_ds1307             10459  0

 Aquí también se ve que el módulo del kernel está cargado, y que se llama rtc_ds1307. En fin, hay mucha historia en linux...

$ ls /dev/rtc?
/dev/rtc0

Esto muestra que el dispositivo está en uso por el kernel y está disponible para ser usado desde los programas usuario.

4) Opcional: Uso herramienta i2cdetect

Opcionalmente se puede usar la herramienta i2cdetect para reconocer el dispositivo al conectarlo. Para ello se debe instalar el paquete i2c-tools, luego de la consabida actualización del sistema
$ sudo apt-get update && sudo apt-get upgrade
$ sudo apt-get install i2c-tools


Si por ejemplo no hubieramos hecho la configuración del punto 1, al usar el utilitario, se mostraría lo siguiente (usando el canal 1 para Raspi modelos B+/ 2 / 3)
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Aquí se ve que el único dispositivo conectado por i2c tiene dirección 0x68, correspondiendo al RTC según el datasheet (0b1101000).

Sin embargo, cuando el kernel cargó el módulo y por lo tanto administra el RTC, el comando entrega:
$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Las letras UU indica que esa dirección está siendo usada por un driver del kernel.

5) Establecer y leer la hora desde el dispositivo rtc0

Aunque el reloj ya está reconocido por el kernel, aún no se está utilizando para establecer la hora en el Raspi. Partamos con los comandos básicos para leer y escribir la hora hacia el RTC:


$ sudo hwclock -r
jue 28 abr 2016 08:30:09 CLST  -0.867263 seconds

Con esto se lee la hora desde el RTC (parámetro -r). En este caso el reloj del RTC estaba bastante atrasado.

La hora del sistema se puede ver con:
$ date
jue may  5 23:02:46 CLST 2016


En mi caso el reloj igual estaba unos minutos atrasado, posiblemente porque tenía el Raspi muchos días funcionando.

Para setear la hora del sistema, se usa este comando:
$ sudo date -s "may 5 2016 23:09:40 CLST"
jue may  5 23:09:40 CLST 2016


Ahora como el reloj del sistema está bien, se puede establecer la hora en el RTC como:
$ sudo hwclock -w

Con esto se escribe la hora hacia el RTC (parámetro -w).

6) Utilización de RTC para establecimiento de la hora del sistema

Todavía falta algo, pues aunque tengamos seteada la hora correcta en el RTC, el sistema al reiniciarse aún sigue utilizando el dispositivo fake-hwclock (rtc en software), que usa el servicio ntp para obtener la fecha y hora actuales desde la red. Por ello, se debe habilitar el servicio hwclock.
Así, para raspbian Jessie se ajustan ambos servicios:
$ sudo update-rc.d hwclock.sh enable
$ sudo update-rc.d fake-hwclock disable


 Finalmente se debe resetear el Raspi, con el comando:
$ sudo shutdown -r now


En todo caso siempre se puede llamar manualmente al servicio ntp para sincronizar la hora del RTC:
$ sudo ntpd -gq; sudo hwclock -w
ntpd: time set -6.827372s