sabato 12 luglio 2014

Orologio Scacchi

  Orologio digitale per Scacchi

Semplice orologio per scacchi, con visualizzazione del tempo su display a 7 segmenti.

Arduino e gli scacchi

 

Caratteristiche principali ver. 1.06

Funzionamento con batterie.
Deviatore gioco.
Funzione SET:
Possibilità di regolare il tempo da 5 minuti a 90 minuti ( 1h e 1/2), con step di 5 minuti, singolarmente per ogni orologio.
Pulsante di Start/ Stop per avviare la partita, Stop per interrompere la partita ed iniziarne una nuova.
Impostato il tempo ripropone la cadenza ma è possibile cambiare con la funzione SET.



Materiale occorrente:

2)  Display 7 seg. catodo comune tipo  (ATA8401ARBJY2) questi sono quelli che ho utilizzato io.
2) 74HC595 8 bit Shift register.
1) AtMega 328P
2) condesatori da 22pF.
1) Quarzo 16MhZ.
8) transistor BC547.
8) resistenze da 1,2K.
8) resistenze da 390 omm.
4) pulsanti n.a.
1) interruttore.
1) Deviatore.
1) led.
1) resistenza da 330 omm.
6) resistenze da 10K.
1) resistenza da 100 omm.
4) batterie ricaricabili 1,2 x4 = 4,8 V.
1) porta batterie.
1) scatola.
materiale vario per l'assemblaggio, zoccolini, vetronite normale o preforata, ecc...
Il costo complessivo e relativamente basso inferiore ai 50 euro.


 Qui sotto vi propongo lo schema elettrico della mia realizzazione, per utilizzare altro materiale dovrete effettuare le oppurtune modifiche.




 Nello schema potete vedere che i display sono collegati tutti in parallelo, solo i catodi comuni vengono comandati dai transistor BC547,  in pratica Arduino invia la composizione dei segmenti per accendere una cifra ma questa si accende effettivamente solo sul display che attiva il relativo transistor, i transistor vengono attivati a turno per 100 microsecondi, ed è così che grazie all'effetto persistenza della retina del nostro occhio sembrano accesi in modo stabile.
L'assorbimento totale compreso Atmega328 è di 80/100 mA. 

Ho utilizzato due 74HC595  uno per comandare gli anodi in parallelo dei display, l'altro per comandare gli 8 transistor dei catodi.
Gli shift register sono comandati dai tre pin:
  pinMode (dataPin, OUTPUT); // comunicazione seriale hc595
  pinMode (clockPin, OUTPUT);// comunicazione seriale hc595
  pinMode (latchPin, OUTPUT);// comunicazione seriale hc595
Il primo comanda gli Anodi dei segmenti, in cascata il secondo comanda i transistor e quindi i relativi catodi.

In questo schema è prevista una versione minimale di Arduino utilizzando un quarzo e 2 condensatori, ma se volete potete utilizzare un normalissimo arduino, non c'è molto da dire per i pulsanti utilizzano lo schema classico, stessa cosa per il deviatore di gioco.

Lo schema è abbastanza lineare e non presenta criticità.

Le prove su  breadboard:

 


vista d'insieme



tasti, display, HC595, transistor BC547




Arduino stand-alone.


Qui sotto potrete vedere lo sketch.

Come potete vedere è completamente commentato, e scritto nel modo più leggibile possibile.
L'attuale funzionalità è leggermente diversa da quella di un'orologio analogico, in quanto allo scadere del tempo (caduta della bandierina), i due orologi si fermano uno con il tempo residuo l'altro sullo 00.00 , questo stabilisce chi ha terminato il tempo per primo.
E' possibile con poche modifiche implementare alcune ulteriori opzioni ( Fischer o Bronstein).

Varie funzioni dello sketch  sono utilizzate in altri post di questo sesso blog ( cubo di Rubik) ecc.




/*
//--------------------------------------------------------------------------//
//********************************
  Sergio  & Adiano Prenleloup
 *********************************
 ***    OROLOGIO SCACCHI  ********
 ****   **********      **********
 ***    Versione 1.06   **********
 ******   9/06/2014   ************
 *********************************

//--------------------------------------------------------------------------//
// Tasti == START/STOP  -- SET  --- Regola
//------------------------------------------
// In questa versione l'orologio esegue le normali funzioni per giuoco scacchi,
//
// Inizialmente viene proposto il tempo di gioco di default 5 minuti.
// E'possibile con la funzione SET cambiare il tempo ( anche in modo diverso
// per i due orologi) alla pressione del tasto SET si accende led, a questo
// punto si preme il tasto Regola che incrementerà il tempo di 5 minuti ad
// ogni pressione, per regolare il secondo orologio spostare il tasto deviatore
// gioco. Finita la regolazione premere nuovamente SET il led si spenge.
// E' possibile regolare da 5 a 90 minuti, con step di 5 minuti.
// Premendo START / STOP parte l'orologio attivo.
// Il gioco prosegue scambiando gli orologi fino al termine del tempo.
// Quando un orologio è arrivato allo 00.00 si ferma tutto fino alla nuova
// pressione del tasto START. Ed il ciclo ricomincia per nuova partita.
// E' possibile durante il gioco interrompere la partita premento START/STOP
// Gli orologi si azzerano e premendo ancora START/STOP è possibile effettuare
// altra partita.
// Questo orologio visualizza a sinistra i minuti e sulla destra i secondi.
//
//
// ------------------------------------------------------------------------//

/* Programma che realizza il Multiplexing.
Invo bit alto ai pin corrispondenti ai segmenti a,b,c,d,e,f,g. (righe)
Si accendono inviando bit alto ai secondi (unità), decine di secondi, minuti,
decine di minuti. (colonne)
//--------------------------------------------------------------------------//

*/
//--------------------------------------------------------------------------//
// gestione Multiplexing e display 7 segmenti

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

//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
  {0,1,1,0,0,0,0},  //uno      1
  {1,1,0,1,1,0,1},  // due     2
  {1,1,1,1,0,0,1},  //tre      3
  {0,1,1,0,0,1,1}, //quattro   4
  {1,0,1,1,0,1,1},  // cinque  5
  {1,0,1,1,1,1,1},  // sei     6
  {1,1,1,0,0,0,0},  // sette   7
  {1,1,1,1,1,1,1},  // otto    8
  {1,1,1,1,0,1,1}  //nove      9
};

//--------------------------------------------------------------------------//
// gestione pulsanti
//
int ButtonA = 12; // pin pulsante Orologio A
int ButtonB = 13; // pin pulsante Orologio B

int SET_pin = 7; // pin pulsante SET si entra in SET
int START_pin = 6; // pin pulsante STAERT e STOP  gioco
int Regola_pin = 5; // pin per la regolazione minuti di gioco
int Led_Set = 4;  // se acceso SET attivo
int stato_bottoni[3];    // gestione pulsanti
boolean stato_switch[3]; // gestione pulsanti
//--------------------------------------------------------------------
//  stato_switch[0]  stato del pulsante START/STOP
//  stato_switch[1]  stato del pulsante SET
//  stato_switch[2]  stato del pulsante Regola
//-------------------------------------------------------------------
// gestione seriale 74hc595

int dataPin = 9;      // al pin seria DATA del 74HC595
int clockPin = 10;    // al CLOK pin del 74HC595
int latchPin = 11;    // LATCH pin del 74HC595
int outputPin = 8;   // disponibile


//-------------------------------------------------------------------
//  gestione orologi e tempi
int lastsec = 0;
int OrologioAttivo = 0; // 0 orologio A,  1 orologio B,
int tempoOrologi[2];  // contiene il tempo degli orologi 0 e 1
//int statoOrologi[2];  // indice orologio attivo
int SET_A = 300; // tempo di 5 minuti
int SET_B = 300; // questi tempi si possono cambiare con la
                 // procedura SET
int Tmax = 5400;  // tempo massimo di gioco 90 minuti ( un'ora e mezzo)
//--------------------------------------------------------------------------//

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

void setup()
{
  pinMode (ButtonA,INPUT); // deviatore gioco
  pinMode (ButtonB,INPUT); // deviatore gioco
  pinMode (SET_pin,INPUT); // pulsante SET
  pinMode (START_pin,INPUT); // pulsante START/STOP
  pinMode (Regola_pin,INPUT); // pulsante Regola
 
  pinMode (outputPin, OUTPUT); // disponibile
  pinMode (Led_Set, OUTPUT);  // led che segnala la situazione di SET
  pinMode (dataPin, OUTPUT); // comunicazione seriale hc595
  pinMode (clockPin, OUTPUT);// comunicazione seriale hc595
  pinMode (latchPin, OUTPUT);// comunicazione seriale hc595

  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);
  digitalWrite(latchPin, LOW);
  digitalWrite(Led_Set,LOW); 
  digitalWrite(outputPin, LOW);  // disponibile
 
  tempoOrologi[0] = SET_A; // tempo di default 5 minuti
  tempoOrologi[1] = SET_B; 

//-----------------------------------------
// fine setup
//-----------------------------------------


 //------------------------------------------------------------//
// Inizio loop principale
//------------------------------------------------------------//
void loop()
{    
   // si attende la pressione del tasto START o del tasto SET
    stato_switch[0]  = 0;
    while  (stato_switch[0] == 0) // fino alla pressione di Start
     {
      tempoOrologi[0] = SET_A;
      tempoOrologi[1] = SET_B; 
      visualizzaTempo();
      controllaPulsante();
  // con la pressione del tasto SET si entra nella procedura     
            while (stato_switch[1] == 1)
                  {
                    digitalWrite(Led_Set,HIGH);
                    proceduraSET();
                   controllaPulsante();
                  }
          digitalWrite(Led_Set,LOW);          
     } 

   
//------------------------------------------------------------
//   Loop ---  G I O C O -------------------------------------
// il deviatore A B scambia gli orologi
// l'orologio che parte è quello con il deviatore alto
// inizia il conto alla rovescia alternando i due
// orologi fino alla fine del tempo di gioco.
//-------------------------------------------------------------

   while (tempoOrologi[OrologioAttivo] > 0)
        {
         Deviatore();
          // scambia l'orologio attivo
          visualizzaTempo();
    //----------------------------------------------------------     
          unsigned long secs = millis() / 1000 - lastsec;
          if (secs >= 1)
             {
              lastsec = millis() / 1000;
     
              aggiornaTempoTrascorso(OrologioAttivo, -1);
             
            }
   //---------------------------------------------------------
         visualizzaTempo();
        
        //------- STOP e Azzera -----------
         stato_switch[0]  = 0;
         controllaPulsante();
          if   (stato_switch[0] == 1)  // stop
                 {
                   tempoOrologi[0] = 0;
                    tempoOrologi[1] = 0; 
                  break; 
               }                        
       }
//---------------------------------------------------------------
//   fine gioco uno degli orologi è arrivato a 0
//   si visualizzano i tempi con orologi fermi
//   fino alla pressione del tasto START
//---------------------------------------------------------------
  stato_switch[0]  = 0;
  
   while (stato_switch[0] == 0)
      {
        controllaPulsante();
        visualizzaTempo(); 
      }  
}  
 
  //-----------------------------------
  // FINE LOOP
  //-----------------------------------



//========================================
//   FUNZIONI
//========================================
 
void Deviatore() // scambio orologi attivi
{
  int oroA = digitalRead (ButtonA); 
  int oroB = digitalRead (ButtonB);

  if (oroA == 1) 
    { 
     OrologioAttivo = 0;
    }  
 
  if (oroB == 1) 
  { 
   OrologioAttivo = 1;
  }   
}

//-----------------------------------------------------------------
// PROCEDURA SET
//    si regola il tempo di gioco ai due orologi anche
//    diverso ( Deviatore) - scatti di 5 minuti fino a 90 minuti
//    poi torna a 5 minuti
//-----------------------------------------------------------------
void proceduraSET() // siamo entrati in SET alla pressione
                    // del tasto SET -- si accende led
                    // per uscire si preme ancora SET
                    // il led si spenge
{
 
    stato_switch[1]  = 0; // azzero tasto SET
    tempoOrologi[0] = SET_A;
    tempoOrologi[1] = SET_B; 
    visualizzaTempo();
    
     while (stato_switch[1] == 0) // fino ad pressione del tasto set
     {  
             controllaPulsante();
          
           if (stato_switch[2] == 1) // se premuto tasto Regola
             {
             
                     Deviatore();  // si regola set orologio attivo
                  if (OrologioAttivo == 0)
                     {
                      SET_A = SET_A + 300;
                       if (SET_A > Tmax) // massimo 90 minuti
                          {
                            SET_A = 300; 
                          }
                           
                     }
              
                      Deviatore(); // si regola set orologio attivo
                     if (OrologioAttivo == 1)
      
                       {
                        SET_B = SET_B + 300;
                          if (SET_B > Tmax) // massimo 90 minuti
                             {
                               SET_B = 300;
                             } 
                       }
                    }
                   
               tempoOrologi[0] = SET_A;
               tempoOrologi[1] = SET_B; 
               visualizzaTempo();
               stato_switch[2]  = 0;     
          }
               tempoOrologi[0] = SET_A;
               tempoOrologi[1] = SET_B; 
               visualizzaTempo();
               stato_switch[1]  = 0;
     // fine procedura set
       }
      
//-----------------------------------------------------------------
// Si aggiorna il tempo dell'orologio attivo
//-----------------------------------------------------------------
void aggiornaTempoTrascorso(int orologio, int delta)
{
  tempoOrologi[orologio] = tempoOrologi[orologio] +delta;
}

//---------------------------------------------------------------
// tempo in minuti e secondi
//---------------------------------------------------------------
void minutiSecondi(unsigned long t, int& m, int& s)
{
  m = t / 60;
  s = t % 60;
}

//---------------------------------------------------------------
// Si visualizzano i tempi dei due orologi
//---------------------------------------------------------------
void visualizzaTempo()
{
  int m1; int s1;
  minutiSecondi(tempoOrologi[0], m1, s1);
  int m2; int s2;
  minutiSecondi(tempoOrologi[1], m2, s2); 

  unsigned long clock1 = m1*100+s1;
  unsigned long clock2 = m2*100+s2;

  visualizzaNumeroOrologio(clock1, 0);
  visualizzaNumeroOrologio(clock2, 4);
 
}
//-----------------------------------------------------------------
//
void visualizzaNumeroOrologio(unsigned long numero, int orologio)
{
 // 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;

  inviaCifra(m, orologio + 1, false);         
  inviaCifra(c, orologio + 2, true);
  inviaCifra(d, orologio + 3, false);
  inviaCifra(u, orologio + 4, false);  
}
//-------------------------------------------------------------------
// si inviano i dati ai 2 74hc595
//-------------------------------------------------------------------
void inviaCifra(int n, int pos, boolean dot)
{
  byte b0 = componi7Segmenti(n);
  bitWrite(b0, 7, (dot ? 1 : 0)); //punto separatore minuti secondi
  byte b1 = componiCifra(pos);
 
 
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, b1);    
  shiftOut(dataPin, clockPin, MSBFIRST, b0);
  digitalWrite(latchPin, HIGH); 
 
//-- outputPin -- in questo non è utilizzato
  digitalWrite(outputPin, HIGH);
  delayMicroseconds(MUXDELAY); 
  digitalWrite(outputPin, LOW);
}
//-------------------------------------------------------------------

byte componiCifra(int n)
{
  byte b = 0;
  bitSet(b, n - 1);
  return b;
}

//-------------------------------------------------------------------
//Attiva i segmenti necessari a mostrare il numero n passato
// ritorna una sequenza di bit
byte componi7Segmenti(int n)
{
  byte b = 0;
  for (int i=0; i< 7; i++)
  {
    bitWrite(b, i, tabNumeriSegmenti[n][i]);
  }
  return b;
}
  
//------------------------------------------------------------
// GESTIONE PULSANTI
//------------------------------------------------------------

 void controllaPulsante()
{
    aggiornaStato(START_pin, stato_bottoni[0], stato_switch[0]);
    aggiornaStato(SET_pin, stato_bottoni[1], stato_switch[1]);
    aggiornaStato(Regola_pin, stato_bottoni[2], stato_switch[2]);
}

void aggiornaStato(int bottone, int& statoBottoneVecchio, boolean& statoSwitch)
{
  //Si legge lo stato corrente del bottone (se premuto o no)
  int statoBottoneCorrente = digitalRead (bottone);
 
  //Se lo stato corrente del bottone è cambiato (diverso dal vecchio stato)
  //si deve gestire il nuovo stato
  if (statoBottoneCorrente != statoBottoneVecchio)
  {
      //se stiamo passando da rilasciato a premuto allora gestiamo la
      //logica antirimbalzo e attiviamo/disattiviamo lo swith
     if (statoBottoneCorrente == HIGH)
     {
       delay(10);
       statoSwitch = !statoSwitch;
     }
     //il nuovo stato diventa lo stato corrente
     statoBottoneVecchio = statoBottoneCorrente; 
  }
}

//-----------------------------------------------------
//   fine
//-----------------------------------------------------


===============================================

Qui sotto un filmato che illustra il funzionamento dell'orologio completo nella sua scatola.





Sviluppi:

  Aggiunta di funzioni Fischer e/o Bronstein.

Penso di migliorare il lavoro aggiungendo altre funzioni, e realizzando una scatola con tasto giuoco più consono ad un'attività scacchistica. Gli attuali orologi in commercio costano dai 30 ai 100 euro e di conseguenza cercherò di rimanere entro limiti di costo compatibili.

A presto

 

5 commenti:

  1. Mi chiamo Cristian, da non molto sto cominciando ad esplorare il mondo di arduino... Innanzitutto volevo farti i complimenti per i tuoi progetti! Sto giusto cercando di replicare il tuo orologio per gli scacchi... Cortesemente riusciresti a girarmi lo schema, quello che hai postato non si vede molto bene....
    Ti ringrazio anticipatamente per la tua disponibilità! A presto!
    Cristian

    RispondiElimina
    Risposte
    1. OK, ho aggiunto un link per scaricare l'immagine JPEG dello schema.
      Grazie per il commento

      Elimina
  2. Ciao!
    Ti scrivo per saper se hai avuto modo di risolver il problema relativo allo sketch da te gentilmente inviato aproposito del conteggio alla rovescia del timer bomba (il problema era fare in modo che il tempo si bloccasse quando giunto a zero). Purtroppo non sono riuscito a venir a capo del problema.
    Ti ringrazio!

    RispondiElimina
  3. Sketch perfettamente funzionante, finito ora di eseguire i test.

    RispondiElimina
    Risposte
    1. Ho creato un nuovo post "Timer" che riporta lo sketch modificato, ed ulteriori spiegazioni.
      Sono contento che funzioni bene.
      Un 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