Arturo no tengo ningún problema en hacerlo como queráis. Normalmente esas decisiones las tomo yo. He querido probar a donde me lleva el consultar cada paso porque lo que es sencillo para mí pude no serlo para los demás..
Yo con electrónica y programación me metería lo necesario como en todo. Se trata de dar los primeros pasos en un campo totalmente inexplorado para muchos. Me refiero a lo básico para entender los por qué de aquello que tenga relación directa con lo que hacemos.
Por desgracia, habrá partes del código que no serán triviales. Todo el mundo debe poder dar el primer paso con facilidad y tener algo que funcione.
La parte del código complicada el algo que normalmente debería quedar oculto al usuario así que una de dos:
1) Se hace un programa que lo contenga todo y que funcione sin más.
2) Hacemos un paquete que además del módulo principal contenga un módulo de librería, para ocultar la complejidad y facilitar su reutilización en otros programas y lo acompañamos con las oportunas instrucciones de instalación que por otra parte serían muy sencillas. Seguramente metería algún modulito más.
Ocultar la complejidad es algo que se hace siempre, de otra forma nos volveríamos locos. Para conducir un coche no hace falta saber ingeniero industrial.
Se pueden hacer las dos versiones. La primera versión totalmente funcional sería la versión monolítica. La segunda incluiría más de un módulo. Sería básicamente el mismo programa codificado de dos formas diferentes.
Aparte de eso sacaré una versión solo para probar el RTC.
Yo sabía que en un dispositivo I2C hay registros de datos en los que puedes leer y escribir y acceder pero no había practicado lo de acceder directamente por posición porque no lo vi necesario y es muy fácil. En muchos dispositivos I2C tipo sensor, hay uno o dos registros y se acceden todos a la vez por sencillez.
Cómo funciona el módulo DS3231
Para manejarlo basta leer o escribir en una serie de registros que son los siguientes:
Código:
#define DS3231_I2C_ADDRESS 0x68
//DS3232 Register Addresses
#define RTC_SECONDS 0x00
#define RTC_MINUTES 0x01
#define RTC_HOURS 0x02
#define RTC_DAY 0x03 // day of Week
#define RTC_DATE 0x04
#define RTC_MONTH 0x05
#define RTC_YEAR 0x06
#define ALM1_SECONDS 0x07
#define ALM1_MINUTES 0x08
#define ALM1_HOURS 0x09
#define ALM1_DAYDATE 0x0A
#define ALM2_MINUTES 0x0B
#define ALM2_HOURS 0x0C
#define ALM2_DAYDATE 0x0D
#define RTC_CONTROL 0x0E
#define RTC_STATUS 0x0F
#define RTC_AGING 0x10
#define TEMP_MSB 0x11
#define TEMP_LSB 0x12
Usa datos codificados en BCD, de momento basta decir que usaremos funciones para pasar del formato decimal normal que usa el compilador de C al formado BCD que usa DS3231. Las funciones son: decToBcd(), bcdToDec()
Para cambiar la hora sería:
Código:
// Ajustar fecha y hora en el DS3231
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(RTC_SECONDS); // Situar el comienzo de la escritura para el registro RTC_SECONDS
Wire.write(decToBcd(second)); // 0..59
Wire.write(decToBcd(minute)); // 0..59
Wire.write(decToBcd(hour)); // 0..23
Wire.endTransmission();
Para leer la hora sería:
Código:
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(RTC_SECONDS); // Nos situamos en el registo 00h de DS3231
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 3); // Pedimos leer 3 bytes empezando en RTC_SECONDS
*second = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read() & 0x3f);
Así que contestando a tu pregunta... sí, se puede leer la temperatura del DS3231
Código:
float GetTemp(){
byte temp;
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(TEMP_MSB);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 2); // Pedimos leer 2 bytes empezando en TEMP_MSB
temp = Wire.read(); // Here's the MSB
return float(temp) + 0.25*(Wire.read()/64); // Ver la nota que sigue.
// NOTA: En lugar de >>6 hemos usado /64
// Ambos métodos son equivalentes, pero el c++ estándar dice que el comportamiento para
// el desplazamiento a la derecha es específico de la implementación.
}
El año se guarda como un byte así que solo contempla los dos últimos dígitos del año. (Va del 2000 al 2099).
El registro RTC_DAY para guardar el día de la semana (en la posición 0x03) contiene un número entre 1 y 7. (1=Domingo, 2=Lunes, ...7=Sábado).
Funciona como un simple contador que se incrementa a medianoche y cuando llega a 8 lo transforma en 1 para repetir el ciclo semanal. Por lo tanto es responsabilidad del usuario (programador) decidir su valor inicial, y por ello
hay que implementar una función que nos diga el número de días transcurridos desde el año 2000 y una vez que sabemos ese dato el número de la semana es trívial calcularlo dividiendo por siete y quedándonos con el resto.
Estos son los secretos de este cacharrito. El cacharrito es muy sencillo. La congruencia de Zeller no lo es tanto.
La complejidad no está en el cacharrito, está en implementar la funcionalidad que el cacharrito no tiene implementada. Hay muchas librerías que hacen cosas diferentes y nosotros tendremos la nuestra. La ventaja será ahorrar código.
Tanto la explicación de como funciona el DS3231 como los consejos para soldar como la lista de materiales, los consejos para hacer pedidos, el diagrama de Arturo, y otra serie de informaciones que merecen ser fácilmente accesibles. deberían se compilados para editar un manual para aquellos que no se conformen con las instrucciones paso a paso.
De aquí podría salir un Libro + software y la aportación de todos los que quieran contribuir. El título puede ser el del programa
Programador fácil de Arduino o puede ser otro.