Arduino Forum

International => Italiano => Software => Topic started by: crc57 on May 04, 2019, 03:10 pm

Title: [Risolto] Lettura e scrittura di un record, come struttura dati, da e su SD
Post by: crc57 on May 04, 2019, 03:10 pm
Salve a tutti, vi sarei grato se mi poteste aiutare a risolvere un problema di lettura da una memoria SD.
Vorrei realizzare un sistema di identificazione RFID e/o impronta digitali memorizzando su una SD alcune informazioni che ho ordinato in una struttura dati.
Code: [Select]


File dbFile;                             // Classe File

struct StruRec {                      // Struttura del record di database
 char       DBTipo;                   // A=amministratore / U=utente / X=revocato
 uint16_t DbImp;                   // ID impronta
 uint32_t DbCard;                  // ID Card RFID
 char       DbNome[20];          // Nominativo utente
}
Record;



Per quanto riguarda la scrittura non ho problemi, scrivo i vari campi con delle semplici dbFile.write(Campo1) ecc. e dopo aver scritto tutti i campi eseguo dbFile.write(LF) come fine record.

Code: [Select]

dbFile.write('U');
dbFile.write(IdImp);
dbFile.write(IdRfid);
dbFile.write(NomUte);
dbFile.write(LF);
dbFile.flush();


Il problema è come popolare, in fase di lettura, la struttura dati?
I records non sono molti quindi anche una lettura sequenziale non dovrebbe creare problemi di prestazioni.
Avrei voluto fare una codifica tipo questa:
Code: [Select]

void LettMicro() {
   dbFile.seek(0);
   while (dbFile.available()) {
      int size = dbFile.readBytesUntil(LF, &Record, 8);

    }
    return;
}

ma naturalmente non funziona.

Grazie a tutti
Title: Re: Lettura di una riga strutturata da SD
Post by: Standardoil on May 04, 2019, 05:40 pm
attacco io, con alcune domande
ma la scrittura funziona bene bene?
intendo dire, hai provato a scrivere, chiudere il file, spegnere, portare la scheda SD sul PC e vedere se ha scritto giusto?
perchè io avrei dei dubbi, primo
e comunque, al di la dei miei dubbi, sei tu che devi essere sicuro che la scrittura vada, secondo
Title: Re: Lettura di una riga strutturata da SD
Post by: crc57 on May 04, 2019, 06:31 pm
Di questo progetto sono ancora nella fase di scrittura del codice, di assemblare l'hardware è ancora presto, ma ho appena finito un braccio robotico con 6 servomotori in cui utilizzo

Code: [Select]

 int size = dbFile.readBytesUntil(LF, Record.SerPos, MaxMot);

per la lettura delle posizioni precedentemente memorizzate dove Record.SerPos è un array di 6 byte dove ho memorizzato ciclicamente gli angoli dei 6 servomotori.
In fase di lettura della SD il braccio robotico riesegue le movenze che avevo eseguito con i comandi manuali e memorizzato nella SD.
In quel caso però il record (la struttura) era costituito da un solo array ed ha funzionato perfettamente.

Code: [Select]

struct StruRec { // Struttura del record di database
 byte SerPos[MaxMot];
}
Record;


In questo caso la struttura è costituita da elementi di tipo diverso.
Title: Re: Lettura di una riga strutturata da SD
Post by: crc57 on May 04, 2019, 06:39 pm
In verità avevo provato anche la libreria di database (https://github.com/jwhiddon/EDB) ma non sono riuscito a far funzionare neppure gli esempi, mi scriveva sulla SD sempre lo stesso record.
Sarebbe stata ottima  ;D
Title: Re: Lettura di una riga strutturata da SD
Post by: Standardoil on May 04, 2019, 07:56 pm
ma allora il tuo problema è la scrittura, non la lettura...
Title: Re: Lettura di una riga strutturata da SD
Post by: vlc0617 on May 05, 2019, 02:35 am
A me sembra che la funzione File.write(data) accetti come argomenty byte, char o char *

https://www.arduino.cc/en/Reference/FileWrite (https://www.arduino.cc/en/Reference/FileWrite)

Quindi

Code: [Select]
dbFile.write(IdImp);

e

Code: [Select]
dbFile.write(IdRfid);

probabilmente non scriveranno correttamente IdImp e IdRfid nel file.

Prova

Code: [Select]
dbFile.write((byte *)&IdImp, sizeof(IdImp));

e

Code: [Select]
dbFile.write((byte *)&IdRfid, sizeof(IdRfid));

Inoltre, con questa istruzione

Code: [Select]
      int size = dbFile.readBytesUntil(LF, &Record, 8);


leggi al massimo 8 byte, ma sizeof(Record) > 8, quindi devi usare

Code: [Select]
      int size = dbFile.readBytesUntil(LF, &Record, sizeof(Record));
Title: Re: Lettura di una riga strutturata da SD
Post by: Standardoil on May 05, 2019, 08:46 am
Infatti gli avevo ben chiesto se si ritrovava con quello che aveva scritto...
Title: Re: Lettura di una riga strutturata da SD
Post by: crc57 on May 06, 2019, 09:32 am
Grazie Standardoil per le dritte, faccio un po' di prove e ti faccio sapere.
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 06, 2019, 11:00 am
Premesso che il C lo trovo leggermente ostico, ma credo ci sia un po' di confusione, e vi prego di correggermi se sbaglio.
L'OP usa una struttura, ma poi cerca di scrivere su file i dati non strutturati ed inserendo un LF per indicare il fine record, il che naturalmente (IMHO) comporta non poche complicazioni in fase di lettura.
Ho come l'impressione che ci sia confusione anche sulla modalità di scrittura, binaria/testuale.


Al momento non saprei tradurlo in C, ma nel caso di scrittura binaria, ipotizzo qualcosa del genere (probabilmente va effettuata una conversione della variabile data)
Code: [Select]

//Scrittura
StruRec data;
dbFile.write(data, sizeof(data));

//Lettura
dbFile.read(data, sizeof(data));

in questo modo, data contiene l'intero record, data.DBTipo e così via.

Ripeto, probabilmente ho scritto una castronata in C, ma mi interessa capire se la logica è corretta.

In alternativa, si potrebbe scrivere un file di testo con separatore, ma anche il quel caso non è necessario usare un LF, se si una dbFile.println("a;b;c;d")


TIA
Federico
Title: Re: Lettura di una riga strutturata da SD
Post by: nid69ita on May 06, 2019, 11:17 am
@federico, direi di si.
Un file testo ha righe a dimensione diversa, quindi un fine linea fa capire quando finisce una riga.
Un file binario ci scrivi dei byte e quindi, ad esempio, una struct a dimensione fissa. Quindi se lo struct è di 100 byte ogni 100 byte c'e' un record.
Ovviamente se il file contiene dati solo binari non è da usare un separatore tipo nuova riga e inoltre il file non è ben leggibile con un editor. Se contiene stringhe almeno una parte è leggibile, ma le variabili numeriche sono memorizzare come in memoria RAM/SRAM quindi non facili da leggere (un long sono 4 byte quindi spezzato nelle 4 parti).   
Un "database" di solito è binario e non testuale.
Title: Re: Lettura di una riga strutturata da SD
Post by: torn24 on May 06, 2019, 11:57 am
@Federico66 quello che dici il linguaggio C lo permette di fare su file, con la libreria standar e su un computer.

Adesso la classe FILE non fa parte della libreria standar del C, mette a disposizione dei metodi che non permettono di salvare struct su SD.
Per cui quello che hanno fatto o cercano di fare, è perché l'unica cosa consentita dai metodi forniti.
Da quello che ho letto il massimo che si può fare con FILE.write, è scrivere un array di char.
Secondo me non è neanche indispensabile organizzare i dati in struct, visto che poi dovrai leggere e scrivere i singoli campi.
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 06, 2019, 11:58 am
@nid69ita: scusa, ma nelle mie premesse ho dimenticato di dire per lavoro progetto e sviluppo sistemi di gestione dati (da quasi 30 anni!) :)
I miei dubbi sono solo sulle modalità di scrittura/lettura dei dati strutturati da parte dell'OP, visto che, non avendo esperienza di C, (senza studiare), non saprei come scrivere (se si puo', ma penso di si) una struct su file binario.

Un file testo ha righe a dimensione diversa, quindi un fine linea fa capire quando finisce una riga.
Certo, ma se i dati li scrivo in formato testo usando println, il fine riga viene già aggiunto, quindi non serve aggiungere un LF, se invece li scrivo con write, allora ho una dimensione fissa per i bytes, quindi quando li leggo, mi serve solo sapere quanti bytes devo leggere per avere un record, e quindi il LF non serve comunque.

In definitiva non capisco l'utilità di queste righe, in quanto penso siano inutili
Code: [Select]

dbFile.write(LF);
int size = dbFile.readBytesUntil(LF, &Record, 8);


Sbaglio?

F

PS
Sono fresco di Arduino, ma l'argomento mi ha incuriosito. Nei giorni scorsi mi è arrivato un modulo SD, quindi studierò :-)
Title: Re: Lettura di una riga strutturata da SD
Post by: Standardoil on May 06, 2019, 01:12 pm
Boh, io sono dell'idea che per un neofita ogni cosa vale per semplificare il lavoro
Quindi voto per scrivere su file di testo, pur se la struttura permetterebbe usare file binari
Dopo scritto di va su un pc per avere conferma
Solo dopo si fa la lettura, che essendo di testo forse è  un pochino più semplice
Magari dopo butto giù  un abbozzo, ma non sarà tanto presto, stasera ho traffico. ..
Title: Re: Lettura di una riga strutturata da SD
Post by: nid69ita on May 06, 2019, 02:25 pm
@Federico66 quello che dici il linguaggio C lo permette di fare su file, con la libreria standar e su un computer.
Per cui quello che hanno fatto o cercano di fare, è perché l'unica cosa consentita dai metodi forniti.
Da quello che ho letto il massimo che si può fare con FILE.write, è scrivere un array di char.
Secondo me non è neanche indispensabile organizzare i dati in struct, visto che poi dovrai leggere e scrivere i singoli campi.
Basta usare un cast e la struct viene vista come un array di byte. E' una cosa normale che fai su PC in C ma anche su Arduino lo fai tranquillamente.   
https://www.programiz.com/c-programming/c-file-input-output#example-write
Che il comando a disposizione sia lo standard fwrite o la write della lib, sempre un puntatore a qualcosa devi dargli e quanti byte scrivere
fwrite(&num, sizeof(struct threeNum), 1, fptr);
Title: Re: Lettura di una riga strutturata da SD
Post by: vlc0617 on May 06, 2019, 02:54 pm
In realta' il modo usato da crc57 per scrivere il record funziona a 2 condizioni

1) che il compilatore non inserisca nella struttura byte di padding https://en.wikipedia.org/wiki/Data_structure_alignment (https://en.wikipedia.org/wiki/Data_structure_alignment)

2) che i dati della struttura non contengano al loro interno il carattere usato come terminatore (LF)

Mentre la 1) probabilmente e' verificata per un processore a 8 bit, la 2) e' piu' problematica perche' la struttura contiene 2 interi (per un totale di 6 bytes) che possono avere qualunque valore (assumiamo che il campo nome utente non contenga LF).

Se almeno un byte di uno dei due interi e' uguale al codice ASCII del LF, la lettura del record si fermera' nel punto sbagliato.

Tra parentesi, anche la scrittura del campo nome utente potrebbe non funzionare, perche' write(char *) mi pare che non scriva il terminatore di stringa (lo '\0' finale), e quindi in fase di lettura non si sapra' quanti caratteri sono validi dei 20 che costituiscono il campo.

Io personalmente avrei usato questo codice per scrivere il record


Code: [Select]
Record.DBTipo = 'U';
Record.DbImp = IdImp;
Record.DbCard = IdRfid;

if (strlen(NomUte) < 20)
strcpy(Record.DbNome,NomUte);
else
// gestire l'errore di stringa troppo lunga

dbFile.write((byte *)&Record, sizeof(Record));
dbFile.flush();


e per la lettura, invece di readBytesUntil

Code: [Select]
dbFile.read(&Record,sizeof(Record));
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 06, 2019, 02:55 pm
Basta usare un cast e la struct viene vista come un array di byte. E' una cosa normale che fai su PC in C ma anche su Arduino lo fai tranquillamente.  
https://www.programiz.com/c-programming/c-file-input-output#example-write
Infatti stavo studiando e ho trovato che si può fare qualcosa del genere:

Code: [Select]

struct datastore {
  char a[a];
  unsigned int b;
  double c;
};

//SCRIVE
struct datastore data1;
data1.a = "abcd";
data1.b = 1;
data1.c = 1.0;
File dataFile1= SD.open("datalog.dat", FILE_WRITE);
dataFile1.write((const uint8_t *)&data1, sizeof(data1));

//READ
struct datastore data2;
File dataFile2 = SD.open("datalog.dat", FILE_READ);
dataFile2.read((uint8_t *)&data2, sizeof(data2));

//data2: contiene l'intera struttura (record)



Per me non è facilissimo capire questo:
Code: [Select]

(const uint8_t *)&data1

ma, se ho ben capito, è il puntatore all'indirizzo di data1 convertito in byte, quindi ritorna data1 (struttura) come un array di byte.
Corretto?
Spero di non aver detto una cavolata, ma mi piace capire quello che scrivo, altrimenti non imparo :-)


TIA
F


Title: Re: Lettura di una riga strutturata da SD
Post by: Standardoil on May 06, 2019, 03:49 pm
Secondo me è l'indirizzo di data1 convertito in puntatore a byte
Title: Re: Lettura di una riga strutturata da SD
Post by: torn24 on May 06, 2019, 04:08 pm
Non ho capito subito ma sicuramente è fuorviante  :)   uint8_t , un intero senza segno a 8 bit, equivale a byte. Comunque è fuorviante, almeno per chi non ha una conoscenza approfondita del linguaggio C.
Title: Re: Lettura di una riga strutturata da SD
Post by: nid69ita on May 06, 2019, 05:24 pm
 Passaggio di parametri per indirizzo.  Che gli passo una struttura, una semplice variabile o un array poco importa.
E' una cosa normale per il C.  Poi un puntatore è un puntatore, il cast in questo caso è per farlo "digerire" al controllo del compilatore che fa sul parametro.  :)


& ritorna indirizzo di data, è un puntatore di tipo datastore, quindi lo convertiamo (cast) a puntatore di tipo const uint_8.   Il cast fa capire al compilatore che sappiamo qul che facciamo, che siamo consci del fatto che passiamo un puntatore ad un qualcosa che vogliamo sia trattato a byte (o uint_8).
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 06, 2019, 06:09 pm
Passaggio di parametri per indirizzo.  Che gli passo una struttura, una semplice variabile o un array poco importa.
E' una cosa normale per il C.  Poi un puntatore è un puntatore, il cast in questo caso è per farlo "digerire" al controllo del compilatore che fa sul parametro.  :)

& ritorna indirizzo di data, è un puntatore di tipo datastore, quindi lo convertiamo (cast) a puntatore di tipo const uint_8.   Il cast fa capire al compilatore che sappiamo qul che facciamo, che siamo consci del fatto che passiamo un puntatore ad un qualcosa che vogliamo sia trattato a byte (o uint_8).
Ti ringrazio, anche oggi ho imparato qualcosa di nuovo :-)

F

PS
Stasera provo e se funziona posto l'esempio per OP, che nel frattempo si è perso :-)
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 07, 2019, 12:19 pm
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 :D

Ho pensato di non aprire un'altro topic, in quanto strettamente legato al post originale, se non è prassi, ditemelo.


TIA
Federico




Versione file binario:
Code: [Select]

#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:
Code: [Select]

#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
}
Title: Re: Lettura di una riga strutturata da SD
Post by: crc57 on May 07, 2019, 03:24 pm
Scusate il ritardo, non sono sparito ;D .
Voglio ringraziare tutti quanti ed ognuno singolarmente per il contributo dato al post.
Mi fa piacere che sia stato utile a molti.
Un ringraziamento particolare a Federico66 il cui codice funziona perfettamente, sia in scrittura che in lettura.
Il LF che mettevo a fine record era senzaltro un errore usando
Code: [Select]
dbFile.readBytesUntil(LF, &Record, 8); ma dovendo essere parte di una esercitazione didattica, volevo mostrare il file creato ai ragazzi nella maniera più ordinata possibile, tant'è che l'ho reintrodotto nella struttura come Filler.
Ho modificato anche un po' la struttura
Devo ammettere che i puntatori sono #potentementecomplicatiepericolosi
Con questo Vs. contributo il mio progetto ha avuto una svolta molto positiva.
Grazie a tutti.

Code: [Select]

struct ABX { // Struttura del record di database
char DBTipo; // A=amministratore / U=utente / X=revocato
unsigned long DbCard; // ID impronta
byte DbImp; // ID Card RFID
char DbNome[20]; // Nominativo utente
char Filler; // filler
} Record;



Code: [Select]

/* prova di scrittura */
Record.DBTipo = 'A';
Record.DbCard = 3134562064;
Record.DbImp = 1;
copyC(Admin, Record.DbNome, 20);
Record.Filler = LF;
dbFile = SD.open(NomeDb, FILE_WRITE);
dbFile.write((const uint8_t *)&Record, sizeof(Record));
dbFile.flush();



Code: [Select]

/* prova di lettura */
dbFile.read((uint8_t *)&Record, sizeof(Record));
Serial.print(Record.DBTipo);
Serial.print(F("-"));
Serial.print(Record.DbCard);
Serial.print(F("-"));
Serial.print(Record.DbImp);
Serial.print(F("-"));
Serial.print(Record.DbNome);
Serial.print(Record.Filler);
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 07, 2019, 03:46 pm
Mi fa piacere che sia stato utile a molti.
A me sicuramente, quindi grazie a te, fino a qualche giorno fa per me il C era solo la terza lettera dell'alfabeto :D

Federico

PS
non mi è chiara la differenza uint8_t e byte, visto che comunque indicano il byte, ma visto che nel reference di Arduino uint8_t non viene segnalato, alla fine ho usato byte
Title: Re: Lettura di una riga strutturata da SD
Post by: nid69ita on May 07, 2019, 03:50 pm
A me sicuramente, quindi grazie a te, fino a qualche giorno fa per me il C era solo la terza lettera dell'alfabeto :D

Federico

PS
non mi è chiara la differenza uint8_t e byte, visto che comunque indicano il byte, ma visto che nel reference di Arduino uint8_t non viene segnalato, alla fine ho usato byte
Sono delle definizioni di tipo per evitare ambiguità
uint_8  è sicuro.  sta per unsigned intero a 8 bit, anche un byte lo è (su tutte le architetture)
ma ad esempio     uint_16   è unsigned intero a 16 bit (2 byte).   NON è detto si la stessa cosa con int in quanto la dimensione in byte di un int dipende dall'architettura, può essere 2 o 4 byte.
Title: Re: Lettura di una riga strutturata da SD
Post by: Federico66 on May 07, 2019, 03:54 pm
Sono delle definizioni di tipo per evitare ambiguità
uint_8  è sicuro.  sta per unsigned intero a 8 bit, anche un byte lo è (su tutte le architetture)
ma ad esempio     uint_16   è unsigned intero a 16 bit (2 byte).   NON è detto si la stessa cosa con int in quanto la dimensione in byte di un int dipende dall'architettura, può essere 2 o 4 byte.
Chiarissimo come sempre, grazie
Title: Re: Lettura di una riga strutturata da SD
Post by: crc57 on May 07, 2019, 11:11 pm
Chiarissimo come sempre, grazie
A riprova di quello che dice nid69ita a proposito di uint16_t, in Arduino UNO è di 2 byte quindi l'ID della card RFID l'ho dovuta definire unsigned long che invece è 4 byte anche su Arduino UNO