Popolare un "database" della libreria EDB da un file .TXT

Sto utilizzando da poco tempo la libreria EDB su una microSD, ho fatto tutte le prove sui tipi di dati e ricerche che poi mi serviranno nell'applicazione e funziona egregiamente.
Naturalmente per popolare il database di prova ho creato i dati in maniera estemporanea all'interno del programma stesso.
Adesso il problema è il seguente: devo popolare il database con dati prelevati da un file .TXT, posso aprire contemporaneamente il file .TXT e il file di database o devo continuamente aprire e chiudere i due file per popolare il database?
Se non ricordo male è possibile aprire un solo file alla volta su Arduino, sbaglio?

crc57:
Se non ricordo male è possibile aprire un solo file alla volta su Arduino, sbaglio?

Il problema è la SRAM dove vengono allocati i buffers ...
... se ben ricordo, ogni file su SD alloca minimo un buffer da 512 Bytes ... e finire la SRAM è un attimo ... ::slight_smile:

Guglielmo

gpb01:
Il problema è la SRAM dove vengono allocati i buffers ...
... se ben ricordo, ogni file su SD alloca minimo un buffer da 512 Bytes ... e finire la SRAM è un attimo ... ::slight_smile:

Guglielmo

La lunghezza del record del file .TXT è lunga solo 39 bytes + CR + LF sono 41 bytes. E quindi anche il record del EDB ha +o- le stesse dimensioni.
Però se il buffer che la libreria alloca è comunque 512 bytes sono problemi.

Comunque non bagniamoci prima che piova. Vi farò sapere.

P.s. I metodi: EDB_Status EDB::open(unsigned long head_ptr) e
EDB_Status EDB::create(unsigned long head_ptr, unsigned long tablesize, unsigned int recsize)
perché hanno il primo parametro = 0 ?
Qual'é il suo significato?

Grazie

crc57:
La lunghezza del record del file .TXT è lunga solo 39 bytes + CR + LF sono 41 bytes. E quindi anche il record del EDB ha +o- le stesse dimensioni.
Però se il buffer che la libreria alloca è comunque 512 bytes sono problemi.

Comunque non bagniamoci prima che piova. Vi farò sapere.

P.s. I metodi: EDB_Status EDB::open(unsigned long head_ptr) e
EDB_Status EDB::create(unsigned long head_ptr, unsigned long tablesize, unsigned int recsize)
perché hanno il primo parametro = 0 ?
Qual'é il suo significato?

Grazie

Intendi dire che il parametro head_ptr è sempre uguale a 0 negli esempi d'uso della libreria?

Se interpreto bene, e non sono sicuro visto che la libreria è scarsamente documentata (i commenti questi sconosciuti), quel parametro specifica il numero della tabella che intendi creare / leggere / scrivere.

db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));

In un esempio come quello sopra riportato: 0 è la prima tabella del database, il secondo e il terzo parametro sono rispettivamente le dimensioni della tabella e del record.

Se devo dirti tecnicamente come viene realizzato ciò, non l'ho capito quindi non so dirti :D.

krypton18:
Intendi dire che il parametro head_ptr è sempre uguale a 0 negli esempi d'uso della libreria?

Se interpreto bene, e non sono sicuro visto che la libreria è scarsamente documentata (i commenti questi sconosciuti), quel parametro specifica il numero della tabella che intendi creare / leggere / scrivere.

db.create(0, TABLE_SIZE, (unsigned int)sizeof(logEvent));

In un esempio come quello sopra riportato: 0 è la prima tabella del database, il secondo e il terzo parametro sono rispettivamente le dimensioni della tabella e del record.

Se devo dirti tecnicamente come viene realizzato ciò, non l'ho capito quindi non so dirti :D.

Si, negli esempi d'uso della libreria è sempre = 0 ma provando a dargli il valore = 1 il programma non ha funzionato quindi dubito che sia quello che tu dici e che io speravo significasse.
Per quanto riguarda i parametri successivi sono d'accordo con te.
Ci sto ancora lavorando, a spizzichi e bocconi, un giorno se ho novità vi saprò dire.
Per adesso grazie e arrivederci.

crc57:
Però se il buffer che la libreria alloca è comunque 512 bytes sono problemi.

Parlo del buffer allocato dalla libreria SD per ogni file aperto ...

Guglielmo

crc57:
Si, negli esempi d'uso della libreria è sempre = 0 ma provando a dargli il valore = 1 il programma non ha funzionato quindi dubito che sia quello che tu dici e che io speravo significasse.
Per quanto riguarda i parametri successivi sono d'accordo con te.
Ci sto ancora lavorando, a spizzichi e bocconi, un giorno se ho novità vi saprò dire.
Per adesso grazie e arrivederci.

Ho trovato la discussione di un altro utente che chiedeva più o meno la stessa cosa, cioè se fosse possibile creare tabelle multiple usando la libreria EDB, a questo indirizzo:

La sua conclusione è stata che "si era scordato di incrementare l'indirizzo nell'EDB header". Poi se sia vero che ha provato e ha funzionato, non lo so.

Nel tuo caso "non ha funzionato" vuol dire che andava in errore la chiamata del metodo db.create, non faceva quello che doveva fare o che scriveva dati a caso?

Hai provato a sostituire l'indirizzo 0 con 1 senza cambiare nessun'altra istruzione nel codice? Oppure hai semplicemente aggiunto la creazione di un'ulteriore tabella con indirizzo 1 oltre allo 0?

Se posti lo sketch possiamo guardarci e fare dei test.

Per esempio ci sono dei flag che ti restituiscono lo stato del metodo utilizzato:

enum EDB_Status {
                          EDB_OK,
                          EDB_ERROR,
                          EDB_OUT_OF_RANGE,
                          EDB_TABLE_FULL
                        };

EDB_Status create(unsigned long, unsigned long, unsigned int);

Con le istruzioni sottocitate, si potrebbe avere qualche indizio in più su cosa succede effettivamente dopo l'utilizzo del metodo db.create :

EDB_Status result = db.create(1, TABLE_SIZE, RECORD_SIZE);

    switch (result)
    {
        case EDB_OUT_OF_RANGE:
            Serial.println("Recno out of range");
            break;
        case EDB_TABLE_FULL:
            Serial.println("Table full");
            break;
        cae EDB_ERROR:
            Serial.println("Error");
            break;
        case EDB_OK:
        default:
            Serial.println("OK");
            break;
}

Chiaramente dovresti usare il monitor seriale per poter visualizzare l'output.

Grazie krypton18, per il momento avevo la necessità di popolare una tabella EDB con i campi presi da un file .TXT.
Sono riuscito nel mio intendo.

  • Ho preparato il file .txt di 1000 record 3 campi per un totale di 40 byte preordinati rispetto al campo che poi avrei utilizzato come chiave di ricerca.
  • Ho popolato la tabella EDB, approssimativamente, in 15 minuti.
  • Le ricerche, in modalità dicotomica, sono invece eccezionali, in meno di 60 ms si riescono a trovare i records cercati. (come da manuale il numero di ricerche = Logaritmo in base 2 del numero degli elementi, nel caso di 1000 elementi il massimo è 10 ricerche).
  • Se la tabella EDB invece è già creata devo solo aprirla ed utilizzarla.

Prossime prove: Arduino DUE e aprire più tabelle.

Grazie a tutti

Per popolare ho utilizzato ...

const char PIPE = 124;

...

		Serial.print(F("Popolamento DB ... "));
		String StrLet;
		StrLet.reserve(TxtLunRec);
		txFile.seek(0);
		while (txFile.available()) {
			StrLet = txFile.readStringUntil(LF);
			RecToCampo(StrLet);
			NewRecord();
		}
		dbFile.close();
...

void RecToCampo(String StrRic) {    // Riceve una stringa e riempie la struttura da riempire
	int pospip;

	pospip = StrRic.indexOf(PIPE);
	strcpy(Record.BoloRum, (StrRic.substring(0, pospip)).c_str());
	StrRic.remove(0, pospip + 1);
	pospip = StrRic.indexOf(PIPE);
	strcpy(Record.CodAur, (StrRic.substring(0, pospip)).c_str());
	StrRic.remove(0, pospip + 1);
	strcpy(Record.CodAzi, StrRic.c_str());
}

...

boolean NewRecord(void){
	EDB_Status result = db.appendRec(EDB_REC Record);
	if (result == EDB_OK) return true;
	printError(result);
	return false;
}

log21000=9,965...
Mentre la ricerca dicotomica ...

unsigned long CercaBoloBin(String Cerca) {
	unsigned long Min, Max, Med;
	unsigned long Start = millis();
	int NumRic = 0;

	Serial.print(F("Ricerca del bolo ... "));
	Serial.print(Cerca);
	Min = 1;
	Max = db.count();
	while (Min <= Max){
		Med = int((Min + Max) / 2);
		EDB_Status result = db.readRec(Med, EDB_REC Record);
		NumRic++;
		if (result == EDB_OK) {
			if (String(Record.BoloRum) == Cerca) {
				Serial.print(F("  ["));
				Serial.print(millis() - Start);
				Serial.print(F("]"));
				Serial.print(F("  {"));
				Serial.print(NumRic);
				Serial.print(F("}"));
				Serial.print(F(" ...record n° "));
				Serial.println(Med);
				return Med;
			}
			if (String(Record.BoloRum) > Cerca) {
				Max = Med - 1;
			}
			else {
				Min = Med + 1;
			}
		}
	}
	Serial.println(F(" ... NON trovato"));
	return 0;
}