Differences

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

Link to this comparison view

pm:lab:lab3-2022 [2022/03/27 15:40]
sebastian.gherman99
pm:lab:lab3-2022 [2023/03/19 14:41] (current)
alexandru.predescu
Line 1: Line 1:
-====== Laboratorul 3: Întreruperi externe. PWM ======+/** 
 + * uncomment this to publish the solution: 
 + * ~~SHOWSOLUTION~~ 
 + */ 
 +~~SHOWSOLUTION~~ 
 + 
 +====== Laboratorul 3: Întreruperi externe. PWM (old) ======
  
 Acest laborator are ca scop familiarizarea voastră cu lucrul cu întreruperile externe și cu modul de generare a semnalelor PWM folosind timer-ele prezente în microcontroller-ul Atmega328p. Vom folosi întreruperi externe pentru a detecta apăsarea unui buton, independent de programul principal. Folosind semnale PWM vom controla un LED RGB și poziția unui servomotor. Acest laborator are ca scop familiarizarea voastră cu lucrul cu întreruperile externe și cu modul de generare a semnalelor PWM folosind timer-ele prezente în microcontroller-ul Atmega328p. Vom folosi întreruperi externe pentru a detecta apăsarea unui buton, independent de programul principal. Folosind semnale PWM vom controla un LED RGB și poziția unui servomotor.
Line 271: Line 277:
 } }
 </​file>​ </​file>​
- 
  
  
Line 277: Line 282:
  
 === Task 0 (întreruperi / 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 ​întreruperea externă INT0 (consultațschema PINOUT) pentru a detecta apăsarea unui buton. Modificați starea LED-urilor RGB (ON / OFF )la fiecare apăsare de buton.
  
-**Tinkercad** - Testați programul folosind următorul montaj: +  ​* Configurați întreruperea externă (INT) pe front descrescător (falling edge) 
- +  * La apăsarea butonului, LED-ul își schimbă starea o singură dată? Adăugați o metodă de [[https://​www.arduino.cc/​en/​Tutorial/​BuiltInExamples/​Debounce|debouncing]] pentru a detecta o singură apăsare pe buton 
-{{:​pm:​lab:​lab3_2021:​button_led_interrupts.png?​600|}} +  * NU este recomandat să folosiți delay în ISR
- +
-<​file>​ +
-ISR(INT0_vect) +
-+
-  // cod întrerupere externă +
-  PORTD ^= (1 << PD7);   +
-+
-</​file>​ +
- +
-  ​* Configurați întreruperea externă (INT) pe front descrescător (falling edge) sau PCINT-ul corespunzător pinului folosit +
-  * Modificați starea LED-ului la apăsarea oricărui buton (PD2, PD4) +
- +
-**Arduino** - Încărcați codul pe placă și observați comportamentul. ​La apăsarea butonului, LED-ul își schimbă starea o singură dată? Adăugați o metodă de [[https://​www.arduino.cc/​en/​Tutorial/​BuiltInExamples/​Debounce|debouncing]] pentru a detecta o singură apăsare pe buton: +
-  * NU este recomandat să folosiți delay în ISR+
   * Se poate folosi funcția //​millis()//​ pentru a verifica intervalul de timp de la ultima apăsare (100 ms ar trebui să fie suficient pentru un pushbutton/​microswitch,​ dar ajustați după caz)   * Se poate folosi funcția //​millis()//​ pentru a verifica intervalul de timp de la ultima apăsare (100 ms ar trebui să fie suficient pentru un pushbutton/​microswitch,​ dar ajustați după caz)
-  * [expert] Se poate folosi un timer pentru a înlocui apelul funcției //​millis()//​ 
  
-<​hidden>​ +{{:pm:​lab:​lab3_task0.png?​direct&​600|}}
-**Soluția** se găsește pe [[https://​www.tinkercad.com/​things/​cVPb9x8NUbX|Tinkercad Button Led Interrupts]] +
-</​hidden>​+
  
-=== Task 1a (LED RGB) ===+=== Task (LED RGB) === 
 +{{:​pm:​lab:​lab3_task1.png?​direct&​600|}}
  
-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 ceva special în montajul ​de mai sus modul de conectare al led-ului RGB ? (Hintdiagrama PINOUT, PWM)
  
-  * Observați modificarea culorii LED-ului +La acest task veți cicla cu ajutorul PWM-ului prin toate culorile led-ului RGB.
-  * Funcția //​analogWrite//​ setează factorul de umplere PWM pentru fiecare culoare+
  
-**Tinkercad** ​Testați programul folosind următorul montaj:+  ​Cu funcția [[https://​www.arduino.cc/​reference/​en/​language/​functions/​analog-io/​analogwrite/​|analogWrite]] veți seta factorul de umplere PWM pentru fiecare culoare
  
-{{:pm:​lab:​lab3_2021:​auto_rgb.png?​600|}} +Bonus modificați programul folosind functia //​setLedColorHSV()//
- +
- +
-<​file>​ +
-void setup() { +
-  // Start off with the LED off. +
-  setColorRGB(0,​0,​0);​ +
-+
- +
-void loop() { +
-  unsigned int rgb[3]; +
- +
-  // Start off with red. +
-  rgb[0] = 255; +
-  rgb[1] = 0; +
-  rgb[2] = 0; +
- +
-  // Choose the colors to increment and decrement. +
-  for (int dec = 0; dec < 3; dec += 1) { +
-    int inc = dec == 2 ? 0 : dec + 1; +
- +
-    // cross-fade the two colors. +
-    for (int i = 0; i < 255; i += 1) { +
-      rgb[dec] -= 1; +
-      rgb[inc] += 1; +
-      setColorRGB(rgb[0],​ rgb[1], rgb[2]); +
-      delay(5); +
-    } +
-  } +
-+
- +
-void setColorRGB(unsigned int red, unsigned int green, unsigned int blue) { +
-  analogWrite(9,​ red); +
-  analogWrite(10,​ green); +
-  analogWrite(11,​ blue); +
-+
-</​file>​ +
- +
-=== Task 1b (LED RGB / HSV) === +
- +
-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   * 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 [[https://​colorpicker.me/#​3237b9|Online Color Picker]]
 +{{ :​pm:​lab:​hue-wheel.png?​direct&​400 |}}
  
-Pentru a urmări corespondența dintre cele 2 reprezentări (RGB și HSV) există selectoare de culori precum: +=== Task 2 (Servo sweep) === 
-[[https://​colorpicker.me/#​3237b9|Online Color Picker]] +{{:pm:lab:lab3_task2.png?direct&600|}}
- +
-<​hidden>​ +
-**Soluția** se găsește pe [[https://​www.tinkercad.com/​things/​2MYGBAcxapa|Tinkercad Auto RGB]] +
-</​hidden>​ +
- +
- +
-=== 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ă. +
- +
-  * Formatul comenzii este următorulR(0-255),​G(0-255),​B(0-255)ex. 0,0,255 va comanda o culoare albastră +
-  * Pentru a identifica sfârșitul comenzii se poate folosi //newline// (\n) (în Tinkercad nu avem această posibilitate,​ dar se poate folosi un alt caracter de control, de ex. o literă) +
-  * La primirea comenzii, se vor schimba valorile factorului de umplere pentru semnalul PWM ce comandă fiecare culoare (R,G,B) +
-  * Folosiți funcția //​parseCSV//​ pentru a extrage într-un vector valorile separate prin virgulă din mesajul comenzii +
- +
-<​file>​ +
-int parseCSV(char* inputString,​ int *outputArray,​ int outputArraySize) { +
-  char *pch; +
-  int val = 0; +
-  int index_serial_data = 0; +
-  pch = strtok(inputString,​ ","​);​ +
- +
-  while (pch != NULL && pch != "​\n"​) { +
-    sscanf (pch, "​%d",​ &​val);​ +
-    outputArray[index_serial_data] = val; +
-    index_serial_data++;​ +
-    if (index_serial_data == outputArraySize) { +
-      break; +
-    ​} +
-    pch = strtok(NULL,​ ","​);​ +
-  ​} +
-  return index_serial_data;​ +
-+
-</​file>​ +
- +
-<​hidden>​ +
-**Soluția** se găsește pe [[https://​www.tinkercad.com/​things/​7TIP4DS6OJz|Tinkercad Serial RGB]] +
-</​hidden>​ +
  
-=== Task 3 (Servo / sweep===+Rulați exemplul standard din Arduino de mai jos, 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)+Modificați programul astfel încât servomotorul să se oprească atunci când ajunge ​în oricare din capete. Cu ajutorul interfeței seriale, se va modifica sensul de rotație.  ​
  
-{{:​pm:​lab:​lab3_2021:​auto_servo.png?600|}}+<note warning>​Atenție la limitele de unghiDepășirea acestora poate avaria servomotorul</​note>​
  
-  * Urmăriți pe osciloscop semnalul PWM generat 
   * Se pot controla până la 12 servomotoare folosind un singur timer   * Se pot controla până la 12 servomotoare folosind un singur timer
-  * Calculați factorul de umplere pentru intervalul de comandă al servomotorului (1ms-2ms). Se poate genera un astfel de semnal cu precizie bună folosind un timer în modul Fast PWM, ca mai devreme?+  * Calculați factorul de umplere pentru intervalul de comandă al servomotorului (1ms-2ms). Se poate genera un astfel de semnal cu precizie bună folosind un timer în modul Fast PWM ?
   ​   ​
 <​file>​ <​file>​
Line 437: Line 347:
 </​file>​ </​file>​
  
-<​hidden>​ +=== Task 3 (Servo / buton) === 
-**Soluția** se găsește pe [[https://www.tinkercad.com/​things/​kLxC5nzUW7L|Tinkercad Auto Servo]] +{{:pm:​lab:​lab3_task3.png?​direct&​600|}}
-</​hidden>​+
  
-=== Task 4 (Servo / buton) === +Folosind ​o întrerupere ​de tip PCINT (Pin Change INTerrupt), modificați incremental poziția servomotorului (0-180 ​și 180-0cu ajutorul butonului.
- +
-Folosind ​întreruperile ​de la **Task 0**, modificați incremental poziția servomotorului (0-180)+
   ​   ​
-{{:​pm:​lab:​lab3_2021:​button_servo.png?600|}}+<note warning>​Atenție la limitele de unghiDepășirea acestora poate avaria servomotorul</​note>​
  
-  * Atenție la limite (min, max). Depășirea acestora poate avaria servomotorul. +  * 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. 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]]   * 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>​ +===== 5. Resurse =====
-**Soluția** se găsește pe [[https://​www.tinkercad.com/​things/​23y5RXDFFVl|Tinkercad Button Servo]] +
-</​hidden>​ +
- +
- +
-===== 4. Resurse =====+
  
   * {{:​pm:​atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|Datasheet Atmega 328p}}   * {{:​pm:​atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|Datasheet Atmega 328p}}
Line 462: Line 363:
 {{:​pm:​lab:​uno.jpg?​direct&​200|pinout Arduino UNO}} {{:​pm:​lab:​uno.jpg?​direct&​200|pinout Arduino UNO}}
   * Responsabili:​ [[dragos_mihai.ene@stud.acs.upb.ro | Dragoș Ene ]] | [[sebastian.gherman99@stud.acs.upb.ro | Sebastian Gherman ]]   * Responsabili:​ [[dragos_mihai.ene@stud.acs.upb.ro | Dragoș Ene ]] | [[sebastian.gherman99@stud.acs.upb.ro | Sebastian Gherman ]]
-===== 5. Linkuri utile =====+ 
 +<​solution>​ 
 +<​hidden>​Arhiva cu soluțiile o puteți descărca de aici: {{:​pm:​lab:​lab3_2021:​lab3-solved.zip}}</​hidden>​ 
 +</​solution>​ 
 + 
 +===== 6. Linkuri utile =====
  
   * [[http://​www.nongnu.org/​avr-libc/​user-manual/​group__avr__interrupts.html|AVR Libc - interrupt.h]]   * [[http://​www.nongnu.org/​avr-libc/​user-manual/​group__avr__interrupts.html|AVR Libc - interrupt.h]]
Line 470: Line 376:
   * [[https://​en.wikipedia.org/​wiki/​Comma-separated_values|CSV]]   * [[https://​en.wikipedia.org/​wiki/​Comma-separated_values|CSV]]
   * [[https://​www.arduino.cc/​en/​Reference/​ServoWriteMicroseconds|Servo.writeMicroseconds]]   * [[https://​www.arduino.cc/​en/​Reference/​ServoWriteMicroseconds|Servo.writeMicroseconds]]
 +
pm/lab/lab3-2022.1648384849.txt.gz · Last modified: 2022/03/27 15:40 by sebastian.gherman99
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