Nell’articolo precedente scrissi che avrei trattato come prossimo argomento l’Arduino Ethernet Shield, purtroppo a causa degli scioperi dei mezzi in tutta Italia, il pacco che mi sarebbe dovuto arrivare in tre giorni, è arrivato dopo ben due settimane (è arrivato proprio oggi!), così ho avuto modo di realizzare un piccolo progetto che avevo in mente già da parecchio tempo!

Una specie di banca dati, o registratore di cassa, insomma, qualcosa che mi ricordi quanti soldi ho nel salvadanaio, ricordandomi anche le date dei prelievi o depositi; Così è nato il programma “Banca Dati”.

Il programma consiste nel far comunicare il computer tramite linguaggio di programmazione C#, con l’arduino che scrive i dati da registrare/leggere su un EEPROM I2C (vedi articolo passato: Data Logger).

Ecco un screen dell’interfaccia grafica:

A prima vista può sembrare un programma molto semplice ma non è del tutto così, la parte più complicata è stata la divisione dei dati per poterli salvare sull’EEPROM.

Spiego in due parole com’è strutturata la memoria dell’EEPROM.

I primi due byte (0 e 1) sono dedicati alla variabile N° di dati in memoria, ovvero, questa variabile contiene il numero di dati salvati in memoria (lo stesso numero che compare sull’interfaccia grafica sulla parte destra sopra il pulsante “Cancella Dati”).

I seguenti byte sono divisi in righe da 7 Byte; dunque è facile calcolare il n° di record che si possono inserire ([32K – 2] / 6 = 5333) :

Byte 0: data_gg -> Il valore numerico del giorno.

Byte 1: data_mm -> Il valore numerico del mese.

Byte 2: data_yy -> Il valore numero dell’anno (vengono omesse le prime due cifre dell’anno).

Byte 3,4,5,6 -> Contengono i 4 byte che costituiscono un dato float.

 

Ecco il programma per l’arduino:

/*Si vuole realizzare una banca dati interfacciata al computer tramite comunicazione seriale (USB)
 che permette di registrare dei record su un EEPROM I2C con la possibilità di ricevere e leggere i dati al computer.
 */

#include <Wire.h> //I2C library

//Funzioni che permettono di leggere/scrivere sull'EEPROM----------------------------------
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
  int rdata = data;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(rdata);
  Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.read();
  return rdata;
}
//Fine funzioni che permettono di leggere/scrivere sull'EEPROM------------------------------

//Funzione per scomporre una variabile FLOAT in 4 Byte--------------------------------------
union SCOMP_FLOAT
{
  float MyFloat;       //Per scomporre una variabile float bisogna assegnare a S_FLOAT.MyFloat il valore desiderato
  char byte_s[4];      //e recuperare i valore dai byte S_FLOAT.byte_s[n] dove n è il numero di byte che va da 0 a 3
}
S_FLOAT;            //Processo inverso per ricomporre la variabile float
//Fine funzione di divisione float-----------------------------------------------------------

/* Unione e divisione Byte (per int)
 somma = (b << 8) | a; Si uniscono MSB (b) ed LSB (a)

 //Si divide
 a = somma; LSB
 b = somma >> 8; MSB
 */

//Variabili di data
byte data_gg = 0;
byte data_mm = 0;
byte data_yy = 0;

//Variabile per l'inserimento del valore
float soldi = 0;
float totale = 0;

//Primi 2 Byte dell'EEPROM che contengono il numero di dati
int datiscritti = 0;
byte datiscrittiLSB = 0;
byte datiscrittiMSB = 0;

int mode = 0; //Dato ricevuto dal pc per decidere se leggere o scrivere
int indirizzo = 2; //Indirizzo di EEPROM; Parte da due perchè i primi due BYTE sono per la memorizzazioni del N° scritture;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop(){

  //Ricezione modalità: Lettura o scrittura--------
  while (Serial.available() <= 0){
  } // Attendi dato
  int lettura = Serial.read();
  if(lettura == 'w')
    mode = 1;
  else if (lettura == 'r')
    mode = 0;
  else if (lettura == 'e')
    mode = 2;
  //Fine ricezione modalità------------------------

  //Fase di lettura--------------------------------
  if (mode == 0){
    erasevar(); //Chiama funzione di reinizializzazioni variabili

    //Leggo il numero di dati scritti sull'EEPROM
    datiscrittiMSB = i2c_eeprom_read_byte(0x50, 0);
    delay(5);
    datiscrittiLSB = i2c_eeprom_read_byte(0x50, 1);
    delay(5);
    datiscritti = (datiscrittiMSB << 8) | datiscrittiLSB;
    //Fine lettura di n° dati scritti sull'EEPROM

    Serial.println(datiscritti); //Invio numero dati sull'EEPROM

    //Inizio lettura dei dati
    for(int i = 1; i <= datiscritti; i++){
      data_gg = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      data_mm = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      data_yy = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      S_FLOAT.byte_s[3] = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      S_FLOAT.byte_s[2] = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      S_FLOAT.byte_s[1] = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      S_FLOAT.byte_s[0] = i2c_eeprom_read_byte(0x50, indirizzo);
      delay(5);
      indirizzo++;

      soldi = S_FLOAT.MyFloat;
      totale += soldi;

      Serial.println(data_gg);
      Serial.println(data_mm);
      Serial.println(data_yy);
      Serial.println(soldi);
    }
    //Fine lettura dei dati
    Serial.println(totale);

  }
  //Fine fase di lettura---------------------------

  //Fase di scrittura------------------------------
  else if (mode == 1){
    erasevar(); //Chiama funzione di reinizializzazioni variabili

    //Leggo il numero di dati scritti sull'EEPROM
    datiscrittiMSB = i2c_eeprom_read_byte(0x50, 0);
    delay(5);
    datiscrittiLSB = i2c_eeprom_read_byte(0x50, 1);
    delay(5);
    datiscritti = (datiscrittiMSB << 8) | datiscrittiLSB;
    //Fine lettura di n° dati scritti sull'EEPROM

    while (Serial.available() <= 0){
    } // Attendi dato

    //Ricevo i dati
    data_gg = Serial.read();
    delay(5); //Pausa di attesa dato
    data_mm = Serial.read();
    delay(5); //Pausa di attesa dato
    data_yy = Serial.read();
    delay(5); //Pausa di attesa dato
    S_FLOAT.byte_s[0] = Serial.read();
    delay(5); //Pausa di attesa dato
    S_FLOAT.byte_s[1] = Serial.read();
    delay(5); //Pausa di attesa dato
    S_FLOAT.byte_s[2] = Serial.read();
    delay(5); //Pausa di attesa dato
    S_FLOAT.byte_s[3] = Serial.read();
    delay(5);
    //Fine ricezione dati

    indirizzo = (datiscritti * 7) + 2; //Trovo l'indirizzo di partenza

    //Li scrivo sull'EEPROM---------------------------------
    i2c_eeprom_write_byte(0x50, indirizzo, data_gg);
    delay(5);
    indirizzo++;

    i2c_eeprom_write_byte(0x50, indirizzo, data_mm);
    delay(5);
    indirizzo++;

    i2c_eeprom_write_byte(0x50, indirizzo, data_yy);
    delay(5);
    indirizzo++;

    i2c_eeprom_write_byte(0x50, indirizzo, S_FLOAT.byte_s[3]);
    delay(5);
    indirizzo++;

    i2c_eeprom_write_byte(0x50, indirizzo, S_FLOAT.byte_s[2]);
    delay(5);
    indirizzo++;

    i2c_eeprom_write_byte(0x50, indirizzo, S_FLOAT.byte_s[1]);
    delay(5);
    indirizzo++;

    i2c_eeprom_write_byte(0x50, indirizzo, S_FLOAT.byte_s[0]);
    delay(5);
    indirizzo++;
    //Fine scrittura dati---------------------------------

    //Aggiorno la variabile datiscritti sull'EEPROM----------
    datiscritti++;
    datiscrittiLSB = datiscritti;
    datiscrittiMSB = datiscritti >> 8;

    i2c_eeprom_write_byte(0x50, 0, datiscrittiMSB);
    delay(5);
    i2c_eeprom_write_byte(0x50, 1, datiscrittiLSB);
    delay(5);
    //Fine aggiornamento variabile datiscritti---------------

  }
  //Fine fase di scrittura-------------------------

  //Cancellamento dati------------------------------
  else if (mode == 2){
    i2c_eeprom_write_byte(0x50, 0, 0);
    delay(5);
    i2c_eeprom_write_byte(0x50, 1, 0);
    delay(5);
  }
  //Fine cancellamento dati---------------------------

  delay(25);
}

void erasevar(){
  //Azzero variabili
  indirizzo = 2; //Parte da due perchè i primi due BYTE sono per la memorizzazioni del N° scritture;
  data_gg = 0;
  data_mm = 0;
  data_yy = 0;
  soldi = 0;
  totale = 0;
  datiscritti = 0;
  datiscrittiLSB = 0;
  datiscrittiMSB = 0;
}

 

Ecco il link per il download del programma: http://www.fileserve.com/file/yGHyfyF/Banca dati.rar

 

Devo fare anche qualche piccola precisazione, gli elementi, una volta letti, non vengono ordinati per data ma semplicemente per ordine di inserimento, devo anche anche aggiungere che non ho inserito alcun tipo di controllo sui TextBox dunque eventi come l’inserimento di lettere al posto della data possono generare errori nel programma.

 

P.S.

Non mi è possibile rendere pubblici tutti i file di codice sorgente del programma in C#.

 

Banca dati, Arduino & EEPROM <-> PC
Tags: