Jocuri de Lumini Tridimensionale

Cuprins

LISTA FIGURILOR

LISTA TABELELOR

CAPITOLUL 1

INFORMAȚII GENERALE

1.1 ALEGEREA ȘI IMPORTANȚA TEMEI

1.2 CE ESTE UN CUB DE LEDURI?

1.3 CE ESTE UN VOXEL?

1.4 CUM FUNCȚIONEAZĂ UN CUB DE LEDURI?

1.5 SCHEMA BLOC

CAPITOLUL 2

INTRODUCERE

2.1 DESCRIEREA PLĂCII ARDUINO UNO

2.2 SPECIFICAȚII

2.3 ALIMENTARE

2.4 MEMORIE 18

2.5 INTRĂRI ȘI IEȘIRI

2.6 COMUNICARE

2.7 PROGRAMARE

2.8 RESET SOFTWARE (AUTOMAT)

2.9 PROTECȚIE DE SUPRA-CURENT A USB-ULUI

2.10 CARACTERISTICI FIZICE

2.11 MODULUL MICRO SD

2.12 DESCRIEREA MICROCONTROLLERULUI STC12C5A60S2

2.13 TRĂSĂTURI

CAPITOLUL 3

CONSTRUCȚIA CUBULUI

3.1. LISTA DE COMPONENTE

3.2. ANATOMIA CUBULUI DE LEDURI

3.3 DIMENSIONAREA CUBULUI

3.4 EXPANSIUNEA PORTURILOR DE INTRARE/IEȘIRE, MULTIPLEXARE

3.5 ALEGEREA LEDURILOR

3.6 ALEGEREA REZISTOARELOR

3.7 ALEGEREA MĂRIMII CUBULUI

3.8 CREAREA ȘABLONULUI

3.9 SUDAREA LEDURILOR ÎN STRATURI

3.10 SUDAREA STRATURILOR

CAPITOLUL 4

CONSTRUCȚIA PLĂCII DE CONTROL

4.1 SCHEMA CONTROLERULUI

4.2 MICROCONTROLERUL STC12C5A60S2

4.3. LATCHUL 74HC573

4.4. SELECTORUL DE STRATURI ULN2803

4.5. SOCLURI DE CI, REZISTOARE ȘI CONECTORI

CAPITOLUL 5

PROGRAMAREA COMPONENTELOR

5.1 PROGRAMAREA JOCULUI DE LUMINI

5.2 COMUNICAREA CALCULATORULUI CU PLACA DE CONTROL

5.3 COMUNICAREA PRIN INTERMEDIUL ARDUINO

CONCLUZII

BIBLIOGRAFIE

ANEXE

LISTA FIGURILOR

Figura 1 Ilustrarea unui voxel într-o grilă, fiecare conținând o valoare a unei culori 18

Figură 1.2 Schema bloc 19

Figură 3.1 Straturile cubului………………………………………………………………………………………………………..28

Figură 3.2 Coloanele cubului ………………………………………………………………………………………………………..28

Figură 3.3 Leduri………………………………………………………………………………………………………………………………30

Figură 3.4 Rezistoare 470Ω …………………………………………………………………………………………………………….32

Figură 3.5 Lungimea picioarelor unui LED …………………………………………………………………………………..35

Figură 3.6 Spațiere între leduri ……………………………………………………………………………………………………33

Figură 3.7 Șablon ……………………………………………………………………………………………………………………………34

Figură 3.8 Trasarea șablonului …………………………………………………………………………………………………….34

Figură 3.9 Testarea șablonului …………………………………………………………………………………………………….35

Figură 3.10 SudareA straturilor…………………………………………………………………………………………………..36

Figură 3.11 Aranjare leduri…………………………………………………………………………………………………………..37

Figură 3.12 Sudare leduri……………………………………………………………………………………………………………….37

Figură 3.13 Sârma de rezistență…………………………………………………………………………………………………….38

Figură 3.14 Strat complet………………………………………………………………………………………………………………38

Figură 3.15 Strat complet lateral……………………………………………………………………………………………….38

Figură 3.16 Testarea ledurilor sudate…………………………………………………………………………………………39

Figură 3.17 Unghi mai mare de 90̊…………………………………………………………………………………………………….40

Figură 3.18 Unghi de 90̊…………………………………………………………………………………………………………………….40

Figură 3.19 8 Straturi……………………………………………………………………………………………………………………40

Figură 3.20 Îndoitură de 3MM………………………………………………………………………………………………………..41

Figură 3.21 Primele straturi sudate……………………………………………………………………………………………..42

Figură 3.22 Testarea fiecărui strat……………………………………………………………………………………………..43

Figură 3.23 Cubul complet……………………………………………………………………………………………………………..43

Figură 3.24 Cubul așezat pe bază……………………………………………………………………………………………………44

Figură 3.25 Sudarea catozilor la masă (1)……………………………………………………………………………………45

Figură 3.26 Sudarea catozilor la masă (2)…………………………………………………………………………………..45

Figură 3.27 Cabluri panglică…………………………………………………………………………………………………………46

Figură 3.28 Sudarea cablurilor panglică de anozi și masă…………………………………………………………46

Figură 4.1 Schema controllerului ……………………………………………………………………………………………….47

Figură 4.2 Pini STC12C5A60S2………………………………………………………………………………………………………….48

Figură 4.3 Latch 74HC573………………………………………………………………………………………………………………..49

Figură 4.4 Circuit de multiplexare……………………………………………………………………………………………….50

Figură 4.5 ULN2803…………………………………………………………………………………………………………………………..51

Figură 4.6 Tranzistori Darlington……………………………………………………………………………………………….51

Figură 4.7 Selectorul de straturi în circuit……………………………………………………………………………….52

Figură 4.8 Socluri CI, Rezistoare, Oscilocuarț…………………………………………………………………………..53

Figură 5.1 DotMatrixJava……………………………………………………………………………………………………………..55

Figură 5.2 Convertor USB către TTL……………………………………………………………………………………………56

Figure 5.3 Controlarea ledurilor direct de la PC……………………………………………………………………..56

Figură 5.4 Ansamblul Arduino……………………………………………………………………………………………………….57

Figură 5.5 Conexiunea dintre Arduino și Placa de Control……………………………………………………….58

Lista tabelelor

Tabel 1 Date de catalog 21

Tabel 2 Lista de componente 26

Tabel 3 Dimensiunile cubului 28

Tabel 4 Consumul ledurilor 28

Tabel 5 Datele de catalog ale ledului 29

Tabel 6 Principiul de functionare 49

CAPITOLUL 1

Informații Generale

Alegerea și importanța temei

Tema “Jocuri de lumini tridimensionale” a fost aleasă în baza unei realizări practice care să reflecte cunoștințele acumulate de-a lungul facultății. Acestea au fost, în mare parte, dobândite la materiile Măsurători în Electronică și Telecomunicații (METc) și Instrumentație în Electronică de Masură (IEM) unde, datorită accesului la echipamentele de laborator, mi-am clădit bazele în partea practică a circuitelor. De asemenea, mai sunt de menționat materiile Proiect 2, Procesoare Electronice de Putere (PEP), Sisteme Electronice Programabile (SEP) și Analiza Asistată de Calculator a Circuitelor Electronice de Putere (AACCEP) care m-au ajutat la înțelegerea părții teoretice și a programării.

Importanța temei este pe plan personal, întrucât imi va pune la încercare atât îndemânarea practică la construcția fizică a cubului și a plăcii de comandă, cât și abilitatea de a stabili un plan teoretic pe baza cunoștințelor acumulate în facultate.

În continuare, îmi voi propune realizarea logică și practică a unui cub de 512 led-uri ce se vor aprinde în vederea formării unui joc de lumini bine coordonat, comandat prin Arduino.

Ce este un cub de leduri?

Un cub de leduri este asemănător unui ecran de leduri, dar este mai special fiindcă mai are încă o dimensiune facându-l astfel tridimensional. Poate fi gândit ca o mulțime de afișaje de mică rezoluție. În afișajele simple este normal ca pixelii să fie amplasați cât mai aproape unul de celălalt pentru a se vedea mai bine, dar la cub trebuie să poți vedea prin el, deci avem nevoie de o distanță mai mare între pixeli (care se transformă în voxeli când vorbim despre 3D). Această distanță este un compromis între cât de ușor se poate vedea în spate și fidelitatea voxelilor.

Având în vedere că este mai multă muncă implicată în crearea unui cub decât în a unui afișaj, ele sunt de obicei de rezoluție mică. Un afișaj de dimensiuni 8×8 pixeli reprezintă doar 64 de leduri, dar un cub de leduri de dimensiunea 8x8x8 reprezintă 512 leduri, un ordin de mărime mai dificil de realizat. De aceea, cuburile de leduri sunt făcute la o rezoluție mai mică [7].

Ce este un voxel?

Am menționat mai sus termenul de voxel. Un voxel reprezintă o valoare pe o grilă aflată într-un spațiu tridimensional. Voxelul este o combinație de “volum” și “pixel”, unde pixelul la rândul său este o combinație de “poză” și “element”. Se mai poate face o analogie cu texelul care reprezintă o imagine 2D într-un bitmap. Precum pixelii dintr-un bitmap, voxelii însuși nu au pozițiile (coordonatele) codate în mod explicit cu valorile acestora. În schimb, poziția unui voxel se deduce pe baza poziției sale în raport cu alți voxeli (de exemplu în structura de date care formează o singura imagine volumetrică). Spre deosebire de pixeli și voxeli, punctele și poligoanele sunt adesea reprezentate în mode explicit de către coordonatele nodurilor lor. O consecință directă a acestei diferențe este aceea că poligoanele sunt capabile de a reprezenta în mod eficient structuri 3D simple cu o mulțime de spațiu gol sau umplut omogen, în timp ce voxelii sunt utilizați la reprezentarea spațiilor eșantionate în mod regulat [20].

Cum funcționează un cub de leduri?

Cubul are 512 leduri. Dacă am avea câte un port dedicat de intrare/ieșire pentru fiecare led ar îngreuna situația foarte mult. Am avea nevoie de un microcontroller cu 512 porturi de intrare/ieșire și am trage 512 fire prin cub.

În schimb, cubul de leduri se bazează pe un fenomen optic numit persistența viziunii. Este un fenomen optic în care s-a constatat că o imagine poate rămâne pe retină, un timp de aproximativ 25% dintr-o secundă, după ce aceasta a încetat să mai fie vizibilă. Așadar, dacă aprindem în mod intermitent un led la o viteză foarte mare, imaginea va rămâne impregnată pe retină încă puțin timp după ce ledul s-a stins. Prin aprinderea în mod intermitent a fiecărui strat al cubului, unul după altul foarte rapid, se creează iluzia unei imagini 3D, când, de fapt, noi ne uităm la o serie de imagini 2D suprapuse una peste cealaltă. Acest lucru se mai numește și care formează o singura imagine volumetrică). Spre deosebire de pixeli și voxeli, punctele și poligoanele sunt adesea reprezentate în mode explicit de către coordonatele nodurilor lor. O consecință directă a acestei diferențe este aceea că poligoanele sunt capabile de a reprezenta în mod eficient structuri 3D simple cu o mulțime de spațiu gol sau umplut omogen, în timp ce voxelii sunt utilizați la reprezentarea spațiilor eșantionate în mod regulat [20].

Cum funcționează un cub de leduri?

Cubul are 512 leduri. Dacă am avea câte un port dedicat de intrare/ieșire pentru fiecare led ar îngreuna situația foarte mult. Am avea nevoie de un microcontroller cu 512 porturi de intrare/ieșire și am trage 512 fire prin cub.

În schimb, cubul de leduri se bazează pe un fenomen optic numit persistența viziunii. Este un fenomen optic în care s-a constatat că o imagine poate rămâne pe retină, un timp de aproximativ 25% dintr-o secundă, după ce aceasta a încetat să mai fie vizibilă. Așadar, dacă aprindem în mod intermitent un led la o viteză foarte mare, imaginea va rămâne impregnată pe retină încă puțin timp după ce ledul s-a stins. Prin aprinderea în mod intermitent a fiecărui strat al cubului, unul după altul foarte rapid, se creează iluzia unei imagini 3D, când, de fapt, noi ne uităm la o serie de imagini 2D suprapuse una peste cealaltă. Acest lucru se mai numește și multiplexare. La aceasată configurație avem nevoie de 64 (pentru anoduri) + 8 (pentru fiecare strat) porturi de intrare/ieșire [6].

Schema bloc

CAPITOLUL 2

Introducere

Descrierea plăcii Arduino Uno

Arduino Uno [1] este o placă cu microcontroller, microcontroller bazat pe modelul ATmega328. Aceasta are 14 pini de intrare/ieșire (dintre care 6 pot fi folosiți ca ieșiri PWM), 6 intrări analogice, un rezonator ceramic de 16 MHz, o conexiune USB, un jack de alimentare, un antet ICSP și un buton de reset. Placa conține tot ce îi este necesar microcontrollerului. Se conectează pur și simplu la calculator prin intermediul unui cablu USB sau se alimentează cu ajutorul unui adaptor AC/DC sau unei baterii.

Uno diferă de celelalte plăci prin faptul că nu folosește un driver cip FTDI USB-către-serial, ci folosește cipul Atmega16U2 (Atmega8U2 updatat la versiunea R2) programat drept un convertor USB-către-serial.

Revizia 2 a plăcii Uno are în plus o rezistență ce trage linia 8U2 HWB la masă, făcând-o mai usor de transpus în modul DFU .

Revizia 3 a plăcii Uno are următoarele caracteristici noi:

Pini de ieșire 1.0: s-au adăugat pini SDA și SCL care sunt amplasați lângă pinul AREF și încă doi pini noi amplasați lângă pinul de RESET, pinul IOREF care îi permite scutului să adapteze voltajul dat de placă. Pe viitor scuturile vor fi compatibile atât cu placa ce folosește AVR , care operează cu 5V, cât și cu placa Arduino Due care operează la 3.3V. Cel de al doilea pin nu este folosit încă, este rezervat pentru scopuri ulterioare.

Un circuit de RESET mai puternic

Cipul Atmega8U2 este înlocuit de Atmega16U2

“Uno” înseamnă unu în limba Italiană și este numit pentru a marca viitoarele lansări de Arduino 1.0. Uno si versiunea 1.0 vor fi versiunile de referință pentru Arduino de aici înainte. Uno este ultima apărută dintr-o serie de plăci Arduino cu USB, de altfel și modelul de referință pentru platforma Arduino.

Specificații

Tabel Date de catalog

Alimentare

Arduino Uno poate fi alimentat via USB sau cu o sursă externă. Sursa este selectată automat.

Sursa externă poate fi, fie de la un adaptor CA/CC ,fie o baterie. Adaptorul poate fi conectat la mufa de alimentare printr-un conector de 2.1 mm. Bateria poate fi conectată la pinii GND și Vin de la conectorul de alimentare.

Placa poate funcționa cu o sursă externă de 6 si 20 de volți. Cu toate aceste, în cazul în care este alimentată cu mai puțin de 7V, pinul de 5V poate furniza mai puțin de cinci volți și placa poate fi instabilă. Dacă se utilizează mai mult de 12V, regulatorul de tensiune se poate supraîncălzi și deteriora placa. Intervalul recomandat este între 7-12 volți.

Pinii de alimentare:

VIN – Tensiunea de intrare a plăcii Arduino atunci când foloseste o sursă externă. Se folosește acest pin și atunci când se furnizează tensiune prin mufa de alimentare

5V – Acest pin furnizează o tensiune stabilă de 5V de la stabilizatorul de pe placă. Placa poate fi alimentată atât de la mufa de alimentare de CC (7-12V), conectorul USB (5V) sau pinul VIN (7-12V). Alimentând prin pinii de 5V sau 3.3V ignoră stabilizatorul și acest lucru poate duce la deteriorarea plăcii

3V3 – O sursă de 3.3V generată de stabilizator. Curentul maxim este de 50 mA

GND – pinii conectați la masă

IOREF – Acest pin furnizază tensiunea de referință cu care lucrează microcontrollerul. Un scut configurat corect poate citi tensiunea de pe acest pin și astfel selectează sursa cea mai adecvată sau activează traductorii de tensiune pe ieșiri pentru a lucra cu 5V sau 3.3V.

Memorie

ATmega328 are o memorie de 32 KB (dintre care 0.5 KB sunt folosiți de bootloader), 2 KB de SRAM și 1 KB de EPROM.

Intrări și Ieșiri

Oricare dintre cei 14 pini digitali de pe Uno pot fi folosiți, fie ca intrare, fie ca ieșire, folosind funcțiile pinMode(), digitalWrite() și digitalRead(). Aceștia operează la 5V, fiecare pin poate furniza sau recepționa un maxim de 50 mA și un rezistor de pull-up (care este deconectat în mod implicit) de 20-50 KΩ. În plus unii pini au și funcții adiționale:

TWI – Pinii A4 sau SDA si pinii A5 sau SCL ofera suport pentru comunicații TWI folosind libraria Wire

AREF – Pinul folosit ca tensiune de referință pentru intrările analogice, ce se programează cu ajutorul funcției analogReference()

RESET – Pinul este folosit de obicei pentru a adăuga încă un buton de reset pentru scuturile care blochează butonul deja existent de pe placă.

Comunicare

Arduino Uno are multe facilități pentru comunicarea cu un computer, cu un alt Arduino sau alte microcontrollere. ATmega328 furnizează comunicare serială UART TTL (5V) , ce este valabilă pe pinii digitali 0 (RX) si 1 (TX) . Un cip ATmega16U2 canalizează această comunicare serială prin USB și apare ca un port de comunicare virtual în software-ul de pe computer. Firmware-ul 16U2 folosește driverele de comunicare USB, astfel nefiind nevoie de alt driver extern. Pe Windows însă este nevoie de încă un fișier cu extensia .inf. Software-ul Arduino conține un monitor serial care permite să se trimită date simple de tip text de la și către placa de Arduino. LED-urile RX si TX de pe placă se vor aprinde intermitent atunci când se transmit date prin intermediul cipului USB-către-serial și a conexiunii USB cu computerul (dar nu și pentru comunicarea serială de pe pinii 0 și 1)

Comunicarea cu pinii digitali de pe placă se face cu ajutorul unui software special.

Programare

Placa Arduino Uno poate fi programată cu ajutorul software-ului oferit de Arduino. Se selectează “Arduino Uno” din meniul Tools → Board Menu (în funcție microcontrollerul de pe placă).

Mictrocontrollerul ATmega328 de pe Arduino Uno vine cu un bootloader instalat care ne lasă să încărcăm un cod nou fără folosirea unui alt programator hardware extern. Comunică folosind protocolul original STK500.

Se poate trece peste acest bootloader, astfel se poate programa microcontrollerul direct prin intermediul antetului ICSP.

Codul sursă Firmware pentru cipul ATmega16U2/8U2 este valabil publicului și vine odata cu placa.

Reset software (automat)

În loc să necesite o apăsare fizică a unui buton de reset înainte de încărcarea codului, Arduino Uno este proiectat într-un mod care îi permite să să fie resetat prin software-ul ce rulează pe computerul cu care este conectat. Una dintre liniile de control al debitului de date (DTR) al cipului ATmega8U2/16U2 este conectată la linia de reset a microcontrollerului ATmega328 printr-un condensator de 100 nF. Când această linie atinge o anumită valoare, linia de reset scade suficient de mult încât sa reseteze cipul. Software-ul Arduino folosește această capacitate pentru a ne lăsa să încărcăm codul prin simpla apăsare a butonului de upload din mediul Arduino. Acest lucru înseamnă că bootloader-ul va avea o pauză mai scurtă, fiindcă scăderea DTR-ului poate fi foarte bine coordonată cu începutul încărcării.

Această configurare are și alte implicații. Atunci când Uno este conectat cu un computer ce operează pe Mac OS X sau Linux, se resetează de fiecare dată când o conexiune este stabilită între el si software-ul său (prin USB). Pentru următoarea jumătate de secundă, bootloader-ul este executat. În timp ce este programat să ignore datele incorecte (de exemplu, orice în afară de încărcarea codului nou), va intercepta primii biți de date trimiși către placă după ce s-a deschis conexiunea. Dacă o schiță care lucrează pe placă primește o configurație nouă sau alte date atunci când pornește prima dată, trebuie să ne asigurăm că software-ul cu care comunică așteaptă o secundă după ce a deschis conexiunea și înainte de a trimite datele.

Uno conține o legătură (etichetată RESET-EN) ce poate fi tăiată pentru a dezactiva resetarea automată. Plăcuțele de pe oricare din marginile legăturii pot fi lipite la loc pentru a o reactiva. Se mai poate dezactiva resetarea automată prin conectarea unui rezistor de 110Ω de la 5V la linia de reset.

Protecție de supra-curent a USB-ului

Arduino Uno are o siguranță resetabilă care protejează porturile USB ale computerului de scurt și supra-curent. Deși cele mai multe computere au asigurată propria lor protecție internă, siguranța oferă un strat suplimentar de protecție.

Dacă USB-ului îi este aplicat un curent mai mare de 500 mA, siguranța va sări automat și va întrerupe conexiunea până când scurtul sau suprasarcina au fost eliminate.

Caracteristici fizice

Lungimea și lățimea maximă a PCB-ului Uno 2.7 și respectiv 2.1 inci, având conectorul USB și mufa de alimentare extinse dincolo de fosta dimensiune. Patru orificii pentru șuruburi permit plăcii să fie atașată de o suprafață sau carcasă. De reținut, că distanța dintre pinii digitali 7 și 8 este de 0.16 inci.

Modulul Micro SD

Modulul este un adaptor de card micro SD cu o interfață SPI. Acesta are un microcontoler care permite citirea și scrierea datelor de pe cardul micro SD cu ajutorul lui Arduino.

Descrierea microcontrollerului STC12C5A60S2

Microcontrollerul STC12C5A60S2 este un tip de microcontroller cu un singur cip ce se bazează pe o performanță ridicată a arhitecturii 80C51 CPU, ce este produs de STC MCU Limited. Cu un kernel îmbunătățit se pot executa instrucțiuni între 1 și 6 cicluri de ceas și conține un set de instrucțiuni compatibil cu 80C51.

Programarea In-System (IPS) și In-Application (IAP) oferă suport userului să facă upgrade sistemului și datelor din el. ISP-ul permite userului să încarce cod nou fără a înlătura microcontrollerul de pe produs. IAP reprezintă scrierea de date nevolatile în memoria Flash în timp ce rulează aplicația. STC12C5A60S2 conține toate păstrează toate caracteristicile standardului 80C51. Acesta are în plus 2 porturi de intrare/ieșire (P4 și P5), o rutină de întrerupere pe 4 priorități, ADC de 10 biți, două UART, un oscilocuarț on-chip, un PCA și un PWM cu 2 canale, SPI.

Trăsături

40 porturi intrare/ieșire

Un CPU 80C51 îmbunătățit ,1T per ciclu, de 6~7 ori mai rapid decât standardul 8051.

Voltaj: 5.5V ~ 3.5V sau 2.2V ~ 3.6V (STC12LE5A60S2).

Frecvența de operare: 0- 35MHz, echivalentul standardului 8051:0~420MHz

On-chip 8/16/20/32/40/48/52/56/60/62K memorie Flash cu capabilități ISP/IAP

On-chip 1280 byte RAM: 256 byte scratch-pad RAM și 1024 bytes auxiliari de RAM

Capabilitatea de adresare până la 64KB

Dual Data Pointer (DPTR) pentru a îmbunătăți viteza datelor

Protecție prin cod asupra memoriei flash de acces

Imunitate la zgomot excelentă, un consum de putere foarte redus

Patru 16-bit timer/counter, compatibili cu Timer0/Timer1 ai standardului 8051, PCA poate fi valabil ca 2 timeri.

10 adrese vector, abilitatea de întrerupere pe 4 priorități

Un UART îmbunătățit cu hardware pentru recunoașterea adreselor și detecție a erorilor de cadru

Al doilea UART cu generator de rată de baud

Un Watch-Dog-Timer de 15 biți

Interfață de comunicare SPI Master/Slave

Convertor Analog-Digital pe 10 biți, 8 canale

Un oscliator intern RC și un oscilocuarț extern

Controlul puterii: mod idle (toate întreruperile pot scoate IDLE mod) , mod de reducere a puterii (întreruperi externe pot scoate modul Power-Down) și mod de încetinire

Modul de reducere al puterii poate fi scos de pinii PCA, RXD, T0/T1, INT0, INT1

CAPITOLUL 3

Construcția cubului

3.1. Lista de componente

În continuare, este prezentată lista componentelor folosite la construirea cubului.

Tabel 2 Lista de componente

3.2. Anatomia cubului de leduri

Un led are doua terminații: una pozitivă (anodul) și una negativă (catodul). Pentru a aprinde un led este necesar să trecem curentul de la terminația pozitivă la cea negativă .

Cubul de leduri este format din coloane și straturi, astfel catodul fiecărui led de pe un strat este lipit unul de celălalt. În aceeași idee fiecare anod al fiecărui led de pe o coloană sunt și ei lipiți unul de celălalt.

Fiecare din cele 64 de coloane sunt conectate la controllerul plăcii cu un fir separat, fiecare coloană putând fi controlată separat. La fel și straturile au un fir separat către controller.

3.3 Dimensionarea cubului

Tabel 3 Dimensiunile cubului

Tabel 4 Consumul ledurilor

Pentru a controla un cub de leduri avem nevoie de două seturi de porturi intrare/ieșire. Un set va fi folosit pentru a alimenta toate coloanele de anozi, iar celălalt set pentru a servi ca masă pentru straturile de catozi.

Pentru partea de anozi a cubului sunt necesare 64 de porturi intrare/ieșire pentru a îi controla, iar pentru catozi sunt suficiente 8. Trebuie să avem în vedere că nu putem conecta straturile de catozi direct la un singur pin al portului de intrare/ieșire deoarece avem un curent prea mare. Pentru cubul de 8x8x8 leduri, cu doar 5mA per led, am avea un curent total de 0.32A atunci când toate ledurile de pe un strat sunt pornite simultan.

3.4 Expansiunea porturilor de intrare/ieșire, multiplexarea

Pentru a scoate cele 64 de linii de ieșire avem nevoie de un circuit de multiplexare. Acest circuit ne va ajuta să multiplexăm 11 linii de intrare/ieșire în 64 de linii de ieșire. Multiplexorul este construit din componente numite latch sau flip-flop [5].

Ce este un latch? Un latch (încuietoare, zăvor) este un circuit bistabil format din două porți logice ȘI-NU care memorează evenimentul marcat prin tranziția temporară a unei intrări în 0 logic, de unde și denumirea sa.

3.5 Alegerea ledurilor

Tabel 5 Datele de catalog ale ledului

Selecționarea ledurilor a fost făcută ținând cont de:

Raportarea la dimensiunile cubului:

Vizibilitatea cubului trebuie să fie aceeași din toate unghiurile.

Ledurile prea mari nu ne vor oferi o vizibilitate prea bună înspre interiorul cubului.

Cubul fiind bazat pe multiplexare și persistența viziunii de a crea imagini avem nevoie de leduri destul de puternice pentru a produce strălucirea dorită la o perioadă de lucru de 1/8.

Lungimea anozilor de 18mm și a catozilor de 16 ~ 17 mm.

Raportarea la amperaj, specificații CI ULN2803:

Conectarea la o sursa cu VCC=5V.

Consumul unui strat de leduri = 64x5mA = 0.32A = 320mA.

Datele de catalog ale circuitul integrat ULN2803 (poate scoate maxim 500mA).

3.6 Alegerea rezistoarelor

Un led ce se conectează într-un circuit trebuie întotdeauna legat în serie cu un rezistor care să limiteze valoarea intensității curentului prin LED.

Rezistoarele R3 ~ R10 de 470Ω au fost alese pe baza următoarelor condiții:

Rolul acestor rezistoare, de a limita curentul printr-un led

Consumul ledurilor If = 5mA

Tensiunea de alimentare VCC = 5V

Tensiunea de referință a ledurilor Vf= 3 ~ 3.3 V

Formulei matematice:

Rezistoarele R1 și R2 de 4.7KΩ au fost alese pentru următoarele roluri:

R1 pentru a conecta un led roșu, la alimentare, ce va indica starea de pornire/oprire a plăcii

R2 pentru a conecta Oscilocuarțul extern la pinii XTAL1 și XTAL2 ai microcontrolerului

Rețeaua de rezistori de 10KΩ a fost aleasă mă asigura că limitez cantitatea de curent ce trece prin circuit, astfel protejez atât ledurile cât și circuitele integrate. Valoarea rezistenței nu este atât de importantă, atât timp cât poate preveni să treacă prea mult curent. Un calcul simplu se poate face cu legea lui Ohm , unde U este VCC = 5V, iar R = 10 KΩ atunci rezultă un curent de 0.5 mA.

3.7 Alegerea mărimii cubului

Vom construi cubul din cât mai puține componente cu putință. Cea mai efecientă modalitate de a îl construi este de a folosi însuși ledurile. Vom îndoi catodul astfel încât, între el și anod să se formeze un unghi de 90̊. Catodul măsoară 16mm din centrul ledului așadar vom avea o spațiere de 15mm (1mm va fi încălecat pentru sudurăm).

Cu un led mic de 3mm ne vom oferi 15mm spațiere care este suficientă pentru a vedea în adâncimea cubului.

3.8 Crearea șablonului

Pentru a putea crea un cub drept, este foarte important ca ledurile să fie așezate simetric, spațierea dintre leduri să fie identică și fiecare led să fie orientat în aceeași direcție. Cel mai ușor mod de a asigura toate aceste lucruri este să folosim un șablon ca cel din figura 3.7.

Am folosit o placă din polimer de 30×30 cm (mai mare decât dimensiunile cubului). Folosindu-mă de dimensiunile catoduzilor am trasat placa astfel încât toate ledurile să fie aliniate pe un strat (figura 3.8).

Următoarea etapă a constat în pregătirea plăcii. Este necesar să înlătur un strat de 64 de leduri, ce vor fi sudate, așa că pana și un singur led înțepenit este îndeajuns să strice totul.

Pentru a mă asigura că ledurile nu se înțepenesc, am realizat șablonul ținând cont de dimensiunea ledurilor. Acest lucru se poate observa în figura de mai jos.

3.9 Sudarea ledurilor în straturi

Fiecare strat conține 64 de leduri, ce sunt sudate între ele. Pe rândul de sus al fiecărui strat, ledul este rotit cu 90̊ în sensul acelor de ceas pentru ca piciorul (catodul) să se conecteze cu catodul ledul următor. După cum se vede în figura 3.10, la margine, acest picior rămâne în afară pentru a îl folosi ca masă, mai târziu, pentru a testa ledurile.

Am început sudura cu rândul din stânga și am poziționat ledurile astfel încât catodul fiecărui led să se suprapună aproximativ 1mm peste catodul ledului vecin.

După sudarea primul rând din stânga poziționăm următorul rând de leduri astfel încât catodul său sa atingă catodul ledului de deasupra.

Odatâ ce terminăm de sudat catozii ledurilor putem observa că acum stratul obținut arată ca un pieptene. Stratul este foarte șubred în starea aceasta, asadar, este nevoie să îl ranforsăm. Pentru asta s-a sudat o sârmă la mijlocul stratului și încă una jos.

Sudarea atât de aproape de corpul ledului poate dăuna componentele electronice dinăuntrul său. Trebuie testat fiecare led sudat pentru a ne asigura că funcționează.

Așadar conectez masa la catodul ledului ce l-am lăsat intenționat în afară și testez fiecare led.

Testarea ledurilor sudate este prezentată în figura de mai jos.

De-a lungul testelor am întâmpinat următoarele probleme:

Sudura nu a fost bine făcută și nu conducea curentul.

Ledul a fost supraîncălzit la sudare si s-a distrus circuitul din interior.

Acum, după ce am văzut ca fiecare led funcționează, trebuie îndreptați anozii astfel încât să formeze unghiul de 90̊ cu catozii, ca totul să fie simetric.

Tot ce am discutat în subcapitolul 3.9 a fost repetat de 8 ori, rezultând cele 8 straturi.

După ce am terminat de sudat toate cele 8 straturi trebuia să găsesc o modalitate de a le putea suprapune pentru a fi sudate unul peste celălalt.

Pentru acest lucru, am găsit următoarea soluție: am îndoind aproximativ 3 mm din anodul ledurilor (exact lungimea unui corp de led), astfel încât, acesta va ocoli corpul ledului și va putea fi sudat de anodul celui de dedesubt fără a strica simetria cubului.

3.10 Sudarea straturilor

A fost necesară introducerea unor distanțiere între straturi care să aibă exact lungimea de 3mm (lungimea anodurilor – 3mm) pentru a putea așeza straturile înainte de sudare. Acum primele staturi sudate între ele arată ca în figura de mai jos.

După ce am sudat fiecare strat, a trebuit să testez fiecare led, din nou, pentru a fi sigur că funcționează corect .

Voi realiza această testare conectând un cablu de la catodul lăsat pe dinafară al primului strat la catodul următorului strat care tocmai a fost sudat.

Astfel, se asigură că circuitul funcționează și nu există întreruperi. Este cel mai eficient mod de a corecta posibilele probleme ce pot să apară în cazul în care procesului de sudură nu s-a realizat corect.

În următoarea imagine se poate observa forma finala a cubului de leduri rezultat în urma sudurii.

3.11 Crearea bazei cubului

După finalizarea procesului de sudură a celor 8 straturi si implicit a cubului, am nevoie de o bază pe care să îl așez și unde să fie create conexiunile cu restul componentelor.

Am decis să folosesc șablonul creat pentru sudarea ledurilor fiindcă era deja format pentru acest lucru.

După ce am poziționat cubul pe placă am îndoit fiecare anod și am continuat cu conectarea fiecărui strat la masă. Acest lucru a fost făcut cu fire dintr-un cablul panglica pe care le-am sudat de catodul fiecărui strat în parte. Astfel fiecare strat poate fi controlat separat.

Următorul pas a fost să conectez firele de masă împreună cu anozii la placa de control. Conexiunile au fost făcute cu cablu panglică fiindcă se asigură un management al cablurilor mult mai bun.

CAPITOLUL 4

Construcția plăcii de control

4.1 Schema Controlerului

În figura de mai jos este reprezentată schema plăcii de control. Aceasta include microcontrollerul STC12C5A60S2, multiplexoarele SN74HC573AN, selectorul de adrese, 10 rezistențe de 10Ω, 2 condensatoare ceramice, 2 condensatoare electrolitice, butonul de pornire, alimentarea, pinii TTL, 1 led de control, 64 de socluri pentru anozii cubului.

Schema a fost creată cu ajutorul programului Altium Designer și printată pe o placuță de test.

4.2 Microcontrolerul STC12C5A60S2

Microcontrolerul STC12C5A60S2 [11] reprezintă creierul întregii operațiuni. Fără el nu ar funcționa cubul.

Acesta este programat (conform codului din anexa 2 [12][13][14]) să controleze latchurile și selectorul de adrese astfel încât informația să poată ajunge la destinația dorită.

Principiul de funcționare este următorul: informația este primită de la Arduino pe pinii 10/11 RXD/TXD, verifică unde trebuie trimisă, comunică cu selectorul de adrese prin pinii P1.0-P1.7 pentru se alege stratul, iar apoi comunică cu rețeaua de multiplexare prin pinii P0.0-P0.7 pentru a se alege coloana.

4.3. Latchul 74HC573

Figură 4.3 Latch 74HC573

Circuitul integrat 74HC573 este latchul pe care l-am folosit să creez rețeaua de multiplexare.

Acesta are următorii pini:

8 intrări (D1-8)

8 ieșiri (Q1-8)

1 pin "latch" (LE)

1 pin de activare a ieșirii (OE)

1 pin GND

1 pin VCC

Rolul latch-ului este de a ne servi drept ca o memorie. Latchul poate reține 8 biți de informație, iar acești 8 biți sunt reprezentați pe pinii de ieșire.

Putem considera un latch cu un led conectat la ieșirea Q0: pentru a aprinde acest led aplicăm 1 la intrarea D1, apoi aplicăm pinului LE valoarea 1.

Atunci când pinul LE se schimbă de la 0 la 1, starea intrării D1 este trimisa la ieșirea Q1, iar ieșirea rămâne la această valoare indiferent de alte schimbări ale stărilor lui D0. Valoarea este reținută până când vor fi încărcate date noi prin schimbarea pinului LE la 0 la 1.

Tabel 6 Principiul de funcționare al unui latch

Pentru a crea o gamă a latchului care să memoreze starea de on/off a 64 de leduri vom avea nevoie de 8 latch-uri. Acestea vor controla coloanele de anozi astfel: pinii de intrare 1D ~ 8D conectați la pinii P00 ~ P07 ai microcontrolerului STC12C5A60S2 prin intermediul rețelei de rezistori de 10KΩ, pinul OE la GND (acesta trebuie să fie mereu 0), iar pinul LE la pinii P20 ~ P27 ai microcontrolerului. Pinii de ieșire 1Q ~ 8Q sunt conectați la coloanele de anozi ale cubului de leduri.

Principiul de funcționare este următorul: latchurile primesc biții de la microcontroler prin pinii de intrare, îi salvează în memorie, microcontrolerul comandă pinului LE să mute datele din memorie la ieșire.

Figură 4.4 Circuit de multiplexare

4.4. Selectorul de straturi ULN2803

Componenta ULN2803 este responsabilă pentru pornirea și oprirea fiecărui strat fiind conectat la masa cubului.

Am mers cu acest integrat fiindcă este compus din 8 perechi de tranzistori Darlington NPN de curenți și tensiuni înalte, iar în componența sa mai există și diode care ajută la reglarea semnalului în parametrii.

Rolul perechilor Darlington este de a amplifica curentul, acestea fiind compuse din două tranzistoare conectate ca în imaginea de mai jos:

Figură 4.6 Tranzistori Darlington

Pinii 11 – 18 (pinii de ieșire) sunt conectați la catozii straturilor, iar pinii 1 – 8 (pinii de intrare) la pinii P10 – P17 ai microcontrolerului STC12C5A60S2.

Între pinii de ieșire ai CI și catozii ledurilor sunt plasate rezistoarele de 470Ω pentru a limita curentul de ieșire atunci când la portul de ieșire indică 0 logic.

Ce se întâmplă exact atunci când acest port indică 0? Înseamnă că tranzistorul din CI este activ, circuitul este închis, astfel se crează o linie directă de la VCC la GND.

4.5. Socluri de CI, rezistoare și conectori

Figura de mai jos arată cum au fost sudate soclurile pentru CI, rezistențele de 470Ω, rețeaua de rezistori de 10KΩ, oscilocuarțul și cei 2 condensatori ceramici de 22pF aferenți oscilocuarțului.

CAPITOLUL 5

Programarea componentelor

5.1 Programarea jocului de lumini

Programarea jocului de lumini a fost facută cu ajutorul unui programului java DotMatrix. Programul are o interfață grafică ce face posibilă crearea jocului de lumini dorit.

După cum se vede în imaginea 5.1 programul este destul de intuitiv, astfel avem pe primul rând axa X, pe rândul din mijloc axa Y, iar pe ultimul rând avem axa Z. Fiecare chenar reprezintâ unul din straturile cubului, luat pe fiecare axă în parte.

Chenarele sunt împărțite fiecare în 64 de pătrate, unde fiecare pătrat reprezintă un led. Pentru a seta un led să se aprindă este nevoie sa se selecteze un pătrat.

În partea din stânga jos se observă codul în hexazecimal care este transmis mai departe către placa de control a ledurilor.

5.2 Comunicarea calculatorului cu placa de control

Programul DotMatrixJava poate comunica cu placa de control printr-un convertor USB către TTL CP2102. Acesta are 6 pini: 5V, 3.3V, GND, TX, RX, RST, dar pentru comunicarea cu placa de control este nevoie doar de 4: 5V, GND, RX și TX care se conectează astfel: 5V la pinul VCC, GND la pinul GND, RX la pinul 31 (TX) și TX la pinul 30 (RX).

5.3 Comunicarea prin intermediul Arduino

Cealaltă metodă de transmitere a datelor este prin Arduino Uno. Jocul de lumini creat cu ajutorul programului DotMatrixJava este salvat și încărcat pe cardul micro SD. Cardul este citit, de către Arduino, prin intermediul unui modul micro SD, iar informațiile sunt transmise către placa de control a ledurilor unde sunt multiplexate și ajung la cubul de leduri.

Pentru ca Arduino să poată citi datele de pe card avem nevoie sa conectăm pinii de pe modulul microSD la Arduino ca în imaginea 5.4: CS la pinul 4, SCK la pinul 13, MOSI la pinul 11, MISO la pinul 12, VCC la pinul de 5V și GND la pinul GND.

După ce a fost stabilită conexiunea modulului microSD cu Arduino este necesar ca Arduino să fie programat pentru a putea citi datele de pe card. Codul se află în anexa lucrării, iar explicația sa se regăsește în organigramă.

Mai departe , Arduino trebuie să comunice cu placa de control a ledurilor pentru a se putea face multiplexarea datelor.

Acesta comunică cu microcontrollerul STC12C5A60S2 prin intermediul pinilor 0 (RX) și 1 (TX) care sunt legați la pinii J30 (RX) și J31 (TX) de pe placa de control.

În imaginea de mai jos se poate observa legătura dintre Arduino și placa de control.

CONCLUZII

În concluzie pot spune că am fost foarte motivat să îmi aleg această temă fiindcă a avut o realizare practică ce mi-a pus la încercare îndemânarea. Sunt de părere că un inginer electronist trebuie să aibă atât cunoștințe teoretice cât și abilități practice întru-cât acestea sunt cel mai greu de dobândit.

Construcția cubului a necesitat îndemânare cu letconul și foarte multă răbdare. Cel mai mare efort a fost depus la sudarea celor 512 leduri între ele în vederea formării unui cub simetric. Am ușurat această muncă prin crearea unei matrițe după care să poată fi aliniate. Matrița a fost calculată folosind dimensiunile catozilor ledurilor.

Un alt pas important al lucrării a fost modul de transmitere a datelor prin multiplexare și construcția plăcii de control a ledurilor. La rețeaua de multiplexoare am avut nevoie de 8 latchuri a câte 8 pini de intrare/ieșire pentru a putea multiplexa semnalul și a îl transmite către 64 de leduri concomitent, iar această rețea a trebuit să fie conectată la microcontroler.

Ultima parte a constat în programarea componentelor necesare pentru ca informația să poată circula dintr-un capăt în altul. Aici intervin următoarele componente: placa Arduino, microcontrollerul STC12C5A60S2 și selectorul de adrese ULN2803.

BIBLIOGRAFIE

ARDUINO

1. https://www.arduino.cc/

2. https://ro.wikipedia.org/wiki/Pagina_principal%C4%83

3. https://www.arduino.cc/en/Main/ArduinoBoardUno

4. http://www.robofun.ro/docs/Arduino%20pentru%20Toti%20pagini%201-30.pdf

CUB DE LEDURI

5. http://www.instructables.com/id/LED-Cube-4x4x4/

6. http://www.instructables.com/id/4X4X4-LED-Cube-w-Arduino-Uno/

7. http://www.instructables.com/id/CHRs-8X8X8-LED-Cube-Revisited-with-improvements/

MICROCONTROLERE

8. http://cs.curs.pub.ro/wiki/pm/

9. http://cs.curs.pub.ro/wiki/pm/lab/lab0

10. http://www.stcmicro.com/cp.html

11. http://openhardware.ro/category/stc-mcu/

12. http://www.stcmcu.com/datasheet/stc/stc-ad-pdf/stc12c5a60s2-english.pdf

13. http://www.datasheet-pdf.com/datasheet/STC/738020/STC12C5A60S2.pdf.html

14. http://www.codeforge.com/read/212286/main.c__html

CIRCUITE INTEGRATE

15. Electronică – circuite electronice – studiu prin simulare, Editura “Tehnică Info”, Chișinău, 2005, Dan Rotar

16. Mihaela Cirlugea, Lelia Festila – "Circuite integrate digitale", editura UT Pres, 2005

Circuite integrate digitale si sisteme cu microprocesoare S. Spanulescu

17. http://pdf1.alldatasheet.com/datasheet-pdf/view/182611/TOSHIBA/ULN2803APG.html

18. http://www.alldatasheet.com/datasheet-pdf/pdf/182611/TOSHIBA/ULN2803APG.html

19. http://www.seattlerobotics.org/encoder/mar97/basics.html

20. https://ro.wikipedia.org/wiki/Pixel#Voxel

21. https://en.wikipedia.org/wiki/Voxel#/media/File:Voxelgitter.png

22. http://www.instructables.com/file/FHTWYK3GI0TDMW9

23. http://www.instructables.com/file/FJXR7WSGI0TDMW5

Anexa 1

ANEXE

COD SURSĂ ARDUINO

#include <SPI.h>

#include <SD.h>

File myFile;

const int chipSelect = 4;

int i = 0;

void setup()

{

Serial.begin(9600);

while (!Serial) {

}

Serial.print("Initializing SD card…");

pinMode(SS, OUTPUT);

if (!SD.begin(chipSelect)) {

Serial.println("initialization failed!");

return;

}

Serial.println("initialization done.");

}

void sendAnimation(byte *data) // trimitere animație

{

Serial.write(0xf2); for (byte i = 8; i < 72; i++)

{

Serial.write(data[i]); // comandă care trimite animația

}

delay(20); // întârziere 20 ms

}

void readAnimation(File & myFile) // citește animatia

{

byte data[72]; // declarare vector în care citim

while (myFile.available())

{

myFile.read(data, 72); // citirea

sendAnimation(data); // apelare funcție de trimitere

}

}

void loop()

{

for ( i=0;i<29;i++)

{

char buffer[50]; // un vector de caractere

sprintf(buffer, "%d.dat", i); // facem i.dat prin //concatenarea lui i cu .dat, i=1..n

myFile = SD.open(buffer); // citește după card i.dat

Anexa 2

if (myFile) {

// citește din fișier până numai este nimic:

while (myFile.available()) {

readAnimation(myFile); // apelare funcție de citire

}

// close the file:

myFile.close(); // închidere fișier deschis

} else {

// dacă fișierul nu a fost deschis arată eroarea:

Serial.println("error!!!.txt");

}

}

if (i==28) // sunt 28 de efecte încărcate

{

i=0;

}

}

COD SURSĂ STC12C5A60S2

#include <STC12C5A60S2.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

volatile uchar display[2][8][8]; // 8x8x8 = (Z,Y,X)

volatile uchar frame = 0; // cadrul current (frontbuffer) index

volatile uchar temp = 1; // cadrul care nu se vede (backbuffer) index

volatile uchar layer = 0; // strat, care este reaprins

#define MAX_BUFFER 128 // dimensiune buffer UART

#define TX_ENABLED

// pornește funcția UART pe TX

volatile uchar rx_buffer[MAX_BUFFER];

volatile int rx_read = 0;

volatile int rx_write = 0;

volatile int rx_in = 0;

#ifdef TX_ENABLED

volatile uchar tx_buffer[MAX_BUFFER];

volatile int tx_read = 0;

volatile int tx_write = 0;

volatile int tx_out = 0;

#endif

///////////////////////////////////////////////////////////

// întrerupere pornită pe URART cu ring buffer

void uart_isr() interrupt 4

{EA = 0;

if (RI) // primește un byte

{RI = 0; //șterge flagul de întrerupere

if (!(rx_write == rx_read && rx_in > 0))

{rx_buffer[rx_write] = SBUF;

rx_write = (rx_write+1)%MAX_BUFFER;

rx_in++;}}

#ifdef TX_ENABLED

else if (TI) // s-a trimis byteul

{TI = 0;// șterge flagul de întrerupere

if (tx_out > 0)

{SBUF = tx_buffer[tx_read];

tx_read = (tx_read+1)%MAX_BUFFER;

tx_out–;

}}

#endif

EA = 1;

}

///////////////////////////////////////////////////////////

#ifdef TX_ENABLED

// trimite un byte via UART (întoarce -1 dacă bufferul TX este full, altfel 0)

int send_uart(uchar dat)

{int res;

EA = 0;

Anexa 3

if (tx_read == tx_write && tx_out > 0)

{// buffer is full

res = -1;

}

else

{

tx_buffer[tx_write] = dat;

tx_write = (tx_write+1)%MAX_BUFFER;

tx_out++;

res = 0;

if (TI == 0)

{TI = 1; // pornire întrerupere și trimite date

}

}

EA = 1;

return res;

}

///////////////////////////////////////////////////////////

// trimite un șir via uart

void send_str(char* s)

{while (*s)

{while (send_uart(*s++) != 0)

{_nop_();

}}}

///////////////////////////////////////////////////////////

// trimite un byte via uart

void send_serial(uchar dat)

{while(send_uart(dat) != 0)

{_nop_();

}}

#endif

///////////////////////////////////////////////////////////

// verifică dacă un byte este valabil în bufferul de primire uart

// întoarce -1 dacă nu, altfel – voaloare byte

int recv_uart()

{int value;

EA = 0;

if (rx_in == 0)

{value = -1;

}else

{value = rx_buffer[rx_read];

rx_read = (rx_read+1)%MAX_BUFFER;

rx_in–;

}

EA = 1;

return value;

}

///////////////////////////////////////////////////////////

// blochează până primește un byte pe uart, returnează valoare byte

uchar read_serial()

{int value;

while ((value = recv_uart()) == -1)

{_nop_();

Anexa 4

}

return (uchar)(value & 0xFF);

}

///////////////////////////////////////////////////////////

void delay5us(void)

{unsigned char a,b;

for(b=7; b>0; b–)

for(a=2; a>0; a–);

}

///////////////////////////////////////////////////////////

void delay(uint i)

{while (i–)

{delay5us();

}}

///////////////////////////////////////////////////////////

// asignează toți regiștrii cubului/ rândurilor (straturilor), de regulă 0, idx – 0/1 pentru bufferul față/spate

void clear(char idx, char val)

{uchar i,j;

for (j=0; j<8; j++)

{for (i=0; i<8; i++)

display[idx][j][i] = val;

}}

///////////////////////////////////////////////////////////

// aprinde un punct specific de pe cub (x,y,z), pornire/oprire

void point(uchar x, uchar y, uchar z, uchar enable)

{uchar ch1 = 1<<x;

if (enable)

display[frame][z][y] = display[frame][z][y]|ch1;

else

display[frame][z][y] = display[frame][z][y]&(~ch1);

}

///////////////////////////////////////////////////////////

// setează o coloană a unui strat la o valoare specificată

// i.e. value = 0 (all 8 leds off), value = 0xFF (all 8 leds on), etc.

void line(uchar y, uchar z, uchar value)

{display[frame][z][y] = value;

}

///////////////////////////////////////////////////////////

// schimbă bufferul din spate cu cel din față

void swap()

{if (frame)

{frame = 0;

temp = 1;

}

else

{

frame = 1;

Anexa 5

temp = 0;

}

clear(temp, 0); // pornește scrierea pe un buffer curat

}

/* cpp – distanța față de punctul din mijloc

le – scrie sau curăță. */

void cirp(char cpp, uchar dir, uchar le)

{uchar a,b,c,cp;

if ((cpp<128)&(cpp>=0)) {

if (dir)

cp=127-cpp;

else

cp=cpp;

a=(dat[cp]>>5)&0x07;

b=(dat[cp]>>2)&0x07;

c=dat[cp]&0x03;

if (cpp>63)

c=7-c;

point (a,b,c,le);

}}

///////////////////////////////////////////////////////////

void main()

{int value;

bit uart_detected = 0,

frame_started = 0;

uchar received = 0;

// inițializare uart – 9600bps@12.000MHz MCU

PCON &= 0x7F; //rata de baud

SCON = 0x50; //8biți si rată de baud variabilă, 1 bit de stop, fără paritate

AUXR |= 0x04; // BRT este frecvența osc (1T)

BRT = 0xD9;// setează valoare de reîncărcare a BRT

AUXR |= 0x01; //folosește BRT ca generator de rată de baud

AUXR |= 0x10; // pornire BRT

ES = 1;// pornește întrerupere UART

// setup timer0

TH0 = 0xc0; // valoare de reîncărcare

TL0 = 0;

TR0 = 1; // start timer0

ET0 = 1; // pornește întrerupere timer0

EA = 1; // pornește întrerupere globală

// șterge buffer principal și buffer din spate

clear(frame, 0);

clear(temp, 0);

while(1)

{if (uart_detected) // este cubul controlat prin UART?

{value = read_serial(); // blochează până vine un byte

if (!frame_started)

{

if (value == 0xF2) // pornire primire lot

Anexa 6

{

frame_started = 1; // primește cadre de date

received = 0; // nu s-au primit rânduri

}}

else

{if (received < 64) // datele cubului pline care nu au fost procesate

{display[temp][received/8][received%8] = value;

received++; // s-a primit încă un rând/byte }

if (received >= 64) // s-a primit întreaga informație de la cub

{

swap();

// arată luminile ledului

frame_started = 0; // este nevoie de un nou cadru de date

}}}

else

{

///////////////////////////////////////////////////////////

//P0; //573 in

//P1; //uln2803

//P2; //573 LE

void print() interrupt 1 // timer0 interrupt

{uchar y;

P1 = 0;

Anexa 7

// face update la un strat pe rând

for (y=0; y<8; y++)

{P2 = 1<<y;

delay(3);

P0 = display[frame][layer][y];

delay(3);}

P1 = 1<<layer;

layer = (layer+1)%8;

// reset timer0

TH0 = 0xc0;

TL0 = 0;

}ss

BIBLIOGRAFIE

ARDUINO

1. https://www.arduino.cc/

2. https://ro.wikipedia.org/wiki/Pagina_principal%C4%83

3. https://www.arduino.cc/en/Main/ArduinoBoardUno

4. http://www.robofun.ro/docs/Arduino%20pentru%20Toti%20pagini%201-30.pdf

CUB DE LEDURI

5. http://www.instructables.com/id/LED-Cube-4x4x4/

6. http://www.instructables.com/id/4X4X4-LED-Cube-w-Arduino-Uno/

7. http://www.instructables.com/id/CHRs-8X8X8-LED-Cube-Revisited-with-improvements/

MICROCONTROLERE

8. http://cs.curs.pub.ro/wiki/pm/

9. http://cs.curs.pub.ro/wiki/pm/lab/lab0

10. http://www.stcmicro.com/cp.html

11. http://openhardware.ro/category/stc-mcu/

12. http://www.stcmcu.com/datasheet/stc/stc-ad-pdf/stc12c5a60s2-english.pdf

13. http://www.datasheet-pdf.com/datasheet/STC/738020/STC12C5A60S2.pdf.html

14. http://www.codeforge.com/read/212286/main.c__html

CIRCUITE INTEGRATE

15. Electronică – circuite electronice – studiu prin simulare, Editura “Tehnică Info”, Chișinău, 2005, Dan Rotar

16. Mihaela Cirlugea, Lelia Festila – "Circuite integrate digitale", editura UT Pres, 2005

Circuite integrate digitale si sisteme cu microprocesoare S. Spanulescu

17. http://pdf1.alldatasheet.com/datasheet-pdf/view/182611/TOSHIBA/ULN2803APG.html

18. http://www.alldatasheet.com/datasheet-pdf/pdf/182611/TOSHIBA/ULN2803APG.html

19. http://www.seattlerobotics.org/encoder/mar97/basics.html

20. https://ro.wikipedia.org/wiki/Pixel#Voxel

21. https://en.wikipedia.org/wiki/Voxel#/media/File:Voxelgitter.png

22. http://www.instructables.com/file/FHTWYK3GI0TDMW9

23. http://www.instructables.com/file/FJXR7WSGI0TDMW5

Anexa 1

ANEXE

COD SURSĂ ARDUINO

#include <SPI.h>

#include <SD.h>

File myFile;

const int chipSelect = 4;

int i = 0;

void setup()

{

Serial.begin(9600);

while (!Serial) {

}

Serial.print("Initializing SD card…");

pinMode(SS, OUTPUT);

if (!SD.begin(chipSelect)) {

Serial.println("initialization failed!");

return;

}

Serial.println("initialization done.");

}

void sendAnimation(byte *data) // trimitere animație

{

Serial.write(0xf2); for (byte i = 8; i < 72; i++)

{

Serial.write(data[i]); // comandă care trimite animația

}

delay(20); // întârziere 20 ms

}

void readAnimation(File & myFile) // citește animatia

{

byte data[72]; // declarare vector în care citim

while (myFile.available())

{

myFile.read(data, 72); // citirea

sendAnimation(data); // apelare funcție de trimitere

}

}

void loop()

{

for ( i=0;i<29;i++)

{

char buffer[50]; // un vector de caractere

sprintf(buffer, "%d.dat", i); // facem i.dat prin //concatenarea lui i cu .dat, i=1..n

myFile = SD.open(buffer); // citește după card i.dat

Anexa 2

if (myFile) {

// citește din fișier până numai este nimic:

while (myFile.available()) {

readAnimation(myFile); // apelare funcție de citire

}

// close the file:

myFile.close(); // închidere fișier deschis

} else {

// dacă fișierul nu a fost deschis arată eroarea:

Serial.println("error!!!.txt");

}

}

if (i==28) // sunt 28 de efecte încărcate

{

i=0;

}

}

COD SURSĂ STC12C5A60S2

#include <STC12C5A60S2.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

volatile uchar display[2][8][8]; // 8x8x8 = (Z,Y,X)

volatile uchar frame = 0; // cadrul current (frontbuffer) index

volatile uchar temp = 1; // cadrul care nu se vede (backbuffer) index

volatile uchar layer = 0; // strat, care este reaprins

#define MAX_BUFFER 128 // dimensiune buffer UART

#define TX_ENABLED

// pornește funcția UART pe TX

volatile uchar rx_buffer[MAX_BUFFER];

volatile int rx_read = 0;

volatile int rx_write = 0;

volatile int rx_in = 0;

#ifdef TX_ENABLED

volatile uchar tx_buffer[MAX_BUFFER];

volatile int tx_read = 0;

volatile int tx_write = 0;

volatile int tx_out = 0;

#endif

///////////////////////////////////////////////////////////

// întrerupere pornită pe URART cu ring buffer

void uart_isr() interrupt 4

{EA = 0;

if (RI) // primește un byte

{RI = 0; //șterge flagul de întrerupere

if (!(rx_write == rx_read && rx_in > 0))

{rx_buffer[rx_write] = SBUF;

rx_write = (rx_write+1)%MAX_BUFFER;

rx_in++;}}

#ifdef TX_ENABLED

else if (TI) // s-a trimis byteul

{TI = 0;// șterge flagul de întrerupere

if (tx_out > 0)

{SBUF = tx_buffer[tx_read];

tx_read = (tx_read+1)%MAX_BUFFER;

tx_out–;

}}

#endif

EA = 1;

}

///////////////////////////////////////////////////////////

#ifdef TX_ENABLED

// trimite un byte via UART (întoarce -1 dacă bufferul TX este full, altfel 0)

int send_uart(uchar dat)

{int res;

EA = 0;

Anexa 3

if (tx_read == tx_write && tx_out > 0)

{// buffer is full

res = -1;

}

else

{

tx_buffer[tx_write] = dat;

tx_write = (tx_write+1)%MAX_BUFFER;

tx_out++;

res = 0;

if (TI == 0)

{TI = 1; // pornire întrerupere și trimite date

}

}

EA = 1;

return res;

}

///////////////////////////////////////////////////////////

// trimite un șir via uart

void send_str(char* s)

{while (*s)

{while (send_uart(*s++) != 0)

{_nop_();

}}}

///////////////////////////////////////////////////////////

// trimite un byte via uart

void send_serial(uchar dat)

{while(send_uart(dat) != 0)

{_nop_();

}}

#endif

///////////////////////////////////////////////////////////

// verifică dacă un byte este valabil în bufferul de primire uart

// întoarce -1 dacă nu, altfel – voaloare byte

int recv_uart()

{int value;

EA = 0;

if (rx_in == 0)

{value = -1;

}else

{value = rx_buffer[rx_read];

rx_read = (rx_read+1)%MAX_BUFFER;

rx_in–;

}

EA = 1;

return value;

}

///////////////////////////////////////////////////////////

// blochează până primește un byte pe uart, returnează valoare byte

uchar read_serial()

{int value;

while ((value = recv_uart()) == -1)

{_nop_();

Anexa 4

}

return (uchar)(value & 0xFF);

}

///////////////////////////////////////////////////////////

void delay5us(void)

{unsigned char a,b;

for(b=7; b>0; b–)

for(a=2; a>0; a–);

}

///////////////////////////////////////////////////////////

void delay(uint i)

{while (i–)

{delay5us();

}}

///////////////////////////////////////////////////////////

// asignează toți regiștrii cubului/ rândurilor (straturilor), de regulă 0, idx – 0/1 pentru bufferul față/spate

void clear(char idx, char val)

{uchar i,j;

for (j=0; j<8; j++)

{for (i=0; i<8; i++)

display[idx][j][i] = val;

}}

///////////////////////////////////////////////////////////

// aprinde un punct specific de pe cub (x,y,z), pornire/oprire

void point(uchar x, uchar y, uchar z, uchar enable)

{uchar ch1 = 1<<x;

if (enable)

display[frame][z][y] = display[frame][z][y]|ch1;

else

display[frame][z][y] = display[frame][z][y]&(~ch1);

}

///////////////////////////////////////////////////////////

// setează o coloană a unui strat la o valoare specificată

// i.e. value = 0 (all 8 leds off), value = 0xFF (all 8 leds on), etc.

void line(uchar y, uchar z, uchar value)

{display[frame][z][y] = value;

}

///////////////////////////////////////////////////////////

// schimbă bufferul din spate cu cel din față

void swap()

{if (frame)

{frame = 0;

temp = 1;

}

else

{

frame = 1;

Anexa 5

temp = 0;

}

clear(temp, 0); // pornește scrierea pe un buffer curat

}

/* cpp – distanța față de punctul din mijloc

le – scrie sau curăță. */

void cirp(char cpp, uchar dir, uchar le)

{uchar a,b,c,cp;

if ((cpp<128)&(cpp>=0)) {

if (dir)

cp=127-cpp;

else

cp=cpp;

a=(dat[cp]>>5)&0x07;

b=(dat[cp]>>2)&0x07;

c=dat[cp]&0x03;

if (cpp>63)

c=7-c;

point (a,b,c,le);

}}

///////////////////////////////////////////////////////////

void main()

{int value;

bit uart_detected = 0,

frame_started = 0;

uchar received = 0;

// inițializare uart – 9600bps@12.000MHz MCU

PCON &= 0x7F; //rata de baud

SCON = 0x50; //8biți si rată de baud variabilă, 1 bit de stop, fără paritate

AUXR |= 0x04; // BRT este frecvența osc (1T)

BRT = 0xD9;// setează valoare de reîncărcare a BRT

AUXR |= 0x01; //folosește BRT ca generator de rată de baud

AUXR |= 0x10; // pornire BRT

ES = 1;// pornește întrerupere UART

// setup timer0

TH0 = 0xc0; // valoare de reîncărcare

TL0 = 0;

TR0 = 1; // start timer0

ET0 = 1; // pornește întrerupere timer0

EA = 1; // pornește întrerupere globală

// șterge buffer principal și buffer din spate

clear(frame, 0);

clear(temp, 0);

while(1)

{if (uart_detected) // este cubul controlat prin UART?

{value = read_serial(); // blochează până vine un byte

if (!frame_started)

{

if (value == 0xF2) // pornire primire lot

Anexa 6

{

frame_started = 1; // primește cadre de date

received = 0; // nu s-au primit rânduri

}}

else

{if (received < 64) // datele cubului pline care nu au fost procesate

{display[temp][received/8][received%8] = value;

received++; // s-a primit încă un rând/byte }

if (received >= 64) // s-a primit întreaga informație de la cub

{

swap();

// arată luminile ledului

frame_started = 0; // este nevoie de un nou cadru de date

}}}

else

{

///////////////////////////////////////////////////////////

//P0; //573 in

//P1; //uln2803

//P2; //573 LE

void print() interrupt 1 // timer0 interrupt

{uchar y;

P1 = 0;

Anexa 7

// face update la un strat pe rând

for (y=0; y<8; y++)

{P2 = 1<<y;

delay(3);

P0 = display[frame][layer][y];

delay(3);}

P1 = 1<<layer;

layer = (layer+1)%8;

// reset timer0

TH0 = 0xc0;

TL0 = 0;

}ss

Similar Posts