This shows you the differences between two versions of the page.
pm:lab:lab3-2021 [2021/03/28 21:52] alexandru.predescu [1. Întreruperi externe. INT vs. PCINT] |
pm:lab:lab3-2021 [2021/04/02 10:55] (current) alexandru.predescu [4. Exerciții] |
||
---|---|---|---|
Line 75: | Line 75: | ||
PWM (**P**ulse **W**idth **M**odulation) este o tehnică folosită pentru a varia în mod controlat tensiunea dată unui dispozitiv electronic. Această metodă schimbă foarte rapid tensiunea oferită dispozitivului respectiv din ON în OFF și invers (treceri rapide din HIGH în LOW, de exemplu 5V - 0V). Raportul dintre perioada de timp corespunzătoare valorii ON și perioada totală dintr-un ciclu ON-OFF se numește factor de umplere (//duty cycle//) și reprezintă, în medie, tensiunea pe care o va primi dispozitivul electronic. Astfel, se pot controla circuite analogice din domeniul digital. Practic, asta înseamnă că un LED acționat astfel se va putea aprinde / stinge gradual, iar în cazul unui motor acesta se va învârti mai repede sau mai încet. | PWM (**P**ulse **W**idth **M**odulation) este o tehnică folosită pentru a varia în mod controlat tensiunea dată unui dispozitiv electronic. Această metodă schimbă foarte rapid tensiunea oferită dispozitivului respectiv din ON în OFF și invers (treceri rapide din HIGH în LOW, de exemplu 5V - 0V). Raportul dintre perioada de timp corespunzătoare valorii ON și perioada totală dintr-un ciclu ON-OFF se numește factor de umplere (//duty cycle//) și reprezintă, în medie, tensiunea pe care o va primi dispozitivul electronic. Astfel, se pot controla circuite analogice din domeniul digital. Practic, asta înseamnă că un LED acționat astfel se va putea aprinde / stinge gradual, iar în cazul unui motor acesta se va învârti mai repede sau mai încet. | ||
- | |||
- | Pentru a controla un LED folosind un semnal PWM, se poate conecta la fel ca în cazul on/off, folosind o rezistență de limitare a curentului. Dacă avem un LED de putere (ex. LED-uri auto, LED-uri pentru iluminare) este necesar un driver specializat. | ||
- | |||
- | {{ :pm:lab:lab3:r_limit.png?300 |}} | ||
- | |||
- | În cazul unui motor, căruia i se aplică un semnal PWM cu factor de umplere de 0%, viteza de rotație a acestuia va fi egală cu 0 RPM. Un factor de umplere de 100% va duce la o turație maximă a acestuia. Pentru astfel de cazuri în care avem sarcină inductivă și curenți mari (releuri, motoare, inductoare, electrovalve, etc.) este necesară utilizarea unui driver (element de comutație/tranzistor, driver motor, etc.) și a unei diode flyback ([[https://en.wikipedia.org/wiki/Flyback_diode|Wikipedia Flyback diode]]). | ||
- | Semnalul PWM generat de microcontroller va comanda driver-ul (ex. baza tranzistorului printr-o rezistență). | ||
- | |||
- | {{ :pm:lab:lab3:flyback_diode_example.png?300 |}} | ||
- | |||
- | O altă utilizare a semnalelor PWM este de a genera semnal analogic cu aplicații în amplificare audio (de clasă D), încărcătoare de baterii, etc. Prin modificarea periodică a factorului de umplere, se pot obține semnale ce aproximează un semnal analogic (ex. o sinusoidă). | ||
- | |||
- | Generarea unui semnal sinusoidal folosind PWM: | ||
- | {{ :pm:lab:pwm_sin_simulation.png?300 |}} | ||
- | |||
- | Semnalele PWM pot avea și alte utilizări, precum trimiterea de comenzi către un dispozitiv de acționare. Un astfel de exemplu este servomotorul, care primește comenzi determinate de factorul de umplere al semnalului PWM pentru a controla poziția. [[https://en.wikipedia.org/wiki/Servo_control|Servo control]] | ||
===== Principiul de funcționare ===== | ===== Principiul de funcționare ===== | ||
Line 99: | Line 83: | ||
Astfel, tensiunea medie care ajunge la dispozitiv este dată de relația: D * Vcc. | Astfel, tensiunea medie care ajunge la dispozitiv este dată de relația: D * Vcc. | ||
- | {{.:lab3:avr_pwm_01.jpg?600|Figura 8. Semnal PWM cu diferiți factori de umplere}} | + | {{.:lab3:avr_pwm_01.jpg?700|Figura 8. Semnal PWM cu diferiți factori de umplere}} |
Modularea folosește variația factorului de umplere a unui semnal dreptunghiular pentru a genera la ieșire o tensiune analogică. Considerând o formă de undă dreptunghiulară //f(t)// cu o valoare minimă //ymin=0// și o valoare maximă //ymax// și factorul de umplere //D// (ca în figură) valoarea medie a formei de undă e dată de relația: | Modularea folosește variația factorului de umplere a unui semnal dreptunghiular pentru a genera la ieșire o tensiune analogică. Considerând o formă de undă dreptunghiulară //f(t)// cu o valoare minimă //ymin=0// și o valoare maximă //ymax// și factorul de umplere //D// (ca în figură) valoarea medie a formei de undă e dată de relația: | ||
Line 117: | Line 101: | ||
Totuși, în multe situații se dorește o frecvență de ordinul kHz sau zeci de kHz a semnalului PWM (ex. controlul motoarelor DC sau BLDC), iar o astfel de metodă nu este cea mai eficientă, fiind necesară intervenția procesorului pentru tratarea întreruperilor frecvente. | Totuși, în multe situații se dorește o frecvență de ordinul kHz sau zeci de kHz a semnalului PWM (ex. controlul motoarelor DC sau BLDC), iar o astfel de metodă nu este cea mai eficientă, fiind necesară intervenția procesorului pentru tratarea întreruperilor frecvente. | ||
</note> | </note> | ||
+ | |||
+ | ==== Aplicații ale PWM ==== | ||
+ | |||
+ | Pentru a controla un LED folosind un semnal PWM, se poate conecta la fel ca în cazul on/off, folosind o rezistență de limitare a curentului. Dacă avem un LED de putere (ex. LED-uri auto, LED-uri pentru iluminare) este necesar un driver specializat. | ||
+ | |||
+ | {{ :pm:lab:lab3:r_limit.png?300 |}} | ||
+ | |||
+ | În cazul unui motor, căruia i se aplică un semnal PWM cu factor de umplere de 0%, viteza de rotație a acestuia va fi egală cu 0 RPM. Un factor de umplere de 100% va duce la o turație maximă a acestuia. Pentru astfel de cazuri în care avem sarcină inductivă și curenți mari (releuri, motoare, inductoare, electrovalve, etc.) este necesară utilizarea unui driver (element de comutație/tranzistor, driver motor, etc.) și a unei diode flyback ([[https://en.wikipedia.org/wiki/Flyback_diode|Wikipedia Flyback diode]]). | ||
+ | Semnalul PWM generat de microcontroller va comanda driver-ul (ex. baza tranzistorului printr-o rezistență) iar dioda flyback va prelua spike-urile de tensiune generate de motor/sarcina inductivă la închiderea tranzistorului (care altfel pot duce la distrugerea tranzistorului). | ||
+ | |||
+ | {{ :pm:lab:lab3:flyback_diode_example.png?300 |}} | ||
+ | |||
+ | O altă utilizare a semnalelor PWM este de a genera semnal analogic cu aplicații în amplificare audio (de clasă D), încărcătoare de baterii, etc. Prin modificarea periodică a factorului de umplere, se pot obține semnale ce aproximează un semnal analogic (ex. o sinusoidă). | ||
+ | |||
+ | Generarea unui semnal sinusoidal folosind PWM: | ||
+ | {{ :pm:lab:pwm_sin_simulation.png?300 |}} | ||
+ | |||
+ | Semnalele PWM pot avea și alte utilizări, precum trimiterea de comenzi către un dispozitiv de acționare. Un astfel de exemplu este servomotorul, care primește comenzi determinate de factorul de umplere al semnalului PWM pentru a controla poziția. [[https://en.wikipedia.org/wiki/Servo_control|Servo control]] | ||
Line 158: | Line 160: | ||
<note important> | <note important> | ||
- | Frecvența semnalului PWM depinde de prescaler și de frecvența oscilatorului. Din secțiunea 15.9.3 (pag 102), formula de calcul a frecvenței în modul Fast PWM este: | + | Frecvența semnalului PWM depinde de prescaler și de frecvența oscilatorului. Din secțiunea 15.9.3 (pag 102), formula de calcul a frecvenței în modul Fast PWM 8-bit este: |
\begin{equation} | \begin{equation} | ||
- | f_{OCnX}=\frac{f_{clk}}{N \cdot 256} | + | f_{OCnX}=\frac{f_{clk}}{N \cdot (TOP + 1)}=\frac{f_{clk}}{N \cdot 256} |
\end{equation} </note> | \end{equation} </note> | ||
Line 204: | Line 206: | ||
===== 3. Aplicații cu PWM în Arduino ===== | ===== 3. Aplicații cu PWM în Arduino ===== | ||
- | În continuare, ne vom folosi de biblioteca Arduino pentru a testa rapid niște aplicații ale semnalelor PWM: controlul unui LED RGB și controlul poziției unui servomotor hobby. Alternativ, pentru cei care doresc să aprofundeze modul de programare la nivel de registre, se pot realiza aplicațiile folosind timer-e în modul Fast PWM și/sau CTC în loc de bibliotecile din Arduino (//analogWrite//, //Servo//). | + | În continuare, ne vom folosi de biblioteca Arduino pentru a realiza niște aplicații ale semnalelor PWM: controlul unui LED RGB și controlul poziției unui servomotor hobby. Alternativ, pentru cei care doresc să aprofundeze modul de programare la nivel de registre, se pot realiza aplicațiile folosind timer-e în modul Fast PWM și/sau CTC în loc de bibliotecile din Arduino (//analogWrite//, //Servo//). |
==== AnalogWrite ==== | ==== AnalogWrite ==== | ||
- | Funcția //analogWrite// din Arduino, configurează de fapt un timer în modul Fast PWM pe 8 biți și poate genera semnal PWM (doar) pe pinii asociați unuia dintre timer-e. ''analogWrite(pin_arduino, value_0_255)'' De exemplu, pe Atmega328p avem următorii pini care pot genera semnal PWM folosind funcția //analogWrite//: | + | Funcția //analogWrite// din Arduino, configurează de fapt un timer în modul Fast PWM pe 8 biți și poate genera semnal PWM (doar) pe pinii asociați unuia dintre timer-e. ''analogWrite(pin_arduino, value_0_255)'' De exemplu, pe Arduino/Atmega328p avem următorii pini care pot genera semnal PWM folosind funcția //analogWrite//: |
^ Pin Arduino ^ Pin Atmega328p ^ Timer output ^ Frecvența PWM (default) ^ | ^ Pin Arduino ^ Pin Atmega328p ^ Timer output ^ Frecvența PWM (default) ^ | ||
Line 217: | Line 219: | ||
| 3 | PD3 | OC2B (Timer2) | 490 Hz | | | 3 | PD3 | OC2B (Timer2) | 490 Hz | | ||
- | Este posibil să avem nevoie să modificăm frecvența semnalului PWM, caz în care trebuie să configurăm explicit Timer-ul (prescaler, TOP) folosind registre. [[https://www.arduino.cc/en/pmwiki.php?n=Tutorial/SecretsOfArduinoPWM|SecretsOfArduinoPWM]] | + | Este posibil să avem nevoie să modificăm frecvența semnalului PWM, caz în care trebuie să configurăm explicit Timer-ul (ex. prescaler, TOP) folosind registre. [[https://www.arduino.cc/en/pmwiki.php?n=Tutorial/SecretsOfArduinoPWM|SecretsOfArduinoPWM]] |
==== LED RGB ==== | ==== LED RGB ==== | ||
Line 223: | Line 225: | ||
Un LED RGB este compus din 3 diode care emit culori diferite: una roșie, una verde și una culoare albastră. Cu acest LED se poate obține orice culoare printr-o combinație de intensități pe fiecare diodă în parte. | Un LED RGB este compus din 3 diode care emit culori diferite: una roșie, una verde și una culoare albastră. Cu acest LED se poate obține orice culoare printr-o combinație de intensități pe fiecare diodă în parte. | ||
Cele trei LED-uri sunt conectate astfel: | Cele trei LED-uri sunt conectate astfel: | ||
- | * ''OC1A'' este asociat timer-ului 1 (pinul ''PB1'' sau pinul 9 de pe Arduino) și controlează LED-ul ''roșu''. | + | * ''OC1A'' este asociat timer-ului 1 (''PB1'' sau pinul 9 de pe Arduino) și controlează LED-ul ''roșu''. |
- | * ''OC1B'' este asociat timer-ului 1 (pinul ''PB2'' sau pinul 10 de pe Arduino) și controlează LED-ul ''verde''. | + | * ''OC1B'' este asociat timer-ului 1 (''PB2'' sau pinul 10 de pe Arduino) și controlează LED-ul ''verde''. |
- | * ''OC2A'' este asociat timer-ului 2 (pinul ''PB3'' sau pinul 11 de pe Arduino) și controlează LED-ul ''albastru''. | + | * ''OC2A'' este asociat timer-ului 2 (''PB3'' sau pinul 11 de pe Arduino) și controlează LED-ul ''albastru''. |
În funcție de LED-ul RGB folosit, LED-urile individuale se pot conecta în modul catod comun/"active-high" (LED-ul este aprins atunci cand pinul aferent este HIGH, si stins atunci cand pinul este LOW) sau anod comun/"active-low" (LED-ul este aprins atunci cand pinul aferent este LOW, si stins atunci cand pinul este HIGH). În ambele cazuri, se folosește câte o rezistență de limitare a curentului pentru fiecare culoare. | În funcție de LED-ul RGB folosit, LED-urile individuale se pot conecta în modul catod comun/"active-high" (LED-ul este aprins atunci cand pinul aferent este HIGH, si stins atunci cand pinul este LOW) sau anod comun/"active-low" (LED-ul este aprins atunci cand pinul aferent este LOW, si stins atunci cand pinul este HIGH). În ambele cazuri, se folosește câte o rezistență de limitare a curentului pentru fiecare culoare. | ||
Line 269: | Line 271: | ||
===== 4. Exerciții ===== | ===== 4. Exerciții ===== | ||
- | === Task 0 (Întreruperi și butoane) === | + | === Task 0 (întreruperi / butoane) === |
Folosiți întreruperi externe (INT și/sau PCINT) pentru a detecta apăsarea unui buton conectat la ''PD2'' (pin 2) și a unuia conectat la ''PD4'' (pin 4). Modificați starea unui LED conectat la ''PD7'' (pin 7) în ISR. | Folosiți întreruperi externe (INT și/sau PCINT) pentru a detecta apăsarea unui buton conectat la ''PD2'' (pin 2) și a unuia conectat la ''PD4'' (pin 4). Modificați starea unui LED conectat la ''PD7'' (pin 7) în ISR. | ||
Line 298: | Line 300: | ||
=== Task 1a (LED RGB) === | === Task 1a (LED RGB) === | ||
- | Conectați un LED RGB la pinii 9, 10, 11 de pe Arduino folosind câte o rezistență de 330ohm și rulați programul de mai jos: | + | Conectați un LED RGB catod comun la pinii 9, 10, 11 de pe Arduino folosind câte o rezistență de 330ohm și rulați programul de mai jos: |
* Observați modificarea culorii LED-ului | * Observați modificarea culorii LED-ului | ||
Line 343: | Line 345: | ||
</file> | </file> | ||
- | === Task 1b (LED RGB/extra) === | + | === Task 1b (LED RGB / HSV) === |
Modificați programul folosind functia //setLedColorHSV//: | Modificați programul folosind functia //setLedColorHSV//: | ||
* Funcția //setLedColorHSV// permite modificarea culorii folosind reprezentarea alternativă HSV (Hue Saturation Value), fiind mai ușor apoi de modificat culoarea, saturația și intensitatea luminoasă. {{:pm:lab:lab3_2021:hsv.txt|setLedColorHSV}} | * Funcția //setLedColorHSV// permite modificarea culorii folosind reprezentarea alternativă HSV (Hue Saturation Value), fiind mai ușor apoi de modificat culoarea, saturația și intensitatea luminoasă. {{:pm:lab:lab3_2021:hsv.txt|setLedColorHSV}} | ||
+ | * Setați valorile pentru saturație (s) și intensitate (v) pe 1 și modificați culoarea (h) în intervalul 0-360 | ||
Pentru a urmări corespondența dintre cele 2 reprezentări (RGB și HSV) există selectoare de culori precum: | Pentru a urmări corespondența dintre cele 2 reprezentări (RGB și HSV) există selectoare de culori precum: | ||
Line 357: | Line 360: | ||
- | === Task 2 (LED RGB/Serial) === | + | === Task 2 (LED RGB / Serial) === |
Scrieți un program care primește comenzi pe serială (USART) și setează o anumită culoare a LED-ului RGB, în funcție de valorile primite pentru fiecare canal, separate prin virgulă (R,G,B). Formatul de tip [[https://en.wikipedia.org/wiki/Comma-separated_values|CSV]] reprezintă o variantă simplă și flexibilă (deși mai puțin eficientă decât transmiterea în format binar, sub formă de octeți) de codificare a datelor trimise pe serială. | Scrieți un program care primește comenzi pe serială (USART) și setează o anumită culoare a LED-ului RGB, în funcție de valorile primite pentru fiecare canal, separate prin virgulă (R,G,B). Formatul de tip [[https://en.wikipedia.org/wiki/Comma-separated_values|CSV]] reprezintă o variantă simplă și flexibilă (deși mai puțin eficientă decât transmiterea în format binar, sub formă de octeți) de codificare a datelor trimise pe serială. | ||
Line 391: | Line 394: | ||
- | === Task 3 (Servo/sweep) === | + | === Task 3 (Servo / sweep) === |
Conectați un servo la pinul 9 și rulați exemplul standard din Arduino, prin care se modifică în mod "continuu" poziția (0-180) | Conectați un servo la pinul 9 și rulați exemplul standard din Arduino, prin care se modifică în mod "continuu" poziția (0-180) | ||
Line 411: | Line 414: | ||
void setup() { | void setup() { | ||
myservo.attach(9); // attaches the servo on pin 9 to the servo object | myservo.attach(9); // attaches the servo on pin 9 to the servo object | ||
- | setup_interrupts(); | ||
// test led | // test led | ||
DDRD |= (1 << PD7); | DDRD |= (1 << PD7); | ||
Line 434: | Line 436: | ||
</hidden> | </hidden> | ||
- | === Task 4 (Servo/buton) === | + | === Task 4 (Servo / buton) === |
- | Folosind întreruperile de la **Task 0**, modificați incremental poziția servomotorului (0-180): | + | Folosind întreruperile de la **Task 0**, modificați incremental poziția servomotorului (0-180) |
| | ||
{{:pm:lab:lab3_2021:button_servo.png?600|}} | {{:pm:lab:lab3_2021:button_servo.png?600|}} | ||
Line 442: | Line 444: | ||
* Atenție la limite (min, max). Depășirea acestora poate avaria servomotorul. | * Atenție la limite (min, max). Depășirea acestora poate avaria servomotorul. | ||
* Dacă lucrați pe placă, folosiți debouncing pentru a obține o funcționare corectă (o apăsare va incrementa o singură dată poziția) | * Dacă lucrați pe placă, folosiți debouncing pentru a obține o funcționare corectă (o apăsare va incrementa o singură dată poziția) | ||
- | * Există și servomotoare care folosesc un alt interval de comenzi (ex. 700-2300), se poate folosi funcția //writeMicroseconds// pentru a controla direct durata pulsului. [[https://www.arduino.cc/en/Reference/ServoWriteMicroseconds|Servo.writeMicroseconds]] | + | * Există și servomotoare care folosesc un alt interval de comenzi (ex. 0.7ms-2.3ms), se poate folosi funcția //writeMicroseconds// pentru a controla direct durata pulsului. [[https://www.arduino.cc/en/Reference/ServoWriteMicroseconds|Servo.writeMicroseconds]] |
<hidden> | <hidden> |