SPECIALIZAREA: ELECTRONICĂ APLICATĂ PROIECT DE LICENȚĂ Absolvent, CÎNDEA RAREȘ ADRIAN 2017 UNIVERSITATEA “LUCIAN BLAGA” DIN SIBIU FACULTATEA DE… [303799]

UNIVERSITATEA “LUCIAN BLAGA” DIN SIBIU

FACULTATEA DE INGINERIE

SPECIALIZAREA: ELECTRONICĂ APLICATĂ

PROIECT DE LICENȚĂ

Absolvent: [anonimizat]

2017

UNIVERSITATEA “LUCIAN BLAGA” DIN SIBIU

FACULTATEA DE INGINERIE

SPECIALIZAREA: [anonimizat], dr, ing, BREAZU MACARIE

Absolvent: [anonimizat]

2017

Introducere

În aceasta lucrare va fi prezentat modul de implementare a [anonimizat], [anonimizat].

[anonimizat] a datelor corespunzătoare și 8 digiți pentru afișarea numerelor.

Pentru realizarea lucrării va fi nevoie de parcurgerea mai multor pași:

Analiza documentației microcontrollerului

Analiza documentației lui MAX7221 pentru conectarea pinilor și a digiților și pentru inițializarea și setarea acestuia

Crearea codului sursă

Setarea Timerului pentru intrerupere

Simularea circuitului în Proteus

Realizarea lucrării practice

Lucrarea va fi împărțita în 3 capitole, [anonimizat], [anonimizat], simulări și realizare practică. Ultimul capitol va fi pentru concluziile trase dupa realizarea proiectului.

Capitolul 1: Aspecte teoretice

1.1 [anonimizat] a [anonimizat]. [anonimizat], în care doi jucători concureaza unul contra celuilalt și aceștia mută pe rând. Ele se numesc ceasuri de șah doar pentru că au fost folosite prima dată în șah.

[1]

[anonimizat], [anonimizat] 1800 organizatorii turneelor au introdus aceste ceasuri de șah pentru a putea măsura exact timpul de joc al fiecărui concurent și de a prevenii tragerile de timp.

În 1843, meciul dintre Howard Staunton și Pierre St. Amant a fost mai degrabă un test de îndurare psihică decât un meci de șah. Meciul lor a avut 66 de mutări și a durat 14 ore și jumătate. Jucătorii din vremurile respective se foloseau de aceste tehnici pentru a obosii adversarul în speranța că acesta va greșii.

[anonimizat] 1851, [anonimizat] (1818-1889) a fost primul care a propus ca timpul fiecărui jucător sa fie limitat.

În 1852, un scriitor pe nume A. Cantab propus folosirea clepsidrelor pentru măsurarea timpului de joc. Propunerea lui era ca fiecare jucător să dispună de o clepsidră care se scurge în 3 ore și de un prieten care să o întoarcă când e cazul. Clepsidra era întoarsă pe orizontală în momentul în care un jucător a mutat și rămânea așa până când îi venea din nou randul sa mute. Această idee a fost bine primită de toată lumea și a fost folosită în turnee între anii 1861 și 1875. Dar, din păcate temperatura și umiditatea afectau nisipul din clepsidre, iar acestea nu mai erau prea precise. De asemenea, se mai întampla să se întoarcă clepsidra pe partea greșită, iar timpul nu mai era măsurat corect.

O altă idee a fost folosirea a două ceasuri de mână pentru măsurarea timpului și se nota pe o hârtie timpul de gândire a fiecărui concurent. Această metodă a fost folosită din 1866 până în 1873.

În vremea respectivă dacă ți se scurgea timpul nu însemna că ai pierdut meciul. În 1867, la Turneul Internațional din Paris, organizatorii au impus o amendă de 5 franci pentru fiecare 15 minute jucate în plus față de timpul limită.

În 1883, un dispizitiv mecanic de măsurarea timpului a fost inventat, cu numele de ceasul de șah “răstogolit”. A fost folosit pentru prima dată la turneul din Londra al acelui an și a fost inventat de către Thomas Bright Wilson(1843-1915) din Manchester, Anglia, cu ajutorul lui Joseph Henry Blackburne. Acesta era format din două ceasuri cu pendul, poziționate fiecare la capetele unei balanțe. Când un jucător a terminat mutarea, acesta mută ceasul într-o anumită poziție, pendulul lui se oprea și pornea ceasul adversarului. La acelaș turneu a fost prima dată când un jucător a pierdut meciul pentru că a depășit timpul limită.

[2]

În 1900 a apărut ceasul de șah analogic cu butoane, perfecționat de către Veenhoff of Groningen.

Primul ceas de șah electronic a fost introdus în 1964, fiind produs de o firmă din Rusia, numită Kiev Relay and Automatic Works.

[3]

1.2 LED display

Un afișaj LED este un panou, care utilizează mai multe diode emițătoare de lumină ca și pixeli formând un afișaj video. Datorită luminii puternice emise de acestea, sunt folosite pentru reclamele magazinelor sau a panourilor publicitare și în ultima vreme sunt des întalnite și la afișarea destinațiilor vehiculelor de transport în comun.

Pentru această lucrare am folosit un afișaj cu 7 segmente. Acestea reprezintă o formă de afișaj electronic pentru numerele zecimale, care sunt o formă simplificată a mult mai complexei metode cu matrici de puncte.

Cele 7 segmente sunt aranjate ca un dreptunghi cu doua segmente verticale pe fiecare parte și cu trei segmente orizontale în partea de jos, la mijloc și sus. De asemenea mai sunt și display-uri cu 14 segmente și display-uri pe 16 segmente pentru afișarea tuturor caracterelor alfanumerice, dar în cadrul acestei lucrări nu a fost nevoie să fie folosite.

[4]

Afișajele cu 7 segmente sunt foarte folosite la ceasurile digitale, contoarele electronice, calculatoarele de buzunar și multe alte dispositive care afisează informații numerice.

1.2.1 Istoric:

Reprezentarea pe 7 segmente poate fi gasită înca în brevetele din anul 1903, când Carl Kinsley a inventat o metodă de a transmite telegrafic litere și numere, pe care le imprima pe o casetă segmentată. În 1908, F. W. Wood a inventat un afișaj cu 8 segmente, care reprezentă numarul 4 folosind o bară pe diagonală. În 1910, afișajul pe 7 segmente luminat de un bec incandescent a fost folosit într-o centrală termică. De asemenea, au fost folosite pentru afișarea numerelor de telefon formate, în timpul tranziției de la conectarea manuală a apelurilor de către un operator prin cabluri la conectarea automată a apelurilor telefonice. Dar acestea nu s-au răspândit în toata lumea până în 1970 când au fost inventate LED-urile.

1.2.2 Implementare:

Într-un afișaj LED simplu, de obicei, toți catozii (terminalele negative) sau toți anozii (terminalele pozitive) ai segmentului sunt conectați și au un pin comun. De aici vine denumirea de display cu anod comun sau display cu catod comun. Prin urmare, dispozitivul cu cele 7 segmente plus punctul decimal va avea nevoie de doar 9 pini. Produsele comerciale au totuși mai mulți și mai sunt incluse spații unde se pot pune pini pentru a se potrivii cu soclul standardului IC.

De asemenea există și afișaje integrate, având un singur sau mai multi digiți, unele dintre aceste având chiar și propriul lor decoder integrat. Cele care contin mai mulți digiți integrați fiind folosite pentru simplificarea schemei electrice, toți digiții având un singur pin comun, anodul sau catodul.

Dar cele mai des întâlnite sunt cele fabricate individual și sunt incluse într-un circuit prin conectarea pinilor fiecărui digit în parte.

1.2.3 Descrierea afișajului LED folosit:

În cadrul acestei lucrări a fost folosit afișajul OPD-S15013UPG-BW produs de Opto Plus LED Corp.

Acesta masoară 1.5 inch (38.1 mm) înăltime si utilizează un chip LED care emite un verde pur și este fabricat din InGaN (Nitrit de Galiu compus cu Nitrit de Indiu) pe un Nitrit de Galiu transparent.

Acest dispozitiv vine în două serii: OPD-S15012UPG-BW care este cu anod comun și OPD-S15013UPG-BW care este cu catod comun.

1.2.4 Circuitul intern:

Fiecare segment [5], [6]

conține câte doua LED-uri, mai puțin punctul decimal care conține doar unul. Aceasta este varianta cu catod comun, anozii fiind conectați fiecare în parte prin pinii corespunzători, ca în imagine.

În tabelul de mai jos este prezentat modul în care aceste segmente afișează numerele corespunzătoare în funcție de codul care trebuie trimis. De exemplu pentru afișarea numărului 3 toate segmentele trebuie să fie aprinse mai puțin segmentele E si F, codul în binar fiind 0b01111001.

1.3 Arduino

Arduino este numele unei companii care produce atât componente hardware cât și componente software. Aceasta dispune de o comunitate de utilizatori care proiectează si produc echipamente cu microcontrollere pentru construirea dispozitivelor digitale și interactive cu ajutorul cărora putem controla obiectele din jurul nostru.

Produsele companiei Arduino sunt distribuite ca open-source atat hardware cât și software, adica oricine le poate produce și distribui atât ca produs fizic cat și ca produs software. Plăcile Arduino se găsesc în comerț și preasamblate, dar și doar componente pentru a fi asamblate de către utilizator.

Plăcile Arduino dispun de pini de intrare și ieșire digitali și analogici, ceea ce face interfațarea cu alte placi sau circuite mult mai ușoară. Acestea mai dispun de o interfața serială de comunicații, de regulă USB (Universal Serial Bus), care sunt de asemenea folosite pentru programarea microcontrollerului.

Limbajul de programare a acestor microcontrollere este un dialect care deriva din C și C++. În plus de asta, pentru realizarea proiectelor software Arduino nu are nevoie de compilerele tradiționale și dispune de propriul mediu de programare care este gratis și se poate descărca și instala cu ușurință de pe site-ul propriu.

1.3.1 Istoric

Proiectui Arduino a inceput în Italia la Interation Design Institute din Ivrea. Un student a folosit un microcontroller care costa 100 de dolari, puțin cam spump pentru cei mai mulți dintre stundenții de atunci. In 2003 Hernando Barragan a creat platforma intitulată “Wiring” ca și lucrare de Masterat, sub supravegherea lui Massimo Banzi si Casey Reas, care sunt cunoscuți pentru contribuțiile limbajului de programare Processing. Această platforma avea intenția să fie simplă, cu cost redus și era bazată pe un PCB cu un microcontroller ATmega168 și un mediu de programare bazat pe limbajul Processing și înca cateva librarii pentru ca programarea microcontrollerului sa fie mai ușoara.

Cu timpul Massimo Banzi împreună cu David Mellis și David Cuartielles au adăugat suport pentru un microcontroller mai ieftin la Wiring, și anume ATmega8. Dar în cele din urmă în loc să se continue dezvoltarea la proiectul Wiring, aceștia au decis să creeze un nou proiect numit Arduino, care includea tot codul sursă conceput pentru Wiring. Numele de Arduino a fost inspirat de la un bar unde fondatorii acestui proiect obișnuiau sa se întâlnească.

După finalizarea platformei, versiuni mult mai ieftine au fost distribuite în comunitatea proiectelor open-source, iar la scurt timp companiile au început productia lor. De exemplu compania Adafruit Industries din New York producatoare de plăci Arduino au estimat că în 2011 peste 300.000 de plăci au fost comercializate, iar în 2013 numărul depașea 700.000 de plăci oficiale.

1.3.2 Plăci oficiale

Placa originala Arduino a fost produsă de compania italiană Smart Projects. Unele plăci cu brand-ul Arduino au fost proiectate de companiile americane SparkFun Electronics si Adafruit Industries. Până in 2016, 17 versiuni de Arduino au fost produse oficial.

Printre acestea se numară:

[8] [9] [10]

Arduino RS232 Arduino Decimila Arduino Uno R3

[11] [12] [13]

Arduino Leonardo Arduino Pro Arduino Mega

[14] [15]

Arduino Nano Arduino Ethernet

1.3.3 Arduino Nano

Pentru această lucrare am folosit Arduino Nano bazat pe ATmega328. Are mai mult sau mai puțin aceași funcționalitate ca Arduino Duemilanove, dar acesta are dimensiuni mai mici. Lipsește doar mufa pentru alimentare, dar mufa pentru cablul Mini-B USB este prezentă.

Specificații Tehnice:

[16]

Arduino Nano are următoarea configurare a pinilor: [17]

Fiecare din cei 14 pini digitali pot fi folosiți atât ca intrare cât și ca ieșire, folosind funcția pinMode(). Ei funcționează optim la 5 volți. Fiecare pin susține sau poate primii un maxim de 40 mA și au câte un rezistor de pull-up intern (deconectat în mod implicit) de 20-50 kOhm. Unii dintre aceștia mai au și funcții mai speciale:

Funcții seriale: Pinii 0 (RX) și 1 (TX). Folosiți pentru a recepta sau transmite date seriale. Acești pini sunt conectați cu pinii corespunzători ai chipului Serial FTDI USB-to-TTL.

Pentru întreruperi externe: Pinii 2 și 3.

Semnal PWM: Pinii 3, 5, 6, 9, 10 si 11. Pot furniza un PWM pe 8 biți cu ajutorul funcției analogWrite().

SPI: Pinii 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). Aceștia sunt pentru comunicarea SPI.

LED: Pinul 13. Există un LED inclus în cablaj care este conectat la pinul 13. Când pinul este HIGH, LEDul se aprinde, când pinul este LOW, LEDul se stinge.

I2C: Pinii 4 (SDA) și pinul 5 (SCL). Suporta comunicarea pe I2C.

Dupa cum spuneam mai sus acesta este bazat pe ATmega328, care este un microcontroller CMOS pe 8 biți de putere mica bazat pe o arhitectură îmbunătățită RISC al lui AVR. Din punctul de vedere al executării instrucțiunilor într-un singur ciclu al ceasului, ATmega328 ajunge aproape la 1 MIPS pe MHz. Acest lucru îi dă proiectantului opțiunea de a optimiza dispozitivul pentru puterea consumată versus viteza de procesare.

Acesta are 3 timeri. Timer0 si Timer2 pe 8 biți, iar Timer1 pe 16 biți, fiecare având prescalere separate și mod de comparare. În vederea realizării întreruperii la fiecare secundă eu am folosit Timer1 și un prescaler de 1024.

timer speed (Hz) = =

În continuare am calculat frecvența de întrerupere:

frecvența de întrerupere =

+1 apare pentru că compare match register este indexat cu 0.

Prin rearanjarea ecuației de mai sus putem calcula compare match register:

compare match register =

Pentru Timer1 acest număr trebuie să fie mai mic de 65536.

Asa că pentru o întrerupere la 1 secundă avem nevoie de frecvența de 1 Hz

compare match register = = 15625 – 1 = 15624.

1.3.4 Configurația pinilor:

[18]

Descrierea pinilor:

VCC – alimentarea digitala

GND – masa

Port B (PB7:0) XTAL1/XTAL2/TOSC1/TOSC2 – Portul B este un port de intrare/ieșire bi-direcțional pe 8 biți cu un rezistor de pull-up intern. Ca și intrare, pinii Portului B care sunt trași pe low extern vor da curent dacă rezistorul de pull-up este activat. Pinii portului B sunt în tri-state când o condiție de reset devine activă, chiar dacă ceasul nu merge.

În funcție de selecția ceasului, PB6 poate fi folosit ca și intrare a amplificatorului oscilator invertor și intrare la circuitul intern al ceasului.

În funcție de selecția ceasului, PB7 poate fi folosit ca și ieșire din amplificatorul oscilator invertor.

Port C (PC5:0) – Portul C este un port de intrare/ieșire bi-direcțional pe 7 biți cu un rezistor de pull-up intern. Ca și intrări, pinii Portului C care sunt trași pe low extern vor da curent dacă rezistorul de pull-up este activat. Pinii portului C sunt tri-state când o condiție de reset devine activă, chiar dacă ceasul nu merge.

PC6/RESET – dacă siguranța RSTDISBL este programată, PC6 este folosit ca pin de I/O.

Dacă siguranța RSTDISBL nu e programata, PC6 esre folosit ca Reset. Un nivel LOW pe acest pin pentru mai mult decat minimul dimensiunii de puls va genera un Reset, chiar daca ceasul nu funcționeaza.

Port D (PD7:0) – Portul D este un port pe 8 biți bi-direcțional de I/O cu un rezistor de pull-up intern. Ca și intrare, pinii Portului D care sunt trași pe low extern vor da current dacă rezistorul de pull-ul este activat. Pinii portului D sunt tri-state când o condiție de reset devine activă, chiar daca ceasul nu merge.

AVCC – reprezintă sursa de tensiune pentru convertorul A/D, PC3:0 si ADC7:6. Ar trebui sa fie conectat extern la VCC, chiar dacă ADCul nu este folosit. Dacă ADCul este folosit ar trebui sa se conecteze la VCC printr-un filtru low-pass.

AREF – reprezintă pinul de referința analogică pentru Convertorul A/D.

ADC7:6 (TQFP si QFN/MLF) – in pachetele TQFP si QFN/MLF, ADC7:6 servesc ca intrări analogice ai convertorului A/D.

1.3.5 Diagrama bloc

[19]

Nucleul AVR este un set bogat de instrucțiuni cu 32 de regiștrii. Toti 32 regiștrii sunt conectați direct la Unitatea Aritmetico-Logica (ALU), permițându-le la 2 regiștri independenți sa fie accesați într-o singură instrucțiune executată într-un ciclu al ceasului. Arhitectura rezultantă este mult mai eficientă din punctul de vedere al codului în timp ce ajunge la viteze de 10 ori mai rapide decât microcontrollerele CISC convenționale.

Registrii

În cadrul acestei lucrări au fost folosiți registrii TCCR1A, TCCR1B, TCNT1, OCR1A și TIMSK1. Aceștia vor fi descriși pe scurt în rândurile următoare.

TCCR1A – Timer/Counter Control Register A

Offset: 0x80

Reset: 0x00

[20]

Biții 4, 5, 6, 7 – COM1, COM1, COM1, COM1 – se numesc Comparatori ai modului de ieșire pentru Canal (Compare Output Mode for Channel)

COM1A și COM1B controleaza comportamentul pinilor comparatorului de ieșire (OC1A și OC1B). Daca unul sau amandoi biți ai lui COM1A[1:0] sunt scriși în 1, ieșirea OC1A va face override la funcționarea normală de port a pinului de I/O dacă este conectat. Dacă unul sau amandoi biți ai lui COM1B[1:0] sunt scriși în 1, ieșirea OC1B va face override la funcționarea normală de port a pinului de I/O dacă este conectat. Bitul DDR (Data Direction Register) corespondent lui OC1A sau OC1B trebuie sa fie setat pentru a valida driver-ul de ieșire.

Când OC1x e conectat la pin, funcționarea biților COM1x[1:0] depinde de setarea bitului WGM1[3:0].

Biții 0 și 1 – WGM19 si WGM11 – Mod de generare a formei de undă (Waveform Generation Mode)

Combinați cu biții WGM1[3:2] ai registrului TCCR1B, acești biți controlează secvența de numărare a counter-ului, sursa valorii maxime a counter-ului, și ce tip de generare a formei de undă va fi folosit. Modurile de operare acceptate de Timer/Counter sunt: Normal mode, CTC mode, și 3 tipuri de PWM (Pulse Width Modulation).

Din cadrul registrului TCCR1A nu este folosit niciun bit dar a fost menționat pentru că și acesta trebuie inițializat.

TCCR1B – Timer/Counter Control Register B

Offset: 0x81

Reset: 0x00

Bitul 7 – ICNC1 – Input Capture Noise Canceler

Scriind acest bit pe 1 se activează captura de intrare a anulării zgomotului. Când anularea zgomotului este activat, intrarea pinului de captura (ICP1) este filtrată. Funcția de filtrare are nevoie de 4 valori succesive egale al pinului ICP1 pentru a schimba ieșirea.

Bitul 6 – ICES1 – Input Capture Edge Select

Acest bit selectează care margine a intrării pinului de captură (ICP1) este folosită pentru a declanșa un eveniment de captură. Când bitul ICES1 este scris în 0, marginea negativă este folosită pentru declansare, si când bitul ICES1 este scris în 1, o margine pozitivă este folosită pentru declanșarea capturii.

Biții 3 si 4 – WGM12, WGM13 – Waveform Generation Mode

Biții 0, 1 si 2 – CS12, CS11, CS12 – Clock Select

Aceștia sunt folosiți pentru selectarea prescaler-ului.

Selectarea biților se face în felul urmator: [22]

Din acest registru a fost nevoie de setarea bitului WGM12 pentru pornirea modului CTC (tabelul de mai jos) și de setarea biților CS10 si CS12 pentru un prescaler de 1064.

[23]

TCNT1L

Offset: 0x84

Reset: 0x00

[24]

TCNT1H

Offset: 0x85

Reset: 0x00

[25]

Cele doua locații, TCHT1H si TCNT1L, combinate TCNT1, dau acces direct, amândouă pentru citirea și scrierea operațiilor la counter-ul pe 16 biți a Timer-ului. Pentru a se asigura că și biții de high și biții de low sunt citiți și scriși simultan când Procesorul accesează acești regiștri, accesul este efectuat folosind un registru High Byte temporar pe 8 biți (TEMP).

Dacă counter-ul TCNT1 se modifică, în timp ce el rulează, apare riscul să se rateze valoarea de comparare dintre TCNT1 și unul dintre regiștrii OCR1x.

În cazul de față registrul TCNT1 = 0, adica counter-ul este inițializat cu 0 și începe să se incrementeze în momentul în care porneste Timer-ul.

OCR1AL

Offset: 0x88

Reset: 0x00

[26]

OCR1AH

Offset: 0x89

Reset: 0x00

[27]

Registrele de comparare la ieșire conțin o valoare pe 16 biți care e comparata în continuu cu valoarea counter-ului (TCNT1). O potrivire poate fi folosită pentru provocarea unei întreruperi sau pentru generarea de forme de unde la ieșire pe pinul OC1x.

Registrele de comparare la ieșire au 16 biți în dimensiune. Pentru a se asigura ca și biții de pe high, și biții de pe low sunt scriși simultan în timp ce Procesorul scrie în acești regiștrii, accesul este efectuat folosind un registru de High Byte temporar pe 8-biți (TEMP).

În cazul de față registrul OCR1A conține la ieșire valoarea 15625, valoare calculată mai sus când au fost prezentate Timer-ele, această valoare fiind comparată în continuu cu valoarea lui TCNT1.

TIMSK1

Offset: 0x6F

Reset: 0x00

[28]

Bitul 5 – ICIE – Input Capture Interrupt Enable

Bitul 2 – OCIEB – Output Compare B Match Interrupt Enable

Bitul 1 – OCIEA – Output Compare A Match Interrupt Enable

Bitul care ne intereseaza pe noi, când este scris 1 în acesta și I-flag-ul din Registrul de Status este setat, adica intreruperea este pornită global, întreruperea comparatorului B este pornită. Vectorul întreruperii corespunzătoare este executat când flag-ul OCFA, localizat în TIFR1, este setat.

Bitul 0 – TOIE – Overflow Interrupt Enable

În final, când valoarea counter-ului registrului TCNT1 ajunge să fie egală cu valoarea din registrul OCR1A, cu ajutorul bitului OCIEA al registrului TIMSK1 se produce întreruperea. Modului CTC resetează valoarea counter-ului și întregul proces se va repeta pe toată durata rulării programului.

1.4 MAX7221

MAX7221 este un drivere de afișaj compact, cu catod comun, care interfațează microprocesoarele de afișaje LED cu 7 segmente. Acestuia i se pot monta până la 8 digiți sau până la 64 de LEDuri individuale. Chipul conține un decodor de tip code-B, scanarea multiplexată a circuitului, drivere pentru segmente și digiți și o 8×8 memorie statică RAM care stochează fiecare digit. Doar de un rezistor exterior este nevoie pentru a seta curentul pe fiecare segment.

MAXul se conectează prin doar 3 linii de comunicații la microprocessor. Fiecărui digit în parte i se poate adresa microprocesorul fără a fi nevoie să se refacă circuitul. De asemenea se poate selecta daca se doreste a se folosii decodarea sau nu.

Dispozitivul include un mod de shutdown de low-power de 150uA, controlul luminozității, registrul pentru scanare, care îi dă voie utilizatorului să afișeze digiții de la 1 la 8 și un mod de testare care aprinde toate LEDurile afișajului.

Printre caracteristicile principale se numară:

Interfața Seriala de 10 MHz

Controlul individual al segmentelor LEDului

Selectarea modului de decodare sau fără decodare

Controlul luminozității atât analog cât și digital

La pornire nu se afișează nimic

SPI, QSPI, interfața serial Microwire

24 de pini

Configurația pinilor este următoarea:

[29]

Aceștia sunt:

Pinul 1, numit DIN (Serial-Data Input), reprezintă pinul prin care datele sunt încărcate în registrul de transfer intern pe 16 biți, pe frontul crescător a semnalului de ceas.

Pinii 2, 3, 5, 6, 7, 8, 10 și 11 numiți DIG 0 – DIG 7, și reprezintă liniile prin care se scurge curentul de la catozii comuni ai afișajului. Driverele digiților sunt de impedanță mare când MAXul este oprit.

Pinii 4 și 9 sunt numiți GND, aceasta este masa și amandoi pini trebuie conectați.

Pinul 12, numit CS (Chip-Select Input), iar acesta este important pentru transferul datelor. Doar când CS este pe LOW datele sunt încărcate în registrul de transfer.

Pinul 13, numit CLK, reprezintă pinul unde se va conecta linia pentru semnalul de ceas. Acesta are o rată maxima de 10 MHz. Pe frontul crescător al semnalului de ceas datele sunt trimise de la microprocesor către registrul intern de transfer al lui MAX. Pe frontul descrescător al semnalului de ceas datele sunt trimise către MAX prin linia DOUT. Această linie este activă doar când CS este LOW.

Pinii 14, 15, 16, 17, 20, 21, 22, 23, numiți SEG A – SEG G, DP, reprezintă pinii prin care curentul intră în afisajele LED. Din nou driverele segmentelor au impedanță mare când sunt oprite.

Pinul 18, numit ISET, reprezintă pinul prin care se setează curentul de vârf prin segmente. Acest lucru se realizează cu ajutorul unei rezistențe numite RSET.

Pinul 19, numit V+, reprezintă pinul prin care se alimentează integratul. Acesta se conectează la +5 V.

Pinul 24, numit DOUT, și reprezintă pinul prin care MAXul trimite date. Datele din DIN sunt valide doar dupa 16.5 ciclii de ceas mai târziu ai lui DOUT.

Un circuit de bază în care se conectează MAX7221 arată în felul următor:

[30]

Modul în care comunică toate blocurile între ele, ceea ce duc la funcționarea MAXului se bazează pe schema bloc următoare:

[31]

În vederea utilizării modului de decodare, MAXul dispune de o serie de caractere prestabilite, acestea includ numerele de la 0 la 9, 4 litere E, H, L și P, un minus și un blank dacă dorim sa nu afișăm nimic. Acestea sunt prezentate în tabelul de mai jos din documentatie:

[32]

Printre alte opțiuni, dacă dorim să conectăm mai multe MAXuri între ele acest lucru se face prin legarea liniei de DIN a MAXului următor la linia de DOUT a MAXului precedent. Acest lucru e prezentat în schema următoare:

[33]

Capitolul 2:

Proiectarea lucrarii

2.1 Schema bloc si Schema electrica

2.1.1 Schema bloc:

După cum se poate observa mai sus în schema bloc, funcționarea întregului sistem se bazează în principal pe un microcontroller, 4 butoane, un display driver si afișajul LED. Microcontrollerul așteaptă informații de la cele 4 butoane, care în funcție de acestea trimite secvențial mai departe catre MAX setul de date corespunzător. În continuare MAX-ul decodifică datele primite de la microcontroller și comandă afisajului LED informațiile care trebuie afișate.

2.1.2 Schema electrica:

În schema prezentată mai sus este reprezentat modul în care au fost conectate toate piesele din circuit. După cum se poate observa pinii 5, 6 si 7 sunt rezervați celor 3 linii de comunicații cu MAXul, DIN, CS si CLK, pinilor 11 si 12 sunt conectate cele 2 butoane responsabile pentru comutarea timpului care trebuie sa se scurgă uneia dintre părti a ceasului cu cealaltă, iar pinilor 2 si 3 sunt conectate cele 2 butoane responsabile cu setarea timpului.

2.2 Analiza documentației

Pentru realizarea lucrării am ales microcontroller-ul Arduino Nano prezentat mai sus, ca și afișaj LED am ales digiții numiți OPD-S15013UPG-BW, care sunt versiunea cu catod comun, iar pentru interfațarea microcontrollerului la afișaje am ales integratul MAX7221, care este versiunea cu catod comun.

Conform documentației, MAX7221 pentru conectarea la microcontroller are nevoie de doar 3 linii de comunicație: pinul de date (DIN), pinul pentru ceas (CLK) si pinul de Chip Select (CS).

De asemenea, tot din documentație, curentul prin afișajele LED se poate seta cu ajutorul pinului de ISET, care setează curentul prin fiecare segment, acesta fiind aproximativ de 100 de ori mai mare decât curentul de pe pinul ISET. În concluzie nu mai este nevoie de nici o rezistentă conectată la LED-urile pentru afișare, iar acestea se pot conecta direct la pinii corespunzători. Curentul de pe pinul ISET se reglează cu ajutorul unei rezistențe RSET ,pe care am ales-o de 100 Kohmi:

U = I ∙ R => I = => I = => I = 0.00005 A = 0.05 mA

Din ecuația de mai sus rezultă un curent de 0.05 mA care înmulțit cu 100 dă un curent de 5 mA pe fiecare segment ai digiților.

Integratul MAX7221 se alimentează la o tensiune între 4 si 5.5 V iar microcontrollerul Arduino Nano se poate alimenta și la 5V, de aceea am ales un regulator de tensiune care să scoată la ieșire 5V, și anume regulatorul L7805CV care poate primii la intrare o tensiune pană la 35V și la ieșire va avea 5V, iar curentul maxim fiind de 1A.

2.3 Descrierea codului

Pentru programarea plăcilor Arduino poate fi folosit orice limbaj de programare cu un compiler care produce codul binar necesar pentru respectivul microprocesor.

În realizarea codului sursă am folosit mediul de dezvoltare integrat Arduino. Această aplicație este scrisă în Java și are originile din mediile de dezvoltare realizate pentru proiectele Processing si Wiring. Mediu de dezvoltare Arduino dispune de un editor al codului cu opțiuni pentru copierea si lipirea textului, căutarea și înlocuirea unui text cu textul dorit, identificare automata, marcarea parantezelor etc., ca în oricare alt editor de text obișnuit. Acesta mai dispune de un mecanism destul de simplu de compilare si incarcare a codului pe placuța Arduino prin apăsarea a două butoane numite “Compile” și ”Upload”.

Pentru început am definit cele 3 linii de comunicare cu MAX-ul, eu am ales pinii 5, 6 si 7:

#define DIN 7

#define CS 6

#define CLK 5

În continuare am definit cele 4 butoane și LED-ul care se leagă la microprocessor, iar pentru acestea am ales pinii 8, 9, 11 si 12 si pinul 10 pentru LED:

#define buttonPin2 11

#define buttonPin3 12

#define buttonPin8 8

#define buttonPin9 9

#define LED 10

Întreg programul are doua stări, o stare în care se setează timpul dorit pentru fiecare jucător și o stare de funcționare normala:

int state = 0;

int stateRunning = 0;

int stateSetting = 1;

Starea curentă și starea precedent a cele 2 butoane în momentul setarii. Vor fi explicate mai pe larg în partea de cod unde au fost folosite.

int buttonPin2CurrState = LOW;

int buttonPin3CurrState = LOW;

int buttonPin2PrevState = LOW;

int buttonPin3PrevState = LOW;

Au mai fost declarate si inițializate celelalte variabile necesare pentru setarea uneia sau celeilalte părti a ceasului, pentru calcularea timpului afișat și doua flag-uri pentru a știi care parte a ceasului să ruleze la momentul respectiv.

int caz1 = 0, caz2 = 0;

int minute = 0, restSecunde = 0, restMinute = 0, ore = 0, secunde1 = 90, secunde2 = 90;

boolean timp1 = false;

boolean timp2 = false;

Pentru setarea pinilor pentru comunicații, pentru LED și pentru butoane am creat funcția initializesi aceasta cuprinde:

void initialise(){

pinMode(DIN, OUTPUT);

pinMode(CS, OUTPUT);

pinMode(CLK, OUTPUT);

digitalWrite(CS, HIGH);

pinMode(LED, OUTPUT);

pinMode(buttonPin2, INPUT);

pinMode(buttonPin3, INPUT);

pinMode(buttonPin8, INPUT);

pinMode(buttonPin9, INPUT);

pinMode(LED_BUILTIN, OUTPUT);

}

Funcția trimite a fost creată pentru a trimite mai ușor datele catre MAX. Pentru aceasta am folosit funcția implicită shiftOut din librăriile de la Arduino, care primește ca parametrii de doi pini, de date și de ceas, ordinea în care se vor trimite biții și datele care sunt trimise.

void trimite(byte address, byte data){

digitalWrite(CS, LOW);

shiftOut(DIN, CLK, MSBFIRST, address);

shiftOut(DIN, CLK, MSBFIRST, data);

digitalWrite(CS, HIGH);

}

După cum se poate observa și în imaginea de mai jos comunicarea pe MAX se face în momentul în care Chip Select-ul trece din HIGH în LOW, se trimite adresa, apoi datele, iar pentru încheierea transferului Chip Select-ul se trece înapoi din LOW în HIGH.

[34]

Cu ajutorul funcției setupTimer1 se setează timer1 pentru întreruperea la 1 secundă. Întreg registrul TCCR1A si TCCR1B se setează pe 0, se inițializează valoarea counter-ului cu 0 cu ajutorul lui TCNT1, iar registrul de comparare se setează pentru 1 Hz dându-i lui OCR1A valoarea 15625.

void setupTimer1(){

TCCR1A = 0;

TCCR1B = 0;

TCNT1 = 0;

OCR1A = 15625;

În continuare se pornește modul CTC (Clear timer on compare match = când counter-ul timer-ului ajunge la aceași valoare cu cea a comparatorului, acesta se resetează) shiftându-i 1 bit la stânga lui WGM12. Biții CS12 și CS10 sunt setați pentru un prescaler de 1024, iar shiftându-i 1 bit la stânga lui OCIE1A pornim intreruperea timer-ului de comparare.

TCCR1B |= (1 << WGM12);

TCCR1B |= (1 << CS12) | (1 << CS10);

TIMSK1 |= (1 << OCIE1A);

}

Mai multe detalii despre aceste configurări le puteți găsii la rubrica Regiștrii din Capitolul 1 la subcapitolul Arduino Nano.

Programul principal abia de aici începe să se execute. În primul rând este apelată funcția initialize, descrisă mai sus, iar cu ajutorul funcției trimite se începe trimiterea unor date necesare pentru setarea MAX-ului.

void setup() {

initialise();

trimite(0x0c, 0x01);

trimite(0x0b, 0x07);

trimite(0x0a, 0x0F);

trimite(0x09, 0xFF);

trimite(0x0f, 0x01);

Adresele acestor configurări au fost prezentate în tabelul următor din documentația de la MAX:

[35]

Pentru început la adresa XC, care este modul de Shutdown se trimite valoarea 1, care îl seteaza în modul de Operare Normala. În continuare la adresa XB, care se refera la limitarea numărului de digiți scanați și pregatiți pentru afișare, se trimite valoarea 7, care îi scanează pe toți cei 8 digiți să fie pregătiți de afișare. La adresa XA se setează intensitatea digiților și i se trimite valoarea F, ceea ce înseamna că intensitatea este maxima. Cu ajutorul MAX-ul, avem posibilitatea de a seta modul de decodare, adică îi trimitem un număr, iar acesta se ocupă singur de segrmentele care trebuie aprinse din acel digit. Avem posibilitatea să setam și doar o parte din digiți să fie în modul decodare, dar în această lucrare i-am folosit pe toți în acest mod. Asa că la adresa X9 îi trimitem valoarea FF. În ultimul transfer pentru configurare i se trimite la adresa XF, care se referă la testarea afișajului, valoarea 1, adică se activează modul de testare și se aprind toate segmentele. După un delay de 1000 de milisecunde se face un nou transfer care îl scoate din modul testare și îl setează în modul normal.

delay(1000);

trimite(0x0f, 0x00);

În continuare se apelează funcția setupTimer1, descrisă mai sus pentru setarea timer-ului , apoi sunt trimise câteva date pentru a se verifica dacă modul de decodare funcționează asa cum trebuie și cu acestea se încheie programul principal prin închiderea unei acolade.

setupTimer1();

trimite(0x01, 0x01);

trimite(0x02, 0x02);

trimite(0x03, 0x03);

trimite(0x04, 0x04);

trimite(0x05, 0x05);

trimite(0x06, 0x06);

trimite(0x07, 0x07);

trimite(0x08, 0x08);

}

În rândurile de mai jos începe funcția loop în care după executarea funcției setup o singură dată, aceasta se repetă în continuu până la închiderea dispozitivului. Aceasta începe printr-o condiție if care aprinde LED-ul dacă starea programului este în modul de setare, daca nu îl stinge.

void loop() {

if(state == stateSetting){

digitalWrite(LED, HIGH);

}else{

digitalWrite(LED, LOW);

}

În continuare cu ajutorul a două condiții if, dacă starea programului este în modul normal și dacă buton de pe pinul 8 este apăsat se trece în starea de setare și celor două cazuri le este atribuită valoarea 0, pentru a începe setarea timpului de la prima valoare.

if(state == stateRunning){

if(digitalRead(buttonPin8) == HIGH){

state = stateSetting;

caz1 = 0;

caz2 = 0;

}

}

Pentru intrarea înapoi în starea normală, din nou cu ajutorul a două condiții if, dacă starea este în modul de setare și dacă butonul de pe pinul 9 este apăsat se trece în starea normală.

if(state == stateSetting){

if(digitalRead(buttonPin9) == HIGH){

state = stateRunning;

}

}

Din nou, cu ajutorul a două condiții if , în timpul stării de funcționare normală, cu ajutorul celor doua butoane se setează timpul cărui jucător se scurge. Celor doua booleane l-i se vor atribui valoarea TRUE sau FALSE în funcție de situație. Cele două nu pot fi simultan TRUE sau simultan FALSE.

if(state == stateRunning){

if(digitalRead(buttonPin2) == HIGH){

timp1 = true;

timp2 = false;

}

if(digitalRead(buttonPin3) == HIGH){

timp1 = false;

timp2 = true;

}

}

În continuare, dacă starea programului este în modul setare, cu aceleași doua butoane se setează timpul de start al fiecărei părti. Sunt 7 valori din care utilizatorul poate alege acest timp și se face prin atribuirea pe rând al lui caz1 si caz2 valori de la 1 la 7.

Pentru ca microcontroller-ul în momentul setării sa nu perceapă mai multe apăsări în timp ce utilizatorul apasă doar odată pe buton, au fost puse doua flag-uri care indică starea curentă și starea precedentă a butonului. Inițial ele sunt egale, pe LOW, dar în momentul în care starii curente a butonului i se atribuie ceea ce a fost citit pe pinul unde este atașat respectivul buton și butonul a fost apăsat, aceasta devine diferită de starea precedentă și i se permite programului să treacă prin condiția if. În final, stării precedente îi este atribuită valoarea stării curente, pentru ca data viitoare când programul ajunge la această condiție deja e starea precedentă și urmează a fi comparată cu starea actuală citită pe pinul respectiv. Mai este pusă o condiție if în vederea asigurării că starea curentă este HIGH, pentru evitarea atribuirii de noi valori a celor două variabile caz1 și caz2. Acest lucru s-ar întampla în starea imediat următoare după ce utilizatorul ridică mâna de pe buton.

if(state == stateSetting){

buttonPin2CurrState = digitalRead(buttonPin2);

if(buttonPin2CurrState != buttonPin2PrevState){

if(buttonPin2CurrState == HIGH){

if(caz1 <= 6){

caz1++;

}

if(caz1 > 6){

caz1 = 1;

}

}

buttonPin2PrevState = buttonPin2CurrState;

}

buttonPin3CurrState = digitalRead(buttonPin3);

if(buttonPin3CurrState != buttonPin3PrevState){

if(buttonPin3CurrState == HIGH){

if(caz2 <= 6){

caz2++;

}

if(caz2 > 6){

caz2 = 1;

}

}

buttonPin3PrevState = buttonPin3CurrState;

}

Cu ajutorul a două switchuri se setează valoarea timpului de start amintit mai sus prin atribuirea variabilelor caz1 și caz2 valori de la 1 la 7. Variabilelor secunde1 și secunde2 îi pot fi atribuite următoarele valori: 5 minute, 7 minute, 10 minute, 30 de minute, 1 ora, 1 ora și 30 de minute, 2 ore; acestea sunt atribuite în secunde si convertite ulterior.

switch(caz1) switch(caz2){

case 0: case 0:

secunde1 = 0; secunde2 = 0;

break; break;

case 1: case 0:

secunde1 = 300; secunde2 = 300;

break; break;

case 2: case 0:

secunde1 = 420; secunde2 = 420;

break; break;

case 3: case 0:

secunde1 = 600; secunde2 = 600;

break; break;

case 4: case 0:

secunde1 = 1800; secunde2 = 1800;

break; break;

case 5: case 0:

secunde1 = 3600; secunde2 = 3600;

break; break;

case 6: case 0:

secunde1 = 5400; secunde2 = 5400;

break; break;

case 7: case 0:

secunde1 = 7200; secunde2 = 7200;

break; break;

} } }

În continuare avem funcția ISR(TIMER1_COMPA_vect) cu ajutorul căreia realizăm întreruperea la fiecare 1 secundă. În interiorul acesteia se calculează defapt timpul care urmează sa fie afișat pe digiți cu ajutorul celor doua funcții timpStanga și timpDreapta care se ocupa de convertirea secundelor în minute și ore și le trimite către MAX.

ISR (TIMER1_COMPA_vect){

if(state == stateSetting){

timpDreapta(secunde2);

timpStanga(secunde1);

}

if(state == stateRunning){

if(timp2 == true){

timpDreapta(secunde2);

if(secunde2 > 0){

secunde2–;

}

}

if(timp1 == true){

timpStanga(secunde1);

if(secunde1 > 0){

secunde1–;

}

}

}

}

În final avem cele două funcții amintite mai sus cu ajutorul cărora se preia numărul de secunde și e transformat în minute și ore dacă e cazul, iar cu ajutorul operației %10 timpul este impărțit pe digiți.

void timpDreapta(int secunde){ void timpStanga(int secunde){

restSecunde = secunde%60; restSecunde = secunde%60;

minute = secunde/60; minute = secunde/60;

restMinute = minute%60; restMinute = minute%60;

ore = minute/60; ore = minute/60;

if(secunde < 3600){ if(secunde < 3600){

trimite(0x01, restSecunde%10); trimite(0x01, restSecunde%10);

restSecunde = restSecunde/10; restSecunde = restSecunde/10;

trimite(0x02, restSecunde%10); trimite(0x02, restSecunde%10);

trimite(0x03, restMinute%10); trimite(0x03, restMinute%10);

restMinute = restMinute/10; restMinute = restMinute/10;

trimite(0x04, restMinute%10); trimite(0x04, restMinute%10);

} }

if(secunde >= 3600){ if(secunde >= 3600){

trimite(0x01, restMinute%10); trimite(0x01, restMinute%10);

restMinute = restMinute/10; restMinute = restMinute/10;

trimite(0x02, restMinute%10); trimite(0x02, restMinute%10);

trimite(0x03, ore%10); trimite(0x03, ore%10);

ore = ore/10; ore = ore/10;

trimite(0x04, ore%10); trimite(0x04, ore%10);

} }

} }

Capitolul 3: Realizare

3.1 Simulare lucrare

Pentru început circuitul a fost realizat și simulat în programul Proteus. Au fost conectate toate componentele conform schemei electrice și a fost incărcat în microcontroller un prim program care afisa toate numere de la 1 la 8 pentru a se verifica că toate merg bine.

În urma realizării complete a codului circuitul a fost simulat ca funcționare normală a dispozitivului și totul functionează bine după cum se poate observa în imaginea de mai jos.

3.2 Realizare practica:

Dupa ce toate simularile au fost realizate cu succes am trecut la realizarea practica si aceasta se poate observa in imaginile de mai jos:

Concluzii

Bibliografie

[1] Site-ul bizzo.ro, modelul Saitek Competition Game Pro oferit spre vânzare. Link-ul pozei: https://www.bizoo.ro/firma/alcorgrup/vanzare/1057625/ceas-sah-electronic

[2] Site-ul chess.com prezintă un articol despre istoria șahului unde e prezentă poza cu link-ul: https://files.chesscomfiles.com/albums/batgirl/35aig5f1334377120/543517_l.jpg

[3] Poza găsită pe site-ul wikipedia.org. Link-ul pozei: https://upload.wikimedia.org/wikipedia/commons/6/6d/Digitalna_sahovska_ura2.jpg

[4] Poza găsită într-un articol pe instructables.com. Link-ul pozei: https://cdn.instructables.com/FCD/YJAF/ICJM6MP1/FCDYJAFICJM6MP1.MEDIUM.jpg

[5] [6] [29] [30] [31] [32] [33] [34] [35] Documentație MAX7221

[8] [9] [10] [11] [12] [13] [14] [15] Pagina oficială https://www.arduino.cc/

[16] [17] Documentație Arduino Nano

[18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] Documentație ATmega328

Similar Posts