Escribir registros en modulo reloj en tiempo real en la memoria no volátil.

Escribir registros en modulo reloj en tiempo real en la memoria no volátil.

Hola, buenas a tod@s. Me podrían ayudar con la rutina y librería para poder escribir y leer en la memoria no volátil de un reloj en tiempo real ¿? Es RTC DS1307

Muchas gracias.

Google: Arduino DS1307 Library

Buenas, la liberia la encontre en su día; lo que no logro encontrar es la manera de entender la rutina para poder escribir registros en la memoria no volatil. Gracias.

¿Que registros exactamente?

Buenas, pues, por ejemplo una fecha y hora en concreto, una variable, un contador; datos que pueda acceder a ellos en cualquier momento. Muchas gracias.

Intenta explicarte bien. Plantea todo con un ejemplo.

Creo que no puedo explicarlo mas concretamente, segun el fabricante del integrado, ha dejado 56 bytes de memoria no volatil para uso y disfrute del usuario final. Los 7 primeros registros estan destinados al uso interno del reloj en tiempo real. Necesito grabar en un registro un numero, que dependera de un contador externo.

Pues sí. Sí has sabido explicarlo más concretamente :) Ahora acabo de echar un vistazo en la página y efectivamente, hay un párrafo muy interesante:

  • 56-Byte, Battery-Backed, General-Purpose RAM with Unlimse ited Writes

Que puede ser muy buena opción para un problema que he leído recurrentemente en este foro: cómo guardar x para que si se va la luz al arrancar sepamos dónde estábamos (sustituye x por cualquier cosa). Escrituras ilimitadas suena muy bien.

En cuanto a cómo escribir en esos registros, voy a echar un vistazo a la librería a ver si se deduce algo. Saludos.

Muchas gracias noter; te lo agradezco sinceramente. Despues de 3 semanas de investigación, no he logrado resolverlo, y la verdad, lo considero algo esencial; para la gran mayoria de proyectos. Muchas gracias.

Esta es la librería DS1307 sobre la que hablaremos

En la librería existe un archivo DS1307.cpp y uno de los procedimientos dice

bool DS1307RTC::write(tmElements_t &tm)
{
  Wire.beginTransmission(DS1307_CTRL_ID);
#if ARDUINO >= 100  
  Wire.write((uint8_t)0x00); // reset register pointer  
  Wire.write(dec2bcd(tm.Second)) ;   
  Wire.write(dec2bcd(tm.Minute));
  Wire.write(dec2bcd(tm.Hour));      // sets 24 hour format
  Wire.write(dec2bcd(tm.Wday));   
  Wire.write(dec2bcd(tm.Day));
  Wire.write(dec2bcd(tm.Month));
  Wire.write(dec2bcd(tmYearToY2k(tm.Year))); 
#else  
  Wire.send(0x00); // reset register pointer  
  Wire.send(dec2bcd(tm.Second)) ;   
  Wire.send(dec2bcd(tm.Minute));
  Wire.send(dec2bcd(tm.Hour));      // sets 24 hour format
  Wire.send(dec2bcd(tm.Wday));   
  Wire.send(dec2bcd(tm.Day));
  Wire.send(dec2bcd(tm.Month));
  Wire.send(dec2bcd(tmYearToY2k(tm.Year)));   
#endif
  if (Wire.endTransmission() != 0) {
    exists = false;
    return false;
  }
  exists = true;
  return true;
}

traje esto para entender como funciona y luego hablamos de lo que quieres.
basicamente usa la librería I2C Wire.h
Segun la hoja de datos para setear la hora tu tienes que


enviar a partir de la dirección 00h los comandos para segundos minutos horas, etc tal como dice esa rutina

Entonces… si ya entendimos esto ahora veamos que quieres.

Al final de la table dice

entonces si escribes en 08h a 3Fh tienes tus 56 bytes de RAM no volatil. como?
bueno agrega esto en DS1307RTC.cpp luego de bool DS1307RTC::write(… y lo que sigue

bool DS1307RTC::writeNVRAM(unsigned int address, byte data)
{
  Wire.beginTransmission(DS1307_CTRL_ID);
#if ARDUINO >= 100  
  Wire.write((uint8_t)address); // reset register pointer  
  Wire.write(data) ;   
#else  
  Wire.send(address); // reset register pointer  
  Wire.send(dec2bcd(data) ;   
#endif
  if (Wire.endTransmission() != 0) {
    exists = false;
    return false;
  }
  exists = true;
  return true;
}

y modifica en DS1307.h

por esto

/*
 * DS1307RTC.h - library for DS1307 RTC
 * This library is intended to be uses with Arduino Time.h library functions
 */

#ifndef DS1307RTC_h
#define DS1307RTC_h

#include <Time.h>

// library interface description
class DS1307RTC
{
  // user-accessible "public" interface
  public:
    DS1307RTC();
    static time_t get();
    static bool set(time_t t);
    static bool read(tmElements_t &tm);
    static bool write(tmElements_t &tm);
    static bool writeNVRAM(uint8_t address, uint8_t num)
    static bool chipPresent() { return exists; }

  private:
    static bool exists;
    static uint8_t dec2bcd(uint8_t num);
    static uint8_t bcd2dec(uint8_t num);
};

#ifdef RTC
#undef RTC // workaround for Arduino Due, which defines "RTC"...
#endif

extern DS1307RTC RTC;

#endif

veamos si funciona.

Ahh me olvidé lo mas importante
Supongamos que la librería compila sin errores, (ya me dirás).

luego para escribir algo solo usas tu objeto, supongamos que es reloj

reloj.writeNVRAM(0x80, 23); // guarda 23 en la direccion 0x80

habra que armar una funcion de lectura tambien

Hola. Creo que esta librería de cuya cabecera pongo un extracto:

class RTC_DS1307 {
public:
    static uint8_t begin(void);
    static void adjust(const DateTime& dt);
    uint8_t isrunning(void);
    static DateTime now();
    static Ds1307SqwPinMode readSqwPinMode();
    static void writeSqwPinMode(Ds1307SqwPinMode mode);
    uint8_t readnvram(uint8_t address);
    void readnvram(uint8_t* buf, uint8_t size, uint8_t address);
    void writenvram(uint8_t address, uint8_t data);
    void writenvram(uint8_t address, uint8_t* buf, uint8_t size);
};

Al parecer ya dispone de los comandos readnvram y writenvram ;)

bueno lo que pone Noter es mejor que lo mio. Nos pisamos Serafín!!

Buenos dias, muchas gracias a ambos. Espero poder solucionarlo con una de las dos opciones. Muchas gracias.

¡¡Ainss!! Si es que las introducciones tienen su importancia. Y es que yo con el rtc iba a lo esencial: leer/escribir fecha y hora. Si la librería ya tiene esas funciones ¿para qué enredar directamente en los registros? Todo cambia si inicias el hilo recordando que existen esos 56 bytes de uso libre, pues yo no les di importancia en su día por el poco espacio que suponía, cuando hojeé el datasheet, y mira por dónde, ahora me ha cambiado la perspectiva.

No te lo discuto, soy de la vieja escuela y muchas cosas no logro entenderlas. Uno de los principales propósitos, por ejemplo; es llevar un registro de las veces que han desconectado la maquina en condiciones anormales (quitando la tensión de golpe del enchufe) así cuando salga algo mal, poder recordar que si hay un protocolo de apagado, que lo respeten. Muchas gracias.

tu librería tiene las funciones, la que yo busqué no las tiene, y por eso me puse a entenderlo para luego implementarlas. Sirve el ejercicio. Voy a tomar tu librería como base. Además me gustó el hilo porque se puede usar para guardar datos que personalicen una placa y quien va a ir a buscar una clave en el RTC? jajaja. Tal vez esa era la idea de este hilo, pero al menos a mi me sirve.

Pero ahora vamos a lo importante. Si por fin has conseguido escribir esos registros y cómo. Cuenta, cuenta... ;) ;) ;) ;)

Hasta la fecha apenas he tenido tiempo, así a bote pronto, más o menos lo entiendo, pero al ser C en su estado más primitivo, me cuesta un poquito. Intentare documentar todos los pasos para futuros problemas venideros. Gracias.

Bueno, surbyte… que quede claro que no es MI librería ¿eh? No se vaya a ofender el amigo JeeLabs ;).
De todas formas tenía lógica que de una manera u otra se incluyera un método para leer o escribir registros, pues finalmente eso es lo que se hace para leer o establecer la hora, sólo que con unos registros concretos que son los que contienen esos datos. Sencillamente dimos con dos librerías distintas y una había segregado el código de escritura/lectura de un registro a métodos aparte. Este pequeño detalle la hace más útil, y además para los que programamos puede servir de paradigma de metodología de programación.

Sobre la logica y el compilado, creo que lo he logrado resolver. Este finde hare las pruebas menesteres, de ir bien la cosa, lo dejare aqui publicado. Muchas gracias a los 2.