Trabajar con EEPROM

Hola a todos, consulta: yo trabajo ya con eeprom, algunas cosas hago, guardo leo y reemplazo, lo que deseo hacer es una especie de agenda, por ejemplo, los números que almacenaría serian de 15 caracteres eso seria 1 usuario, y un total de 200, y quiero luego de eso poder consultar la eeprom en busca de esos usuarios, borrarlos y reutilizar ese espacio para guardar otro, o sea debería ser reconocido como vacío para poder guardar otro usuario...se puede lograr algo así trabajando con la eeprom?
muestro lo que uso para escribir y leer y borrar:

struct {
  char User[15];
} parametros;

void cargaParams() {
  byte *p = (byte*)  &parametros;
  for (int x = 0; x < sizeof(parametros); x++) {
    *p++ = EEPROM.read(x);
  }
}

void salvaUser() {
  byte *p = (byte*) &parametros.User;
  for (int x = 0; x < sizeof(parametros); x++) {
    EEPROM.write(x, *p++);
  }
}

el tema es que si sigo agrandando la estructura y agregando variables voy a llenar enseguida la capacidad de memoria de arduino...

el guardado tendría que ser en el primer espacio vacío de 15 caracteres,;
suponiendo que tengo 50 usuarios, pero el 25 esta borrado, en ese lugar guardaría el usuario 51, aunque seguiría teniendo 50 porque el 25 en realidad se borro, pero se estaría agregando el 51, y si los 50 están en uso, ese 51 se agregaría al final.. y luego poder hacer una búsqueda para ver si un determinado numero esta o no en la lista de los 50..
ojala me haya podido explicar bien.. aguardo ansiosa cualquier comentario sobre lo que deseo hacer

Hola, @AnyPopins
Primero, no especificó qué microcontrolador o EEPROM va a usar.
Si es la EEPROM interna de un arduino, tiene que ser una que tenga más de 3K bytes de EEPROM. (15 x 200 = 3000).

También puede usar un arduino y usar una EEPROM externa.

En segundo lugar, este proceso que desea utilizar es una pseudo base de datos.

Sí, es posible hacer esto, pero debe escribir una rutina para manejar estos datos como una base de datos.

Una rutina que debe tener, entre otros recursos, un "índice" único para cada usuario en la base de datos y punteros que indiquen la cantidad de índice en esta base de datos.

RV mineirin

La librería ya esta hecha @AnyPopins y se llama EDB Extendend Data Base

Te dejo sus características en inglés off course

This Arduino Extended Database Library increases the maximum number of records allowed in a database from 256 records (byte) to a theoretical maximum of 4,294,967,295 records (unsigned long). The maximum record size was also increased from 256 bytes (byte) to 65,534 bytes (unsigned int).

You may use this library in conjunction with the standard Arduino EEPROM library, an external EEPROM such as the AT24C1024, or any other platform that supports byte level reading and writing such as an SD card.

El proyecto no ha recibido actualizaciones desde 2017 por lo que ten cuidado si lo usas con el IDE y los errores que ocacione, mi consejo, usa un IDE no mas alla de 2019. Los mas actuales pueden generar problemas pero con probar no se pierde nada.
En los ejemplos tienes desde SD, hasta EEPROM de 1MB como la AT24C1024 asi que cubre con creces tus necesidades y te facilita todo el trabajo.
Los ejemplos son muy simples de usar/entender.

Hola chicos gracias a los 2 ( ruilviana y Surbyte) por las respuestas...
voy a mirar la librería y a ver que sale Surbyte...gracias y saludos

Any.

Edito:
me sale el siguiente error:
"Librería inválida encontrada en C:\Users\XXXXXXX\Documents\Arduino\libraries\EDB-master: No encontrado archivos de encabezado (.h)"

Mal instalada.
Mira que no tenga una carpeta EDB-master y luego otra idéntica
Asi me quedó a mi y funciona


Mira como estan las carpetas, olvida que etan en OneDrive, considera desde Documentos\Arduino\libraries\EDB-master
Solo una debe haber.
El ejemplo EDB_Simple.ino compila con IDE 1.8.13 sin problemas.

El Sketch usa 3172 bytes (1%) del espacio de almacenamiento de programa. El máximo es 253952 bytes.
Las variables Globales usan 323 bytes (3%) de la memoria dinámica, dejando 7869 bytes para las variables locales. El máximo es 8192 bytes.

hola Surbyte ya esta solucionado muchas gracias...a veces una imagen vale mas q mil palabras jajaja el problema fue que al descomprimir me repetía la carpeta, o sea xxx/EDB-master/EDB-master, y al ver la imagen que posteaste borré una y ahí anduvo bárbaro el ejemplo EDB_Internal_ EEPROM compila genial en 1.8.15...
gracias y perdón, a veces es una pavada que da bronca no ver antes de preguntar pero bueno, gracias por la paciencia igual y la buena onda de responder...ya aprenderé algún día...

saluditos,
Any.

Siempre al descomprimir te pone dos carpetas iguales. Asi que al hacerlo dile Extraer aqui

Dale gracias Surbyte..

Hola, ahora empieza lo divertido jaja, la librería esta buenísima, el tema es poder hacerla funcional a mis intereses...
pongo el código que me sirve:

 EDB_Internal_EEPROM.pde
 Extended Database Library + Internal Arduino EEPROM Demo Sketch 
 
 The Extended Database library project page is here:
 http://www.arduino.cc/playground/Code/ExtendedDatabaseLibrary
 
 */
#include "Arduino.h"
#include <EDB.h>

// Use the Internal Arduino EEPROM as storage
#include <EEPROM.h>

// Uncomment the line appropriate for your platform
#define TABLE_SIZE 512 // Arduino 168
//#define TABLE_SIZE 1024 // Arduino 328
//#define TABLE_SIZE 4096 // Arduino Mega

// The number of demo records that should be created.  This should be less 
// than (TABLE_SIZE - sizeof(EDB_Header)) / sizeof(LogEvent).  If it is higher, 
// operations will return EDB_OUT_OF_RANGE for all records outside the usable range.
#define RECORDS_TO_CREATE 10

// Arbitrary record definition for this table.  
// This should be modified to reflect your record needs.
struct LogEvent {
  int id;
  //int temperature;
} 
logEvent;

// The read and write handlers for using the EEPROM Library
void writer(unsigned long address, byte data)
{
  EEPROM.write(address, data);
}

byte reader(unsigned long address)
{
  return EEPROM.read(address);
}

// Create an EDB object with the appropriate write and read handlers
EDB db(&writer, &reader);

// Run the demo
void setup()
{
  Serial.begin(9600);
  Serial.println("Extended Database Library + Arduino Internal EEPROM Demo");
  Serial.println();

  randomSeed(analogRead(0));
  
  Serial.print("Creating table...");
  // create table at with starting address 0
  db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));
  Serial.println("DONE");

  recordLimit();
  countRecords();
  createRecords(RECORDS_TO_CREATE);
  countRecords();
  selectAll();
  deleteOneRecord(RECORDS_TO_CREATE / 2);
  countRecords();
  selectAll();
  appendOneRecord(RECORDS_TO_CREATE + 1);
  countRecords();
  selectAll();
  insertOneRecord(RECORDS_TO_CREATE / 2);
  countRecords();
  selectAll();
  updateOneRecord(RECORDS_TO_CREATE);
  selectAll();
  countRecords();
  deleteAll();
  Serial.println("Use insertRec() and deleteRec() carefully, they can be slow");
  countRecords();
  for (int i = 1; i <= 20; i++) insertOneRecord(1); // inserting from the beginning gets slower and slower
  countRecords();
  for (int i = 1; i <= 20; i++) deleteOneRecord(1); // deleting records from the beginning is slower than from the end
  countRecords();
 
}

void loop()
{
}

// utility functions

void recordLimit()
{
  Serial.print("Record Limit: ");
  Serial.println(db.limit());
}

void deleteOneRecord(int recno)
{
  Serial.print("Deleting recno: ");
  Serial.println(recno);
  db.deleteRec(recno);
}

void deleteAll()
{
  Serial.print("Truncating table...");
  db.clear();
  Serial.println("DONE");
}

void countRecords()
{
  Serial.print("Record Count: "); 
  Serial.println(db.count());
}

void createRecords(int num_recs)
{
  Serial.print("Creating Records...");
  for (int recno = 1; recno <= num_recs; recno++)
  {
    logEvent.id = recno; 
    //logEvent.temperature = random(1, 125);
    EDB_Status result = db.appendRec(EDB_REC logEvent);
    if (result != EDB_OK) printError(result);
  }
  Serial.println("DONE");
}

void selectAll()
{  
  for (int recno = 1; recno <= db.count(); recno++)
  {
    EDB_Status result = db.readRec(recno, EDB_REC logEvent);
    if (result == EDB_OK)
    {
      Serial.print("Recno: "); 
      Serial.print(recno);
      Serial.print(" ID: "); 
      Serial.print(logEvent.id);
      Serial.print("\r\n"); 
      //Serial.print(" Temp: "); 
      //Serial.println(logEvent.temperature);   
    }
    else printError(result);
  }
}

void updateOneRecord(int recno)
{
  Serial.print("Updating record at recno: ");
  Serial.print(recno);
  Serial.print("...");
  logEvent.id = 1234; 
  //logEvent.temperature = 4321;
  EDB_Status result = db.updateRec(recno, EDB_REC logEvent);
  if (result != EDB_OK) printError(result);
  Serial.println("DONE");
}

void insertOneRecord(int recno)
{
  Serial.print("Inserting record at recno: ");
  Serial.print(recno);
  Serial.print("...");
  logEvent.id = recno; 
  //logEvent.temperature = random(1, 125);
  EDB_Status result = db.insertRec(recno, EDB_REC logEvent);
  if (result != EDB_OK) printError(result);
  Serial.println("DONE");
}

void appendOneRecord(int id)
{
  Serial.print("Appending record...");
  logEvent.id = id; 
  //logEvent.temperature = random(1, 125);
  EDB_Status result = db.appendRec(EDB_REC logEvent);
  if (result != EDB_OK) printError(result);
  Serial.println("DONE");
}

void printError(EDB_Status err)
{
  Serial.print("ERROR: ");
  switch (err)
  {
    case EDB_OUT_OF_RANGE:
      Serial.println("Recno out of range");
      break;
    case EDB_TABLE_FULL:
      Serial.println("Table full");
      break;
    case EDB_OK:
    default:
      Serial.println("OK");
      break;
  }
}

pero yo quiero ahora poder agregar los teléfonos para agendar, como hago para que se cree un orden de ese id y vaya agregando, y si quiero modificar, poder retomar ese id y hacer update de ese numero, y luego en caso de borrarlo, poder usar ese lugar libre...
en el caso del lugar libre, no se si es conveniente, que si borro por ejemplo el registro 5 de 10, luego recrear el índice, o como hacer para saber que el 5 esta libre y usarlo...
espero me puedan orientar, aguardo ansiosa alguna respuesta, gracias...

Ese trabajo que mencionas lo hizo un gran programador que ya no anda por acá. Te lo busco y te pongo un link con la información. Se basó en EDB y luego agregó la indexación que mencionas.

Ok dale Surbyte muchas gracias...

Bueno no recordaba el nombre o alias del compañero que lo hizo y luego vino la luz, @noter.
El tema surgió como una colaboración entre varios, @Lucario y @noter se propusieron pero luego @noter tomó la posta y se fue solo, solo resolviendo el problema. Los demas quisimos colaborar desde nuetros lugares como pudimos.
El escribió la modificación de la librería que permite indexar los registros.
Acá el hilo.

Gestión e indexación de registros de una tabla en SD.

Hola Surbyte, ahí estuve mirando la librería de noter, consulta: puedo trabajar con eeprom? o si o si tiene que ser SD? de hecho no tengo, pero desearía saber si se puede usar con eeprom, así como esta obvio da error "initialization failed!".. supongo que porque no esta la SD.

La idea fue genérica y ese ejemplo es para SD, claramente no funciona en EEPROM pero si el enfoque realizado por @noter.
Si tienes paciencia luego lo miro.

Si dale obvio, toda la paciencia del mundo jaja.. gracias..