This is an old revision of the document!


Laboratorul 0: Aplicații introductive

Capitole utile din Datasheet ATmega328P

  • 1. Pin Configurations - pag. 3
  • 14. I/O-Ports - pag. 58

1. Introducere

1.1. De ce?

I: Ce facem noi aici? Unde se foloseste ce invatam? Chiar e util?

R: Well, ca sa spunem pe scurt: “multe”, “peste tot” si “da”; ar fi raspunsurile, dar mai bine o luam pe un exemplu.

Tocmai ti-ai construit un nou PC si i-ai pus si RGB pe RAM, pe ventilatoare, pe carcasa, o gramada. Acum vine intrebarea, cine “apasa” butoanele astfel incat culorile sa iasa asa cum le pui tu in software? CPU-ul sa stea el si sa aiba grija sa schimbe culorile? Dupa mine e cam o irosire de resurse. Aici intervine un microcontroller! E un procesor mai mic, mai simplist, cu un task bine determinat in sistem. Treaba lui in cazul nostru este sa controleze RGB-ul intreaga lui viata.

1.2. Ce e un microcontroller (µC)?

TLDR, un calculator intr-un cip. Mai in detaliu, el este un circuit integrat ce reunește o unitate de procesare (CPU), memorii(volatile RAM, nevolatile EEPROM, Flash, ROM) și diverse periferice ce îi permite acestuia să comunice cu mediul extern.

1.3. µC in the wild

Le gasim in diferite dispozitive precum: telefoane, electro-casnice, sateliti, avioane, in fabrici etc. Există o gamă largă de microcontrollere disponibile și acestea se aleg în funcție de aplicație, având în vedere mai ales optimizarea costului și a consumului energetic pentru dispozitivul unde µC urmează a fi folosit.

Exemple de proiecte

 [1] Bird tracking  [2] Bird tracking  [3] Palm size quad-copter [4] Robot line follower (Tare N' Bară) [5] Robot ce joacă fotbal (IronFoot) [6] Robot submarin (R0X1) [7] Self-balancing skateboard

Pentru alte exemple, puteți începe căutarea de aici: https://www.hackster.io/projects/tags/microcontroller

1.4. Ce gasim intr-un µC?

  • Unitatea centrală de procesare (µP core) cu o arhitectură care poate fi pe 8, 16, 32 sau 64 de biţi
  • Memorie de date volatilă (RAM) și/sau non-volatilă (Flash sau EEPROM)
  • Memorie de program non-volatilă (Flash sau EEPROM)
  • Porturi digitale de intrare-ieşire de uz general (GPIO - General Purpose Input Output)
  • Interfeţe seriale de comunicație (USART, SPI, I2C, PCM, USB, SDIO etc.)

More

  • Interfețe ethernet
  • Interfețe pentru afișaj grafic (LVDS, HDMI sau alte protocoale dedicate controlului afișajelor LCD)
  • Timere (cu rol intern, sau utilizate în generarea semnalelor periodice -ex: PWM-, sau ca watchdog)
  • Convertoare analog-digitale și digital-analogice (ADC, DAC), front-end-uri analogice și alte circuite dedicate semnalelor analogice
  • Sursă de tensiune integrată
  • Interfață pentru programare şi debugging


Perifericele reprezintă orice dispozitiv, intern sau extern, care se conectează la un sistem de calcul și îi extinde funcționalitatea de bază. În cazul microcontroller-ului, există o serie de astfel de periferice incluse direct în circuitul integrat (exemple mai sus). Deși nu seamănă cu perifericele unui PC (monitor, placă grafică, tastatură, mouse etc.), fără ele microcontroller-ul nu ar putea interacționa cu mediul exterior. Mai mult, perifericele ne ajută să conectăm alte elemente mai performante la controller si sa îi putem oferi funcționalități similare unui sistem PC (conexiune la internet, linie de date USB, display grafic etc.)

2. Microchip (Atmel) AVR

Pe parcursul semestrului vom lucra cu microcontrollere din familia AVR de la Microchip. Acestea au arhitectură Harvard pe 8 biţi şi set redus de instrucţiuni (RISC).

Va mai amintiti de banda de asamblare (pipeline)? Haideti sa va dam un “fun fact”. µC AVR au o unitate de execuţie în bandă de asamblare cu două niveluri, acest lucru permiţând că următoarea instrucţiune să fie adusă din memorie (fetch) în timp ce instrucţiunea curentă este în execuţie. Majoritatea instrucţiunilor se execută într-un singur ciclu de instrucţiune, acest lucru permiţând atingerea unui throughput de 1MIPS pe MHz.

2.1. ATmega328P

 atmega324| Un µC ATmega324 în capsulă PDIP

Cu micutul acesta vom lucra noi. Este un microcontroller pe 8 biți din familia megaAVR. Registrele şi magistrala internă de date sunt pe 8 biţi.

Specificatiile µC-ului

  • 32 KB Flash (determină dimensiunea maximă a programului care poate fi executat)
  • 1 KB EEPROM
  • 2 KB RAM
  • 20 MHz frecvența maximă de lucru
  • Tensiune de alimentare între 1.8V și 5.5 V
  • 6 canale de PWM
  • 8 canale de ADC, cu rezoluție de 10 biți
  • 3 porturi digitale de I/O (GPIO - General Purpose I/O) , fiecare cu 7 sau 8 pini, în total 23 de pini de I/O
  • 3 timere (două pe 8 biți și unul pe 16 biți)
  • Interfeţe de comunicație seriale: USART, SPI, TWI
  • Interfaţe de programare ISP și debug JTAG


La acest microcontroller vom invata sa ii configuram pinii si sa interactionam cu mediul exterior din cod. Acesta are 28 de pini (prezentați mai jos), dintre care 5 sunt pentru alimentare sau funcții auxiliare, iar 23 sunt pentru I/O. microcontrollerul are patru porturi: A, B, C si D; din care doar ultimele 3 sunt accesibile noua prin pini externi.

Configurarea pinilor pentru ATmega328P

Pentru mai multe detalii, mereu puteti consulta datasheet-ul (documentația tehnică sumarizată) a microcontrollerului. :)

2.2. Placuta de laborator

Fundatia Arduino a creat seturi de placute de dezvoltare open source, placute pe care le vom folosi si noi la laborator. O placuta de dezvoltare este un circuit care ne pune la dispozitie facil pinii µC-ului de pe ea si care contine cirtuite de alimentare, de protectie si eventual programatorul µC-ului.

Programatorul este un cip special, chiar un microcontroller uneori, care are rolul sa incarce codul in memoria µC. Nu putem lega µC-ul direct la firele de USB de la un PC, avem nevoie de cineva sa “traduca” informatia respectiva.

Pinout Arduino UNO:  Pionout Arduini UNO

2.3. Framework-ul Arduino

Desi la laborator va vom pune sa lucrati direct cu adrese de memorie pentru a configura pinii si a ii controla, va vom arata cum sa folositi si un framework numit Arduino. Acesta este scris in C++ si este practic o biblioteca cu functii ajutatoare si headere (fisiere .h) cu define-uri pentru fiecare procesor in parte. Ca orice nivel de abstractizare in plus, acesta face dezvoltarea mai usoara, dar aduce si un performance penalty de chiar si 20 de ori mai incet uneori. 3

3. Let's get to work

3.1. Actuatori si Traductori (Senzori)

Pentru a putea intefața cu mediul exterior, sunt utilizate diferite componente electronice care au rol fie de actuator (modifică starea mediului exterior) sau de traductor/senzor (sunt influențate de mediul exterior și oferă informații microcontroller-ului despre diverși parametri).

Exemplu actuatori:

  • Ventilatoare;
  • Indicatoare sonore - buzzere;
  • Indicatoare luminoase;
  • Rezistențe de încălzire.

Uneori pentru a putea activa un actuator, este nevoie de un element de acționare. Spre exemplu, daca am dori sa pornim un motor, µC-ul doar da o comanda logica de start la un tranzistor ce se va deschide si va lasa un curent mare sa treaca prin el (aici prin “curent mare” comparam fata de maximul de cativa miliamperi pe care ii poate scoate un µC).

Exemplu Senzori:

  • Butoane;
  • Fotorezistori - rezistenta lui electrica este influentata de cantitatea de lumina;
  • Termistori - rezistenta lui electrica este influentata de temperatura.

În funcție de tipul traductoarelor, acestea pot avea nevoie de prelucrarea semnalului înainte ca acesta să fie preluat de µC (signal conditioning) - de exemplu fotorezistorul trebuie folosit într-un montaj cu divizor de tensiune sau cu sursă de curent -, sau pot fi conectate direct la microcontroller - de exemplu butonul.

3.1.1. LEDs

LED-urile - Light Emitting Diode - numite și diode electroluminesciente emit lumină când ele sunt polarizate direct. A nu se confunca cu becurile deoarece au metode de functionare radical diferite.

In depth În funcție de semiconductorii care sunt utilizați în construcție, și de plasticul ce are rol de lentilă de dispersie și filtru optic, LED-urile pot emite lumină în diferite culori. Nu confundați LED-urile cu becurile! În timp ce becurile emit lumina prin încalzirea unui filament de tungsten la temperaturi foarte mari, LED-urile emit lumina trecând un curent printr-un material semiconductor (joncțiune p-n). Spre deosebire de becuri, al căror randament este de sub 5% - majoritatea energiei primite de ele se pierde prin efect caloric -, LED-urile au un randament de transformare a energiei electrice în energie luminoasă mult mai mare.


LED-urile pot fi utilizate pe post de indicator luminos (adesea utilizate în diferite aparate pentru a semnaliza faptul că aparatul este pornit și realizează un anumit lucru), sau pentru iluminare, caz în care sunt utilizate LED-uri de putere. În cadrul laboratorului LED-urile sunt utilizate pentru a indica starea unui pin.

Calculul rezistenței de limitare a curentului

LED-urile sunt diode, așadar, curentul prin acestea crește exponențial cu creșterea tensiunii aplicate. Pentru a utiliza un LED pentru indicarea stării unui pin (mai degrabă spus pentru a indica prezența de tensiune), curentul prin LED trebuie limitat. Aceasta se poate realiza în cel mai simplu mod prin înserierea unei rezistențe cu LED-ul.

Un LED este proiectat să opereze la un curent nominal (ex: 10mA). Căderea de tensiune pe LED urile indicatoare, de mică putere, la acest curent este dată de chimia LED-ului, care da si culoarea acestuia. In cadrul laboratorului, deoarece folosim un LED de un curent asa mic, putem sa il alimentam direct de pe pinii logici ai µC-ului.

Schema utilizată este următoarea:

 Schema de lucru și calculul rezistenței de limitare a curentului prin LED

Solutie: Dacă alimentarea microcontroller-ului este de 5V pentru un LED roșu ce dorim să îl folosim la 10mA, specificat de producător cu o cădere de tensiune de 1.7V, trebuie să folosim o rezistență de 330 de ohmi.

3.1.2. Butoane

Cel mai simplu mod de interacțiune al utilizatorului cu un microcontroller îl constituie folosirea butoanelor. Modul de conectare al unui push-button in acest laborator este dat în figura de mai jos:

 Conectarea unui push-button: a) incorect, cu intrare flotantă, b) corect, cu rezistență de pull-up

Conectarea unui push-button: a) incorect, cu intrare flotantă, b) corect, cu rezistență de pull-up

a) Arată un buton conectat la pinul PD0 al µC. La apăsarea butonului, intrarea PD0 va fi legată la GND, deci va fi în starea logică “0”. Acest mod de legare este incorect deoarece atunci când butonul nu este apăsat, intrarea se află într-o stare nedefinită (ca și cum ar fi lăsată în aer), ea nefiind conectată nici la GND, nici la Vcc! Această stare se numește stare de impedanță mărită. În practică, daca am citi acum valoarea pinului, se va produce un rezultat de 1 sau 0 în funcție de condițiile de mediu. Spre exemplu, dacă apropiem degetul de acea intrare, citirea va fi 1, iar, daca îndepărtăm degetul, citirea va fi 0.

b) Arată modul corect de conectare al butonului, folosind o rezistență de pull-up între pinul de intrare și Vcc. Această rezistență are rolul de a aduce intrarea în starea “1” logic atunci când butonul este liber prin “ridicarea” potențialului liniei la Vcc. Alternativ, se poate folosi o rezistență de pull-down (conectată la GND), caz în care intrarea este ținută in starea logică “0” cât timpul butonul nu este apăsat.

La laborator: Pentru a economisi spațiu exterior, în µC-ul ATmega328P, aceste rezistențe au fost incluse în interiorul circuitului integrat. Inițial ele sunt dezactivate iar activarea acestora se poate face prin software.

3.2. Lucrul cu registrele

Acesta poate fi considerat cel mai important pas atunci cand dorim sa folosim un µC. Trebuie sa invatam cum sa configuram intern µC-ul pentru ca sa indeplineasca functiile dorite de noi. In acest laborator vom configura pinii pentru a fi de I/O: unii pini sa citeasca daca se afla tensiune pe ei (input) sau altii sa dea 0 volti sau 5 volti in functie de comenzile noastre din software (output).

Pentru a clarifica niste terminologie: acum cand spunem ca setam un registru sau scriem intr-un registru, nu ne referim la registrii de uz general din procesor cu care ati lucrat la IOCLA. Ne referim la adrese de memorie rezervate in µC. Vom repeta iarasi impreuna: “Prin registru ne referim la o adresa de memorie”. Practic cum merg lucrurile “under the hood”, la acesti bytes sunt legaturi fizice si daca scriem un bit de 1 sau de 0 in anumite pozitii, activam sau dezactivam elemente din µC.

Mereu pentru a afla cum sa configurati un periferic, datasheet-ul µC-ului este cea mai buna locatie sa aflati exact fiecare configurare unde se afla si ce face. Deoarece nu este deloc placut sa scrii in cod *(0x04) = 0b0000 0001, producatorii de µC ofera biblioteci ( avr-libc) pentru a da nume acestor adrese. Urmatorul cheatsheet va arata cum sa configurati un anumit bit de la o anumita adresa folosind macrouri (care sunt considerate si best practice).

Pentru a scrie o valoare într-un registru se poate face direct atribuirea unei valori, însă acest mod nu face codul foarte ușor de înteles. Recomandarea noastră este de a folosi măștile pe biți ((1 << x)) sau macro-ul _BV(x). De asemenea recomandăm folosirea numelui pinului în loc de indexul acestuia, pentru că numele acestora sunt sugestive pentru funcția pe care o îndeplinesc (spre exemplu, în registrul ADCSRA al convertorului analog-digital, bitul ADEN este bitul de enable). Numele pinilor, ca și în cazul registrelor, sunt deja definite în avr-libc.

Operație Formă
Scriere bit pe 1
 macro |= (1 << bit_index) 
Scriere bit pe 0
 macro &= ~(1 << bit_index) 
Toggle bit
 macro ^= (1 << bit_index) 
Citire bit
 macro & (1 << bit_index) 

Exemplu: Lucrul cu registre

DDRB = 8;               // AȘA NU.
DDRB = (1 << 3);        // Nici așa, este hardcodat indexul pinului.
DDRB |= (1 << PB3);     // AȘA DA.
DDRB |= _BV(PB3);       // AȘA DA.

Detalii despre lucru cu biții din registre puteți citi și la secțiunea tutoriale de pe wiki.

Nu va temeti, vom avea destule laboratoare in care sa va obisnuiti cu lucrul cu registre si configurarea µC-ului. Va incurajam sa depuneti acum la inceput niste efort pentru un drum usor in acest semestru.

3.3. Registrele de I/O

Pentru acest laborator v-am scutit de cautarea in datasheet, lucru ce poate parea complicat la inceput si am sintetizat pentru voi ce adrese de memorie (registrii) trebuie sa modificati pentru lucrul in acest laborator.

Microntroller-ul ATmega324 oferă 4 porturi I/O a câte 8 pini, iar intern, fiecare port are asociat trei registre a câte 8 biți prin care utilizatorul poate controla la nivel de pin fluxul datelor: poate scrie/citi date în/din portul respectiv. Aceste trei registre sunt:

  • DDRn - Data Direction Register
    • stabilește direcţia pinilor portului
    • dacă bitul x are valoarea 0 atunci pinul x este de intrare
    • dacă bitul x are valoarea 1 atunci pinul x este de ieșire
  • PORTn - Data Register
    • stabilește valorile de ieşire ale pinilor sau activează/dezactivează rezistenţele de pull-up
    • dacă bitul x are valoarea 0 atunci
      • dacă pinul x este de ieșire el va avea valoarea LOW
      • daca pinul x este de intrare rezistența de pull-up va fi dezactivată
    • data bitul x are valoarea 1 atunci
      • daca pinul x este de ieșire el va avea valoarea HIGH
      • dacă pinul x este de intrare rezistența de pull-up va fi activată
  • PINn - Input Pins Address
    • putem citi date de pe portul respectiv
    • dacă pinul x are valoarea LOW atunci bitul x va avea valoarea 0
    • daca pinul x are valoarea HIGH atunci bitul x va avea valoarea 1

n poate să fie A, B, C sau D în funcţie de portul selectat. x poate să fie între 0 și 7.

Descrierea detaliată a porturilor şi registrelor corespunzătoare acestora se găseşte în datasheet-ul ATmega324, în capitolul I/O Ports.

3.3.1. Exemplu de lucru cu iesiri

Să presupunem că avem un LED legat la pinul 1 al portului B (numit PORTB1 sau PB1). Pentru a aprinde sau stinge LED-ul trebuie să urmăm următorii pași:

  • Pinul PB1 trebuie configurat ca ieșire
    • Bitul 1 (PB1) din registrul DDRB va fi 1
    • DDRB |= (1 « PB1);
  • Pentru a aprinde LED-ul trebuie ca pinul PB1 sa ia valoarea HIGH
    • Bitul 1 (PB1) din registrul PORTB va fi 1
    • PORTB |= (1 « PB1);
  • Pentru a stinge LED-ul trebuie ca pinul PB1 sa ia valoarea LOW
    • Bitul 1 (PB1) din registrul PORTB va fi 0
    • PORTB &= ~(1 « PB1);

3.3.2. Exemple de lucru cu intrari

Să presupunem ca avem un buton legat la pinul 4 al portului D (numit PORTD4 sau PD4), din cazul b) prezentat anterior. Pentru a determina starea butonului (apăsat sau liber) trebuie să urmăm următorii pași:

  • Pinul PD4 trebuie configurat ca intrare
    • Bitul 4 (PD4) din registrul DDRD va fi 0
    • DDRD &= ~(1 « PD4);
  • Pentru a determina starea de apăsare a butonului trebuie să citim valoarea pinului la care este atașat. Acesta va fi 1 atunci când butonul este liber și 0 atunci când butonul este apăsat
    • Citim valoarea bitului 4 (PD4) din registrul PIND
    • char val = PIND & (1 « PD4);


Hello World cu registri

Vom scrie un program care stinge și aprinde un LED la intervale de 500 ms. Acest lucru se face modificând tensiunea unuia dintre pinii microcontroller-ului, în cazul nostru pinul 5 din portul B (PB5), pe placa Arduino UNO, pinul didital 13.

// este de preferat sa folosim macrouri pentru a nu hardcoda valori
// daca vrem sa schimbam pinul, acum avem o singura linie de modificat
#define LED PB5
 
void setup() {
  DDRB |= (1 << LED);
  // sau
  // DDRB |= _BV(LED);
}
 
void loop() {
  PORTB |= (1 << LED); // ori _BV(LED)
  delay(500); // functie din framework-ul de Arduino pentru a simplifica momentan programarea
  PORTB &= ~(1 << LED); // ori _BV(LED)
  delay(500);
}

3.4. Framework-ul Arduino

Cum am spus si mai devreme, acest framework aduce un nivel de abstractizare in plus ce mascheaza lucrul cu registre si operatii pe biti in spatele unor functii mai incede, dar convenabile.

3.4.1 Setup-ul IDE-ului

  • Tool-ul cel mai des intalnit si oferit de fundatia Arduino este Arduino IDE. Acesta ofera suport pentru mai multe placi si procesoare AVR, cat si posibilitatea de a instala biblioteci 3'rd party, dar pe lnaga niste syntax highlighting se simte ca si cum ati programa in Notepad++.
  • Un alt tool folosit de Microchip este AVR Studio (depracated) si mai nou Atmel Studio. Acesta este un tool profesional si destul de greu de utilizat la capacitati maxime. Daca vreti sa il utilizati, ar fi ca si cum ati folosi un flex sa va taiati friptura.
  • Un al treilea IDE posibil ar fi Visual Studio Code cu extensia de la PlatformIO pentru a avea acces automat la bibliotecile µC-lor si a incarca codul pe acestea, in acelasi timp avand si intellisense.

Vorbiti cu asistentul de laborator pentru ce IDE va sugereaza/folosi el pentru a va putea ajuta mai usor daca intampinati dificultati.

3.4.2. Primul cod

Cel mai simplu cod de arduino ce poate fi compilat este uratorul:

Cod

void setup() { // setup facut de user pentru configurarea µC-ului
}
 
void loop() { // codul userului ce ruleaza in bucla
}


Ce poate fi tratat ca urmatorul cod clasic de C in spate:

Cod

#include "µC_header" // importam header-ul µC-ului pentru a avea macrouri conveniente
 
void setup() { // setup facut de user pentru configurarea µC-ului
}
 
void loop() { // codul userului ce ruleaza in bucla
}
 
int main(void) {
    // ... // probabil niste configurari default puse de compilator
 
    setup();
 
    while (1) {
        loop();
    }
 
    return -1; // nu ar trebuii sa se ajunga aici
}


3.4.3. Lucrul cu I/O folosind Arduino

Acestea sunt cele 3 functii de baza puse la dispozitie de framework-ul Arduino pentru a lucra cu pinii ca si I/O.

Acum cand vom dori sa ne referim la un pin anume, vom folosit identificatorul pinului asa cum apare pe placuta Arduino utilizata (de la 0 la 13 sau de la A0 la A7).

pinMode() Este utilizat pentru a configura pinul daca sa fie de output, input sau input cu pull-up.

Semnatura: void pinMode(pin, mode)

pin: de la 0 la 13 sau de la A0 la A7

mode: INPUT, OUTPUT, sau INPUT_PULLUP

digitalWrite() Este folosit pentru a seta un pin pe HIGH sau LOW (5 respectiv 0 volti in setup-ul nostru). HIGH si LOW sunt 2 macrouri din framework si sunt doar niste int-uri in spate.

Semnatura: void digitalWrite(pin, value)

pin: pinul de Arduino value: HIGH sau LOW (macrouri ale framework-ului)

digitalRead() Returneaza HIGH sau LOW reprezentand starea pinului. HIGH si LOW sunt 2 macrouri din framework si sunt doar niste int-uri in spate.

Semnatura: int digitalRead(pin)


Hello World folosind Arduino
#define LED 13 // este de preferat in continuare sa folosim macrouri, nu hardcodam valori
 
void setup() {
  pinMode(LED, OUTPUT);
}
 
void loop() {
  digitalWrite(LED, HIGH);
  delay(500);
  digitalWrite(LED, LOW);
  delay(500);
}

4. Prima aplicație

4.1. Legătura cu mediul exterior: traductoare, senzori și actuatori

Pentru a putea intefața cu mediul exterior, sunt utilizate diferite componente electronice care au rol fie de actuator (modifică starea mediului exterior) sau de traductor/senzor (sunt influențate de mediul exterior și oferă informații microcontroller-ului despre diverși parametri).

Actuatorii sunt acele elemente care influențează mediul exterior. Putem spune că actuatorii sunt elementele ce pot fi comandate și care pot interacționadirect cu mediul pentru a influența diferiți parametri (ventilatoare, indicatoare sonore - buzzere , indicatoare luminoase, rezistențe de încălzire, etc). Uneori pentru a putea activa un actuator, este nevoie de un element de acționare. De exemplu, pentru a putea porni un motor(actuator) prin comanda dată de microcontroller, trebuie să folosim un element de acționare (care pornește ventilatorul) intermediar care să poată comanda curenți mari (prin ventilator) folosind curenți foarte mici de comandă (ieșirea microcontrollerului). În acest exemplu, soluția ar fi utilizarea unui tranzistor.

Traductoarele (sau traductorii) sunt acele elemente care iși modifică proprietățile electrice în funcție de parametrii mediului exterior și oferă microcontroller-ului informații despre mediul exterior. De exemplu: un fotorezistor va avea rezistența electrică mult mai mare în lipsa luminii, iar când aceasta este iluminată va avea o rezistență electrică de zeci sau chiar sute de ori mai mică. Un alt exemplu de traductor este butonul simplu normal deschis: când este apăsat el închide un contact, când nu este apăsat, contactul din interior este deschis. În funcție de tipul traductoarelor, acestea pot avea nevoie de prelucrarea semnalului înainte ca acesta să fie preluat de microcontroller (signal conditioning) - de exemplu fotorezistorul trebuie folosit într-un montaj cu divizor de tensiune sau cu sursă de curent -, sau pot fi conectate direct la microcontroller - de exemplu butonul.

În cadrul acestui laborator veți utiliza LED-uri pe post de indicator luminos de semnalizare a stării unui pin și butoane pentru a transmite informație către microcontroller.

4.1.1. Diode LED

LED-urile - Light Emitting Diode - numite și diode electroluminesciente emit lumină când ele sunt polarizate direct. În funcție de semiconductorii care sunt utilizați în construcție, și de plasticul ce are rol de lentilă de dispersie și filtru optic, LED-urile pot emite lumină în diferite culori. Nu confundați LED-urile cu becurile! În timp ce becurile emit lumina prin încalzirea unui filament de tungsten la temperaturi foarte mari, LED-urile emit lumina trecând un curent printr-un material semiconductor (joncțiune p-n). Spre deosebire de becuri, al căror randament este de sub 5% - majoritatea energiei primite de ele se pierde prin efect caloric -, LED-urile au un randament de transformare a energiei electrice în energie luminoasă mult mai mare.

LED-urile pot fi utilizate pe post de indicator luminos (adesea utilizate în diferite aparate pentru a semnaliza faptul că aparatul este pornit și realizează un anumit lucru), sau pentru iluminare, caz în care sunt utilizate LED-uri de putere.

În cadrul laboratorului LED-urile sunt utilizate pentru a indica starea unui pin.

LED-urile sunt diode, așadar, curentul prin acestea crește exponențial cu creșterea tensiunii aplicate. Pentru a utiliza un LED pentru indicarea stării unui pin (mai degrabă spus pentru a indica prezența de tensiune), curentul prin LED trebuie limitat. Aceasta se poate realiza în cel mai simplu mod prin înserierea unei rezistențe cu LED-ul.

Calculul rezistenței de limitare a curentului:

Un LED este proiectat să opereze la un curent nominal (ex: 10mA). Căderea de tensiune pe LED urile indicatoare, de mică putere, la acest curent, este dată de culoarea LED-ului, puterea acestuia și de temperatură. Ea poate varia de la 1.7V în cazul LED-urilor roșii, 2-2.3V pentru cele Orange, galbene și verzi și ajunge la 3.2-3.5V în cazul LED-urilor albastre și albe.

Schema utilizată este următoarea:  Schema de lucru și calculul rezistenței de limitare a curentului prin LED

Schema de lucru și calculul rezistenței de limitare a curentului prin LED

Întrucât microcontroller-ul are ieșirile comandate folosind stâlp Push-Pull CMOS, tensiunea Upin în starea de 1 logic va fi apropiată de tensiunea de alimentare a microcontroller-ului.

Exemplu:Dacă alimentarea microcontroller-ului este de 5V pentru un LED roșu ce dorim să îl folosim la 10mA, specificat de producător cu o cădere de tensiune de 1.7V, trebuie să folosim o rezistență de 330 de ohmi.

4.1.2. Butoanele

Cel mai simplu mod de interacțiune al utilizatorului cu un microcontroller îl constituie folosirea butoanelor. Modul de conectare al unui push-button este dat în figura de mai jos:

 Conectarea unui push-button: a) incorect, cu intrare flotantă, b) corect, cu rezistență de pull-up

Conectarea unui push-button: a) incorect, cu intrare flotantă, b) corect, cu rezistență de pull-up

a) arată un buton conectat la pinul PD0 al µC. La apăsarea butonului, intrarea PD0 va fi legată la GND, deci va fi în starea logică “0”. Acest mod de legare este incorect deoarece atunci când butonul nu este apăsat intrarea se află într-o stare nedefinită (ca și cum ar fi lăsată în aer), ea nefiind conectată nici la GND, nici la Vcc. Această stare se numește stare de impedanță mărită și nu poate fi citită de către circuitele interne ale µC deoarece un bit dintr-un registru poate să ia doar valorile 0 sau 1. În practică, citirea unei intrări în stare de impedanță mărită va produce un rezultat de 1 sau 0 în funcție de condițiile de mediu. Spre exemplu, dacă apropiem degetul de acea intrare, citirea va fi 1, iar, daca îndepărtăm degetul, citirea va fi 0.

b) arată modul corect de conectare al butonului, folosind o rezistență de pull-up între pinul de intrare și Vcc. Această rezistență are rolul de a aduce intrarea în starea “1” logic atunci când butonul este liber prin “ridicarea” potențialului liniei la Vcc. Alternativ, se poate folosi o rezistență de pull-down (conectată la GND), caz în care intrarea este ținută in starea logică “0” cât timpul butonul nu este apăsat.

Pentru a economisi spațiu exterior, în µC ATmega324, aceste rezistențe au fost incluse în interiorul circuitului integrat. Inițial ele sunt dezactivate iar activarea acestora se poate face prin software scriind o valoare în registrul de ieșire (PORTn) al unui port care a fost configurat drept intrare. Bitul PUD din registrul SFIOR este setat inițial pe 0, adică atunci când se scrie în PORTn se activează rezistențele de pull-up.

4.2. Lucrul cu registrele I/O

Microntroller-ul ATmega324 oferă 4 porturi I/O a câte 8 pini, iar intern, fiecare port are asociat trei registre a câte 8 biți prin care utilizatorul poate controla la nivel de pin fluxul datelor: poate scrie/citi date în/din portul respectiv. Aceste trei registre sunt:

  • DDRn - Data Direction Register
    • stabilește direcţia pinilor portului
    • dacă bitul x are valoarea 0 atunci pinul x este de intrare
    • dacă bitul x are valoarea 1 atunci pinul x este de ieșire
  • PORTn - Data Register
    • stabilește valorile de ieşire ale pinilor sau activează/dezactivează rezistenţele de pull-up
    • dacă bitul x are valoarea 0 atunci
      • dacă pinul x este de ieșire el va avea valoarea LOW
      • daca pinul x este de intrare rezistența de pull-up va fi dezactivată
    • data bitul x are valoarea 1 atunci
      • daca pinul x este de ieșire el va avea valoarea HIGH
      • dacă pinul x este de intrare rezistența de pull-up va fi activată
  • PINn - Input Pins Address
    • putem citi date de pe portul respectiv
    • dacă pinul x are valoarea LOW atunci bitul x va avea valoarea 0
    • daca pinul x are valoarea HIGH atunci bitul x va avea valoarea 1

n poate să fie A, B, C sau D în funcţie de portul selectat. x poate să fie între 0 și 7.

Descrierea detaliată a porturilor şi registrelor corespunzătoare acestora se găseşte în datasheet-ul ATmega324, în capitolul I/O Ports.

Registrele DDRn, PORTn, PINn, precum şi registrele perifericelor nu fac parte din cele 32 de registre de uz general. Ele nu sunt folosite pentru stocarea datelor, ci au ca rol comunicarea cu perifericul corespunzător. Pentru a face accesul la acestea mai simplu, ele sunt mapate în memorie. Astfel, pentru a scrie o valoare într-un registru este necesar să se scrie valoarea la adresa de memorie corespunzătoare registrului. Adresele lor se pot vedea în datasheet, în capitolul Register Summary, iar în avr-libc sunt definite macro-uri pentru fiecare dintre aceste adrese.

Pentru a scrie o valoare într-un registru se poate face direct atribuirea unei valori, însă acest mod nu face codul foarte ușor de înteles. Recomandarea noastră este de a folosi măștile pe biți ((1 << x)) sau macro-ul _BV(x). De asemenea recomandăm folosirea numelui pinului în loc de indexul acestuia, pentru că numele acestora sunt sugestive pentru funcția pe care o îndeplinesc (spre exemplu, în registrul ADCSRA al convertorului analog-digital, bitul ADEN este bitul de enable). Numele pinilor, ca și în cazul registrelor, sunt deja definite în avr-libc.

Operație Formă
Scriere bit pe 1
 register |= (1 << bit_index) 
Scriere bit pe 0
 register &= ~(1 << bit_index) 
Toggle bit
 register ^= (1 << bit_index) 
Citire bit
 register & (1 << bit_index) 

Lucrul cu registre

DDRB = 8;               // AȘA NU.
DDRB = (1 << 3);        // Nici așa, este hardcodat indexul pinului.
DDRB |= (1 << PB3);     // AȘA DA.
DDRB |= _BV(PB3);       // AȘA DA.

Detalii despre lucru cu biții din registre puteți citi și la secțiunea tutoriale de pe wiki.

4.2.1. Exemplu de lucru cu ieșiri

Să presupunem că avem un LED legat la pinul 1 al portului B (numit PORTB1 sau PB1). Pentru a aprinde sau stinge LED-ul trebuie să urmăm următorii pași:

  • Pinul PB1 trebuie configurat ca ieșire
    • Bitul 1 (PB1) din registrul DDRB va fi 1
  • Pentru a aprinde LED-ul trebuie ca pinul PB1 sa ia valoarea HIGH
    • Bitul 1 (PB1) din registrul PORTB va fi 1
  • Pentru a stinge LED-ul trebuie ca pinul PB1 sa ia valoarea LOW
    • Bitul 1 (PB1) din registrul PORTB va fi 0

4.2.2. Exemplu de lucru cu intrări

Să presupunem ca avem un buton legat la pinul 4 al portului D (numit PORTD4 sau PD4), din cazul b) prezentat anterior. Pentru a determina starea butonului (apăsat sau liber) trebuie să urmăm următorii pași:

  • Pinul PD4 trebuie configurat ca intrare
    • Bitul 4 (PD4) din registrul DDRD va fi 0
  • Pentru a determina starea de apăsare a butonului trebuie să citim valoarea pinului la care este atașat. Acesta va fi 1 atunci când butonul este liber și 0 atunci când butonul este apăsat
    • Citim valoarea bitului 4 (PD4) din registrul PIND

4.3. Lucrul cu I/O folosind Arduino

4.4. Hello World

Vom scrie un program care stinge și aprinde un LED la intervale de 500 ms. Acest lucru se face modificând tensiunea unuia dintre pinii microcontroller-ului, în cazul nostru pinul 5 din portul B (PB5), pe placa Arduino UNO, pinul didital 13.

Exemplu folosind biblioteca Arduino.

#define LED 13
 
void setup() {
  pinMode(LED, OUTPUT);
}
 
void loop() {
  digitalWrite(LED, HIGH);
  delay(500);
  digitalWrite(LED, LOW);
  delay(500);
}

Exemplu folosind scrieri in registrii procesorului.

void setup() {
  DDRB |= (1 << PB5);
}
 
void loop() {
  PORTB |= (1 << PB5);	
  delay(500);
  PORTB &= ~(1 << PB5);	
  delay(500);
}

5. Tinkercad

Tinkercad este un program online, gratis de modelare 3D recunoscut pentru simplitatea in utilizare. Acesta ofera suport de simulare pentru placa Arduino UNO.

https://www.tinkercad.com

6. Exerciții

6.1. Exerciții Tinkercad

Task 0 Rulați exemplul Hello Word folosind simulatorul Tinkercad. LED-ul este marcat cu L pe placa Arduino si este conectat la pinul digital 13. Puteti adauga inca un LED ca in exemplul de montaj.

Task 1 Adaugati un buton la pinul digital 2 (PD2) si faceti LED-ul sa se aprind cand butonul este apasat.

Task 2 Adaugati inca un buton la pinul digital 3 (PD3). Folsoiti butoanele pentru a creste/micsora durata delay-ului folosit la exemplul Hello Word.

6.2. Exerciții Arduino, necesita componente hardware

Task 3 Incarcati programul Hello Word pe placa Arduino UNO folosind Arduino IDE.

Task 4 Realizati montajul de la Task 2 folosind un breadboard si rulati programul.

7. Resurse

pm/lab/lab0-2021.1646076733.txt.gz · Last modified: 2022/02/28 21:32 by robert_mihai.lica
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0