Differences

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

Link to this comparison view

pm:lab:lab3-2022 [2022/03/27 04:10]
dragos_mihai.ene [4. Resurse]
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 82: Line 88:
  
 Tensiunea primită de un dispozitiv reprezintă media acestor pulsuri și este raportul dintre perioada de timp corespunzătoare valorii ON și perioada totală dintr-un ciclu ON-OFF. Aceast raport se numește **factor de umplere (//duty cycle//)**. 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. Tensiunea primită de un dispozitiv reprezintă media acestor pulsuri și este raportul dintre perioada de timp corespunzătoare valorii ON și perioada totală dintr-un ciclu ON-OFF. Aceast raport se numește **factor de umplere (//duty cycle//)**. 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.
- +{{ :​pm:​lab:​main-qimg-72a9c6569290abe0a85dceabaf8c7ff9.gif?​direct&​400 |}} 
-{{:​pm:​lab:​main-qimg-72a9c6569290abe0a85dceabaf8c7ff9.gif?​direct&​400 |}} {{:​pm:​lab:​pwm_led.gif?​direct&​200|}} ​+{{ :​pm:​lab:​pwm_led.gif?​direct&​200 |}} 
  
  
Line 109: Line 115:
    * Wait For T_off    * Wait For T_off
  
-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 Brushless DC), iar o astfel de metodă nu este cea mai eficientă, fiind necesară intervenția procesorului pentru tratarea întreruperilor frecvente.
 </​note>​ </​note>​
  
Line 147: Line 153:
 Alternativ, putem configura fiecare timer (atât cele de 8 biți cât și cele de 16 biți) în moduri ce au ca TOP o valoare specificată într-unul din registrele OCRnA sau OCRnB. Un timer configurat astfel are doar un canal ce genereaza output așa cum ne-am aștepta. Și canalul corespunzător registrului ce conține valoare TOP va genera semnal, însa nu în modul dorit.</​note>​ Alternativ, putem configura fiecare timer (atât cele de 8 biți cât și cele de 16 biți) în moduri ce au ca TOP o valoare specificată într-unul din registrele OCRnA sau OCRnB. Un timer configurat astfel are doar un canal ce genereaza output așa cum ne-am aștepta. Și canalul corespunzător registrului ce conține valoare TOP va genera semnal, însa nu în modul dorit.</​note>​
  
- +Din punct de vedere al microcontroller-ului Atmega328p există 3 tipuri de PWM:
-Conform tabelului **15-5.** din {{:​pm:​atmel-7810-automotive-microcontrollers-atmega328p_datasheet.pdf|datasheet}},​ Timer-ul 1 mai poate fi configurat să funcționeze și în modul PWM. Din punct de vedere al microcontroller-ului Atmega328p există 3 tipuri de PWM:+
   * **Fast PWM**   * **Fast PWM**
   * **Phase Correct PWM**   * **Phase Correct PWM**
Line 176: Line 181:
 \end{equation} </​note>​ \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. Î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>​
  
 ===== Lucrul cu PWM-ul ===== ===== Lucrul cu PWM-ul =====
  
-Lucrul cu PWM-ul presupune inițializarea unui timer și configurarea output-ului pe pini. Fiecare timer are doi pini pe care genera ca output un astfel de semnal (cele două canale): Timer0 are ''​OC0A''​ și ''​0C0B'',​ Timer1 are ''​OC1A''​ și ''​OC1B''​ etc.+Lucrul cu PWM-ul presupune inițializarea unui timer și configurarea output-ului pe pini. Fiecare timer are doi pini pe care poate genera ca output un astfel de semnal (cele două canale): Timer0 are ''​OC0A''​ și ''​0C0B'',​ Timer1 are ''​OC1A''​ și ''​OC1B''​ etc.
  
-{{:pm:lab:lab3_2021:​atmega328_pwm.png?700|}}+{{ :pm:lab:uno.jpg?direct&700 |pinout Arduino UNO}}
  
 De exemplu, presupunem că avem Timer1 configurat pe modul de funcționare Fast PWM (modul de funcționare nu trebuie neapărat să conțină cuvântul '​PWM'​ ca să poată fi folosit pentru generarea unui semnal). Fast PWM este caracterizat de o frecvență fixă și un prag stabilit de programator,​ ce poate fi modificat în timpul execuției. ​ De exemplu, presupunem că avem Timer1 configurat pe modul de funcționare Fast PWM (modul de funcționare nu trebuie neapărat să conțină cuvântul '​PWM'​ ca să poată fi folosit pentru generarea unui semnal). Fast PWM este caracterizat de o frecvență fixă și un prag stabilit de programator,​ ce poate fi modificat în timpul execuției. ​
Line 234: Line 239:
  
 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: 
-  * ''​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 (''​PB2''​ sau pinul 10 de pe Arduino) și controlează LED-ul ''​verde''​. 
-  * ''​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.
  
-{{:​pm:​lab:​lab3_2021:​rgb_led_pinout.jpeg?​400|}}+{{ :​pm:​lab:​lab3_2021:​rgb_led_pinout.jpeg?​400 |}}
  
  
Line 247: Line 248:
 ==== Servomotoare ==== ==== Servomotoare ====
  
-Servomotoarele sunt construite pe baza unui motor DC sau BLDC, au angrenaje integrate și un arbore (ax) care poate fi controlat cu precizie. Servo-urile standard permit poziționarea arborelui la diferite unghiuri, de obicei între 0 și 180 de grade. Există și variante cu rotație continuă ce permit modificarea precisă a vitezei de rotație a arborelui.+Servomotoarele sunt construite pe baza unui motor DC sau Brushless DC, au angrenaje integrate și un arbore (ax) care poate fi controlat cu precizie. Servo-urile standard permit poziționarea arborelui la diferite unghiuri, de obicei între 0 și 180 de grade. Există și variante cu rotație continuă ce permit modificarea precisă a vitezei de rotație a arborelui.
  
 Servomotoarele hobby ([[https://​en.wikipedia.org/​wiki/​Servo_(radio_control)|Servo]]) sunt în mod uzual comandate printr-un semnal PWM cu frecvența de 50 Hz și perioada semnalului T_on în intervalul 1-2 ms, unde 1.5 ms reprezintă poziția de centru. Practic, semnalul PWM este folosit pentru a codifica și transmite poziția dorită către microcontroller-ul integrat care se ocupă de poziționarea efectivă servomotorului. Servomotoarele hobby ([[https://​en.wikipedia.org/​wiki/​Servo_(radio_control)|Servo]]) sunt în mod uzual comandate printr-un semnal PWM cu frecvența de 50 Hz și perioada semnalului T_on în intervalul 1-2 ms, unde 1.5 ms reprezintă poziția de centru. Practic, semnalul PWM este folosit pentru a codifica și transmite poziția dorită către microcontroller-ul integrat care se ocupă de poziționarea efectivă servomotorului.
Line 276: Line 277:
 } }
 </​file>​ </​file>​
- 
  
  
Line 282: 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 442: 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}}
   * Arduino UNO pinout   * Arduino UNO pinout
 {{:​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 ]] +  * 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 475: 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.1648343413.txt.gz · Last modified: 2022/03/27 04:10 by dragos_mihai.ene
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