Buongiorno a tutti,
mi trovo con un problema curioso su uno sketch che mi fa, tra le altre cose, anche da data logger.
Ho un ESP8266 con collegato un lettore di microSD. Lo sketch riceve via rete dei dati che deve salvare in un file sulla SD e che si deve chiamare con la data corrente con l'underscore come separatore, ovvero "gg_mm_aaaa.log", file che viene creato automaticamente al primo utilizzo. Lo sketch funziona quasi sempre perfettamente, solo occasionalmente, e per tutto il giorno, non crea il file ma una struttura di directory, ovvero "/gg/mm/" e dentro ci scrive il file "aaaa.log". Ovviamente, quando poi vado a tentare di leggere il contenuto del file, lo stesso risulta inesistente.
Inizialmente avevo pensato ad un errore nella costruzione del nome, magari dovuta al fatto che alcuni giorni sono ad una cifra ed altri a due, ma non c'è una discriminante: il file 1_7_2023,log lo ha generato, al pari del 2_7_2023, poi i files dei giorni 3 e 4 luglio li ha sbagliati per riprendere regolarmente dal 5 luglio....
Di seguito le parti relative all'inizializzazione della SD e la funzione incriminata
#include <SD.h>
#define CS_PIN D8
#include <LittleFS.h>
...
void setup(void) {
....
// verifica se la scheda SD è presente
if (!SD.begin(CS_PIN)) {
Serial.println("Scheda SD non rilevata.");
}else{
Serial.println("Scheda SD rilevata correttamente.");
SD_presente = true;
}
scriviSD("Sistema avviato","master.log");
.....
bool scriviSD(String Cosa, String Dove){ // Cosa è il contenuto da scrivere, Dove è il file ove scrivere
if (SD_presente) {
File dataFile = SD.open(Dove, FILE_WRITE);
// Se il file si apre, prosegue
if (dataFile) {
dataFile.println(String(ntp_giorno) + "/" + String(ntp_mese) + "/" + String(ntp_anno) + " " + timeClient.getFormattedTime() + ":: " + Cosa);
dataFile.close();
}else{
Serial.println("Apertura in scrittura del file '" + Dove + "' fallita");
return false;
}
}else{
return false;
}
return true;
}
Siete a conoscenza di bug di questa libreria sull'ESP8266?
Grazie
LittleFS è un tipo di filesystem per la memoria flash integrata dell'ESP8266, ma tu qui stai usando una SD quindi questa libreria è completamente inutile (ed infatti la includi, ma poi non la usi da nessuna parte).
Lo spezzone di codice che hai messo è incompleto, manca tutta la parte dove vai a generare il nome del file dove con tutta probabilità ha origine il problema che hai.
La libreria LittleFS non ha alcun bug di questo tipo.
Mmm ... hai letto il reference della libreria SD? Perché è chiaramente specificato:
The library supports FAT16 and FAT32 file systems on standard SD cards and SDHC cards. It uses short 8.3 names for files. The file names passed to the SD library functions can include paths separated by forward-slashes, /, e.g. “directory/filename.txt”. Because the working directory is always the root of the SD card, a name refers to the same file whether or not it includes a leading slash (e.g. “/file.txt” is equivalent to “file.txt”). As of version 1.0, the library supports opening multiple files.
Credo che se ci fosse un problema nella creazione del nome, questo dovrebbe manifestarsi sempre, anche perché questo sketch riceve centinaia di dati da loggare e sbaglia solo occasionalmente. Sono perplesso.. comunque farò un controllo più approfondito per vedere se ci può essere qualcosa che modifica impropriamente "data_testo ", inoltre modifico la ScriviSD() in questo modo, vediamo come va
bool scriviSD(String Cosa, String Dove){ // Cosa è il contenuto da scrivere, Dove è il file ove scrivere
if (SD_presente) {
Dove.replace("/","_");
File dataFile = SD.open(Dove, FILE_WRITE);
// Se il file si apre, prosegue
if (dataFile) {
dataFile.println(String(ntp_giorno) + "/" + String(ntp_mese) + "/" + String(ntp_anno) + " " + timeClient.getFormattedTime() + ":: " + Cosa);
dataFile.close();
}else{
Serial.println("Apertura in scrittura del file '" + Dove + "' fallita");
scriviSD("Apertura in scrittura del file '" + Dove + "' fallita","master.log");
return false;
}
}else{
return false;
}
return true;
}
L'ho letto adesso, però i nomi che non riesce a creare sono compatibili con il formato 8.3, come ad esempio 7_5_2023.log e, comunque, sull'ESP8266 questo limite sembra essere superato.
Ad ogni modo faccio tesoro della tua segnalazione e correggo il codice, non mi costa nulla.
Infine, la SdFat non l'ho provata, forse sono stato troppo pigro?
Si, credo che effettivamente su ESP8266 sia superato perché leggo ...
Arduino "class SD" shim wrapper
This is a simple wrapper class to replace the ancient Arduino SD.h
access method for SD cards. It calls the underlying SDFS and the latest
SdFat lib to do all the work, and is now compatible with the rest of the
ESP8266 filesystem things.
Comunque con tutte queste concatenazioni di stringhe fatte in questo modo, niente di più facile che se qualcosa non va a buon fine ottieni una stringa "sporca".
Questo a mio avviso è il modo "peggiore" di usare la classe String, tanta allocazione dinamica e variabili temporanee create e distrutte dietro il sipario.
Visto che hai un tempo in formato "epoch" ed una stringa più o meno di dimensione costante, io avrei usato una C string (array di char) e l'istruzione strftime() (cosa che ti consente di gestire anche lo 0 dei numeri inferiori a 10 in modo automatico).
time_t now = time(nullptr); // time_t now = timeClient.getEpochTime();
struct tm timeInfo= *localtime(&now);
char data_testo[32];
strftime(data_testo, 32, "%d_%m_%Y.log", &timeInfo);
Serial.println(data_testo);
Ammetto di essere uno dei "pigri" che usa la String come eredità dalla conoscenza di altri linguaggi di programmazione.....
Farò tesoro anche di questo consiglio.
Come tante volte ribadito in questo forum, io non mi faccio nessun problema di sorta nell'uso di String anche con microcontrollori poco "dotati" di SRAM come Arduino Uno ad esempio, però c'è modo e modo di fare questa cosa.
Bisogna sempre tenere a mente che si parla comunque di un sistema embedded che non è dotato di un meccanismo di garbage collection.