Introducere

Denumire proiect: AccelSnake
Autor: Tanase Narcis-Ciprian
Grupa: 331CC

Scopul proiectului este implementarea jocului clasic snake, folosind ca dispozitiv de intrare un accelerometru iar ca dispozitiv de iesire(afisare) o matrice de leduri.

Regulile jocului sunt foarte simple: Utilizatorul controleaza un sarpe ce se misca pe o tabla dreptunghiulara. Pe aceasta tabla se afla la orice moment un singur cadou ce poate fi colectionat de sarpe. Atunci cand a fost colectat un cadou apare altul (la o pozitia aleatoare) iar sarpele isi mareste dimensiunea cu o unitate. Trebuie evitata situatia in care capul sarpelui se intersecteaza cu un segment al corpului. Pe de alta parte, coliziunile cu peretii sunt permise, iar sarpele va iesi in acest caz din peretele opus. Jocul are trei nivele de dificultate, iar la fiecare nivel creste viteza de deplasre. De asemenea, utilizatorul are la dispozitie 3 vieti, iar la sfarsitul jocului (dupa pierderea celor trei vieti) va fi afisat scorul realizat (atunci cand se colecteaza un cadou, utilizatorul primeste 10 puncte).

Am decis sa fac acest proiect pentru ca majoriattea implementarilor de snake folosesc ca display un ecran LCD, iar inputul se da prin intermediul unor butoane. Consider ca abordarea pe care am ales-o este mai interesanta si mi va permite sa inteleg cum functioneaza diferite componente hardware dar si diferite facilitati ale microcontrollerului ATMega16, cum ar fi convertorul analog digital sau sistemul de intreruperi.

Descriere generală

Schema bloc dupa care functioneaza aplicatia este destul de simpla. Utilizatorul da inputul prin intermediul unui accelerometru. Atunci cand sarpele se deplaseaza pe orizontala, directia lui poate fi schimbata daca accelerometrul este miscat in sus sau in jos, iar daca sarpele se deplaseaza pe verticala, directia lui se poate modifica daca accelerometrul este miscat spre stanga sau spre dreapta. Rezultatul miscarii este receptat de accelerometru si transmis convertorului analog-digital inclus in microcontrollerul ATMega16. Dupa prelucrarea inputului si actualizarea starii jocului, se transmite outputul catre matricea de leduri.

O schemă bloc cu toate modulele proiectului vostru, atât software cât şi hardware însoţită de o descriere a acestora precum şi a modului în care interacţionează.

Exemplu de schemă bloc: http://www.robs-projects.com/mp3proj/newplayer.html

Hardware Design

Lista de piese

  • 1 x accelerometru MMA7341L
  • 1 x matrice de leduri 8×8 TOM-2088BH-B
  • 1 x integrat ULN2804AG
  • 8 x rezistenta de 220 Ohmi

Circuit principal

Circuitul de baza este organizat in jurul uC-ului ATMega16 si cuprinde componente necesare pentru alimentarea si programarea uC-ului:

Matrice de leduri

Matricea pe care o voi folosi pentru afisare contine 64 de leduri, asezate in forma unui patrat cu latura de 8 leduri. Schema unei astfel de matrice este detaliata in figura de mai jos:

Pentru aprinderea ledului situat pe randul x si coloana y (1 ⇐ x, y ⇐ 8) trebuie sa aplicam acestuia o tensiune suficient de mare; din punct de vedere digital, asta inseamna ca pe randul x sa aplicam un nivel logic '1' iar pe coloana y un nivel logic '0'.

Tehnica pe care o voi folosi pentru manipularea matricei de leduri este cea de 'scanare'. Mai intati se va afisa coloana 1. Astfel, se incarca pe randurile 1..8 semnale logice '0' si '1', in functie de ce se doreste a fi afisat pe coloana 1, apoi se pune pe prima coloana un nivel logic '0'. Dupa acest prim pas se pune coloana 1 pe '1' logic si se trece la coloana '2'. Se incarca pe randurile 1..8 valorile corespunzatoare cele de-a doua coloana, dupa care se pune coloana 2 pe '0' logic. Procedeul se repeta pentru toate cele 8 coloane. Trebuie observat ca atunci cand dorim sa afisam starea tablei de joc, afisarea nu se face dintr-o data, ci este compusa din 8 sub-faze (cate una pentru fiecare coloana). Acest lucru este necesar deoarece microcontrollerul ATMega16 nu poate produce suficient curent pentru aprinderea tuturor celor 64 de leduri (sau a unui numar apropiat) simultan. In schimb, se pot aprinde maxim 8 leduri la un anumit moment de timp. Pentru ca efectul sa fie cel dorit, trebuie ca aprinderea unei coloane si trecerea la urmatoarea coloana aiba loc la o frecventa foarte mare, pacalind astfel ochiul uman.

Sa presupunem ca avem nevoie de un curent de 20 mA pentru aprinderea unui singur LED. Daca la un moment dat trebuie sa avem aprinse 8 leduri, ATMega16 nu poate produce destul curent fara a provoca daune portului pe care se face afisarea. Se poate folosi un amplificator cu tranzistor ca in figura de mai jos:

Rezistorul R3 functioneaza ca un limitator de curent atat pentru LED cat si pentru tranzistor. Rezistorii R1 si R2 formeaza impreuna un divizor de tensiune. Desi aceasta solutie functioneaza, am decis sa folosesc circuitul integrat ULN2804AG. Acesta se bazeaza pe tranzistoare Darlington, fiecare tranzistor putand produce pana la 100 mA de curent. Asadar, schema finala a circuitului matricei de leduri este urmatoarea:

Accelerometru

Accelerometrul pe care am decis sa il folosesc este MMA7341L. Acest dispozitiv ofera posibilitatea de a masura acceleratia pe 3 axe (pe verticala si 2 pe orizontala). Pentru jocul de snake, schimbarea directiei la un moment dat se face alegand din doua optiuni posibile: stanga sau dreapta, atunci cand sarpele se deplaseaza in sus sau jos; sus sau jos, atunci cand sarpele se deplaseaza in stanga sau dreapta. Din acest motiv, ar fi suficienta utilizarea unei singure axe de deplasare. Accelerometrul poate fi conectat la microcontrollerul ATMega16 cu usurinta, prin construirea unui circuit ca cel detaliat in schema de mai jos:

Software Design

Codul aplicatiei a fost scris in limbajul C, compilatorul folosit fiind WinAVR iar editorul Programmers Notepad. Simularea jocului s-a facut in Proteus. Mai jos este atasata o imagine cu aceasta simulare:

Starea jocului este memorata intr-o matrice de dimensiunea 8×8 (ce corespunde matricei de leduri pe care se face afisarea). Spatiile goale sunt reprezentate prin valoarea 0, cadoul este reprezentat prin valoarea 0xFF iar corpul sarpelui este format din numere cuprinse intre 1 si n, unde n este lungimea sarpelui. Numerotarea se face de la capul sarpelui spre coada acestuia.

Atunci cand dorim sa mutam sarpele cu o unitate, pe o anumita directie, trebuie practic sa incrementam fiecare valoare din corpul sau, apoi sa stergem elementul coada si sa inseram un nou element cap (cu valoarea 1).

Daca sarpele colecteaza un cadou, atunci dimensiunea sa se va mari cu o unitate, adica se va mai adauga un nou element in fata capului (acest element va deveni noul cap).

Pentru simularea in Proteus am legat cele doua butoane la pinii PB0 respectiv PB1, pentru a avea acces la Timer0 si Timer2. La apasarea uni buton se genereaza o intrerupere pentru timerul corespunzator, iar in rutina intreruperii se va procesa inputul. Matricea de leduri a fost conectata la porturile A si D. La portul D se conecteaza catodul ledurilor iar la portul A se conecteaza anodurile.

Pentru a nu abuza de memoria microcontrollerului, care este oricum destul de limitata, majoritatea variabilelor globale din program sunt de tipul unsigned char. De asemenea, am minimizat si numarul de variabile locale pentru a nu depasi limita stivei.

Mai jos este o lista cu antetele functiilor folosite in implementarea jocului, insotite de o scurta descriere:

/**
 * Initializeaza variabilele de joc.
 */
void init_game(void);
 
/**
 * Reseteaza tabla de joc (o umple cu zerouri).
 */
void reset(void);
 
/**
 * Initializeaza counterul care determina viteza jocului.
 */
void init_counter(void);
 
/**
 * Initializeaza butonul de pe pinul PB0 ca intrare.
 */
void init_input1(void);
 
/**
 * Initializeaza butonul de pe pinul PB1 ca intrare.
 */
void init_input2(void);
 
/**
 * Initializeaza porturile de iesire.
 */
void init_output(void);
 
/**
 * Face toate initializarile necesare aplicatiei.
 */
void init(void);
 
/**
 * Genereaza un cadou aflat la o pozitie aleatoare pe tabla.
 */
void generate_gift(void);
 
/**
 * Incarca o coloana a tablei de joc in vederea afisarii.
 */
void load_col(unsigned char j);
 
/**
 * Deseneaza tabla de joc pe matricea de leduri.
 */
void draw_board(void);
 
/**
 * Deseneaza textul corespunzator unui anumit nivel.
 */
void draw_level(unsigned char level);
 
/**
 * Intoarce 1 daca la urmatorul pas se va produce o coliziune
 * intre capul sarpelui si o parte a corpului. Intoarce 0 in
 * caz contrar.
 */
unsigned char detect_collision(void);
 
/**
 * Misca sarpele pe tabla.
 */
void move_snake(void);
 
/**
 * Rutina de apasarea a butonului de pe PB0.
 */
ISR(TIMER0_COMP_vect);
 
/**
 * Rutina de apasarea a butonului de pe PB1.
 */
ISR(TIMER1_COMPB_vect);
 
/**
 * Rutina counterului (deplasarea sarpelui la un interval de timp).
 */
ISR(TIMER2_COMP_vect);

Rezultate Obţinute

Placuta initiala:

p1553_03-06-10.jpg

p1554-01-_03-06-10.jpg

Componente pentru partea a doua a proiectului:

p1614_03-06-10.jpg

Hardware final:

p0159_04-06-10.jpg

p0157_04-06-10.jpg

p0158_04-06-10.jpg

p0200-01-_04-06-10.jpg

Concluzii

Desi partea software a proiectului este functionala, nu pot spune acelasi lucru si despre hardware. Componentele au fost lipite in circuit, insa acesta nu functioneaza. De asemenea, nu am putut cumpara un accelerometru in timp util, asa ca am decis sa realizez partea de input cu ajutorul a doua butoane. Chiar daca nu am reusit tot ce mi-am propus atunci cand am decis sa realizez acest proiect, sper sa il continui in viitor si sa implementez corect si partea de hardware.

Download

Arhiva are urmatoarea structura de directoare/fisiere:

  • Schema Proteus: contine schemele pentru simulare in Proteus AccelSnake.dsn si AccelSnake2.dsn. Se va folosi AccelSnake2.dsn;
  • Cod C: contine sursa snake.c, care va fi compilata cu WinAVR si folosita pentru simularea in Proteus;
  • Schema Bloc: contine o imagine cu schema bloc a aplicatiei;
  • Schema Circuit: contine schemele in Eagle pentru circuitele detaliate in documentatie.

Arhiva proiect

Jurnal

  • cumparare componente pentru circuitul de baza
  • realizare placuta imprimata
  • lipire componente pe placuta imprimata
  • testarea circuitului de baza si debugging
  • proiectarea circuitului pentru jocul de snake
  • implementare software a jocului
  • cumparare componente
  • lipire componente pe circuitulu final
  • testarea aplicatiei finale si debugging

Bibliografie/Resurse

Datasheet-uri

Software

Hardware

pm/prj2010/dtudose/accelsnake.txt · Last modified: 2021/04/14 17:07 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0