12
(PIC16LF877A, 8x8 BiColor DotLedMatrix) In un mondo di iPad, iPhone, ixxxx, tutto questo sembra ancronistico però... ecco la trasposizione elettronica del famoso gioco Forza4. Descrizione Tutto ebbe inizio nel momento in cui trovai in una bancarella un display a matrice di LED 8x8 bicolore ad un prezzo irrisorio (3.50EU): questo era sufficiente per creare lo schema di gioco che è in realtà 7 colonne per 6 righe. L'idea è sempre quella di usare componenti da costi contenuti (o free samples) e, anche in questo caso penso di aver ottenuto un buon compromesso. Il PIC utilizzato per esempio è un comune P16F877A, tanti PIN a disposizione, vari mA di corrente disponibile in ogni PIN... Per risparmiare spazio, un ULN2803 per assorbire la corrente dei LED mi è sembrata la soluzione più efficace, nulla vieta di sostituirlo con transistors equivalenti; tasti di recupero per la tastiera di comando (3 tasti comando : dx, sx, giu, 1 tasto power)... ad onor del vero avevo pensato ad una versione con accellerometro a due assi, magari nella versione 2012! un paio di transistor per l'autopower off, un semplice diodo per un rudimentale controllo livello carica batteria e una cella Li-Ion recuperata da una vecchia batteria per notebook. Anche la scelta del liguaggio/compilatore non è stata semplice. Avendo precedentemente realizzato in VB6 una versione per PC dell'omonimo gioco, pensavo di poter convertire in modo "semplice" il codice scritto in Visual Basic. In realtà 2 sono stati i problemi principali 1) Implementazione dell'algoritmo senza ricorsione 2) Stack limitato a 8 chiamate (nel P16xxxx) ALGORITMO IMPLEMENTATO Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=... 1 di 12 21/04/11 10.10

Forza4 PIC microcontroller

Embed Size (px)

DESCRIPTION

Forza4 PIC microcontroller

Citation preview

Page 1: Forza4 PIC microcontroller

(PIC16LF877A, 8x8 BiColor DotLedMatrix)

In un mondo di iPad, iPhone, ixxxx, tutto questo sembra ancronistico però... ecco la trasposizione elettronica del

famoso gioco Forza4.

Descrizione

Tutto ebbe inizio nel momento in cui trovai in una bancarella un display a matrice di LED 8x8

bicolore ad un prezzo irrisorio (3.50EU): questo era sufficiente per creare lo schema di gioco

che è in realtà 7 colonne per 6 righe.

L'idea è sempre quella di usare componenti da costi contenuti (o free samples) e, anche in

questo caso penso di aver ottenuto un buon compromesso.

Il PIC utilizzato per esempio è un comune P16F877A, tanti PIN a disposizione, vari mA di

corrente disponibile

in ogni PIN...

Per risparmiare spazio, un ULN2803 per assorbire la corrente dei LED mi è sembrata la

soluzione più efficace, nulla vieta di sostituirlo con transistors equivalenti;

tasti di recupero per la tastiera di comando (3 tasti comando : dx, sx, giu, 1 tasto power)... ad

onor del vero avevo pensato ad una versione con accellerometro a due assi, magari nella

versione 2012!

un paio di transistor per l'autopower off, un semplice diodo per un rudimentale controllo livello

carica batteria e una cella Li-Ion recuperata da una vecchia batteria per notebook.

Anche la scelta del liguaggio/compilatore non è stata semplice. Avendo precedentemente

realizzato in VB6 una versione per PC dell'omonimo gioco, pensavo di poter convertire in modo

"semplice" il codice scritto in Visual Basic. In realtà 2 sono stati i problemi principali

1) Implementazione dell'algoritmo senza ricorsione

2) Stack limitato a 8 chiamate (nel P16xxxx)

ALGORITMO IMPLEMENTATO

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

1 di 12 21/04/11 10.10

Page 2: Forza4 PIC microcontroller

Questo come altri giochi (tris, scacchi, etc...) sono di solito risolti usando diversi algoritmi, ma

tutti ricorsivi, dato che tendono a calcolare tutte le possibili mosse dei giocatori eseguendo la

costruzione di un "albero" di mosse possibili a cui viene assegnato un "peso".

L'algoritmo usato in questa implementazione è riconducibile ad un algoritmo MiniMax modificato

comunemente

chiamato NegaMax. Se vediamo il sorgente VB6, notiamo come la funzione Pensa :

- ha il compito di analizzare lo schema di gioco , eseguendo una mossa "virtuale",

- controllare un eventuale vittoria (ed uscire)

- richiamare se stessa se il livello lo consente, moltiplicando per -1 il risultato ottenuto

(da qui il nome NEGAmax)

Questo "livello" di pronfodità di controllo determina la bontà della giocata, ma anche un aumento

dei tempi di esecuzione della mossa. Nei PC di oggi non ci sono particolari problemi di stack,

quindi il livello di chiamate alle procedure lo possiamo considerare "infinito", nei PIC16 però il

numero di chiamate non può superare 8 livelli di stack.

Un rapido calcolo porta a definire un numero fisso per il livello, impostato in fase di

progettazione del

codice:

main 1° livello di stack

Pensa3 2° livello di stack

Display_PutPixel 3° livello di stack (per gestione del display)

mettiPezzo 3° livello di stack

Win4 3° livello di stack

togliPezzo 3° livello di stack

nextcolore 3° livello di stack

Pensa2 4° livello di stack

Pensa1 5° livello di stack

Pensa0 6° livello di stack

Da questo elenco si capisce che è difficile riuscire a chiamare per più di 5 volte la procedura

"pensa", dato che al suo interno sono comunque richiamate altre funzioni di supporto.

Per esempio la stessa Win4 è stata riscritta in un unico corpo (differentemente dal programma

VB6, che richiamava diverse funzioni:Win4Diag,Win4Oriz,Win4Vert) proprio per evitare di

sovraaffollare il ristretto stack a disposizione. Anche in questo caso la chiamata a 4 livelli di

"Pensa" è un giusto compromesso tra spazio a disposizione ,velocità della mossa e bontà della

giocata (che consente una visione sucessiva alla possibile mossa dell'avversario).

Proprio su questo punto inziano alcune note dolenti, visto che il quarzo utilizzato è un

"conservativo" 8Mhz: nel calcolare tutte le possibili mosse il tempo impiegato (a causa anche

della procedura di interrupt) non è dei più rapidi (qualche mio amico sembrava proprio scocciato

da questa attesa!) e lo possiamo rilevare in circa 20 secondi: ma perchè quando si gioca con un

avversario in carne ed ossa, si avverte meno questo senso di lentezza ???

Va da sè che inserendo un quarzo da 20 Mhz i tempi si dimezzano ampiamente !

Nell'assegnare un valore alla mossa, viene usata una tabella di pesi prefissata, che

"caratterizza" in un qualche modo la "personalità" del PIC, portandolo a preferire, per esempio,

le colonne centrali; volendo modificare questo comportamento dovrete assegnare dei valori

differenti all'array "Weight".

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

2 di 12 21/04/11 10.10

Page 3: Forza4 PIC microcontroller

Risolto il problema della ricorsione (di fatto è stata replicata 4 volte la funzione Pensa) e dello

stack (limitando il numero di procedure nidificate),si passa alla scelta del compilatore.

Il BASIC di OshonSoft sembrava poter gestire matrici e la ricorsione, a patto di usare variabili

globali; in realtà in fase di simulazione però, trovandomi valori sballati nelle variabili, sono stato

costretto a passare su MikroC 7.0 di Mikroelektronica; quest'ultimo tuttavia non gestendo

agevolmente le matrici mi ha costretto a rappresentare la matrice di gioco in un array di 6x7=42

elementi "Board".

Due livelli di gioco consentono di semplificare/velocizzare la mossa del PIC: nella modalità facile

si prevede la possibilità di generare "MaxMosseCasuali" (5) mosse casuali durante la sessione

di gioco, mentre nella difficile solo una, la prima.

CONSIDERAZIONI ELETTRICHE

Ci troviamo a dover gestire 8x8x2=128 LED con meno di 40 pin (in realtà ne avanzano) e con

una cella al litio da circa 2200mAh.

Innanzi tutto il PIC è del tipo funzionante a bassa tensione, questo ci permette "virtualmente" di

funzionare fino 2V... questo però non è possibile dato che la cella al Litio non dovrebbe

scendere sotto ai 3V: meglio così, daremo un segnale di batteria scarica al momento opportuno.

E' ovvio che la gestione dei LED deve essere multiplexata: abbiamo 8 righe, la persistenza sulla

retina del nostro occhio la inganniamo se scendiamo sotto i 20ms... 20ms:8=>2.5 ms.

Va da sè che la procedura di interrupt che gestirà la scansione delle righe dovrà essere inferiore

ai 2.5 ms. Per avere meno senso si sfarfallio è stato scelto un valore di circa 1.7ms:

' Timer0 Registers:' Prescaler=1:32; TMR0 Preset=150; Freq=589,62264Hz; Period=1,696 msOPTION_REG.T0CS = 0 ' bit 5 TMR0 Clock Source Select bit:0=Internal Clock (CLKO) /1=Transition on T0CKI pinOPTION_REG.T0SE = 0 ' bit 4 TMR0 Source Edge Select bit: 0=low/high / 1=high/lowOPTION_REG.PSA = 0 ' bit 3 Prescaler Assignment bit: 0=Prescaler is assigned tothe Timer0OPTION_REG.PS2 = 1 ' bits 2-0 PS2:PS0: Prescaler Rate Select bitsOPTION_REG.PS1 = 0OPTION_REG.PS0 = 0TMR0 = 150 ' preset for timer register

Per ogni riga assorbiremo la corrente (tramite l'ULN2803) dei led alimentati direttamente dalla

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

3 di 12 21/04/11 10.10

Page 4: Forza4 PIC microcontroller

porta del microcontrollore.

Avendo la possibilità di avere Led multicolore dovremo gestire una porta per gli 8 led di colore

rosso e una porta per gli 8 led di colore verde: accendendo entrambi i led di uno stesso "pixel"

otterremo il colore giallo.

Nel datasheet del Display si capisce che alimentando con una corrente di circa 20mA i LED

abbiamo una caduta di tensione di circa 2.1V (sia per il rosso che per il verde), a questa

dobbiamo aggiungere la tensione dell'ULN2803 (circa 0.85V): avendo 2.95V possiamo calcolare

il valore della resistenza da inserire in serie alla "riga" dei LED anche se a dire il vero sarebbe

meglio usare una resistenza per ogni colonna (quindi 8+8=16 resistenze in totale).

Fissando a 3.3V la minima tensione della batteria otteniamo

(3.3V-2.95V)/20mA=17.5 ohm

In realtà non essendo contento della luminosità ottenuta dai calcoli, ho "leggermente"

aumentato la corrente (stressando forse le porte del PIC) fissando una rLed di 6.8ohm :

considerato l'utilizzo non continuativo e multiplexato il tutto viene ampiamente ridimensionato e

digerito dal PIC (l'utilizzo in ambienti molto luminosi o all'esterno in presenza di giornata

soleggiata è praticamente impossibile!)

Fate attenzione però alla potenza dissipata: se accendiamo tutti i LED abbiamo 20mA x 8 =

160mA P=RxIxI=17x0.16x0.16=0.43 W, anche se multiplexata nel caso peggiore potremmo

trovarci con tutti i led sempre accesi, quindi direi di scegliere un accomodante 1/2 Watt.

la gestione dell'autopower off avviene con una coppia di normali transistor NPN-PNP. La

corrente gestita è di 100mA e di 200mA di picco e quindi viene (abbastanza) rispettata: dopo

circa un minuto e mezzo di inattività da parte dell'utente il gioco si spegne (senza salvare !!)

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

4 di 12 21/04/11 10.10

Page 5: Forza4 PIC microcontroller

il calcolo del livello di tensione delle cella viene valutato tramite l'ADC leggendo la tensione

presente sul diodo 1N4148. La tensione in questione possiamo considerarla "fissa" ed

approssimarla ad un valore di 0.75V. Quello che varia nel nostro caso è la VREF , essendo

collegata alla batteria, che rifletterà direttamente le sue variazioni.

Quindi nel caso di batteria carica

4.1 : 0.75 = 1024 : x x= (0.75*1024)/4.1 = 187

nel caso di batteria scarica

3 : 0.75= 1024 : x x= (0.75*1024)/3=256

Da qui si capisce come dopo qualche prova e una timida taratura possiamo avvisare l'utente sul

livello di carica della batteria gestendo il pixel in posizione 7,8:

pixel spento : carica normale

pixel verde : batteria in esaurimento

pixdel rosso : ricaricare batteria

verificando il valore letto dall ADC (AN0) e confrontandolo con dei valori di finestra fissi.

IL PROGRAMMA

Ecco la rappresentazione in memoria dello schema di gioco (array "Board")

Colonna 1 7 ---------------------- Riga 6 | 35 36 37 38 39 40 41 | 27 29 30 31 32 33 34 | 21 22 23 24 25 26 27 | 14 15 16 17 18 19 20 | 07 08 09 10 11 12 13Riga 1 | 00 01 02 03 04 05 06

Due funzioni specifiche consentono di passare dalla forma matriciale a quella vettoriale

degli indici, in particolare:

iTOrc => converte l'indice di Board in una coppia di valori indice riga, indice colonna

rcTOi => converte una coppia di indici riga,colonna in un indice del vettore Board

Come già accennato il vettore "Weight" contiene il "carattere" dell'algoritmo ossia un peso per

ogni casella dello schema: questo viene usato dalla funzione "Pensa".

In una futura versione si potrebbero gestire diversi array Weight prelevandoli magari dalla

Eeprom del PIC in modo da simulare un comportamento differente tra una sessione di gioco e

l'altra.

Un funzione importante è quella che verifica la vittoria di un certo colore "Win4". Questa

controlla prima le posizioni orizzontali, poi le verticali quindi le due diagonali seguendo uno

schema fisso di casella di partenza specificati in W4Oriz,W4Vert,W4Diag1,W4Diag2.

Questi contengono gli indici di Board da cui iniziare a contare le pedine dello stesso colore.

Per esempio i primi valori di "W4Oriz" sono

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

5 di 12 21/04/11 10.10

Page 6: Forza4 PIC microcontroller

0,1,2,3,7,...

significa che la procedura verificherà le 4 caselle adiacenti partendo dalla 0,1,2,3... la posizione

4 non dovrà essere verificata poichè nel senso orizzontale non è possibile mettere più di 3

pedine in fila; pertanto la prossima casella di partenza che dovrà essere verificata risulta essere

la 7.

Come si calcolano le caselle adiacenti ?

Beh dallo schemino si capisce che

per le orizzontali - => basta sommare 1 all'indice precedente

per le verticali | => basta sommare 7 all'indice precedente

per la diagonale / => basta sommare 8 all'indice precedente

per la diagonale => basta sommare 6 all'indice precedente

Due funzioni speciali permettono di

1) ricominciare una nuova partita

2) salvare la situazione corrente

Per ricominciare ci si deve spostare con il tasto sx sulla colonna 1 e tenendo premuto il tasto sx,

premere contemporaneamente il tasto dx (attenzione questo annulla anche l'ultimo salvataggio).

In modo analogo per salvare una partita ci si deve spostare con il tasto dx sulla colonna 7 e

tenendo premuto il tasto dx, premere contemporaneamente il tasto sx: dopo circa mezzo

secondo l'array "Board" viene salvato nella Eeprom del PIC (posizioni da 0 a 41) (vedere

"SaveBoard" e "LoadBoard").

All'accensione successiva verrà ripristinata la situazione salvata.

UTILIZZO DEL DISPLAY

Come già accennato il display viene gestito tramite la multiplazione. Le righe sono attivate

sequenzialmente una dopo l'altra (vedi "interrupt") in modo automatico dal PIC ogni 1.7ms: in

questa fase sono attivati i Led che sono scritti nella "memoria video". La matrice (8x8)

"Display" viene infatti utilizzata come una rudimentale memoria video di 64 byte: ogni byte

rappresenta un pixel della matrice e può assumere i valori:

0 : led spenti

1 : led rosso ON

2 : led verde ON

3 : led rosso ON & led verde ON

Per semplificare l'accesso al display, apposite funzioni permettono di accedere alla memoria

video:

Display_PutPixel : accende un pixel alla posizione riga,colonna

Display_CLS : accende tutti i pixel della matrice con un certo colore

Display_bar : mostra la barra di scelta livello

Display_SceltaLivello : mostra la schemata di scelta livello

SCHEMA ELETTRICO

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

6 di 12 21/04/11 10.10

Page 7: Forza4 PIC microcontroller

In realtà sono 2 gli schemi elettrici che generano 2 board differenti: una per la parte MCU e

l'altra per la parte display: questa è stata più una necessità iniziale di sviluppo.

Schema display

Prevede la connessione con la parte MCU con 8 fili per i led rossi, 8 fili per i led verdi e 9 per la

gestione delle righe (8+1massa). La pedinatura del display LED 8x8 presente nel PDF risulta

essere:

1 Cat Row 8 Cat Row 1 24

2 Cat Row 7 Cat Row 2 23

3 Cat Row 6 Cat Row 3 22

4 Cat Row 5 Cat Row 4 21

5 Anode Col1 Gr Anode Col8 Rd 20

6 Anode Col2 Gr Anode Col8 Rd 19

7 Anode Col3 Gr Anode Col8 Rd 18

8 Anode Col4 Gr Anode Col8 Rd 17

9 Anode Col5 Gr Anode Col8 Rd 16

10 Anode Col6 Gr Anode Col8 Rd 15

11 Anode Col7 Gr Anode Col8 Rd 14

12 Anode Col8 Gr Anode Col8 Rd 13

Le resistenze utilizzate sono da 6.8 Ohm 1/2 watt.

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

7 di 12 21/04/11 10.10

Page 8: Forza4 PIC microcontroller

Schema MCU

Sono previsti una serie di connettori (strip line femmina) su cui innestare i 3 cavi "flat"

autocostruiti

(uno per i led rossi, uno per i verdi , uno per le righe).

Anche il quarzo è innestato su un connettore femmina, così da poterlo cambiare per velocizzare

le operazioni di gioco.

Nessun componente è critico.

Le resistenze sono da 1/4 di watt.

Schema elettrico eagle.

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

8 di 12 21/04/11 10.10

Page 9: Forza4 PIC microcontroller

Schema LochMaster.

Realizzazione su millefori. Lato componenti

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

9 di 12 21/04/11 10.10

Page 10: Forza4 PIC microcontroller

Realizzazione su millefori. Lato Rame

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

10 di 12 21/04/11 10.10

Page 11: Forza4 PIC microcontroller

Realizzazione Cablaggio

REALIZZAZIONE PRATICA

Il tutto è stato inserito in una scatola di derivazione Gewiss 10x15 abbassata di circa 2,5 cm.

Sulla parte superiore è stato praticato un buco rettangolare della dimensione del display e sono

stati "appoggiati" i tasti dx,giu,sx, mentre il tasto power è posto lateralmente.

Tagliando la scatola ho dovuto inserire dei tasselli (D=4mm) nei fori dei 4 angoli per poter

riagganciare

il coperchio.

La batteria risulta quindi inserita all'interno e chiusa dalle 4 viti: per ricaricarla si deve

necessariamente aprire il coperchio svitandole.

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

11 di 12 21/04/11 10.10

Page 12: Forza4 PIC microcontroller

BUON DIVERTIMENTO !

Sono a disposizione

gli schemi,

i sorgenti,

il programma Win32 del gioco da me sviluppato in VB6.

Anteprima http://www.grix.it/editor/FCK26/editor/fckeditor.html?InstanceName=...

12 di 12 21/04/11 10.10