Eccomi qua.
Al momento sono molto intenzionato ad imparare, e per imparare bisogna avere qualcosa da realizzare, quindi ho preso la palla al balzo (questo post) e ho cercato di scrivere una procedura per gestire un file di dati strutturati su SD (scrittura, lettura, ricerca).
Questo mi ha dato modo di lavorare molto con le
stringhe C (ho cercato di evitare la
classe String), che per me sono un vero cruccio (abitualmente lavoro con C#, VB.Net).
Posto qui le due versioni (file binario, file di testo), con la speranza che qualcuno esperto possa verificare il codice ed eventualmente indicarmi come migliorarlo/ottimizzarlo.
Naturalmente questo aiuterebbe anche l'OP
Ho pensato di non aprire un'altro topic, in quanto strettamente legato al post originale, se non è prassi, ditemelo.
TIA
Federico
Versione file binario:
#include <SD.h>
#define pinSD 10
char fileName[12] = "data.dat";
//Definisce la struttura (record)
struct dataStore {
char a[10];
unsigned int b;
double c;
};
//Variabile per il record cercato
struct dataStore data;
//Variabile di appoggio per un record
struct dataStore dataRow;
//Stringa di appoggio per la stampa
char dataLine[50];
//Stringa da cercare nel db
char stringaDaCercare[10] = "D6";
void setup() {
Serial.begin(9600);
Serial.println(__FILE__);
//Verifica la presenda della card
if (!SD.begin(pinSD)) {
Serial.println("SD card failed!");
while (1);
}
Serial.println("SD card ready");
//Se il file esiste lo elimina
if (SD.exists(fileName)) {
sprintf(dataLine, "Delete file: %s", fileName);
Serial.println(dataLine);
SD.remove(fileName);
}
//Apre il file per la scrittura
File fileW = SD.open(fileName, FILE_WRITE);
if (fileW) {
sprintf(dataLine, "Write file: %s", fileName);
Serial.println(dataLine);
//Numero massimo di record da scrivere
int maxSize = 10;
for (int i = 0; i < maxSize; i++) {
//Valorizza il record
sprintf(dataRow.a, "%s%d", "D", i);
dataRow.b = i;
dataRow.c = (double)i / 2.0;
//Scrive il record su file
fileW.write((const byte *)&dataRow, sizeof(dataRow));
//Scrive il record sulla seriale
//Nota: sprintf ha problemi con i double/float, ho trovato due alternative
// 1: dtostrf per la conversione in stringa e poi sprintf
char c[5];
dtostrf(dataRow.c, 2, 2, c);
sprintf(dataLine, "%s;%d;%s", dataRow.a, dataRow.b, c);
// 2: conversione del double in due interi (parte intera+decimale)
//sprintf(dataLine, "%s;%d;%d.%02d", data.a, data.b, (int)data.c, (int)(data.c*100)%100);
Serial.println(dataLine);
}
fileW.close();
}
else {
sprintf(dataLine, "ERROR Write file: %s", fileName);
Serial.println(dataLine);
}
//Valorizza il primo capo con un valore di errore
strncpy(data.a, "NULL", 10);
//Apre il file per la lettura
File fileR = SD.open(fileName, FILE_READ);
if (fileR) {
sprintf(dataLine, "Read file: %s", fileName);
Serial.println(dataLine);
//Cicla tutti i bytes leggendo un record alla volta
while (fileR.available()) {
//Legge un record (legge tanti bytes quanti ne servono per riepire il record)
fileR.read((byte *)&dataRow, sizeof(dataRow));
//Se il primo campo è uguale a stringaDaCercare (quello che cerco), setta data ed esce
if (strncmp(dataRow.a, stringaDaCercare, 10) == 0) {
data = dataRow;
break;
}
}
fileR.close();
}
else {
sprintf(dataLine, "ERROR Write file: %s", fileName);
Serial.println(dataLine);
}
//Se il primo campo è diverso da "NULL" stampo il record trovato
if (strncmp(data.a, "NULL", 10) != 0) {
char c[5];
dtostrf(data.c, 2, 2, c);
sprintf(dataLine, "Trovato: %s;%d;%s", data.a, data.b, c);
Serial.println(dataLine);
} else {
Serial.println("Non trovato");
}
}
void loop() {
// vuoto
}
Versione file testo:
#include <SD.h>
#define pinSD 10
char fileName[12] = "data.txt";
struct dataStore {
char a[10];
unsigned int b;
double c;
};
//Variabile per il record cercato
struct dataStore data;
//Variabile di appoggio per un record
struct dataStore dataRow;
//Stringa di appoggio
char dataLine[50];
//Stringa da cercare nel db
char stringaDaCercare[10] = "S8";
void setup() {
Serial.begin(9600);
Serial.println(__FILE__);
//Verifica la presenda della card
if (!SD.begin(pinSD)) {
Serial.println("SD card failed!");
while (1);
}
Serial.println("SD card ready");
//Se il file esiste lo elimina
if (SD.exists(fileName)) {
sprintf(dataLine, "Delete file: %s", fileName);
Serial.println(dataLine);
SD.remove(fileName);
}
//Apre il file per la scrittura
File fileW = SD.open(fileName, FILE_WRITE);
if (fileW) {
sprintf(dataLine, "Write file: %s", fileName);
Serial.println(dataLine);
//Numero massimo di record da scrivere
int maxSize = 10;
for (int i = 0; i < maxSize; i++) {
//Valorizza il record
sprintf(dataRow.a, "%s%d", "S", i);
dataRow.b = i;
dataRow.c = (double)i / 2.0;
//Crea la stringa delimitata
//Nota: sprintf ha problemi con i double/float, ho trovato due alternative
// 1: dtostrf per la conversione in stringa e poi sprintf
char c[5];
dtostrf(dataRow.c, 2, 2, c);
sprintf(dataLine, "%s;%d;%s", dataRow.a, dataRow.b, c);
// 2: conversione del double in due interi (parte intera+decimale)
//sprintf(dataLine, "%s;%d;%d.%02d", data.a, data.b, (int)data.c, (int)(data.c*100)%100);
//Scrive il record su file
fileW.println(dataLine);
//Scrive il record sulla seriale
Serial.println(dataLine);
}
fileW.close();
}
else {
sprintf(dataLine, "ERROR Write file: %s", fileName);
Serial.println(dataLine);
}
//Valorizza il primo capo con un valore di errore
strncpy(data.a, "NULL", 10);
//Apre il file per la lettura
File fileR = SD.open(fileName, FILE_READ);
if (fileR) {
sprintf(dataLine, "Read file: %s", fileName);
Serial.println(dataLine);
//Cicla il file leggendo una riga alla volta (fino a \n, fine riga)
while (fileR.available()) {
String line = fileR.readStringUntil('\n');
//Converte la stringa (riga) in un char array
line.toCharArray(dataLine, line.length());
//Estrae il primo campo
char * strtokIndx;
strtokIndx = strtok(dataLine, ";");
strcpy(dataRow.a, strtokIndx);
//Se il primo campo è uguale a stringaDaCercare (quello che cerco), setta data ed esce
if (strncmp(dataRow.a, stringaDaCercare, 10) == 0) {
strncpy(data.a, dataRow.a, 10);
strtokIndx = strtok(NULL, ";");
data.b = atoi(strtokIndx);
strtokIndx = strtok(NULL, ";");
data.c = atof(strtokIndx);
break;
}
}
fileR.close();
}
else {
sprintf(dataLine, "ERROR Read file: %s", fileName);
Serial.println(dataLine);
}
//Se il primo campo è diverso da "NULL" stampo il record trovato
if (strncmp(data.a, "NULL", 10) != 0) {
char c[5];
dtostrf(data.c, 2, 2, c);
sprintf(dataLine, "Trovato: %s;%d;%s", data.a, data.b, c);
Serial.println(dataLine);
} else {
Serial.println("Non trovato");
}
}
void loop() {
//VUOTO
}