Guardar datos secuencialmente en 24LS256

Buenas noches.
Hace ya varios días que intento almacenar datos tipo char secuencialmente (uno tras otro) en una memoria 24LC256 desde un Nano. En internet encontré varios códigos, pero la mayoría ejemplifican el almacenamiento solo en una o algunas posiciones de memoria.
Mi propósito más adelante es elaborar un datalogger en el que los datos sean almacenados en la memoria EEPROM y luego por medio una pequeña aplicación de visual basic sean leídos por el puerto serial.
He tratado reducir al mínimo el código para poder entenderlo mejor, inclusive inserté varios serial-prints como "debuggers" pero cuando se lee los datos almacenados (empleando la aplicación ofrecida por Sparkfun Reading and Writing Serial EEPROMs - SparkFun Learn, observo que se han guardado solo unos 15 datos y al parecer mi código regresa al inicio y comienza a sobreescribir el dato anterior.

Quisiera por favor alguna recomendación para mejorar el código:


#include <Wire.h>
#include <RTClib.h>

#define disk1 0x50 

RTC_DS3231 rtc;

unsigned int address = 0;


char pal1[]=""; 
int analogo = 0;


void setup() {
  
Serial.begin(9600);
Wire.begin(); 
rtc.begin();

Serial.print("direccion actual inicio");
Serial.print(" ");
Serial.println(address);  

Serial.println("Fecha(dd/mm/aa)  Hora   Temp(°C)  Delta(Temp)");
Serial.println("===============================================");

}

void loop() {

DateTime now = rtc.now();
char buf2[] = "DD/MM/YYYY hh:mm:ss ";
now.toString(buf2);

Serial.println(strlen(buf2));
Serial.println(sizeof(buf2));
Serial.print("buf2 es: ");
Serial.println(buf2);

Serial.print("direccion antes del bucle");
Serial.println(address);

for(byte i=0; i<=strlen(buf2);i++){
writeEEPROM(disk1, address+i, buf2[i]);

Serial.print("contador=");
Serial.println(i);

}

address+=strlen(buf2)+1;

Serial.print("direccion despues del bucle");
Serial.println(address);

delay(1000);

}

//write a byte or single char - less than 256
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) {
  
  Wire.beginTransmission(deviceaddress);
  Wire.write((byte)eeaddress >> 8);      //writes the most significant byte, move LSB off to right to get rid of it
  Wire.write((byte)eeaddress & 0xFF);    //writes the least significant byte, mask off LSB with bitwise AND 0
  Wire.write(data);
  Wire.endTransmission();
  delay(30);  //15 need this for sure
  }

//read a byte or single char - less than 256
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((byte)eeaddress >> 8);      //writes the most significant byte
  Wire.write((byte)eeaddress & 0xFF);    //writes the least significant byte
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) 
    rdata = Wire.read();
  return rdata;
  }

Que raro, muestra la salida de tu pantalla (Monitor serie).

Al margen del problema en sí, hay un detalle en esta línea que no está bien

for(byte i = 0; i <= strlen(buf2); i++){

Debería ser

for(byte i = 0; i < strlen(buf2); i++){

ya que los índices van a estar en el rango 0 a strlen(buf2) - 1.

Saludos

Ante todo, gracias por las respuestas.

A) Esta es la salida del monitor serie:

20:06:37.331 -> 20
20:06:37.378 -> 21
20:06:37.378 -> buf2 es: 07/06/2022 20:06:29

20:06:37.425 -> direccion antes del bucle 0
20:06:37.425 -> contador=0
20:06:37.425 -> contador=1
20:06:37.425 -> contador=2
20:06:37.471 -> contador=3
20:06:37.518 -> contador=4
20:06:37.518 -> contador=5
20:06:37.565 -> contador=6
20:06:37.612 -> contador=7
20:06:37.612 -> contador=8
20:06:37.659 -> contador=9
20:06:37.706 -> contador=10
20:06:37.706 -> contador=11
20:06:37.753 -> contador=12
20:06:37.799 -> contador=13
20:06:37.799 -> contador=14
20:06:37.846 -> contador=15
20:06:37.893 -> contador=16
20:06:37.893 -> contador=17
20:06:37.940 -> contador=18
20:06:37.940 -> contador=19
20:06:38.034 -> contador=20
20:06:38.034 -> direccion despues del bucle 21

20:06:39.018 -> 20
20:06:39.018 -> 21
20:06:39.018 -> buf2 es: 07/06/2022 20:06:31
20:06:39.065 -> direccion antes del bucle 21
20:06:39.065 -> contador=0
20:06:39.065 -> contador=1
20:06:39.065 -> contador=2
20:06:39.112 -> contador=3
20:06:39.158 -> contador=4
20:06:39.158 -> contador=5
20:06:39.205 -> contador=6
20:06:39.252 -> contador=7
20:06:39.252 -> contador=8
20:06:39.299 -> contador=9
20:06:39.346 -> contador=10
20:06:39.346 -> contador=11
20:06:39.393 -> contador=12
20:06:39.440 -> contador=13
20:06:39.440 -> contador=14
20:06:39.486 -> contador=15
20:06:39.533 -> contador=16
20:06:39.533 -> contador=17
20:06:39.580 -> contador=18
20:06:39.627 -> contador=19
20:06:39.674 -> contador=20
20:06:39.674 -> dirección después del bucle 42, etc.

B) Cuando aplico el código de Sparkfun (solo el que corresponde a la lectura de la EEPROM) obtengo:

⸮/06/2022 20:10:10
07/06/2022 20:10:11
07/06/2022 20:10:13
07/06/2022 20:100:09:55
7/06/2022 20:09:57
07/06/2022 20:09:58
07/06/2022 20:10:00
7/06/2022 20:10:02
07/06/2022 20:10:03
07/06/2022 20:10:05
07/06/2022 20:10:07
07/06/2022 20:10:08

Sea cual fuere el tiempo que haya transcurrido, siempre se almacenan pocos datos y al parecer regresa al inicio y comienza a sobrescribir.

Saludos

A ver, la dirección va subiendo primero 0 luego 21 luego 42.
Estara mal el código de Sparkfun o lo usarás incorrectamente.
Cual es el código con el que lees?
Primero quita las impresiones de byte a byte
El valor de contador dentro del for () no tiene sentido imprimierlo.
Quedate con la impresion de la dirección y el valor de buf2
A ver como funciona este código?

#include <Wire.h>
#include <RTClib.h>

#define disk1 0x50 

unsigned int address = 0;

void setup() {
  
	Serial.begin(9600);
	Wire.begin(); 
	rtc.begin();
	Serial.println("Lectura de datos de la 24LS256");
	Serial.print("Direccion actual inicio  :" + String(address));
}

void loop() {


	char buf2[] = "DD/MM/YYYY hh:mm:ss ";

	Serial.print("Direccion :" + String(address)+ " => ");

	for (byte i=0; i<strlen(buf2); i++){
		 buf2[i] = readEEPROM(disk1, address+i);
	}
	Serial.println(buf2);
	address += strlen(buf2)+1;
	delay(1000);
}

//write a byte or single char - less than 256
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) {
  
  Wire.beginTransmission(deviceaddress);
  Wire.write((byte)eeaddress >> 8);      //writes the most significant byte, move LSB off to right to get rid of it
  Wire.write((byte)eeaddress & 0xFF);    //writes the least significant byte, mask off LSB with bitwise AND 0
  Wire.write(data);
  Wire.endTransmission();
  delay(30);  //15 need this for sure
  }

//read a byte or single char - less than 256
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((byte)eeaddress >> 8);      //writes the most significant byte
  Wire.write((byte)eeaddress & 0xFF);    //writes the least significant byte
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) 
    rdata = Wire.read();
  return rdata;
}

El problema es que el código no tiene limite y seguirá leyendo aunque eso no es correcto.
Deberias insertar algun valor que diga si continua o no o por ejemplo, si se decide terminar todos los valores sean FF por dar un ejemplo.

for(byte i = 0; i < strlen(buf2); i++){

@anon90500195 yo diría que como está originalmente estba bien así guarda el caracter cero de fin de cadena y al recuperar ya tendría caracter para saber hasta cuándo llegaba la cadena.
Si tenemos la cadena "HOLA":
cadena[0]=H
cadena[1]=O
cadena[2]=L
cadena[4]=A
cadena[5]='\0'

strlen(cadena) dará 4
sizeof(cadena) dará 5

@disk1 falta la parte de lectura que no la has puesto, yo la de escritura la simplificaría, como ejemplo que no tiene RTC ni EEPROM:

unsigned int address = 0;
char *buf2 = "DD/MM/YYYY hh:mm:ss ";
#define disk1 0x50 
void setup() 
{
  Serial.begin(115200);
  delay(500);
  Serial.println();
  Serial.println();
  Serial.println("Comienzo.");
  Serial.println("--------------------------------------");
}
void loop() 
{
  buf2 = "DD/MM/YYYY hh:mm:ssZ";
  Serial.println(strlen(buf2));
  Serial.println(sizeof(buf2));
  Serial.print("buf2 es: ");
  Serial.println(buf2);
  Serial.print("direccion antes del bucle=");
  Serial.println(address);
  while(*buf2) we(disk1, address++, (byte)*buf2++);
  Serial.println();
  Serial.print("direccion despues del bucle=");
  Serial.println(address);
  delay(1000);
}
void we(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  Serial.print((char)data);
  Serial.print('.');
  delay(80);  //15 need this for sure
}

(mira cómo está definido buf2 y cómo se recorre con el while en una única línea de código en vez de unsar una iteración "for")

esto dará la siguiente salida por la consola:


Comienzo.
--------------------------------------
20
4
buf2 es: DD/MM/YYYY hh:mm:ssZ
direccion antes del bucle=0
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z.
direccion despues del bucle=20
20
4
buf2 es: DD/MM/YYYY hh:mm:ssZ
direccion antes del bucle=20
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z.
direccion despues del bucle=40
20
4
buf2 es: DD/MM/YYYY hh:mm:ssZ
direccion antes del bucle=40
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z.
direccion despues del bucle=60
20
4
buf2 es: DD/MM/YYYY hh:mm:ssZ
direccion antes del bucle=60
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z.
direccion despues del bucle=80
...

Ojo, en este caso no estoy guardando el /0, si quieres guardar también el /0 para poder después leer cadenas con ancho no delimitado puede ser tan simple como añadir otra escritura eeprom:

...
  Serial.print("direccion antes del bucle=");
  Serial.println(address);
  while(*buf2) we(disk1, address++, (byte)*buf2++);
  we(disk1, address++, (byte)*buf2++); //añadir el '\0'
  Serial.println();
  Serial.print("direccion despues del bucle=");
...

Y esto dará esta salida:

Comienzo.
--------------------------------------
20
4
buf2 es: DD/MM/YYYY hh:mm:ssZ
direccion antes del bucle=0
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z..
direccion antes del bucle=0
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z..
direccion despues del bucle=21
20
4
buf2 es: DD/MM/YYYY hh:mm:ssZ
direccion antes del bucle=21
D.D./.M.M./.Y.Y.Y.Y. .h.h.:.m.m.:.s.s.Z..
direccion despues del bucle=42

Saludos

Totalmente de acuerdo, por eso entiendo que no es correcto utilizar strlen() sino que debería usarse sizeof().

Saludos

Muchas gracias por los aportes, voy a ensayar los cambios propuestos a ver como se comporta el código.
Saludos.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.