EDB, Json e SD, strani risultati quando carico il database

Salve a tutti,
sto lavorando ad una sorta di registratore di cassa con arduino e sto avendo dei problemi con il database degli articoli, spero che qualcuno di voi mi possa dare una mano.

Hardware utilizzati:

  • arduino mega
  • lettore rfid 125hz
  • bluetooth hc-06
  • schermo touchscreen con lettore sd

Idea generale del progetto: l'hardware finale utilizzerá lo schermo per visualizzare un menú contenente degli articoli suddivisi per categoria. L'utente utilizzerá una scheda rfid per potersi autenticare e acquistare gli oggetti scelti. Lo storico degli acquisti verrá mandato ad un applicazione android. Tale applicazione viene utilizzata per salvare/monitorare il venduto, modificare/creare articoli, modificare/creare nuovi utenti.

Ho giá l'applicazione android che comunica con arduino tramite il modulo bluetooth, la comunicazione avviene tramite stringhe json opportunamente decodificate.
Per la codifica/decodifica lato arduino utilizzo la libreria "ArduinoJson".
Per comunicare con la scheda sd utilizzo "SDFat"
Per il database utilizzo "EDB"

Ho scritto tutto il codice necessario, a livello logico tutto dovrebbe andare come premesso, il problema é che spesso e volentieri, al momento della lettura del database, ho dei risultati totalmente sbagliati.
Di seguito riporto i pezzi di codice interessati:

// database.ino
#include <ArduinoJson.h>
#define SD_CHIP_SELECT 53     // enable monitor pin
SdFat SD;                     // the actual SD superclass
File dbFile;                  // read/write file
#include <EDB.h>              // Extended Arduino Database lib
#include <EEPROM.h>           // temp location of the data flow

EDB db(&writer, &reader);     // the actual database class

/*database structure */
#define TABLE_SIZE 4096
struct Articolo {           // ARTICOLO
  const char* aID;          // index, used for remove/modify
  const char* artName;      // name of the article
  double artPrice;          // price of the article
  int categoria;            // category - to query the sub/menu
} articolo;

struct Cliente {            // CLIENTE
  int cliTag[14];           // intarray from the RFID tag
  const char* cliName;      // name of the client
  double cliAmount;         // the actual available credit
} cliente;

struct Categoria {          // CATEGORIA  
  int catID;                // index, used on the article queries
  const char* catName;      // name of the category
  int r;                    // rgb color of the category
  int g;
  int b;                 
} categoria;

StaticJsonBuffer<512> jsonBuffer;

void writer(unsigned long address, byte data)
{
  dbFile.seek(address);
  dbFile.write(data);
  dbFile.flush();
}
byte reader(unsigned long address)
{
  dbFile.seek(address);
  return dbFile.read();
}

void InitializeDatabase()
{
  /***** Check SD *******/
  bool mysd = 0;
  while (!mysd)
  {
      if (!SD.begin(SD_CHIP_SELECT, SPI_FULL_SPEED)){
        Serial.println(F("Nessuna carta presente"));
        Serial.println(F("Riprovo...."));
      }
      else
      {
        mysd= 1;
        Serial.println(F("Carta Inizializzata"));
      }
  }
  
  //SD.remove("categories.db");
  FirstInitialization();

}

void Exists(char* data, byte dataStruct)
{
  if (SD.exists(data)){                     // database exists, open it
    dbFile = SD.open(data, FILE_WRITE);
    db.open(0);
  }
  else                                      // no database found. create it
  {
    dbFile = SD.open(data, FILE_WRITE);
    db.create(0,TABLE_SIZE, dataStruct);
  }
}

void InsertCategory(char* category)
{
  Exists("categories.db", sizeof(categoria));
  
  JsonObject& JsonCategoria = jsonBuffer.parseObject(category);
  int catID = JsonCategoria["catID"];                 // index, used on the article queries
  const char* catName = JsonCategoria["Nome"];        // name of the category
  int r = JsonCategoria["colorR"];                    // rgb color of the category
  int g = JsonCategoria["colorG"];
  int b = JsonCategoria["colorB"];

  categoria.r = r;
  categoria.g = g;
  categoria.b = b;
  categoria.catName = catName;
  categoria.catID = catID;

  EDB_Status result = db.appendRec(EDB_REC categoria);
  if (result != EDB_OK){
    Serial.print("Errore scrittura: ");
    Serial.println(result);
  }
  
}

void FirstInitialization()
{
  InsertCategory("{\"catID\":0,\"Nome\": \"Consumabili\",\"colorR\":0,\"colorG\": 0,\"colorB\": 255}");
  InsertCategory("{\"catID\":1,\"Nome\": \"Alcolici\",\"colorR\":255,\"colorG\": 0,\"colorB\": 0}");
  InsertCategory("{\"catID\":2,\"Nome\": \"Snack\",\"colorR\":0,\"colorG\": 255,\"colorB\": 0}");
  InsertCategory("{\"catID\":3,\"Nome\": \"Bibite\",\"colorR\":255,\"colorG\": 255,\"colorB\": 0}");
}

// ... later on the monitor.ino file
void ShowCategories()
{
  //Serial.println("Should show categories");
  LCD.clrScr();
  Exists("categories.db", sizeof(categoria));
  int row = 0;
  int column = 0;
  
  int i =1;
  for (i; i<=db.count(); i++)
  {
    db.readRec(i, EDB_REC categoria);
    LCD.setColor(categoria.r, categoria.g, categoria.b);
    LCD.fillRoundRect(row*120, column*75, (row*120)+119, (column*75)+76);
    LCD.setColor(255,255,255);
    LCD.drawRoundRect(row*120, column*75, (row*120)+119, (column*75)+76);
    LCD.setBackColor(categoria.r, categoria.g, categoria.b);
    LCD.setColor(255-categoria.r,255-categoria.g,255-categoria.b);
    LCD.print(categoria.catName, 8+(row*120), 24+(column*75));
    Serial.println(categoria.catName);
    LCD.setBackColor(0,0,0);

    row++;
    if(row ==2){
      row = 0; 
      column++;
    }
  }
}

Il risultato di questo codice é esattamente quello aspettato: una griglia di bottoni del colore salvato nel database, con un etichetta contenente il nome della categoria salvata. Ma questo avviene SOLAMENTE se creo il database nello stesso momento della prima inizializzazione, se provo a chiudere e caricare il database in un secondo momento (il metodo "firstInitialization" é stato creato a scopo di test, l'idea é di avere un db creato dalle stringhe ricevute da bluetooth ma il risultato é identico) il campo "catName" contiene

// risultato dal serial printando il campo catName all'interno di ShowCategories
ome": "Consumabili","colorR":0,"colorG": 0,"colorB": 255}
ome": "Alcolici","colorR":255,"colorG": 0,"colorB": 0}
ome": "Snack","colorR":0,"colorG": 255,"colorB": 0}
ome": "Bibite","colorR":255,"colorG": 255,"colorB": 0}

Nessun problema invece per i campi integer. ho provato ad utilizzare al posto di const char* un char array con un limite definito, inizializzandolo con strcpy ma il risultato é una serie infinita di caratteri randomici. Ho provato ad utilizzare il tipo String, ma questo da come risultato l'alterazione (??) dell'ultimo campo dell'array nel database (in questo caso, prende bibite, e aggiunge "bibitete", "bibi", bibt"..
Non riesco a risolvere questo problema, spero vivamente qualcuno di voi sappia illuminarmi, grazie in anticipo

Buongiorno,
essendo il tuo primo post, ti chiederei cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con attenzione il REGOLAMENTO ... Grazie.

Guglielmo

Ma, non conoscevo questa libreria EDB, però:

  1. la EDB che trovo qui: Arduino Playground - ExtendedDatabaseLibrary
    se noti negli esempi usa sempre un record con SOLO int, mai stringhe.

  2. la EDB del punto 1 dice che si basa su questa: Arduino Playground - DatabaseLibrary
    ma in questa l'esempio ha questa struct e NON usa puntatori a char come hai fatto tu ma array di char con quanto spazio massimo può occupare ogni stringa.

struct MyRec {
 char date[11];         // array di char, non puntatore a char !!
 char time[9];
 int temperature;
} myrec;

@gpb01: Scusami, provvedo subito

@nid69ita:

1: si ho notato che usa solo int nell'esempio, ma ho anche notato che non ha specificato da nessuna parte quali tipi di variabili sono utilizzabili ne che é possibile usare solamente integers, ho solo presupposto che si possano utilizzare perlomeno i tipi "standard".

riguardo array di char, come scritto nel primo post é stato uno dei miei approcci ma con risultati ancora peggiori. Ho trovato una soluzione che sembra funzionare: a quanto pare strcpy non aggiunge il carattere NULL alla fine della stringa. Aggiungendola a mano il tutto sembra funzionare a dovere.

Per chi dovesse imbattersi in questo problema la mia soluzione é:

struct Categoria {          // CATEGORIA 
  int catID;                // index, used on the article queries
  char catName[14];   // name of the category
  int r;                     // rgb color of the category
  int g;
  int b;                 
} categoria;

// nell'inizializzazione del record
// ...
const char* name = JsonCategoria["Nome"];        // name of the category
strcpy(categoria.catName, name);
categoria.catName[13] = '\0';

Sono sicurissimo che la strcpy() mette il NULL (se lo trova), forse i dati JsonCategoria["Nome"]; non c'e' l'anno
http://www.cplusplus.com/reference/cstring/strcpy/