Recomendacion para almacenar datos

Buenas compañeros, necesito guardar diariamente unos 10 000 datos ( datos de peso, hora, fecha, correlativo,etc), estoy usando una SD pero su ciclos de escritura no pasan de los 100 000 creo y esto no me ayuda mucho ya que en una semana y media se me van averiando 3 tarjetas SD.
los datos mas o menos se escribirán cada 2 segundos durante varias horas diariamente es por eso que una SD no creo que soporte todo el sistema.

Yo creo que estas encarando mal el tema.
Yo usaría un disco duro SATA con interfaz USB como almacenamiento externo.

He visto proyectos que unen discos externos USB y Arduino. Ni hablar de Raspberry Pi.

Ejemplos como este al que le falta bastante pero mira dice haber conectado un disco de 500GB a un UNO

Mass Storage Support for USB Host Library 2.0 released!

No se nada de si son lo sufientemente rápidos para lograr tu objetivo. Solo te doy opciones para que sea n analizadas.

josepaul:
pero su ciclos de escritura no pasan de los 100 000 creo y esto no me ayuda mucho ya que en una semana y media se me van averiando 3 tarjetas SD

¿Y por qué así? ¿Me vas a decir que esos 10 000 datos se sobreescriben siempre?

Si dejaras que la tarjeta se llenara, ahí sí podrías empezar a sobrescribir. Si escribes de principio a fin de su capacidad, notarás que los ciclos de escritura en un área específica se reducen, equilibrando así el desgaste y prolongando su vida útil.

Si te pones a sobrescribir en el mismo archivo una y otra y otra vez, ahí sí no te discuto el tema de los ciclos de escritura.

Aunque desconociendo la cifra oficial, 100 mil me suena más a EEPROM que a memoria flash. Además el dato es meramente teórico, podría soportar más o podría soportar menos.
Has estado usando tarjetas SD, y... ¿has comprobado que realmente la vida útil se le agota tan rápido como dices?

Sí REALMENTE así lo fuera, entonces tendrás que utilizar "equipo de trabajo pesado", que viene siendo lo que surbyte acaba de comentar.

¿Y una base de datos? Los datos los puedes obtener rápido pero grabar sobre esta a esa velocidad NO (evidente por la conexión), pero si haces un sistema de cola no hay problemas. Como ventaja tendrías el respaldo de poder hacer un Backup de los datos si los subes en los servidores e incluso hacer aplicaciones de escritorio o Apps que listaran esos datos.

Lo que ya Arduino UNO no serviría.

No sé, depende de muchos factores y necesidades lo que mejor te puede venir.

Lucario448, lo que hago es abrir, editar y cerrar el archivo en casi segundo y medio osea que que la memoria esta casi 8 horas repitiendo el mismo proceso, y pienso que deben ser los ciclos de escritura pues ya son 3 SD que se mueren.

Survyte ahora mismo empiezo a hojear los datos muchas gracias, ojala halle la solucion.

Arduinito si pense en un momento en enviar por RF, wifi o bluetooht a una PC pero en la instalacion donde va ir el sistema no hay PC ni mucho menos internet pues es en el campo. Ni que hablar con algun celular pues habria que desarrolar una app que haga de base de datos ya que no hay internet para usar wifi.

Bueno si la situación es muy extrema haría dos cosas:

-El texto de entrada con los datos lo comprimiría. Edito: He comprobado que sí, Arduino dispone de librerías que ofuscan un texto y se consigue cierta disminución del tamaño, pero no hay función nativa como pasa con php que permite diferentes tipos de niveles de compresión. Ahora bien pasa lo de siempre sólo será óptimo cuando el String sea muy largo.

-Para obtener los datos de vuelta Arduino tendrá que hacer la operación a la inversa. Es más lento el proceso pero ahorrarás espacio.

-Luego se me ocurre cambiar la SD por una SD adaptable que permita una microSD y poner una de 128GB que ya es un espacio decente para texto plano y suelen tener de media una transferencia de 48MB/s

Algo así: 128 GB plus Micro SD SDHC/SDXC Card CLASS 10

Y mezclando ambos conceptos almacenar todo lo posible.

josepaul:
Lucario448, lo que hago es abrir, editar y cerrar el archivo

¿Editar? ¿No es un "datalogger" donde los "datos históricos" se conservan en vez de sobrescribirse?

Arduinito:
-Luego se me ocurre cambiar la SD por una SD adaptable que permita una microSD y poner una de 128GB que ya es un espacio decente para texto plano y suelen tener de media una transferencia de 48MB/s

Si pero dos cosas me preocupan:

128 GB pertenece a la familia de los XC; y si estos eliminaron completamente la compatibilidad con SPI... simplemente no se podría al menos que exista un módulo que convierta el protocolo SDIO a SPI (o que la placa soporte nativamente este primero).

Si la velocidad es algo que se deba tomar en cuenta... con SPI sería imposible alcanzar 48 MB/s. Las tarjetas SD compatibles con este protocolo, soportan una frecuencia de reloj (SCK) de hasta 25 MHz; a semejante ritmo apenas alcanzaría los 2 MB/s (para texto plano aún así es una velocidad descomunal).
Para un pobre Arduino Uno que va a 16 MHz, la cuarta parte de dicha velocidad es la máxima para SPI; sumado a tener que lidiar con un sistema de archivos, la velocidad de escritura en el mejor de los casos, es de 54 KB/s. Esta cifra aumenta hasta 87 KB/s si el acceso es "en crudo".

En resumen: si quien manipula la tarjeta tuviera soporte nativo de SDIO, se obtendrían los beneficios que mencionaste.
SPI está limitado solamente en velocidad y compatibilidad; no así en capacidad hasta los 2 TB (siguiendo la lógica del direccionamiento con 32 bits, de bloques de 512 bytes).

Mmm lo que dice Lucario no lo sabía yo :confused:

Lucario entonces el limite de escrituras no aumenta cuando solo se edita el archivo y se conserva el texto anterior, aun no lo tengo en claro pues pensaba que con solo abrir el archivo, editarlo y cerrarlo (datalogeer) el numero de escrituras aumentaba por cada proceso que haga y en 100 000 mil escrituras aprox. mi SD se dañara. Si fuese asi pues creo que otro seria el problema del daño de las SD.

Es que... si guardas un dato y luego otro pero conservando el antiguo, eso debería equilibrar el desgaste. Sobrescribiendo no porque se escribe en una misma ubicación una y otra vez.

¿Qué es lo que te hace pensar que se daña?

Yo tengo una duda razonable al respecto. Efectivamente, un logger incremental efectivamente no realizará escrituras reiteradas sobre el mismo bloque de datos; pero ¿en los bloques donde está la FAT?
No he encontrado información fidedigna al respecto (tampoco me he molestado demasiado, la verdad) pero en la práctica he visto "cascar" muchos pendrives a mi alrededor y una de las costumbres a las que yo achaco algunas de esas catástrofes es el editar ciertos documentos que crean un archivo temporal (por ejemplo, word) directamente en la misma ruta.

noter:
Efectivamente, un logger incremental efectivamente no realizará escrituras reiteradas sobre el mismo bloque de datos; pero ¿en los bloques donde está la FAT?

Oh, no tomé en cuenta eso :o
Pero entonces que separe los datos en diferentes archivos, ¿no crees?

Bueno. Leyendo un poco más, parece ser que la lógica interna de la flash intenta equilibrar los ciclos de escritura entre diferentes celdas para evitar hacerla en "puntos" calientes, osea que no debería existir dicho problema, o al menos no debería presentarse con demasiada rapidez.
No obstante, la práctica me dice que el almacenamiento flash no es infalible (cierto es que también hay mucha diferencia entre marcas), así que yo intentaría optimizar el programa para evitar escrituras innecesarias, como hacer flush, o abrir/cerrar el archivo en cada escritura.

Explico: En un solo día el arduino puede guardar unos 10 000 datos mas o menos, al terminar la jornada se extrae la SD para vaciar los archivos a la PC, luego se elimina el archivo para al dia siguiente nuevamente empezar a vaciar nuevos archivos.
Estos son los datos que se alojan en la SD

DATOS sd jpg.jpg

10000 datos/dia son 416 datos/hora o , esto no debería destruir una SD, algo ocurre.
Porque no volvemos a comenzar y pon si quieres la parte que guardas datos y supondremos datos azarosos.
Intenta poner el código y podremos hacer pruebas.

Esta es la funcion que guarda los datos,la uso cada segundo o cada 2 segundos, hasta alrededor de los 10 000 datos diarios aproximadamente como explique anteriormente.

void guardarSD(){

  DateTime now = RTC.now(); // Obtiene la fecha y hora del RTC  
 myFile = SD.open("BALANZA.csv", FILE_WRITE);  //Abrimos la carpeta BALANZA

if (myFile) {
  
       myFile.println();                    
       myFile.print("     RACIMO,");   //GUARDAMOS EL NUMERO DE RACIMOS
       myFile.print(racimos);
                  
       myFile.print(",          LOTE,");   //GUARDAMOS EL NUMERO DE RACIMOS
       myFile.print(lote);
              
       myFile.print(",       PESO,");    //GUARDAMOS EL PESO
       myFile.print(numero2);
       myFile.print("  ");
       myFile.print(",Kg,");

       myFile.print("CINTA COLOR");  //GUARDAMOS EL COLOR DE CINTA
       myFile.print(",");
       myFile.print(cinta[i]);  
       myFile.print(",");
       
 myFile.print("      FECHA,");              //GUARDAMOS FECHA, HORA Y MINUTOS
 myFile.print(now.day(), DEC); // Dia
 myFile.print('.');
 myFile.print(now.month(), DEC); // Mes
 myFile.print('.');
 myFile.print(now.year(), DEC); // Año
 myFile.print(',');
 
 myFile.print("      HORA,");
 myFile.print(now.hour(), DEC); // Horas
 myFile.print(':');
 myFile.print(now.minute(), DEC); // Minutos
 myFile.print(':');
 myFile.print(now.second(), DEC); // Segundos
 myFile.print(",");
    
      myFile.close(); //cerramos archivo 
     
      myGLCD.setBackColor(VGA_BLACK);
      myGLCD.setColor(VGA_WHITE);
      myGLCD.setFont(arial_italic);
      myGLCD.print("DATO SE GUARDO CORRECTAMENTE",13, 320); 
   
                   
      }
      else{
      myGLCD.setBackColor(VGA_BLACK);
      myGLCD.setColor(VGA_RED);
      myGLCD.setFont(arial_italic);
      myGLCD.print("ERROR DE DATOS VERIFICAR SD3",10, 320);
      Serial.println("no se guardo informacion en SD");
       

       
      }
 }

¿Esa es la forma en que guardas datos? A menos de que borres BALANZA.csv, así no se sobrescribirá nada.

Si quieres, te puedo dar una idea de cómo generar automáticamente un archivo nuevo (sin tener que ir a cambiar el código) cada cierta cantidad de datos; para tanto conservar los datos antiguos (si se necesitaran para referencias o generar datos estadísticos), como equilibrar el desgaste de la tarjeta y aprovechar al máximo su capacidad.

1 Like

Soy todo oidos Lucario, creo que eso facilitaria un poco el sistema

Se me ocurre lo siguiente:

Agregar lo siguiente en las globales:

#include <EEPROM.h>
#define DATOS_POR_ARCHIVO 10000

char nombre[13];
unsigned int cuentaDatos;
unsigned long cuentaArchivos;
boolean nuevoArchivo;

Esto en el setup:

void setup() {
  // ¿Implementar mecanismo que ignore los valores almacenados en la EEPROM?
  EEPROM.get(0, cuentaDatos);
  EEPROM.get(2, cuentaArchivos);
  sprintf(nombre, "BAL%05d.csv", cuentaArchivos);
  // El resto...
}

Y finalmente guardarSD quedará así:

void guardarSD() {
  DateTime now = RTC.now(); // Obtiene la fecha y hora del RTC
  if (nuevoArchivo) { // Cuando ya se hayan creado 10000 archivos, ahí es donde empiezan los problemas
    do {
      sprintf(nombre, "BAL%05d.csv", ++cuentaArchivos);
    } while (!SD.exists(nombre));
    nuevoArchivo = false;
    EEPROM.put(2, cuentaArchivos);
  }
  myFile = SD.open(nombre, FILE_WRITE);  //Abrimos la carpeta BALANZA

  if (myFile) {

    myFile.println();
    myFile.print("     RACIMO,");   //GUARDAMOS EL NUMERO DE RACIMOS
    myFile.print(racimos);

    myFile.print(",          LOTE,");   //GUARDAMOS EL NUMERO DE RACIMOS
    myFile.print(lote);

    myFile.print(",       PESO,");    //GUARDAMOS EL PESO
    myFile.print(numero2);
    myFile.print("  ");
    myFile.print(",Kg,");

    myFile.print("CINTA COLOR");  //GUARDAMOS EL COLOR DE CINTA
    myFile.print(",");
    myFile.print(cinta[i]);
    myFile.print(",");

    myFile.print("      FECHA,");              //GUARDAMOS FECHA, HORA Y MINUTOS
    myFile.print(now.day(), DEC); // Dia
    myFile.print('.');
    myFile.print(now.month(), DEC); // Mes
    myFile.print('.');
    myFile.print(now.year(), DEC); // Año
    myFile.print(',');

    myFile.print("      HORA,");
    myFile.print(now.hour(), DEC); // Horas
    myFile.print(':');
    myFile.print(now.minute(), DEC); // Minutos
    myFile.print(':');
    myFile.print(now.second(), DEC); // Segundos
    myFile.print(',');

    myFile.close(); //cerramos archivo
    if (++cuentaDatos >= DATOS_POR_ARCHIVO) {
      cuentaDatos = 0;
      nuevoArchivo = true;
    }
    EEPROM.put(0, cuentaDatos);

    myGLCD.setBackColor(VGA_BLACK);
    myGLCD.setColor(VGA_WHITE);
    myGLCD.setFont(arial_italic);
    myGLCD.print("DATO SE GUARDO CORRECTAMENTE", 13, 320);


  }
  else {
    myGLCD.setBackColor(VGA_BLACK);
    myGLCD.setColor(VGA_RED);
    myGLCD.setFont(arial_italic);
    myGLCD.print("ERROR DE DATOS VERIFICAR SD3", 10, 320);
    Serial.println("no se guardo informacion en SD");



  }
}

Un detalle que cabe destacar: "BALANZA" es de 7 caracteres, lo que nos deja espacio para apenas un dígito. El nombre lo reduje a "BAL" para tener espacio para 5 dígitos; lo que abre la posibilidad a tener hasta 10 mil archivos distintos.

PD: los print siempre fuerzan la escritura, así que... tómalo en cuenta.

1 Like