Orologio scacchi oled
In questo post descrivo il progetto per un nuovo orologio per gioco degli scacchi che utilizza due display oled.
Su questo blog avevo già pubblicato un mio lavoro "Orologio digitale per scacchi".
Purtroppo quel lavoro è stato parzialmente smontato perché non più funzionante, ho quindi deciso di fare un nuovo orologio.
Caratteristiche principali
Deviatore gioco, centrale che scambia gli orologi.
Funzione SET ( tasto BIANCO) :
Possibilità di regolare (tasto BLU ) 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 (tasto ROSSO) per avviare la partita, Stop per interrompere la partita ed iniziarne una nuova.
Questo orologio è del tutto simile al precedente, lo sketch è riutilizzato in gran parte, ho modificato eliminando le parti non necessarie ed aggiungendo librerie e codice per la visualizzazione su "OLED".
Materiale occorrente:
1 Arduino UNO ( è possibile usare anche altre schede compatibili).
2 Display moduli OLED da 0,96 pollici 128x64 I2C.
1 Scheda TCA9548A espansione canali I2C.
1 Deviatore una via due posizioni.
3 Pulsanti momentanei.
5 resistenze da 10K.
*************
Nel mio lavoro ho utilizzato anche:
2 led Uno Giallo uno Verde
2 resistenze da 180 ohm.
Qui sotto lo schema elettrico.
Montaggio su basetta forata della scheda TCA9548 e collegato con Arduino, pulsanti ed oled.
Orologio in funzione.
Fine tempo orologio, uno degli orologi ha finito il tempo e si ferma su 00.00
Funzionamento ed istruzioni rimangono le stesse del precedente lavoro.
In questa versione utilizzo Arduino uno, al quale collego sia la schedina TCA espansione canali I2C, e due Oled I2C da 0,96 pollici.
L'utilizzo degli oled semplifica molto lo schema, ma per utilizzarli ho usato la libreria U8x8lib.
Nel mio sketch uso molto poco della libreria se interessati guardate il video 355 di Paolo Aliverti, colgo l'occasione per ringraziarlo per tutti i video che fa.
Anche sul mio canale YouTube trovate un video sul funzionamento dell'orologio di scacchi.
Qui sotto lo sketch
/*
/*
ScacchiTCA6548.ino
version for U8x8 API
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
Copyright (c) 2016, olikraus@gmail.com
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
//--------------------------------------------------------------------------//
//********************************
Sergio & Adiano Prenleloup
*********************************
*** OROLOGIO SCACCHI ********
**** ********** **********
*** Versione V300825
****** 30/08/2025 ************
*********************************
*** ADATTAMENTO DEL PROGRAMMA ***
*** CON MODULI OLED I2C *****
**********************************
// Si cambia solo la parte visualizzazione
// usando display OLED I2C
//--------------------------------------------------------------------------//
// 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 premendo 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.
//
//
// ------------------------------------------------------------------------//
*/
//VERSIONE CON DEVIATORE
// VERSIONE FUNZIONANTE BENE
// VERSIONE SENZA FISCHER
//
//
//**************************************************************
//**** AGGIUNTE PER OLED
//*************************************************************
#include <Arduino.h>
#include <LibPrintf.h>
#include <U8x8lib.h>
#include <Wire.h>
// Please UNCOMMENT one of the contructor lines below
// U8x8 Contructor List
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/// U8X8_PIN_NONE);
U8X8_SSD1306_128X64_ALT0_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
// same as the NONAME variant, but may solve the "every 2nd line skipped" problem
U8X8_SSD1306_128X64_ALT0_HW_I2C u8x8_b(/* reset=*/ U8X8_PIN_NONE);
// same as the NONAME variant, but may solve the "every 2nd line skipped" problem
// End of constructor list
#define TCAADDR 0x70
//#include <Adafruit_GFX.h>
//#include <Adafruit_SSD1306.h>
#define SCREEN_ADDRESS 0x3c
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
//Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//*************************************************************************
unsigned long tb = 0;
unsigned long tbounce= 50;
// per memorizzare il tempo millis al setup
//----------------------------------------------------------------------
//**************************************************************************
//*************************************************************************
//--------------------------------------------------------------------------//
// gestione pulsanti
//
int ButtonA = 12; // pin pulsante Orologio A
int ButtonB = 11; // pin pulsante Orologio B
int oroA = 10; // accende orologio A
int oroB = 9; // accende orologio B
int statoA = 0;
int statoB = 0;
int statoAP = 0;
int statoBP = 0;
int SET_pin = 8; // pin pulsante SET si entra in SET
int START_pin = 13; // pin pulsante STAERT e STOP gioco
int Regola_pin = 7; // 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 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)
//--------------------------------------------------------------------------//
//--------------------------------------------------------------------------//
//long tb = 0;
//long tbounce= 50;
int orologioA;
int orologioB;
void setup()
{
Wire.begin();
tcaselect(0);
u8x8.begin();
u8x8.setPowerSave(0);
tcaselect(1);
u8x8_b.begin();
u8x8_b.setPowerSave(0);
tcaselect(0);
u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);
//u8x8.drawString(0, 0, "Hello World");
//u8x8.setFont(u8x8_font_courB24_3x4_r);
u8x8.drawString(0,5,"V300825");
delay(1000);
u8x8.clearDisplay(); // Clear the buffer
tcaselect(1);
u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);
//u8x8.drawString(0, 0, "Hello World");
//u8x8.setFont(u8x8_font_courB24_3x4_r);
u8x8.drawString(0,6,"START");
delay (1000);
u8x8.clearDisplay(); // Clear the buffer
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 (oroA, OUTPUT); // orologioAattivo PIN 8
pinMode (oroB, OUTPUT); // orologioBATTIVO PIN 9
tempoOrologi[0] = SET_A; // tempo di default 5 minuti
tempoOrologi[1] = SET_B;
tb = millis();
tbounce= 50;
}
//-----------------------------------------
// 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();
visualizzaTempo();
//----------------------------------------------------------
unsigned long secs = millis() / 1000 - lastsec;
if (secs >= 1)
{
lastsec = millis() / 1000;
aggiornaTempoTrascorso(OrologioAttivo, -1);
}
Deviatore();
//---------------------------------------------------------
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 tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void Deviatore() // scambio orologi attivi
{
if (digitalRead(ButtonA))
{
if ((millis()-tb ) > tbounce){
digitalWrite(oroB,HIGH);digitalWrite(oroA,LOW);
orologioA = 0; orologioB = 1;
tb = millis();
}
}
if (digitalRead(ButtonB))
{
if ((millis()-tb) > tbounce){
digitalWrite(oroB,LOW);digitalWrite(oroA,HIGH);
orologioB = 0; orologioA = 1;
tb = millis();
}
}
// orologioA = digitalRead(ButtonA);
// orologioB = digitalRead(ButtonB);
if (orologioA == 1)
{
OrologioAttivo = 0;
}
if (orologioB == 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
{
tcaselect(0);
//u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);
//u8x8.drawString(0, 0, "Hello World");
u8x8.clearDisplay();
u8x8.setFont(u8x8_font_courB24_3x4_r);
u8x8.drawString(0,5,"SET");
delay(1000);
u8x8.clearDisplay(); // Clear the buffer
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);
// char bufferm1[10];
// sprintf(bufferm1 ,"%0d",m1);
// char buffers1[10];
// sprintf(buffers1 ,"%0d",s1);
char bufA[6];
sprintf(bufA ,"%02d:%02d", m1, s1);
tcaselect(0);
u8x8.setFont(u8x8_font_courB24_3x4_r);
u8x8.drawString(0,5,bufA);
//u8x8.drawString(6,5,":");
// u8x8.drawString(9,5,buffers1);
int m2; int s2;
minutiSecondi(tempoOrologi[1], m2, s2);
//char bufferm2[10];
//sprintf(bufferm2 ,"%0d",m2);
//char buffers2[10];
//sprintf(buffers2 ,"%02d",s2);
char bufB[6];
sprintf(bufB ,"%02d:%02d", m2, s2);
tcaselect(1);
u8x8.setFont(u8x8_font_courB24_3x4_r);
u8x8.drawString(0,5,bufB);
// u8x8.drawString(6,5,":");
// u8x8.drawString(9,5,buffers2);
}
//------------------------------------------------------------
// 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
//-----------------------------------------------------
Grazie per l'attenzione, potete lasciare un commento o domande, cercherò di rispondere a tutti.
Al prossimo post
Nessun commento:
Posta un commento
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