Carpetas y archivos

Muy Buenos dias,
Tengo un pequeño problema al crear carpetas y drear archivos en ellas. Las carpetas que creo tienen como nombre la hora (utilizando un RTC) y en la carpeta creo varios archivos. No tengo problema al crear la primera carpeta y meter los datos en ella. El problema es que cuando quiero crear la segunda carpeta empieza desde el ultimo archivo y no desde el primero.
Aqui les explico:
Esto es lo que necesito:

153000/ <---Esta es primera carpeta (el nombre es la hora)
Data00.bin <-- Estos son los archivos
Data01.bin
Data02.bin
Data03.bin
153100/
Data00.bin
Data01.bin
Data02.bin
Data03.bin

Esto es lo que obtengo

153000/
Data00.bin
Data01.bin
Data02.bin
Data03.bin
153100/
Data03.bin <--- El archino no empieza desde 00
Data04.bin
Data05.bin
Data06.bin

Esta es la loop:

void loop(void) {

  boolean bintocsv = digitalRead(CONVERT_BUTTON);
  debouncer_rec.update();

  timeRTC_t dateTime;
  timeDateRTC(&dateTime);

  char folderDate[12];

  sprintf(folderDate, "%u%u%u", dateTime.hour, dateTime.minute, dateTime.second);

  sd.chdir("/");

  if (!sd.exists(folderDate))             
  {
    sd.mkdir(folderDate);
  }

  else
  {
    sd.chdir(folderDate);                 //Make folder as Root
  }

sysReady();

  if ( debouncer_rec.rose()) {
    delay(10);

    logData();
    ledSdWaitConvert ();

  }
}

Les agradeceria infinitamente si comparten alguna odea o una possible solucion. La solucion la pondre en el hilo porque muy seguramente a alguien le va a servir.

Para crear una cadena como "Data05.bin", se necesita de sprintf y una variable contadora.

¿Por qué no simplemente reinicias ese contador cada vez que se ingrese a una carpeta nueva?

Mil gracias Lucario448 pour tu pronta respuesta y por que me guiaste a una possible solucion. Ahora quite la creacion de la carpeta del loop y solo la hago cuando cuento los archivos.

Lucario448:
¿Por qué no simplemente reinicias ese contador cada vez que se ingrese a una carpeta nueva?

Ahora explico un poco mas:

Includes:

#define FILE_BASE_NAME "Log"
// Temporary log file.  Will be deleted if a reset or power failure occurs.
#define TMP_FILE_NAME FILE_BASE_NAME "##.bin"

// Size of file base name.
const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
const uint8_t FILE_NAME_DIM  = BASE_NAME_SIZE + 7;                   
char binName[FILE_NAME_DIM] = FILE_BASE_NAME "00.bin";     

SdFat sd;
SdBaseFile binFile;

Loop:

void loop(void) {

  boolean bintocsv = digitalRead(CONVERT_BUTTON);
  debouncer_rec.update();

  // Read any Serial data.
  do {
    delay(10);
  } while (Serial.available() && Serial.read() >= 0);

  if ( debouncer_rec.rose())
    logData();
  delay(10);
  sd.chdir("/");                    // Root of SD card
 }

Funcion LogData:

void logData() {
  createBinFile();
  recordBinFile();
  renameBinFile();
}

CreateBinFile (no es tan importante para mi problema):

void createBinFile() {
  // max number of blocks to erase per erase call
  const uint32_t ERASE_SIZE = 262144L;
  uint32_t bgnBlock, endBlock;

  // Delete old tmp file.
  if (sd.exists(TMP_FILE_NAME)) {
    Serial.println(F("Deleting tmp file " TMP_FILE_NAME));
    if (!sd.remove(TMP_FILE_NAME)) {
      error("Can't remove tmp file");
    }
  }
  // Create new file.
  Serial.println(F("\nCreating new file"));
  binFile.close();
  if (!binFile.createContiguous(TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) {
    error("createContiguous failed");
  }
  // Get the address of the file on the SD.
  if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
    error("contiguousRange failed");
  }
  // Flash erase all data in the file.
  Serial.println(F("Erasing all data"));
  uint32_t bgnErase = bgnBlock;
  uint32_t endErase;
  while (bgnErase < endBlock) {
    endErase = bgnErase + ERASE_SIZE;
    if (endErase > endBlock) {
      endErase = endBlock;
    }
    if (!sd.card()->erase(bgnErase, endErase)) {
      error("erase failed");
    }
    bgnErase = endErase + 1;
  }
}

RenameBinFile: (Aqui es donde estoy hacienda algo mal)

void renameBinFile()
{
  timeRTC_t dateTime;
  timeDateRTC(&dateTime);
  char folderDate[12];  //Name for folder
  
  sprintf(folderDate, "%u", dateTime.minute);  //String of name with Date values

  sd.chdir("/"); //Return to Root
  if (!sd.exists(folderDate))
  {
    sd.mkdir(folderDate);
    //binName = 0;
    binName[BASE_NAME_SIZE + 1] = '0'; //Initialize name to X0
    binName[BASE_NAME_SIZE] = '0'; //Initialize name to 00
  }
  else
    sd.chdir(folderDate); //Se hace carpeta: folderDate nuevo root 

  while (sd.exists(binName))
  {
    if (binName[BASE_NAME_SIZE + 1] != '9') {   //x9
      binName[BASE_NAME_SIZE + 1]++; //incrementa el numero del archivo segundo digito
    }
    else
    {
      binName[BASE_NAME_SIZE + 1] = '0';
      if (binName[BASE_NAME_SIZE] == '9')     //9x   
      {
        error("Can't create file name");
      }
      binName[BASE_NAME_SIZE]++; //incrementa el numero del archivo primer digito
    }
  }
  if (!binFile.rename(sd.vwd(), binName)) {
    error("Can't rename file");
  }
  Serial.print(F("File renamed: "));
  Serial.println(binName);
  Serial.print(F("File size: "));
  Serial.print(binFile.fileSize() / 512);
  Serial.println(F(" blocks"));
}

Ahora lo que obtengo es:
19/ <--- Nombre de la Carpeta (solo puse el minuto)
Log00.bin
Log01.bin
Log02.bin
Log03.bin
etc...
20/
Log01.bin
Log02.bin
Log03.bin
etc...
/ <--- En la carpeta principal
Log00.bin
Log01.bin

No entiendo porque cuando se crea una carpeta nueva se regresa a la raiz graba un archivo y luego entra a la carpeta para seguir grabando los demas archivos.

sd.chdir("/"); //Return to Root

kammateo:
No entiendo porque cuando se crea una carpeta nueva se regresa a la raiz graba un archivo y luego entra a la carpeta para seguir grabando los demas archivos.

Quizá por...

if (!sd.exists(folderDate))
  {
    sd.mkdir(folderDate);
    //binName = 0;
    binName[BASE_NAME_SIZE + 1] = '0'; //Initialize name to X0
    binName[BASE_NAME_SIZE] = '0'; //Initialize name to 00
  }
  else
    sd.chdir(folderDate); //Se hace carpeta: folderDate nuevo root

O sea, si la carpeta no existe, la creo pero no me introduzco en ella.

La solución en simple: en esa sección, borra "else". Sólo la palabra, no la instrucción que la involucra.

PD:

Serial.print(binFile.fileSize() / 512);

No es la manera correcta de calcular cuántos bloques ocupa un archivo. Ejemplo: el archivo tiene un tamaño de 900 bytes, entonces 900 / 512 = 1.75. Pero como estamos con división de enteros, el resultado de dicha división es 1.
Entonces... ¿puedo almacenar 900 bytes en un solo bloque de 512 bytes? Inmediatamente la respuesta va a ser "no"; por lo tanto, es falso que un archivo de 900 bytes ocupa un bloque (además que está demostrado si la división conservara decimales, porque 1 < 1.75 < 2).

Si la división conservara los decimales, la siguiente operación sería un redondeo en "función techo" ("ceiling"); pero como convertir enteros a float y operarlos de esa manera es menos eficiente; la forma correcta de calcular la cantidad de bloques sería:

Serial.print(binFile.fileSize() % 512 == 0 ? binFile.fileSize() / 512 : (binFile.fileSize() / 512) + 1);

// binFile.fileSize() % 512 == 0 ? - ¿El tamaño de archivo es múltiplo de 512 (abarca todos los bloques sin desperdiciar ni un solo byte)?
// binFile.fileSize() / 512 - Solo para cuando sea exactamente múltiplo de 512
// (binFile.fileSize() / 512) + 1 - Al verificar previamente que no es múltiplo de 512, podemos asegurar que esto equivale al redondeo en "función techo"

Algo similar ocurre con los clústeres de un sistema de archivos (usualmente de 4096 bytes u 8 bloques). Si el tamaño real de un archivo fuera de 4097 bytes; el tamaño en disco sería de 8192 bytes.
Por esta razón, es que la acumulación de muchos archivos pequeños suele desperdiciar espacio. Por otro lado, reducir el tamaño del clúster a 512 bytes puede no ser buena idea; clústeres más pequeños aprovechan mejor el espacio, a costa del rendimiento; sobre todo en la copia masiva de archivos pequeños.

Lucario448:
La solución en simple: en esa sección, borra "else". Sólo la palabra, no la instrucción que la involucra.

Mil gracias Lucario. Lo intente pero no funciono como queria. Pero segui viendo con lupa el programa y en otra parte del programa cometia el mismo error. Mil gracias en serio, eres un maestro!!!
Y estoy modificando el codigo para contar los bloques y lo que dices tiene mucho sentido!
Mil gracias!!! :slight_smile: :slight_smile: :slight_smile: