n° 219
Novembre 2017
Giugno 20, 2018, 02:52:18 *
Benvenuto! Accedi o registrati.
Hai dimenticato l'e-mail di attivazione?

Accesso con nome utente, password e durata della sessione
Notizia:
 
   Indice   Linux Windows Techassistance Gameassistance videogame hardware Aiuto Ricerca Agenda Downloads Accedi Registrati  


* Messaggi recenti
Messaggi recenti
Pagine: [1]   Vai giù
  Stampa  
Autore Discussione: Utilizzo del protocollo DGT con Arduino  (Letto 1680 volte)
0 utenti e 1 Utente non registrato stanno visualizzando questa discussione.
EtaBetaPot
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 8


Mostra profilo E-mail
« inserita:: Marzo 01, 2018, 05:43:10 »

Buongiorno a tutti, sto realizzando una scacchiera elettronica simile alle scacchiere elettroniche della DGT. L’elettronica che ho costruito con l’ausilio di Arduino mi legge la scacchiera e come risultato posso ottenere per ogni mossa effettuata stringhe del tipo “e2-e4” o a mio piacimento in altri formati. Il problema è capire come lavora il protocollo della DGT, per poi trasformare le mosse lette dalla scacchiera in protocollo DGT da inviare ad esempio a programmi scacchistici tipo “Fritz” tramite la seriale di Arduino. Non possiedo purtroppo le conoscenze approfondite di C/C++ per analizzare il protocollo dgtbrd13 che ho postato e dunque mi sono rivolto a questa grande comunità per ricevere un aiuto.
Sperando che qualcuno mi dia qualche dritta, saluto cordialmente.
Igor

Link al protocollo DGT: http://svn.lirec.eu/scenarios/MyFriend/Watching2Players/iCatChess/ElectronicBoard/dgtbrd13.h
Registrato
michele.p
Administrator
Sr. Member
*****

Karma: +11/-2
Scollegato Scollegato

Messaggi: 657


Mostra profilo
« Risposta #1 inserita:: Marzo 01, 2018, 06:14:38 »

Nell'header che hai riportato sembrano esserci tutti i commenti dai quali estrapolare il funzionamento (e il significato) delle varie variabili.
Suggerisco di dare un'occhiata anche qui (in Python):

https://github.com/niklasf/python-asyncdgt

compreso in basso il paragrafo Related projects dove vi è il programma picochess.

Mia opinione da 2 cent Sorriso : forse ti conviene passare da Arduino a RaspBerry o a micropython (se possibile):

https://micropython.org/
Registrato
EtaBetaPot
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 8


Mostra profilo E-mail
« Risposta #2 inserita:: Marzo 01, 2018, 07:01:14 »

Grazie Michele per avermi risposto, è interessante la pyboard, ma il suo costo rispetto ad arduino nano mi trattiene nel cambiare l'hardware del mio progetto. Il Pyton non lo conosco affatto e credo che sia interpretato e non compilato... o sbaglio ?.
Mi basterebbe un esempio del tipo...
Muovo il pedone bianco dalla casella e2 alla casella e4.. cosa devo trasmettere sulla seriale di arduino verso il programma Fritz ?
Forse le seguenti definizioni mi possono aiutare ?.... grazie nuovamente
Codice:
/* DEFINITION OF THE BOARD-TO-PC MESSAGE ID CODES and message descriptions */

/* the Message ID is the logical OR of MESSAGE_BIT and ID code */
#define MESSAGE_BIT         0x80

/* ID codes: */
#define DGT_NONE            0x00
#define DGT_BOARD_DUMP      0x06
#define DGT_BWTIME          0x0d
#define DGT_FIELD_UPDATE    0x0e
#define DGT_EE_MOVES        0x0f
#define DGT_BUSADRES        0x10
#define DGT_SERIALNR        0x11
#define DGT_TRADEMARK       0x12
#define DGT_VERSION         0x13

/* Macros for message length coding (to avoid MSB set to 1) */

#define BYTE    char

#define LLL_SEVEN(a) ((BYTE)(a&0x7f))            /* 0000 0000 0111 1111 */
#define LLH_SEVEN(a) ((BYTE)((a & 0x3F80)>>7))   /* 0011 1111 1000 0000 */


/* DGT_MSG_BOARD_DUMP is the message that follows on a DGT_SEND_BOARD
   command */

#define DGT_MSG_BOARD_DUMP  (MESSAGE_BIT|DGT_BOARD_DUMP)
#define DGT_SIZE_BOARD_DUMP 67

/* message format:
byte 0: DGT_MSG_BOARD_DUMP
byte 1: LLH_SEVEN(DGT_SIZE_BOARD_DUMP) (=0 fixed)
byte 2: LLL_SEVEN(DGT_SIZE_BOARD_DUMP) (=67 fixed)
byte 3-66: Pieces on position 0-63

Board fields are numbered from 0 to 63, row by row, in normal reading
sequence. When the connector is on the left hand, counting starts at
the top left square. The board itself does not rotate the numbering,
when black instead of white plays with the clock/connector on the left hand.
In non-rotated board use, the field numbering is as follows:

Field A8 is numbered 0
Field B8 is numbered 1
Field C8 is numbered 2
..
Field A7 is numbered 8
..
Field H1 is numbered 63

So the board always numbers the black edge field closest to the connector
as 57.

Piece codes for chess pieces: */

#define EMPTY       0x00
#define WPAWN       0x01
#define WROOK       0x02
#define WKNIGHT     0x03
#define WBISHOP     0x04
#define WKING       0x05
#define WQUEEN      0x06
#define BPAWN       0x07
#define BROOK       0x08
#define BKNIGHT     0x09
#define BBISHOP     0x0a
#define BKING       0x0b
#define BQUEEN      0x0c
#define PIECE1      0x0d  /* future use: pointing device in rest */
#define PIECE2      0x0e  /* future use: pointing device right button */
#define PIECE3      0x0f  /* future use: pointing device left button */

/* message format DGT_MSG_BWTIME */

#define DGT_MSG_BWTIME      (MESSAGE_BIT|DGT_BWTIME)
#define DGT_SIZE_BWTIME     10

/*
byte 0: DGT_MSG_BWTIME
byte 1: LLH_SEVEN(DGT_SIZE_BWTIME) (=0 fixed)
byte 2: LLL_SEVEN(DGT_SIZE_BWTIME) (=10 fixed)
byte 3:
D4: 1 = Flag fallen for left player, and clock blocked to zero
0 = not the above situation
D5: 1 = Time per move indicator on for left player ( i.e. Bronstein, Fischer)
0 = Time per move indicator off for left player
D6: 1 = Left players flag fallen and indicated on display
0 = not the above situation
(D7 is MSB)
D0-D3: Hours (units, 0-9 Binary coded) white player (or player at the A side of the board)
byte 4: Minutes (0-59, BCD coded)
byte 5: Seconds (0-59, BCD coded)

byte 6-8: the same for the other player
 
byte 9: Clock status byte: 7 bits
D0 (LSB): 1 = Clock running
0 = Clock stopped by Start/Stop
D1: 1 = tumbler position high on (white) player (front view: \ , left side high)
0 = tumbler position high on the other player (front view: /, right side high)
D2: 1 = Battery low indication on display
0 = no battery low indication on display
D3: 1 = Black players turn
0 = not black players turn
D4: 1 = White players turn
0 = not white players turn
D5: 1 = No clock connected; reading invalid
0 = clock connected, reading valid
D6: not used (read as 0)
D7:  Always 0
The function of the information bits are derived from the full information
as described in the programmers reference manual for the DGT TopMatch
*/
Registrato
EtaBetaPot
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 8


Mostra profilo E-mail
« Risposta #3 inserita:: Marzo 04, 2018, 01:59:41 »

Leggendo il protocollo mi sono fatto questa idea, purtroppo sbagliata perché provando Arduino collegato al PC con il programma Fritz in esecuzione non funziona.Posterò alla fine il codice x arduino.

Prendendo come riferimento la trasmissione a scacchiera singola in modalità UPDATE_BOARD , mi sembra che inizialmente la scacchiera una volta collegata al PC con il programma Fritz, aspetta il comando di 1 byte dal PC DGT_SEND_UPDATE_BRD (0x44), per poi identificarsi e rilevare la sua presenza, mandando penso una stringa al PC del tipo : " DGT Projects - This DGT board is produced by DGT Projects.\n
 DGT Projects is a registered trade mark.\n
 220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0 "

I messaggi inviati alla scacchiera sono caratterizzati sempre da un byte che identifica il messaggio, seguito da altri byte a seconda del messaggio da inviare.
I possibili messaggi da inviare alla scacchiera sono:
Codice:
DGT_SEND_CLK (0x41) // la scacchiera risponde con DGT_MSG_BWTIME contenente informazione sull'orologio
DGT_SEND_BOARD (0x42) // la scacchiera risponde con DGT_MSG_BOARD_DUMP trasmettendo i pezzi sulla scacchiera
DGT_SEND_UPDATE (0x43) // pone la scacchiera nella modalità UPDATE, compatibile con FRITZ5 (Fritz 5 manda questo codice)
DGT_SEND_UPDATE_BRD (0x44) // pone la scacchiera nella modalità UPDATE_BOARD, per versioni successive a Fritz 5
DGT_RETURN_SERIALNR (0x45) // restituisce un messaggio DGT_MSG_SERIALNR (Numero di serie della scacchiera ? )
DGT_RETURN_BUSADRES (0x46) // restituisce un messaggio DGT_MSG_BUSADRES … boh  
DGT_SEND_TRADEMARK (0x47) // restituisce un messaggio della marca del prodotto
DGT_SEND_VERSION (0x4d) // restituisce un messaggio DGT_MSG_VERSION, versione del firmware
DGT_SEND_UPDATE_NICE  (0x4b) // pone la scacchiera in modalità aggiornamento affinché trasmetta solo i risultati dei messaggi DGT_MSG_FIELD_UPDATE e DGT_MSG_BWTIME durante il gioco
DGT_SEND_EE_MOVES (0x49) // legge i dati dalla memoria interna della scacchiera restituendo il messaggio DGT_MSG_EE_MOVES   */
DGT_SEND_RESET (0x40) // disattiva la scacchiera, disattivando la modalità UPDATE */

La scacchiera dopo aver interpretato il comando ricevuto, risponde nel seguente modo:
Invia prima l’intestazione del messaggio da trasmettere. L'intestazione del messaggio contiene il codice del messaggio (ID) e la dimensione in byte totali del messaggio stesso [MESSAGE SIZE].
L'inizio del messaggio in arrivo al PC per essere riconosciuto, deve avere a (1) l'MSB del messaggio stesso.

Trasmette il 1° byte inerente all’intestazione del messaggio:
MESSAGGIO ID da un byte, ricordando sempre che l’MSB del messaggio deve essere sempre a 1.
Trovo che il MESSAGGIO ID è l'OR logico di 0x80 con il codice ID dove per codice ID intendono questo:
/* codice ID: */
DGT_NONE                  (0x00)   // se la scacchiera è in modalità reset ? boh…
DGT_BOARD_DUMP         (0x06)   // è il messaggio che segue il comando DGT_SEND_BOARD
DGT_BWTIME               (0x0d)   // gestisce il tempo.. per ora non mi serve
DGT_FIELD_UPDATE       (0x0e)   // segue messaggio di 5 byte quando cambia un pezzo sulla scacchira
DGT_EE_MOVES          (0x0f)   // contiene i contenuti della EEROM della scacchiera (non mi serve)
DGT_BUSADRES           (0x10)   // ??
DGT_SERIALNR           (0x11)   // segue il numero seriale della scacchiera
DGT_TRADEMARK          (0x12)   // segue la marca della scacchiera
DGT_VERSION            (0x13)   // segue la versione del firmware

Formato di [MESSAGE SIZE] :
Trasmette il 2° byte credo un carattere a byte singolo:
MSB di MESSAGE SIZE da un byte, MSB sempre 0, la lunghezza totale del messaggio trasmesso è da D13 a D7, compresi i 3 byte di intestazione.
Definizioni per la codifica della lunghezza dei messaggi (per evitare che MSB  di [MESSAGE SIZE] sia impostato su 1) :
#define BYTE    char
#define LLL_SEVEN(a) ((BYTE)(a&0x7f))            /* 0000 0000 0111 1111 */
#define LLH_SEVEN(a) ((BYTE)((a & 0x3F80)>>7))   /* 0011 1111 1000 0000 */
Trasmette il 3° byte:
LSB di MESSAGE SIZE da un byte, MSB sempre 0, la lunghezza totale del messaggio trasmesso è da D6 a D0, compresi i 3 byte di intestazione seguito dai dati: Da 0 a ((2 EXP 14) meno 3) byte di dati, di cui l'MSB è sempre zero.

Supponiamo ora un possibile esempio di dialogo tra l’Arduino ed il programma Fritz in esecuzione sul PC ….
La comunicazione è a 9600 baud senza bit di parità.
L’Arduino è in attesa di dati in USB dal PC.
Riceve da Fritz il comando DGT DGT_SEND_UPDATE (0x43), dunque ricevendo il byte 0x43 deve poi trasmettere al PC la stringa
" DGT Projects - This DGT board is produced by DGT Projects.\n
 DGT Projects is a registered trade mark.\n
 220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0 " per farsi riconoscere dal programma Fritz.

Poi credo che riceve da Fritz il comando DGT_SEND_BOARD (0x42) per trovare i pezzi sulla scacchiera.
Arduino deve rispondere al comando con DGT_BOARD_DUMP (0x06)
Formato del messaggio DGT_BOARD_DUMP
byte 0: DGT_MSG_BOARD_DUMP (Credo che devo impostarlo a (0x06))
byte 1: LLH_SEVEN(DGT_SIZE_BOARD_DUMP) (Credo che devo impostarlo a 0x00)
byte 2: LLL_SEVEN(DGT_SIZE_BOARD_DUMP) (Credo che devo impostarlo a 0x67)
byte 3-66: Pezzi sulle posizioni da 0-63
I campi della scheda sono numerati da 0 a 63, in sequenza riga per riga.
Il conteggio inizia dal quadrato in alto a sinistra.

La casella A8 è numerata 0
La casella B8 è numerata 1
La casella C8 è numerata 2
La casella D8 è numerata 3
La casella E8 è numerata 4
La casella F8 è numerata 5
La casella G8 è numerata 6
La casella H8 è numerata 7
..
La casella A7 è numerata 8
..
La casella H1 è numerata 63

Valore che identifica i pezzi scacchistici:
Casella vuota      0x00
Pedone bianco      0x01
Torre bianca      0x02
Cavallo bianco      0x03
Alfiere bianco      0x04
Re bianco      0x05
Regina bianca      0x06
Pedone nero      0x07
Torre nera      0x08
Cavallo nero      0x09
Alfiere nero      0x0a
Re nero         0x0b
Regina nera      0x0c

Ora per trasmettere a Fritz la posizione devo trasmettere da Arduino i seguenti byte:
byte 0 : 0x06
byte 1 : 0x00
byte 2 : 0x67
byte 3-66: Pezzi sulle posizioni da 0-63 iniziando dal pezzo collocato nella casella A8 fino ad arrivare alla casella H1.

Ho provato con questo codice ma non funziona …

Codice:
byte read_byte;   //conterrà il valore letto dalla seriale
  byte write_byte;  //conterrà il valore scritto nella seriale
  
  void setup() {
   Serial.begin(9600); // apro la seriale, mi pare che il Programma Fritz dialoga al massimo a 9600 baud.
}

 //programma principale
 void loop() {
   //controllo se c'è qualcosa in arrivo dalla seriale
   if (Serial.available()) {
     read_byte = Serial.read(); //leggo il primo byte
     switch (read_byte) { //controllo i codici dei comandi
       case 0x43: //Ricevo da Fritz il comando DGT DGT_SEND_UPDATE
         //invio a Fritz per fare riconoscere la scacchiera
        Serial.print(F(" DGT Projects - This DGT board is produced by DGT Projects.\n"));
        Serial.print(F(" DGT Projects is a registered trade mark.\n"));
        Serial.print(F(" 220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0 "));                
                break;
       case 0x42: //Ricevo da Fritz il comando DGT_SEND_BOARD (0x42) e dunque devo rispondere con il comando DGT_BOARD_DUMP (0x06)  
          Serial.print (0x06,HEX); // byte 0 inviato
          Serial.print (0x00,HEX); // byte 1 inviato
          Serial.print (0x67,HEX); // byte 2 inviato
          // ora velocemente riempirò la scacchiera con i pedoni bianchi , tanto per vedere se aggiornerò la scacchiera visibile da Fritz.
          for (int i=0; i <= 63; i++){
              Serial.print (0x01,HEX);            
            }   break;
        }
     }
     while (Serial.available()) { //svuoto il buffer da eventuali altri caratteri che non mi servono più
        byte a = Serial.read();
   }
}

Registrato
michele.p
Administrator
Sr. Member
*****

Karma: +11/-2
Scollegato Scollegato

Messaggi: 657


Mostra profilo
« Risposta #4 inserita:: Marzo 08, 2018, 06:44:43 »

Non è facile seguire dei post così lunghi anche perché significherebbe, poi, andare a provare ciò che riporti.

Secondo me ti conviene, com'è logico in questi casi, andare per passi successivi. Far eseguire una sola azione, la più semplice del protocollo in oggetto e verificare se funziona eventualmente capendo il motivo di un non funzionamento.

Altrimenti detto, punta un tagret e cerca di ottenere solo quello.
Poiché non conosco tale protocollo allora la domanda è: qual è l'azione più semplice che si può compiere facendo uso del protocollo DGT?
Registrato
EtaBetaPot
Newbie
*

Karma: +0/-0
Scollegato Scollegato

Messaggi: 8


Mostra profilo E-mail
« Risposta #5 inserita:: Marzo 11, 2018, 01:05:43 »

Grazie Michele,hai pienamente ragione. Sto facendo dei piccoli passi positivi ... Vi aggiornerò sui risultati.
Ciao
Registrato
Pagine: [1]   Vai su
  Stampa  
 
Vai a:  

Copyright © 2017 Edizioni Master SpA. p.iva : 02105820787

Tutti i diritti di proprietà letteraria e artistica riservati. - Privacy



powered by Simple Machines