contachilometri digitale GLCD

Ciao a tutti! sono nuovo del forum, tuttavia seguo arduino da ormai da un anno, tutto grazie alle riviste di elettronica e soprattutto al mio ex professore di elettronica con cui abbiamo fatto 2 robottini :slight_smile: arduino mi è subito piaciuto dal primo momento, avendo avuto qualche esperienza di PIC ho notato quanto era facile utilizzarlo senza essere esperti di informatica o senza conoscere per forza tutta l'architettura del microprocessore, grazie alle numerose librerie a disposizione... detto questo vi illustro il mio progetto, un contachilometri digitale che calcola: velocità, massima velocità fatta , Km percorsi parziali e totali, tempo di utilizzo parziale e totale... non ho trovato applicazioni simili quindi mi son deciso di farne uno per un vecchio motorino che sto restaurando...
ho utilizzato sempicemente un display GLCD compatibile KS108 e un reed switch preso da un contaKm di una bici ed ovviamente ARDUINO! 8) , per calcolare gli impulsi ho usato una soluzione trovata sul mio libro di arduino ( molto utile ) di usare il contatore sul timer1 sul piedino 5 per contare gli impulsi senza interrompere il programma o senza gli interrupt..... ho dovuto semplicemente spostare un collegamento nella libreria del GLCD... forse è meglio che vi faccio vedere lo sketch, mi servirebbe una mano da chi ha piu esperienza di me per migliorare lo stile del codice, semplificare le istruzioni per risparmiare memoria... insomma qualsiasi consiglio! XD per adesso metto solo il main dello sketch per questioni di lunghezza del messaggio non mi lascia pubblicare...

/************sketch arduino contachilometri digitale************\
 ***********************Luca Bizzotto, 4 TNA**********************
 * in questo sketch viene usato un Display Grafico per realizzare
 * un contachilometri digitale, si utilizza il pin digitale 5 
 * il quale è collegato al Timer1 dell'ATmega, dopo averlo impostato
 * esso può essere usato come contatore di impulsi, senza utilizzare
 * interrupt e senza interrompere il programma... 
 */


#include "glcd.h"                   // includo le librerie necessarie
#include "fonts/allFonts.h"        //  allo sketch
#include "bitmaps/allBitmaps.h"   //
#include "Time.h"                //
#include "EEPROM.h"             //

unsigned long KmPrecedentiDec = 0;      // dichiaro le variabili necessarie 
unsigned long KmPercorsiDec = 0;       //  
unsigned long KmTotaliDec = 0;        //
unsigned int  MaxSpeed = 0;          //
unsigned int  velocityDec = 0;      //
unsigned int  impulsi = 0;         //  
unsigned int  oreTotali = 0;      //
unsigned int  minutiTotali = 0;  //
unsigned int  oreTot = 0;       //
unsigned int  minutiTot = 0;   // 
boolean count = true;         //
float velocity = 0.0;        //
float KmTotali = 0.0;       //
float KmPercorsi = 0.0;    //
gText KmH;                // definisco aree di testo del display che 
gText KmT;               //  in seguito verranno utilizzate
gText KmP;              //
gText TT;              //
gText TP;             //
gText MXS;           // 

const byte EEPROM_ID = 0x99;      // si assegna un ID per in seguito si verifica
const int ID_ADDR = 0;           // se la EEPROM è stata già programmata
byte id = EEPROM.read(ID_ADDR); // legge il valore esistente nella EEPROM


void setup() {                          

  if (id != EEPROM_ID)                 // se è diverso da quello che ci si aspettava
    EEPROM.write(ID_ADDR, EEPROM_ID); // vuol dire che non lo avevamo scritto, allora scrivi...

  GLCD.Init(NON_INVERTED);              // inizializza il GLCD
  GLCD.DrawBitmap(motron, 0,0);        //  disegna la scritta iniziale,
  delay(2000);                        //   la tiene per 2 sec poi parte il prog

  Serial.begin(9600);  
  setTime(0,0,0,1,1,12);            // setta l'ora alle 00:00:00 del 1/1/12
                                   // a noi interesserà il delta del tempo trascorso

  digitalWrite(5, HIGH);                     // si inizializza il contatore 
  TCCR1A = 0;                               //
                                           //
  AvviaConteggio();                       //
                                         //
                                        //
  GLCD.ClearScreen();                  //  cancella le scritte precedenti
  GLCD.SelectFont(Arial_bold_14);     //   seleziona il carattere arial Bold
  GLCD.CursorToXY(94, 35);           //    sposta il cursore nella pos X 94 Y 32
  GLCD.print("Km/h");               //     scrive alcune scritte statiche
  GLCD.SelectFont(SystemFont5x7);  //      che rimarranno scritte sul display
  GLCD.CursorToXY(2, 2);          //
  GLCD.print("TP");              //
  GLCD.CursorToXY(67, 2);       //
  GLCD.print("TT");            //
  GLCD.CursorToXY(2, 30);     //
  GLCD.print("MXS");         //
  GLCD.CursorToXY(67, 55);  //        
  GLCD.print("KMT");       //        
  GLCD.CursorToXY(2, 55); //        
  GLCD.print("KMP");     //          



  KmTotali = readLong(1);        // carica i valori precedentemente salvati
  MaxSpeed = readInt(5);       //  nella EEPROM e li carica nelle corrispondenti
  oreTotali = readInt(7);     //   variabili...
  minutiTotali = readInt(9);

}
void loop() {

  impulsi = AvviaConteggio();                            // salva gli impulsi nel registro ed al contempo                               
                                                        //  resetta il conteggio, che conterà in contemporanea
  Serial.println();                                    //   al programmma
  //Serial.println(millis());
  //Serial.println(impulsi);
  velocity = (impulsi * 0.05);                       // moltiplico gli impulsi per la distanza in M percorsa dalla ruota 
  KmPercorsi = (KmPercorsi + (velocity/1000));     // divido la velocità per 1000 in modo da convertire in Km
  KmTotali = ( KmTotali + (velocity/1000));       // e la sommo ai km fatti precedentemente
  velocityDec = (velocity * 3.6);                // ora da M/s diventano KM/H

  StampaVelocita(velocityDec);                 // scrivo sul display la velocità a cui sto andando

  if (velocityDec > MaxSpeed)                // se la velocità istantanea è maggiore di quella massima mai fatta
    MaxSpeed = velocityDec;                 // diventa la nuova velocità massima

  if (count == true){                     // se la variabile è vera
    KmPrecedentiDec = KmPercorsiDec;     //  salvo nella variabile KmPrecedenti i km percorsi
    count = false;                      //   metto count false in modo da non tornare qui e riscrivere
    Serial.println("salva km prec");
    Serial.println(KmPrecedentiDec);
  }
 
  if((KmPercorsiDec - KmPrecedentiDec) >=  1){    // se è passato un chilometro 
        writeInt(KmTotaliDec, 1);                   //  scrivo tutti i valori nella EEPROM
        writeInt(MaxSpeed, 5);
        writeInt((oreTot), 7);
        writeInt((minutiTot), 9);
        //writeLong(0, 1);                   //  scrivo tutti i valori nella EEPROM
        //writeInt(0, 5);
        //writeInt(0, 7);
        //writeInt(0, 9);
    count = true;
    
  }


  KmPercorsiDec = KmPercorsi;                    // mettendo una variabile FLOAT in una INT si salva solo 
  KmP.DefineArea(22, 55, 6, 1, SystemFont5x7);  //  la parte dec intera del numero 
  KmP.print(KmPercorsiDec);                    //   scrivo i dati sul display
  // Serial.println(decimale);

  KmTotaliDec = KmTotali;                        // definisco un area che parte da X 87 Y 55 PIXEL che è fatta                  
  KmT.DefineArea(87, 55, 6, 1, SystemFont5x7);  // da 6 caratteri e una colonna...        
  KmT.print(KmTotaliDec);                      // e scrivo i valori dentro di essa        
  Serial.println(KmTotaliDec);                 


  TP.DefineArea(16, 2, 6, 1, SystemFont5x7);    // definisco un area che parte da...   
  minuti(minute(), TP);                        //  chiamo la funzione con il tempo trascorso che poi  
  ore(hour(), TP);                            //   verrà scritto sul display

  oreTot = (oreTotali + hour());             // sommo il tempo precedentemente fatto con quello istantaneo
  minutiTot = (minutiTotali + minute());    // 

  if (minutiTot >= 60){                    // se minutiTot è maggiore di 59 lo devo sottrarre a 60, incrementare
    minutiTot = minutiTot - 60;     //  di un ora e quello che rimane sono i minuti
    ++oreTot;
  }

  TT.DefineArea(81, 2, 6, 1, SystemFont5x7);   // scrivo il tempo totale sul display   
  minuti(minutiTot, TT); 
  ore(oreTot, TT );
  // Serial.println(hour());
  // Serial.println(minute());

  MXS.DefineArea(22, 30, 6, 1, SystemFont5x7); // definisco l'area MXS
  MXS.print(MaxSpeed);                        //  e ci scrivo la velocità massima mai fatta..

  delay(984);                               // ritardo di un secondo da una misura di impulsi e l'altra
}                                          //  le istruzioni anche se di poco ritardano il programma quindi  
                                          //   per avere un secondo totale devo ritardare un pò meno di 1 sec

Benevento e complimenti

io adesso sto aspettando un modulo a colori e con touch screen, mi potresti passareil tuo codice che vorrei fare una versione tft+touch a 3,2 pollici?

Ciao, bel lavoretto ed anche utile, complimenti :grin:

cece99:
io adesso sto aspettando un modulo a colori e con touch screen, mi potresti passareil tuo codice che vorrei fare una versione tft+touch a 3,2 pollici?

certo! solo che siccome sono nuovo non so bene come fare... intanto posto le due parti mancanti dello sketch si fa così?

parte EEPROM:

 void writeInt (unsigned int intero, int INTERVAL_ADDR)  // la chiamata accetta il valore long e l'indirizzo in cui salvare
{

  byte loByte, hiByte;                                   // dichiara le variabili
  hiByte = highByte(intero);                        //  salva la word + significativa
  loByte = lowByte(intero);                        //   salva la word - significativa
  EEPROM.write(INTERVAL_ADDR, hiByte);               // la salva nell indirizzo indicato
  EEPROM.write(INTERVAL_ADDR+1, loByte);            // salva l'altro pezzo un indirizzo piu avanti
}
 
  unsigned int readInt(int INTERVAL_ADDR)       // ammette l'indirizzo in cui leggere
 {
   byte loByte, hiByte;                          // dichiara le variabili
   hiByte = EEPROM.read(INTERVAL_ADDR);        //  va a leggere la word + significativa
   loByte = EEPROM.read(INTERVAL_ADDR+1);     //   va a leggere la word - significativa
  
   unsigned int intero = word(hiByte, loByte);
   return intero;  // e la ritorna...
 }


void writeLong (unsigned long longValue, int INTERVAL_ADDR)  // la chiamata accetta il valore long e l'indirizzo in cui salvare
{
  #define  highWord(W) ((W) >> 16)                          // questo serve per dividere il long in due word per poi salvarlo
  #define  lowWord(W) ((W) & 0xffff)                       //  in due diverse posizioni della memoria
  

  int loWord, hiWord;                                   // dichiara le variabili
  hiWord = highWord(longValue);                        //  salva la word + significativa
  loWord = lowWord(longValue);                        //   salva la word - significativa
  writeInt(hiWord, INTERVAL_ADDR);               // la salva nell indirizzo indicato
  writeInt(loWord, INTERVAL_ADDR+2);          // salva l'altro pezzo un indirizzo piu avanti
}
 
 
  unsigned long readLong(int INTERVAL_ADDR)       // ammette l'indirizzo in cui leggere
 {
   int loWord, hiWord;                          // dichiara le variabili
   hiWord = readInt(INTERVAL_ADDR);        //  va a leggere la word + significativa
   loWord = readInt(INTERVAL_ADDR+2);     //   va a leggere la word - significativa
  
   unsigned long longValue = (((long)hiWord) << 16 | (loWord)); // ricompone la nostra variabile long

   return longValue;  // e la ritorna...
 }

Contatore:

unsigned int conteggio;            // dichiaro la variabile  
 
unsigned int AvviaConteggio()   
{
  TCCR1B = 0;                   // fermo il conteggio
  conteggio = TCNT1;           //  salvo gli impulsi contati
  TCNT1 = 0;                  //   resetto il contatore 

  bitSet(TCCR1B, CS12);     // la sorgente di Counter Clock è un pin esterno
  bitSet(TCCR1B, CS11);    //  clock sul fronte di salita
  bitSet(TCCR1B, CS10);   

  return conteggio;      // ritorna con il conteggio

}

void minuti(int cifra, gText T) {   // la chiamata ammette la cifra da scrivere e il nome della 
                                   //  porzione di display da usare
T.CursorToXY(13,0);               //   sposta il cursore di 13 pixel dall'area di cui si sta parlando 
T.print(":");                    //    mette i : per il tempo

if (cifra < 10){               // se la cifra è minore di 10
  T.CursorToXY(19,0);         //  devo metterci lo zero davanti
  T.print("0");
  T.CursorToXY(25,0);       // e poi scrivo la cifra
  T.print(cifra);
}
else { 
  
  T.CursorToXY(19,0);   // sennò la scrivo semplicemente
  T.print(cifra);
}
}

  
void ore(int cifra, gText T){ // vedere sopra...


if (cifra < 10){
  T.CursorToXY(0,0);
  T.print("0");
  T.CursorToXY(6,0);
  T.print(cifra);
}
else { 
  
  T.CursorToXY(0,0);
  T.print(cifra);
}
}

void StampaVelocita(unsigned int decimale){            // la chiamata ammette un valore intero
    
  if(decimale < 10){                                 // se questo è minore di 10
 
  KmH.DefineArea(43, 18, 2 ,1, fixednums15x31);    // pulisco l'area delle 2 cifre significative
  KmH.ClearArea(); 
  KmH.DefineArea(75, 18, 1 ,1, fixednums15x31);  // mentre qui vado + in fondo, 1 sola cifra e sovrascrivo
  KmH.print(decimale);
                                                // PS tutto questo serve per evitare quel fastidioso          
  }                                            // refresh che si ha se si usa continuamente ClearArea
                                              // basta sovrapporre il num su quello esistente...
                                             //  ma se la cifra è 2 mentre quella scritta è 124 io devo cancellare 1 e 2   
  else if(decimale < 100){                  // e sovrascrivere il 2 sul 4... capito?             
 
  KmH.DefineArea(43, 18, 1 ,1, fixednums15x31);  // si ripete la questione
  KmH.ClearArea();
  KmH.DefineArea(59, 18, 2 ,1, fixednums15x31);
  KmH.print(decimale);
  }
 
 else {
 
  KmH.DefineArea(43, 18, 3 ,1, fixednums15x31);
  KmH.print(decimale);
  }
  }

penso che sia un pò confuso il mio stile di programmazione, magari se qualcuno mi dice cosa ne pensa se si capisce o no...