Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:lab:lab3-2023-2024 [2024/03/24 15:05]
florin.stancu created
pm:lab:lab3-2023-2024 [2025/03/23 22:35] (current)
dan.tudose [3. Exerciții]
Line 1: Line 1:
 +~~SHOWSOLUTION~~
 +
 ====== Laboratorul 3: Timere, Pulse Width Modulation (PWM) ====== ====== Laboratorul 3: Timere, Pulse Width Modulation (PWM) ======
  
Line 4: Line 6:
  
   * 1. Pin Configurations   * 1. Pin Configurations
-    * secțiunea 1.1 - pag. 11 +    * secțiunea 1.1 - pag. 15 
-  * 12. 8-bit Timer/​Counter0 with PWM +  * 16. 8-bit Timer/​Counter0 with PWM 
-    * secțiunea ​12.9 - Register Description - pag. 110 +    * secțiunea ​16.9 - Register Description - pag. 140 
-  * 13. 16-bit Timer/​Counter1 with PWM +  * 17. 16-bit Timer/​Counter1 with PWM 
-    * secțiunea ​13.11 - Register Description - pag. 137 +    * secțiunea ​17.14 - Register Description - pag. 173 
-  * 14. 8-bit Timer/​Counter2 with PWM and asynchronous operation +  * 19. 8-bit Timer/​Counter2 with PWM and asynchronous operation 
-    * secțiunea ​14.11 - Register Description - pag. 157+    * secțiunea ​19.11 - Register Description - pag. 202
  
 ===== 1. Pulse Width Modulation ===== ===== 1. Pulse Width Modulation =====
Line 27: Line 29:
  
 Factorul de umplere se exprimă în procente și reprezintă cât la sută din perioada unui semnal acesta va fi pe nivelul ON. În figura de mai jos, se pot observa semnale PWM cu factori de umplere diferiți. Astfel, se poate deduce foarte ușor formula pentru a obține valoarea factorului de umplere (D): Factorul de umplere se exprimă în procente și reprezintă cât la sută din perioada unui semnal acesta va fi pe nivelul ON. În figura de mai jos, se pot observa semnale PWM cu factori de umplere diferiți. Astfel, se poate deduce foarte ușor formula pentru a obține valoarea factorului de umplere (D):
-  ​+
 $D[\%] = \frac{t\_on}{t\_on + t\_off} \cdot 100 = \frac{pulse\_width}{period} \cdot 100$ $D[\%] = \frac{t\_on}{t\_on + t\_off} \cdot 100 = \frac{pulse\_width}{period} \cdot 100$
  
Line 83: Line 85:
  
 <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 8-bit este:  +În acest laborator vom folosi doar modul Fast PWM pe 8 biți. Pentru variantele de Fast PWM oferite de către celelalte timere (0 și 2) și pentru celelalte moduri PWM, consultați datasheet-ul.
- +
-\begin{equation} +
-f_{OCnX}=\frac{f_{clk}}{N \cdot (TOP + 1)}=\frac{f_{clk}}{N \cdot 256} +
-\end{equation} </​note>​ +
- +
-<note important>​ +
-În acest laborator vom folosi doar modul Fast PWM. Pentru variantele de Fast PWM oferite de către celelalte timere (0 și 2) și pentru celelalte moduri PWM, consultați datasheet-ul.+
 </​note>​ </​note>​
  
Line 101: Line 96:
  
 <file c> <file c>
-/* OC1A is PB1, must be set to OUTPUT */ +/* OC1A is PD5, must be set to OUTPUT */ 
-DDRB |= (1 << ​PB1);+DDRB |= (1 << ​PD5);
 /* We must choose Fast PWM 8-bit, WGMn[3:0] = 0b0101 */ /* We must choose Fast PWM 8-bit, WGMn[3:0] = 0b0101 */
 /* Note: WGM11 and WGM10 are on TCCR1A, while WGM12 and WGM13 are on TCCR1B! */ /* Note: WGM11 and WGM10 are on TCCR1A, while WGM12 and WGM13 are on TCCR1B! */
Line 119: Line 114:
 Deși nu îl vom folosi la laborator, este util de știut diferențele între modul de PWM rapid și acesta care poate fi mai precis (necesar în unele aplicații, precum controlarea motoarelor). Deși nu îl vom folosi la laborator, este util de știut diferențele între modul de PWM rapid și acesta care poate fi mai precis (necesar în unele aplicații, precum controlarea motoarelor).
  
-Principala diferență între acest mod și cel de Phase Correct ​este faptul că timer-ul va porni de la BOTTOM (i.e., poziția zero), va urca până la TOP (valoarea maximă) apoi va număra, descrescător,​ înapoi la BOTTOM. Comparatorul va da semnalul de output după aceiași regulă ca la Fast PWM, în funcție de rezultatul comparării cu registrul ''​OCRnx''​. Însă cea mai importantă diferență este faptul că valoarea lui ''​OCRnx''​ rămâne salvată pe toată durata unui ciclu complet, astfel se păstrează durata semnalului ON pe toată perioada //T_on + T_off// și rezultă un semnal "​curat",​ fără decalaje ale frecvenței de PWM (de exemplu, unele frecvențe nedorite ar putea avea pierderi de energie în motoare DC).+Principala diferență între acest mod și cel de Fast PWM este faptul că timer-ul va porni de la BOTTOM (i.e., poziția zero), va urca până la TOP (valoarea maximă) apoi va număra, descrescător,​ înapoi la BOTTOM. Comparatorul va da semnalul de output după aceiași regulă ca la Fast PWM, în funcție de rezultatul comparării cu registrul ''​OCRnx''​. Însă cea mai importantă diferență este faptul că valoarea lui ''​OCRnx''​ rămâne salvată pe toată durata unui ciclu complet, astfel se păstrează durata semnalului ON pe toată perioada //T_on + T_off// și rezultă un semnal "​curat",​ fără decalaje ale frecvenței de PWM (de exemplu, unele frecvențe nedorite ar putea avea pierderi de energie în motoare DC).
  
 {{.:​lab3:​phase_correct_pwm.png?​500| Phase Correct PWM Timing}} {{.:​lab3:​phase_correct_pwm.png?​500| Phase Correct PWM Timing}}
Line 129: Line 124:
 ===== 3. Exerciții ===== ===== 3. Exerciții =====
  
-Obiectivul exercițiilor este să controlăm culoarea unui LED RGB cu ajutorul PWM. Cu acest LED se poate obține orice culoare printr-o combinație de intensități pe fiecare diodă în parte!+Descărcați schelet codului și analizați-l: {{:​pm:​lab:​lab3-skel.zip|schelet}}
  
-Cele trei LED-uri sunt conectate la: +Ce timer calculează numărul de systick-uri?
-  * ''​OC1A''​ este asociat ​timer-ului 1 (pinul ''​PD5''​). Acest timer controlează LED-ul ''​roșu''​. +
-  * ''​OC2A''​ este asociat timer-ului 2 (pinul ''​PD7''​). Acest timer controlează LED-ul ''​verde''​. +
-  * ''​OC0A''​ este asociat timer-ului 0 (pinul ''​PB3''​). Acest timer controlează LED-ul ''​albastru''​.+
  
-**Reminder**: LED-urile ​sunt conectate in modul anod comun / "​active-low" ​(LED-ul ​este aprins atunci cand pinul aferent este LOWsi stins atunci cand pinul este HIGH).+**Task 1 (3 puncte):** 
 +  * Identificați timerul care numără systick-urile
 +  * Configurați un timer (conform descrierii pinilor) în modul Fast PWM cu ieșire inversată și prescaler 64, astfel încât ​LED-ul ​verde să pulseze ciclic de la intensitate 0 la 255. 
 +  * Un puls complet (de la minim la maxim sau invers) trebuie să dureze 3 secunde.  
 +  * La apăsarea butonului PB2direcția de pulsare se va inversa (de la creștere la descreștere sau invers).
  
-**Task ​0**:+**Task ​2 (5 puncte):**
  
-   - Descărcați [[arhiva cu scheletul de cod]] și rulațexemplulCe observați că se întamplă pe plăcuță? +  * Folosind întreruperi (cu debouncing),​ configurați butoanele PB2 și PD6 pentru a regla intensitatea LED-urilor roșu șalbastru
-      Conectați-vă și verificați consola ​de monitorizare a serialei; vă mai amintiți de la laboratorul trecut cum se făcea temporizarea?​ +    Inițial, ambele LED-uri pornesc cu un factor de umplere de 0%. 
-      Ce puteți spune despre comportamentul LED-ului? Ce timer este folosit ​și în ce mod este el configurat? +    * La fiecare apăsare a butonului PB2, LED-ul roșu își crește factorul ​de umplere cu 25%. 
-      Unde se modifică intensitatea?​ Ce input primește acea formulă ​și unde se folosește output-ul?+    * La fiecare apăsare a butonului PD6, LED-ul albastru îșcrește factorul ​de umplere cu 25%. 
 +    * Factorul de umplere va evolua astfel: 0% → 25% → 50% → 75% → 100% → revenire ​la 0%. 
 +  * Deoarece timerul 1 este folosit pentru numărarea milisecundelor (systicks), acesta nu poate fi configurat în Fast PWM. Vom învăța să implementăm PWM manual folosind întreruperi:​ 
 +    Timerul 1 are două comparatoare;​ folosiți comparatorul B (COMPB) pentru a genera o întrerupere (TIMER1_COMPB) la o valoare între 0 și 1500 (valoarea medie pentru 50% fiind 750). 
 +    LED-ul roșu se va aprinde la întreruperea comparatorului A (la resetarea timerului) ​și se va stinge la întreruperea comparatorului B, astfel încât valoarea din OCR2B să stabilească factorul de umplere.
  
-**Task ​1**:+**Task ​3 (2 puncte):**
  
-   - Dorim să facem și culoarea ​**blue** să facă similar. +  ​Redați melodia ​din scheletul ​de laborator folosind speaker-ul conectat ​la PD4
-      * Vedeți mai sus ce timer va trebui să configurați! Folosiți tot modul Fast PWM (însă, **obligatoriu**:​ **citiți** și folosiți descrierea registrelor de la **Secțiunea 12.9** ​din [[|https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-42743-ATmega324P_Datasheet.pdf|Datasheet-ul lui ATmega324P]],​ acestea diferă față ​de cele de la Timer 1!); +  Nu se poate folosi timerul pentru ​că acesta ​folosit ​la număratul systick-urilor
-      * Faceți ca această nouă culoare să pulseze mai rapid decât cea roșie! Ce observați?​ +  Reconfigurați timerul 0 pentru ​a fi folosit în modul CTC și schimbați valoarea pinului PD4 în cadrul întreruperii COMPA 
- +  * Folosiți vectorii predefiniți:​ 
-**Task 2**: +    * surprise_notesnote cu frecvențele (în Hertz) corespunzătoare. 
- +    * durationsduratele fiecărei note. 
-   - Pentru a nu o supăra pe Greta Thunberg, ne trebuie și culoarea <color green>​**green**</​color>​! Însă, cum vă imaginați, este mai complicat: deoarece GPIO-ul ''​PD7''​ are outputul asociat Timerului 2, însă acest Timer este deja folosit pentru a număra milisecundele de la momentul pornirii MCU-ului (**system ticks**)..+  La fiecare notă, frecvențva fi setată folosind registrul OCR0A
-       ​No worries! Vom învăța să facem PWM manual, prin întreruperi,​ pe ideea: timer-ul nostru numără de la ''​0''​ la valoarea ''​188''​ apoi face Clear (executând întreruperea ''​COMPA''​ -- care ne incrementează ''​systicks'''​);​ +
-       * Ne amintim ​că fiecare timer are 2 comparatoare,​ deci îl vom folosi pe al doilea (''​COMPB''​) pentru a genera o întrerupere (''​TIMER2_COMPB''​) la o valoare prag între ''​0 -- 188''​ (deci valoarea medie pentru 50% va fi ''​94''​);​ +
-       * LED-ul verde va trebui aprins (deci GPIO-ul pus pe 0) din întreruperea comparatorului ''​A''​ (i.e., atunci când se resetează timerul) iar, la întreruperea comparatorului ''​B'',​ va trebui oprit (i.e., GPIO setat pe 1), astfel factorul de umplere fiind dat de valoarea registrului ''​OCR2B''​ ;)  +
-       * **Atenție**:​ Valoarea comparatorului ''​A''​ va trebui să rămână tot ''​OCR2A = 188''​ (dorim, în continuare, să avem numărătoarea de milisecunde)! +
- +
-**Task 3**: +
-   Dorim să ciclăm prin toate culorile reprezentabile folosind cele 3 LED-uri RGBPentru a facilita acest lucru, le vom calcula în domeniul alternativ de reprezentare **HSV** (Hue, Saturation, Value), apoi le vom converti în **RGB** pentru a le putea outputa: +
-       ​aveți formula implementată în funcția ''​convert_HSV_to_RGB()''​! +
-       * parametrul Hue va da nuanțculorii, Saturation și Value pot fi hardcodate la 255 pentru intensitate maximă; +
-       * folosiți contorul de system ticks pentru a anima schimbarea culorii, similar cum era acesta ​folosit ​pentru a pulsa intensitatea la primele exerciții (desigur, dezactivați codul ce face acest lucru). +
- +
-**Task 4 (bonus)**:​ +
- +
-  - Speaker-ul de pe placă este conectat pe pinul ''​PD4'',​ așa cum am văzut ​în primul laborator. ''​PD4''​ este și ieșirea B a timer-ului 1, deci am putea folosi un factor de umplere de 50% pentru a produce sunet pe speaker. Scopul acestui exercițiu este să redați melodia pusă în scheletul de laborator (vedeți modulul ''​sound.c''​). +
-      ''​surprise_notes''​ sunt diferitele ​note folosite, ​cu valorile ​frecvențelor în Hertzi; +
-      ''​durations''​ este un vector cu duratele ​asociate ​fiecărei note din ''​surprise_notes'';​ +
-      ''​update_notes''​ va trebui să redea notele muzicale în ordinea dorită, reconfigurând timer-ul mereu  +
-      * Cel mai simplu va fi să reconfigurați Timer-ul 1 să fie în mod CTC, deci TOP va fi ''​OCR1A''​ ce va da frecveța semnalului; pentru a obține un semnal de 50%, ''​OCR1B''​ va trebui să fie la jumătate din valoarea primului registru; +
-      * Funcția ''​update_notes''​ va trebui apelată în bucla principală la fiecare 25ms (folosiți ''​systicks''​ pentru a știi când a trecut acest interval de timp de la ultimul update). +
-      * **Atenție**:​ resetați ''​TCNT''​ la fiecare update al ''​TOP''​-ului! Altfel, în unele situații, va trebui să așteptați un overflow pentru ca ''​TCNT''​ să se reseteze. +
-  - **Bonus 2**: animarea culorilor RGB de la exercițiul anterior și redarea sunetelor trebuie să funcționeze în același timp!+
  
 +**Bonus (1 punct):**
 +  * Redați melodia cu o viteză cu 25% mai mare decât cea inițială.
  
 ===== 4. Linkuri utile  ===== ===== 4. Linkuri utile  =====
Line 182: Line 163:
   * [2] [[http://​www.avrfreaks.net/​index.php?​name=PNphpBB2&​file=printview&​t=68302 |Newbie'​s Guide to AVR PWM]]   * [2] [[http://​www.avrfreaks.net/​index.php?​name=PNphpBB2&​file=printview&​t=68302 |Newbie'​s Guide to AVR PWM]]
   * [3] [[https://​docs.arduino.cc/​tutorials/​generic/​secrets-of-arduino-pwm|Secrets of Arduino PWM]]   * [3] [[https://​docs.arduino.cc/​tutorials/​generic/​secrets-of-arduino-pwm|Secrets of Arduino PWM]]
 +  * [4] [[https://​ww1.microchip.com/​downloads/​en/​DeviceDoc/​Atmel-42743-ATmega324P_Datasheet.pdf|Datasheet ATmega324P]]
  
 ===== 5. Responsabili laborator ===== ===== 5. Responsabili laborator =====
  
-  * [[florin.stancu@upb.ro|Stancu Florin]] +  * Iancu Ivasciuc 
-  * [[dicu.teodor@gmail.com|Teodor Dicu]] +  * Andrei Zamfir
  
pm/lab/lab3-2023-2024.1711285553.txt.gz · Last modified: 2024/03/24 15:05 by florin.stancu
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