giovedì 22 maggio 2014

Cronometro Rubik

Cronometro per Cubo di Rubik

Questo post nasce da un'idea di Gladiorosso, un appassionato del cubo di Rubik.

Un grazie ad Adriano che ha revisionato e corretto lo sketch. 

Questo cronometro servirà a verificare il tempo impiegato per risolvere il cubo.

 



Vediamo le caratteristiche del cronometro:

Visualizza e conteggia su 6 ( sei) display a 7 segmenti, minuti, secondi e centesimi di secondo.

Un pulsante di Start e di Stop conteggio.

E' possibile alimentarlo con batteria o da USB.

Questo il materiale occorrente:
Arduino UNO
-------------------------------------------------
n.6 -  Display 7 segmenti a catodo comune. 
(Io ho utilizzato questi ):
WD05212AUR-20.
VR = 5 V
IAF = 25mA
-------------------------------------------------
 n. 6 - Transistor NPN BC547.
n. 7 - resistenze da 560 omm.
n. 6 - resistenze da 1.2k.
un pulsante normalmente aperto.
una resistenza da 10k.
una resistenza da 100 omm.
un condensatore ceramico da 100nF.
materiale per collegamenti e o basette forate.
Eventuale uleriore pulsante per il reset.
Se si desidera l'alimentazione a batteria, un interruttore, un contenitore per pacco batterie, e attacco per alimentazione su arduino.

Questo lo schema dei collegamenti:



Come si puo subito notare lo schema non è una novità, lo stesso è stato già pubblicato su questo blog (primi passi) il 21 Settembre 2012. 

Programma che realizza il Multiplexing.

La novità è nello sketch:

Ho dovuto infatti rivedere il precedente lavoro che non riusciva a visualizzare e nello stesso tempo conteggiare il tempo in modo corretto.
La revisione software è stata fatta da Adriano che ha reso la funzione " visualizzaNumero ", più semplice e più efficiente.
Eseguite queste correzioni, estesa l'operatività a 6 display anzichè quattro, ecco che è stato semplice realizzare il cronometro.
La funzione " visualizzaNumero " è interessante perchè applicabile anche per altri lavori: Occorre passare un numero intero nel nostro caso per 6 display utilizziamo unsigned long .

Dallo sketch qui sotto potrete vedere come funziona.

 Nel nostro caso il numero che passeremo è composto dalla sommatoria dei centesimi, secondi e minuti.
//------------------------------------------------------------------------------//

   // compone n da visualizzare
   unsigned long n = ( centesimi + (secondi*100) + (minuti*10000));
   visualizzaNumero(n);
   //-----------------------------------------------------------------------------


la visualizzaNumero(n); provvede a visualizzarlo con 6 display a 7 segmenti.

Lo sketch qui sotto è ampiamente commentato, il funzionamento di base è  spiegato anche nel post (primi passi ) pubblicato il 14 otobre 2012.

Io ho eseguito un prototipo su basetta forata ( 7x9) , non è un lavoro molto semplice meglio sarebbe fare un circuito stampato.

Ho previsto un pulsante.

Ho utilizzato la   void Pulsante () è una procedura già collaudata in altri sketch con pulsanti su questo blog. In ogni caso è commentata anche in questo sketch.

Il cronometro:

Nel nostro caso  dopo l'accensione di Arduino, viene eseguita una funzione di controllo che visualizza il numero 888888.

1) Eseguita una sola volta questa funzione si mette in attesa dello start visualizzando i sei segmenti centrali di ogni display.
2) Alla pressione del tasto esegue lo "START" parte il conteggio del tempo che viene visualizzato, con la visualizzaNumero
3) Con la seconda pressione del tasto si esegue lo "STOP",  termina il conteggio e viene visualizzato il tempo impiegato.

4) Ad una terza pressione del tasto si si torna al punto (1) pronti per altro conteggio.

Per avere un'alimentazione a batteria basterà alimentare Arduino con un pacco batterie (eventualmente interrotto da normale interruttore).

 lo sketch

/*
//--------------------------------------------------------------------------//
//********************************
  Sergio  & Adiano Prenleloup
 ********************************* 
 ***cronometro 6 display  ********
 *********  RUBIK   **************
 *** Versione 1.05 ***************
 ****** 22/05/2014 ***************
 *********************************

//--------------------------------------------------------------------------//

/* Programma che realizza il Multiplexing.
Invo bit alto ai pin corrispondenti ai segmenti a,b,c,d,e,f,g.
Si accendono inviando bit alto alle unità, poi, alle decine, centinaia,
migliaia, decine di migliaia, centinaia di migliaia.
//--------------------------------------------------------------------------//
Questa versione visualizza i centesimi di secondo, i secondi ed i minuti.
Realizzando un cronometro con start e stop tramite pulsante.
Allo start si avvia il conteggio (che viene visualizzato), allo STOP
si ferma il conteggio e si mostra il risultato.

Si utilizza la funzione millis per calcolare il tempo.
//--------------------------------------------------------------------------//


*/
const int MUXDELAY = 100; // tempo in microsecondi per multiplexing

// corrispondenza pin Unità, Decine, Centinaia, Migliaia
// con questi pin si comanda la base del transistor
// collegato al catodo comune del display

int Unit = 8;      // pin digitale unità
int Deci = 9;      // pin digitale decine
int Cent = 10;     // pin digitale centinaia
int Mill = 11;     // pin digitale migliaia
int DecMill = 12;  // pin digitale decine di migliaia
int CenMill = 13;  // pin digitale centinaia di migliaia



// corrispondenza segmenti display con pin
//-----------------------------------------
// Occorre rispettare la corrispondenza
// segmento pin associato come tabella.
// Altrimenti occorre apportare le opportune
// modifiche alle righe qui sotto.

int segA = 4;
int segB = 3;
int segC = 2;
int segD = 1;
int segE = 0;
int segF = 5;
int segG = 6;


//Associazione tra segmenti e pin arduino

int tabSegmentiPin[7] = {
  4, //seg a
  3, //seg b
  2, //seg c
  1, //seg d
  0, //seg e
  5, //seg f
  6  //seg g
};


//Associazione tra numeri rappresentabili e segmenti da accendere
int tabNumeriSegmenti[10][7] = 
{ 
 //a,b,c,d,e,f,g
  {1,1,1,1,1,1,0},  //zero
  {0,1,1,0,0,0,0},
  {1,1,0,1,1,0,1},
  {1,1,1,1,0,0,1},
  {0,1,1,0,0,1,1}, //quattro
  {1,0,1,1,0,1,1},
  {1,0,1,1,1,1,1},  
  {1,1,1,0,0,0,0},
  {1,1,1,1,1,1,1},
  {1,1,1,1,0,1,1}  //nove
};

//--------------------------------------------------------------------------//

//variabili del tempo di start e di stop
// si utilizzano per la lettura del tempo con millis()
unsigned long TempoStart = 0;
unsigned long TempoStop = 0;

//--------------------------------------------------------------------------//
// gestione pulsante
//
int Button = 7; // pin pulsante
// variabili gestione pulsante
int StatoPulsante = 0;
int old_Stato = 0;
int OnOff = 0; // cambia di stato ad ogni pressione del pulsante

//--------------------------------------------------------------------------//

void setup()
{
  

  pinMode (Button,INPUT); 
//---------------------------------  
  pinMode (segA, OUTPUT);
  pinMode (segB, OUTPUT);
  pinMode (segC, OUTPUT);
  pinMode (segD, OUTPUT);
  pinMode (segE, OUTPUT);
  pinMode (segF, OUTPUT);  
  pinMode (segG, OUTPUT);
//-------------------------------
  pinMode (Unit, OUTPUT);
  pinMode (Deci, OUTPUT);
  pinMode (Cent, OUTPUT);  
  pinMode (Mill, OUTPUT);
  pinMode (DecMill, OUTPUT);
  pinMode (CenMill, OUTPUT);
 //------------------------------- 
  digitalWrite (Unit, LOW);
  digitalWrite (Deci, LOW);
  digitalWrite (Cent, LOW);
  digitalWrite (Mill, LOW);
  digitalWrite (DecMill, LOW);
  digitalWrite (CenMill, LOW);
//--------------------------------  
  // controllo display
  // 
 start();  // si visualizza 888888
}
//-----------------------------------------
// fine setup
//-----------------------------------------

 
 //------------------------------------------------------------//
// Inizio loop
//------------------------------------------------------------//
void loop()
{
  TempoStop = 0; // azzero stop tempo
  OnOff = 0;   // azzero pressione tasto
  nonumero();  // visualizzo segmenti centrali
  spegniCifre(); // spengo le cifre
  //-------------------------------------------------------------// 
  Pulsante();   // attendo la pressione del pulstante per start
  
  if (OnOff == 1) // attesa di partenza conteggio
  {
    // E' partito il conteggio
    TempoStart = millis();  // memorizza inizio del conteggio
    while (OnOff == 1)
    {
      Conteggio();  // conteggia e visualizza minuti e secondi
      Pulsante();   // fino alla pressione del pulsante
    }
   //-----------------------------------------------------------// 
    // blocca il tempo di Stop
    TempoStop = millis();
    // visualizza il risultato fino alle pressione del tasto 
    while (OnOff == 0)
    {      
      VediStop();  // visualizza il risultato
      Pulsante();  // fino alle pressione del tasto
    }
  }
 // torna a loop  
} 
//-------------------------------------------------------------//   
// End loop principale
//-------------------------------------------------------------//




//--------------------------------------------//
// FUNZIONI 
//-------------------------------------------//
//-----------------------------------------
// Procedura di partenza
// si visualizza la cifra 8 su tutti i display
// per controllo
//-----------------------------------------
void start()
{
  unsigned long n = 888888;
  for (int i = 0; i < 1000; i++)
  {
   visualizzaNumero(n);
   delay(1);
   }
 
}
 
 //-------------------------------------------------------
 // accende i segmenti centrali in attesa di start conteggio
void nonumero()
{
  for (int i = 0; i < 6; i++)
  {
   digitalWrite(tabSegmentiPin[6], HIGH);
   digitalWrite (i+8, HIGH);
   delayMicroseconds (10);
    digitalWrite (i+8, LOW);
   }
  spegniSegmenti();
  
}
 
  
//-----------------------------------------------
// Prepara quanto contento in TTS per mostrarlo
// in modo corretto con la funzione visualizzaNumero
// in TTS è contento il numero intero lungo dei millisecondi
// trascorsi dallo start al tempo attuale
// oppure al tempo di stop
//-------------------------------------------------------
void MostraTempo(unsigned long TTS) // in TTS è contenuto il tempo trascorso in millisecondi
{
   unsigned long millesimi = (TTS%1000); //contiene i millesimi trascorsi
   unsigned long sectr = (TTS /1000);   // contiene i secondi trascorsi
   unsigned long secondi = (sectr % 60); // contiene i secondi trascorsi in modulo 60
   unsigned long minuti = (sectr /60);   // contiene i minuti trascorsi
   unsigned long centesimi = (millesimi/10); // si prendono solo i centesimi
   
   // compone n da visualizzare
   unsigned long n = ( centesimi + (secondi*100) + (minuti*10000));
   visualizzaNumero(n);
   //-----------------------------------------------------------------------------
}

 //----------------------------------------
 // Conteggia e visualizza minuti e secondi
 // centesimi dal tempo di start  al tempo 
 // trascorso
 //----------------------------------------
 void Conteggio()
{ 
  unsigned long Tempo = millis() - TempoStart;
  MostraTempo(Tempo);
}

//-----------------------------------------------------
// conteggia e visualizza minuti, secondi e centesimi
// dal tempo di start al tempo di STOP
//----------------------------------------------------
void VediStop()
{
  unsigned long TTS = (TempoStop - TempoStart);
  MostraTempo(TTS);
}
//----------------------------------------------------- 

   
//----------------------------------------------------
// funzione che visualizza con il multiplexing il numero
// passato (unsigned long )
// visualizza unita, decine, centinaia ecc...
// utilizzando i sei display
// il numero viene prima scomposto in unità, decine centinaia ecc...
// quindi si accendono con le chiamate 
// alle singole subrutin le unità, decine, ecc...
//----------------------------------------------------
void visualizzaNumero(unsigned long numero)
{
 // scomposizione di numero
 // si scompone il numero che ogni display dovrà visualizzare.
 //----------------------------------------------------
  int u = numero % 10;
  int d = (numero / 10) % 10;
  int c = (numero / 100) % 10;
  int m = (numero / 1000) % 10;
  int dm = (numero / 10000) % 10;
  int cm = (numero / 100000) % 10;
  
  spegniCifre(); // si spengono tutte le cifre
  
  //-----------------------------------------------  
  // la serie di if accende le cifre necessarie
   if (numero > 99999)
   {
     accendiCenMill(cm);
     delayMicroseconds(MUXDELAY);
     digitalWrite (CenMill, LOW);
   }

   if (numero > 9999)
   {     
     accendiDecMill(dm);
     delayMicroseconds(MUXDELAY);
     digitalWrite (DecMill, LOW);
   }
  
   if (numero > 999)
   {
     accendiMigliaia(m);
     delayMicroseconds(MUXDELAY);
     digitalWrite (Mill, LOW);
   }
   
   if (numero > 99)
   {
     accendiCentinaia(c);
     delayMicroseconds(MUXDELAY);
     digitalWrite (Cent, LOW);     
   }

   if (numero > 9)
   {
      accendiDecine(d);
      delayMicroseconds(MUXDELAY);
      digitalWrite (Deci, LOW);     
   }
   
   accendiUnit(u); 
   delayMicroseconds(MUXDELAY);
   digitalWrite (Unit, LOW);        
}
  
//---------------------------------------------------------  
  
  
  //Funzione che spenge tutti i segmenti
void spegniSegmenti()
{
  digitalWrite (segA, LOW);
  digitalWrite (segB, LOW);
  digitalWrite (segC, LOW);
  digitalWrite (segD, LOW);
  digitalWrite (segE, LOW);
  digitalWrite (segF, LOW);
  digitalWrite (segG, LOW);
  
}
 // funzione che spegne tutte le cifre
void spegniCifre()
{
  digitalWrite (Unit, LOW);
  digitalWrite (Deci, LOW);
  digitalWrite (Cent, LOW);
  digitalWrite (Mill, LOW);
  digitalWrite (DecMill, LOW);
  digitalWrite (CenMill, LOW);
}

 // Funzione accendi tutti i segmenti
 
void accendiTuttiSegmenti()
{
  for (int i=0; i < 7; i++)
    digitalWrite (ottieniPin(i), HIGH);
}

//-----------------------------------------
// funzioni che accendono le cifre
//----------------------------------------
// Funzione Unità

void accendiUnit(int numUnita)
{
  spegniSegmenti();
  digitalWrite (Unit, HIGH);
  attivaSegmenti(numUnita); 
}
  
// Funzione Decine

void accendiDecine(int numDecine)
{
  spegniSegmenti();
  digitalWrite (Deci, HIGH);
  attivaSegmenti(numDecine);
}
  
   
// Funzione Centinaia

void accendiCentinaia(int numCentinaia)
{
  spegniSegmenti();
  digitalWrite (Cent, HIGH);
  attivaSegmenti(numCentinaia);

} 
// Funzione Migliaia

void accendiMigliaia(int numMigliaia)
{
  spegniSegmenti();
  digitalWrite (Mill, HIGH);
  attivaSegmenti(numMigliaia);

  } 
  
  // funzione decine di migliaia
  void accendiDecMill(int numDecMill)
{
    spegniSegmenti();
  digitalWrite (DecMill, HIGH);
  attivaSegmenti(numDecMill);
  
  } 
  
  // funzione centinaia di migliaia
  
  void accendiCenMill(int numCenMill)
{
    spegniSegmenti();
  digitalWrite (CenMill, HIGH); 
  attivaSegmenti(numCenMill);
  
  } 
 //-------------------------------------------------- 
    
  
//ritorna il pin associato al segmento passato
int ottieniPin(int seg)
{
  return tabSegmentiPin[seg];
}

//Attiva i segmenti necessari a mostrare il numero n passato
void attivaSegmenti(int n)
{
  for (int i=0; i< 7; i++)
  {
    int segAttivo = tabNumeriSegmenti[n][i];
    
    if (segAttivo == 1)
    {
      digitalWrite(ottieniPin(i), HIGH); 
    }
  }
}
//------------------------------------------------------------
// funzione che gesisce il pulsante
// alla pressione del pulsante
// OnOff passa da 0 a 1 e viceversa
// ad una successiva pressione
//------------------------------------------------------------
 void Pulsante ()
 {
 // legge il valore restituito dal pin e lo memorizza in StatoButton_1
  StatoPulsante = digitalRead (Button); 

// controlla se lo stato attuale è cambiato
if ((StatoPulsante == HIGH) && (old_Stato == LOW))    
   {
     delay (10); // antirimbalzo
     OnOff = 1 - OnOff;  // cambia se premuto
   }
   // mettiamo in oldStatoButton_1 il valore attuale
   old_Stato = StatoPulsante;    
 }    
 
//------------------------------------------------------------------------------------- 

 Qui sotto un breve filmato che dimostra il funzionamento:


Io non ho realizzato un prototipo definitivo penso che quanto esposto sopra possa essere sufficiente alla realizzazione di un Vostro prototipo.

Al prossimo post.

Aggiunta modifica per doppio pulsante START e STOP

Questo è il listato modificato si dovrà anche modificare lo schema aggiungendo un pulsante collegato al pin A0 come 14 digitale.


/*
//--------------------------------------------------------------------------//
//********************************
  Sergio  & Adiano Prenleloup
 ********************************* 
 ***cronometro 6 display  ********
 *********  RUBIK   **************
 *** Versione 1.06 ***************
 ****** 11-09-2015 ***************
 *nome = crono_Rubik_106_2_Puls **
 *********************************
// modifica fatta al 1.05 per
// utilizzo di 2 pulsanti
// uno di Start ed uno di Stop
// da un commento di Alw Sbo
// del 10/09/2015 
//--------------------------------------------------------------------------//

/* Programma che realizza il Multiplexing.
Invo bit alto ai pin corrispondenti ai segmenti a,b,c,d,e,f,g.
Si accendono inviando bit alto alle unità, poi, alle decine, centinaia,
migliaia, decine di migliaia, centinaia di migliaia.
//--------------------------------------------------------------------------//
Questa versione visualizza i centesimi di secondo, i secondi ed i minuti.
Realizzando un cronometro con start e stop tramite pulsante.
Allo start si avvia il conteggio (che viene visualizzato), allo STOP
si ferma il conteggio e si mostra il risultato.

Si utilizza la funzione millis per calcolare il tempo.
//--------------------------------------------------------------------------//


*/
const int MUXDELAY = 100; // tempo in microsecondi per multiplexing

// corrispondenza pin Unità, Decine, Centinaia, Migliaia
// con questi pin si comanda la base del transistor
// collegato al catodo comune del display

int Unit = 8;      // pin digitale unità
int Deci = 9;      // pin digitale decine
int Cent = 10;     // pin digitale centinaia
int Mill = 11;     // pin digitale migliaia
int DecMill = 12;  // pin digitale decine di migliaia
int CenMill = 13;  // pin digitale centinaia di migliaia



// corrispondenza segmenti display con pin
//-----------------------------------------
// Occorre rispettare la corrispondenza
// segmento pin associato come tabella.
// Altrimenti occorre apportare le opportune
// modifiche alle righe qui sotto.

int segA = 4;
int segB = 3;
int segC = 2;
int segD = 1;
int segE = 0;
int segF = 5;
int segG = 6;


//Associazione tra segmenti e pin arduino

int tabSegmentiPin[7] = {
  4, //seg a
  3, //seg b
  2, //seg c
  1, //seg d
  0, //seg e
  5, //seg f
  6  //seg g
};


//Associazione tra numeri rappresentabili e segmenti da accendere
int tabNumeriSegmenti[10][7] = 
 //a,b,c,d,e,f,g
  {1,1,1,1,1,1,0},  //zero
  {0,1,1,0,0,0,0},
  {1,1,0,1,1,0,1},
  {1,1,1,1,0,0,1},
  {0,1,1,0,0,1,1}, //quattro
  {1,0,1,1,0,1,1},
  {1,0,1,1,1,1,1},  
  {1,1,1,0,0,0,0},
  {1,1,1,1,1,1,1},
  {1,1,1,1,0,1,1}  //nove
};

//--------------------------------------------------------------------------//

//variabili del tempo di start e di stop
// si utilizzano per la lettura del tempo con millis()
unsigned long TempoStart = 0;
unsigned long TempoStop = 0;

//--------------------------------------------------------------------------//
// gestione pulsante (START) rimane uguale
//
int Button = 7; // pin pulsante
// variabili gestione pulsante
int StatoPulsante = 0;
int old_Stato = 0;
int OnOff = 0; // cambia di stato ad ogni pressione del pulsante

// gestione pulsante (STOP) ** linee aggiunte ***
//
int Button_Stop = 14; // Si utilizza A0 come digitale in quanto
                 // si sono utilizzati tutti gli altri pin digitali
// variabili gestione pulsante
int StatoPulsante_Stop = 0;
int old_Stato_Stop = 0;
int OnOff_Stop = 0; // cambia di stato ad ogni pressione del pulsante

// *** fine linee aggiunte

//--------------------------------------------------------------------------//

void setup()
{
  

  pinMode (Button,INPUT); // pulsante Start
  pinMode (Button_Stop,INPUT); // linea aggiunta puls STOP
  
//---------------------------------  
  pinMode (segA, OUTPUT);
  pinMode (segB, OUTPUT);
  pinMode (segC, OUTPUT);
  pinMode (segD, OUTPUT);
  pinMode (segE, OUTPUT);
  pinMode (segF, OUTPUT);  
  pinMode (segG, OUTPUT);
//-------------------------------
  pinMode (Unit, OUTPUT);
  pinMode (Deci, OUTPUT);
  pinMode (Cent, OUTPUT);  
  pinMode (Mill, OUTPUT);
  pinMode (DecMill, OUTPUT);
  pinMode (CenMill, OUTPUT);
 //------------------------------- 
  digitalWrite (Unit, LOW);
  digitalWrite (Deci, LOW);
  digitalWrite (Cent, LOW);
  digitalWrite (Mill, LOW);
  digitalWrite (DecMill, LOW);
  digitalWrite (CenMill, LOW);
//--------------------------------  
  // controllo display
  // 
 start();  // si visualizza 888888
}
//-----------------------------------------
// fine setup
//-----------------------------------------

 //------------------------------------------------------------//
// Inizio loop
//------------------------------------------------------------//
void loop()
{
  TempoStop = 0; // azzero stop tempo
  OnOff = 0;   // azzero pressione tasto
  //-------------------------------------
  // linea aggiunta
   OnOff_Stop = 0;   // azzero pressione tasto
  //-----------------------------------
  nonumero();  // visualizzo segmenti centrali
  spegniCifre(); // spengo le cifre
  //-------------------------------------------------------------// 
  Pulsante();   // attendo la pressione del pulstante per start
  
  if (OnOff == 1) // attesa di partenza conteggio
  {
    // E' partito il conteggio
    TempoStart = millis();  // memorizza inizio del conteggio
    while (OnOff == 1)
    {
      Conteggio();  // conteggia e visualizza minuti e secondi
      Pulsante_Stop();   // fino alla pressione del pulsante
                    // modificata per pulsante STOP
    }
   //-----------------------------------------------------------// 
    // blocca il tempo di Stop
    TempoStop = millis();
    // visualizza il risultato fino alle pressione del tasto 
    while (OnOff == 0)
    {      
      VediStop();  // visualizza il risultato
      Pulsante();  // fino alle pressione del tasto Start
    }
  }
 // torna a loop  
//-------------------------------------------------------------//   
// End loop principale
//-------------------------------------------------------------//




//--------------------------------------------//
// FUNZIONI 
//-------------------------------------------//
//-----------------------------------------
// Procedura di partenza
// si visualizza la cifra 8 su tutti i display
// per controllo
//-----------------------------------------
void start()
{
  unsigned long n = 888888;
  for (int i = 0; i < 1000; i++)
  {
   visualizzaNumero(n);
   delay(1);
   }
}
 //-------------------------------------------------------
 // accende i segmenti centrali in attesa di start conteggio
void nonumero()
{
  for (int i = 0; i < 6; i++)
  {
   digitalWrite(tabSegmentiPin[6], HIGH);
   digitalWrite (i+8, HIGH);
   delayMicroseconds (10);
    digitalWrite (i+8, LOW);
   }
  spegniSegmenti();
  
}
  
//-----------------------------------------------
// Prepara quanto contento in TTS per mostrarlo
// in modo corretto con la funzione visualizzaNumero
// in TTS è contento il numero intero lungo dei millisecondi
// trascorsi dallo start al tempo attuale
// oppure al tempo di stop
//-------------------------------------------------------
void MostraTempo(unsigned long TTS) // in TTS è contenuto il tempo trascorso in millisecondi
{
   unsigned long millesimi = (TTS%1000); //contiene i millesimi trascorsi
   unsigned long sectr = (TTS /1000);   // contiene i secondi trascorsi
   unsigned long secondi = (sectr % 60); // contiene i secondi trascorsi in modulo 60
   unsigned long minuti = (sectr /60);   // contiene i minuti trascorsi
   unsigned long centesimi = (millesimi/10); // si prendono solo i centesimi
   
   // compone n da visualizzare
   unsigned long n = ( centesimi + (secondi*100) + (minuti*10000));
   visualizzaNumero(n);
   //-----------------------------------------------------------------------------
}

 //----------------------------------------
 // Conteggia e visualizza minuti e secondi
 // centesimi dal tempo di start  al tempo 
 // trascorso
 //----------------------------------------
 void Conteggio()
  unsigned long Tempo = millis() - TempoStart;
  MostraTempo(Tempo);
}

//-----------------------------------------------------
// conteggia e visualizza minuti, secondi e centesimi
// dal tempo di start al tempo di STOP
//----------------------------------------------------
void VediStop()
{
  unsigned long TTS = (TempoStop - TempoStart);
  MostraTempo(TTS);
}
//----------------------------------------------------- 

   
//----------------------------------------------------
// funzione che visualizza con il multiplexing il numero
// passato (unsigned long )
// visualizza unita, decine, centinaia ecc...
// utilizzando i sei display
// il numero viene prima scomposto in unità, decine centinaia ecc...
// quindi si accendono con le chiamate 
// alle singole subrutin le unità, decine, ecc...
//----------------------------------------------------
void visualizzaNumero(unsigned long numero)
{
 // scomposizione di numero
 // si scompone il numero che ogni display dovrà visualizzare.
 //----------------------------------------------------
  int u = numero % 10;
  int d = (numero / 10) % 10;
  int c = (numero / 100) % 10;
  int m = (numero / 1000) % 10;
  int dm = (numero / 10000) % 10;
  int cm = (numero / 100000) % 10;
  
  spegniCifre(); // si spengono tutte le cifre
  
  //-----------------------------------------------  
  // la serie di if accende le cifre necessarie
   if (numero > 99999)
   {
     accendiCenMill(cm);
     delayMicroseconds(MUXDELAY);
     digitalWrite (CenMill, LOW);
   }

   if (numero > 9999)
   {     
     accendiDecMill(dm);
     delayMicroseconds(MUXDELAY);
     digitalWrite (DecMill, LOW);
   }
  
   if (numero > 999)
   {
     accendiMigliaia(m);
     delayMicroseconds(MUXDELAY);
     digitalWrite (Mill, LOW);
   }
   
   if (numero > 99)
   {
     accendiCentinaia(c);
     delayMicroseconds(MUXDELAY);
     digitalWrite (Cent, LOW);     
   }

   if (numero > 9)
   {
      accendiDecine(d);
      delayMicroseconds(MUXDELAY);
      digitalWrite (Deci, LOW);     
   }
   
   accendiUnit(u); 
   delayMicroseconds(MUXDELAY);
   digitalWrite (Unit, LOW);        
}
  
//---------------------------------------------------------  
  
  
  //Funzione che spenge tutti i segmenti
void spegniSegmenti()
{
  digitalWrite (segA, LOW);
  digitalWrite (segB, LOW);
  digitalWrite (segC, LOW);
  digitalWrite (segD, LOW);
  digitalWrite (segE, LOW);
  digitalWrite (segF, LOW);
  digitalWrite (segG, LOW);
  
}
 // funzione che spegne tutte le cifre
void spegniCifre()
{
  digitalWrite (Unit, LOW);
  digitalWrite (Deci, LOW);
  digitalWrite (Cent, LOW);
  digitalWrite (Mill, LOW);
  digitalWrite (DecMill, LOW);
  digitalWrite (CenMill, LOW);
}

 // Funzione accendi tutti i segmenti
void accendiTuttiSegmenti()
{
  for (int i=0; i < 7; i++)
    digitalWrite (ottieniPin(i), HIGH);
}

//-----------------------------------------
// funzioni che accendono le cifre
//----------------------------------------
// Funzione Unità

void accendiUnit(int numUnita)
{
  spegniSegmenti();
  digitalWrite (Unit, HIGH);
  attivaSegmenti(numUnita); 
}
  
// Funzione Decine

void accendiDecine(int numDecine)
{
  spegniSegmenti();
  digitalWrite (Deci, HIGH);
  attivaSegmenti(numDecine);
}
  
   
// Funzione Centinaia

void accendiCentinaia(int numCentinaia)
{
  spegniSegmenti();
  digitalWrite (Cent, HIGH);
  attivaSegmenti(numCentinaia);

// Funzione Migliaia

void accendiMigliaia(int numMigliaia)
{
  spegniSegmenti();
  digitalWrite (Mill, HIGH);
  attivaSegmenti(numMigliaia);

  } 
  
  // funzione decine di migliaia
  void accendiDecMill(int numDecMill)
{
    spegniSegmenti();
  digitalWrite (DecMill, HIGH);
  attivaSegmenti(numDecMill);
  
  } 
  
  // funzione centinaia di migliaia
  
  void accendiCenMill(int numCenMill)
{
    spegniSegmenti();
  digitalWrite (CenMill, HIGH); 
  attivaSegmenti(numCenMill);
  
  } 
 //-------------------------------------------------- 
    
  
//ritorna il pin associato al segmento passato
int ottieniPin(int seg)
{
  return tabSegmentiPin[seg];
}

//Attiva i segmenti necessari a mostrare il numero n passato
void attivaSegmenti(int n)
{
  for (int i=0; i< 7; i++)
  {
    int segAttivo = tabNumeriSegmenti[n][i];
    
    if (segAttivo == 1)
    {
      digitalWrite(ottieniPin(i), HIGH); 
    }
  }
}
//------------------------------------------------------------
// funzione che gestisce il pulsante
// alla pressione del pulsante
// OnOff passa da 0 a 1 e viceversa
// ad una successiva pressione
//------------------------------------------------------------
 void Pulsante ()
 {
 // legge il valore restituito dal pin e lo memorizza in StatoButton_1
  StatoPulsante = digitalRead (Button); 

// controlla se lo stato attuale è cambiato
if ((StatoPulsante == HIGH) && (old_Stato == LOW))    
   {
     delay (10); // antirimbalzo
     OnOff = 1 - OnOff;  // cambia se premuto
   }
   // mettiamo in oldStatoButton_1 il valore attuale
   old_Stato = StatoPulsante;    
 }    
//-------------------------------------------------------------------------------------
 //------------------------------------------------------------
// funzione che gestisce il pulsante di STOP
// E' del tutto identica alla precedente
// si cambiano solo i nomi *_Stop
//------------------------------------------------------------
 void Pulsante_Stop ()
 {
 // legge il valore restituito dal pin e lo memorizza in StatoButton_1
  StatoPulsante_Stop = digitalRead (Button_Stop); 

// controlla se lo stato attuale è cambiato
if ((StatoPulsante_Stop == HIGH) && (old_Stato_Stop == LOW))    
   {
     delay (10); // antirimbalzo
     OnOff_Stop = 1 - OnOff_Stop;  // cambia se premuto
   }
   // mettiamo in oldStatoButton_1 il valore attuale
   old_Stato_Stop = StatoPulsante_Stop;    
 }    
//-------------------------------------------------------------------------------------

14 commenti:

  1. ciao finalmente sono riuscito a replicare il tuo circuito e funziona perfettamente =) ora vorrei modificare lo sketch in modo che conti in formato secondi-minuti-ore (HH:MM:SS) dove devo intervenire ?
    Ti ringrazio per la tua disponibilità! a presto!

    RispondiElimina
    Risposte
    1. Per ottenere i tempi ore, minuti, secondi puoi sostituire la "MostraTempo", vedi qui sotto
      Non ho collaudato a lungo le modifiche ma dovrebbe funzionare bene.
      Fammi sapere
      //-----------------------------------------------
      // Prepara quanto contento in TTS per mostrarlo
      // in modo corretto con la funzione visualizzaNumero
      // in TTS è contento il numero intero lungo dei millisecondi
      // trascorsi dallo start al tempo attuale
      // oppure al tempo di stop
      //-------------------------------------------------------
      void MostraTempo(unsigned long TTS) // in TTS è contenuto il tempo trascorso in millisecondi
      {
      /* Versione originale
      unsigned long millesimi = (TTS%1000); //contiene i millesimi trascorsi
      unsigned long sectr = (TTS /1000); // contiene i secondi trascorsi
      unsigned long secondi = (sectr % 60); // contiene i secondi trascorsi in modulo 60
      unsigned long minuti = (sectr /60); // contiene i minuti trascorsi
      unsigned long centesimi = (millesimi/10); // si prendono solo i centesimi

      unsigned long n = ( centesimi + (secondi*100) + (minuti*10000));
      */


      // versione modificata ----------------------------------------------------------
      unsigned long millesimi = (TTS%1000); //contiene i millesimi trascorsi
      unsigned long sectr = (TTS /1000); // contiene i secondi trascorsi
      unsigned long secondi = (sectr % 60); // contiene i secondi trascorsi in modulo 60
      //-------------------------------------------------------------------
      // linee aggiunte per conteggiare secondi, minuti, ore
      unsigned long minutitr = (sectr /60); // contiene i minuti trascorsi
      unsigned long minuti = (minutitr % 60); // minuti trascorsi modulo 60
      unsigned long ore = (( minutitr/60) % 24); // ore trascorse modulo 24
      //-------------------------------------------------------------------
      // compone n da visualizzare
      unsigned long n = ((secondi) + (minuti*100)+ (ore*10000));
      visualizzaNumero(n);
      //-----------------------------------------------------------------------------
      }

      // fine parte modificata

      Ti saluto
      Sergio

      Elimina
  2. è possibile chiedere qualche modifica?

    RispondiElimina
    Risposte
    1. Penso di si descrivi nei dettagli cosa proponi.
      Sergio

      Elimina
  3. Ciao volevo proporti e chiederti se fattibile queste modifica:
    memorizzare all interno di variabili che vengono fatti ogni sessione prima di uno spegnimento del prototipo ad esempio faccio
    5 soluzioni del cubo con diversi tempi...memorizzare questi 5 tempi ed estrapolare migliore e peggiore visualizzandoli in maniera fissa su
    2 serie di micro display sempre 7segmenti ad esempio verde (tempo migliore) rosso (tempo peggiore) idem se faccio n-solve visualizzare sempre
    il migliore e il peggiore, poi con un pulsante di reset azzerare tutti i display. Posso immaginare che la soluzione sia immagazzinare ad ogni stop conteggio il tempo in delle variabili
    che man mano poi con un ciclo for si confrontano tra loro e il migliore/peggior tempo vengono visualizzati. ( il top sarebbe anche la visualizzazione della media dei tempi ma forse oso troppo...)
    Ho notato poi che quando parte u nconteggio e si ferma col pulsante il tempo scompare dal display per rivederlo bisogna premere un altra volta il pulsante. si puo evitare la doppia pressione e vedere il tempo appena si preme lo stop conteggio.
    Che ne pensi si puo fare o è impossibile?

    RispondiElimina
    Risposte
    1. Ciao!
      Sono in un periodo con molti impegni e non ho tempo da dedicare all'elettronica, l'ultimo post pubblicato è di Gennaio.
      Con il progetto attuale si utilizzano tutti i pin digitali dallo 0 al 13, rimangono liberi solo i pin analogici, si potrebbero utilizzare come digitali ma in ogni caso sono insufficienti per quello che chiedi.

      Quello che chiedi è realizzabile ma con un nuovo progetto e con nuovo materiale, vedi post orologio scacchi.
      Si può provare ad aggiungere un commutatore ed alcuni led di colore diverso, e quindi selezionando con il commutatore si visualizzi il tempo attuale, il tempo migliore, il peggiore, con i led che fanno da guida.
      Si potrebbe rifare il progetto con un display LCD magari a 4 linee e su ogni linea si visualizza il tempo desiderato, logicamente in sostituzione dei 7 segmenti perché anche il display a bisogno di alcuni pin digitali.
      Altra soluzione potrebbe essere un LCD seriale I2C in questo caso avremmo disponibili i 2 pin necessari ( non ho in questo momento un LCD di questo tipo quindi non posso fare delle prove)
      Come ti ho spiegato all'inizio non ho molto tempo, se trovo il tempo cerco di fare qualcosa di semplice, poi vedremo...
      Ti saluto
      Sergio

      Elimina
  4. Per fare ex novo il progetto con le specifiche indicate sopra...bisognerebbe usare lo stesso arduino? sarebbe davvero una cosa fighissima....e per me almeno il fascino dei display 7 segmenti non ha concorrenza! :)

    RispondiElimina
    Risposte
    1. Si può utilizzare Arduino UNO o eventualmente il mega, ma con altro materiale aggiuntivo, quindi si dovrebbe realizzare un c.s. con i relativi componenti, insomma un lavoro di un certo impegno.

      Meno lavoro si potrebbe avere utilizzando dei display 7 segmenti I2C che si trovano già in commercio, ma quelli che ho visto son a 4 cifre.
      Si potrebbero visualizzare solo i minuti ed i secondi per quello che riguarda i tempi migliori o peggiori, tralasciando i centesimi o arrotondandoli al secondo.
      Lasciando invece il display di conteggio così come adesso.
      Ci studio e poi vediamo....
      Sergio

      Elimina
  5. Cosa dovrei aggiungere allo sketch per usare un pulsante per lo start ed uno per lo stop ? Grazie in anticipo e complimenti per il tutto

    RispondiElimina
    Risposte
    1. Ho fatto delle semplici modifiche allo sketch in pratica dovrai aggiungere un tasto con lo schema identico a quello del pulsante collegato al pin 7, lo dovrai collegare al pin A0 che corrisponde al pin digitale 14.

      In sostanza le modifiche allo sketch non fanno altro che duplicare la funzione Pulsante()
      Chiamandola Pulsante_Stop(), qui si useranno le stesse variabili che per chiarezza lettura ho chiamato nello stesso modo cosi modificate = nome_Stop
      Lo sketch si compila ma non ho più il cronometro per fare una prova reale.
      Facci sapere se ti funziona!!
      Aggiungo il codice modificato in fondo al post

      Saluti Sergio

      Elimina
  6. Ciao, lo sketch modificato con i due pulsanti (start / stop) purtroppo non funziona, all'accensione parte subito il conteggio e premendo i pulsanti non cambia niente, ho provato a guardare il programma ma per me che sono alle prime esperienze sembra corretto... qualche idea del problema?

    RispondiElimina
  7. Ciao, scusa se riscrivo, vorrei un tuo parere/aiuto, a parte sistemare i pulsanti di start e stop vorrei poter modificare questo programma per visualizzare la velocità in KMh anzichè il tempo, teoricamente con la formula V= S/T, ovvero: "velocità è uguale allo spazio diviso al tempo impiegato per percorrere un determinato tragitto che io imposterei a 1 metro" il risultato poi moltiplicato x 3.6 dovrebbe darmi la velocità in KMh. Puoi dirmi dove intervenire per queste modifiche?

    Grazie
    Marco

    RispondiElimina
  8. disculpe pero para activar y desactivar con 2 sensores infrarrojos se tendria que modificar el programa? si es asi como seria

    muchas gracias y buen proyecto

    RispondiElimina
    Risposte
    1. Utilizza la versione sketch per due pulsanti.

      ***cronometro 6 display ********
      ********* RUBIK **************
      *** Versione 1.06 ***************
      ****** 11-09-2015 ***************
      *nome = crono_Rubik_106_2_Puls **
      *********************************
      // modifica fatta al 1.05 per
      // utilizzo di 2 pulsanti
      // uno di Start ed uno di Stop
      // da un commento di Alw Sbo
      // del 10/09/2015
      ** Dovrai utilizzare i due infrarossi come due pulsanti uno per start ed uno per stop.
      Devi solo integrare la parte hardware del progetto.
      Buon lavoro!
      Se vuoi condividere il risultato con altri lettore invia un link o contattami per pubblicarlo in questo post.
      Ti saluto
      Sergio.

      Elimina

Vi ringrazio per la lettura e vi invito al prossimo post.
Se il post vi è stato utile, vi è piaciuto oppure no, scrivete un commento.

Un saluto a tutti.
Sergio

Copyright - Condizioni d’uso - Disclaimer
http://avventurarduino.blogspot.it/2012/10/inizia-lavventura-arduino-12-settembre.html