RP2350-Zero/PWM

Zo stránky 3D liga wiki
Verzia z 11:52, 3. september 2026, ktorú vytvoril Sebastian (diskusia | príspevky) (Vytvorená stránka „=== PWM === PWM (Pulse Width Modulation, modulácia šírky impulzu) funguje tak, že pin veľmi rýchlo prepína medzi HIGH a LOW. To, aké percento času je pin v stave HIGH (tzv. '''duty cycle'''), určuje "priemerný" účinok signálu – napríklad ako jasno svieti LED, akou rýchlosťou sa točí motor, alebo v akej polohe má byť servo. 500px RP2350 má hardvérovú PWM perifériu s viacerými tzv. "slice" jednotkami, pričom ka…“)
(rozdiel) ← Staršia verzia | Aktuálna úprava (rozdiel) | Novšia verzia → (rozdiel)
Prejsť na navigáciu Prejsť na vyhľadávanie

PWM

PWM (Pulse Width Modulation, modulácia šírky impulzu) funguje tak, že pin veľmi rýchlo prepína medzi HIGH a LOW. To, aké percento času je pin v stave HIGH (tzv. duty cycle), určuje "priemerný" účinok signálu – napríklad ako jasno svieti LED, akou rýchlosťou sa točí motor, alebo v akej polohe má byť servo.

RP2350 má hardvérovú PWM perifériu s viacerými tzv. "slice" jednotkami, pričom každý slice ovláda dva kanály (A a B). Vďaka tomu vie generovať PWM na viacerých pinoch súčasne bez zaťaženia procesora.

Knižnice ako Servo.h majú už vstavanú podporu pre PWM. Najprv si ukážeme príklady "ručného" PWM signálu pre RGB LED modul a pre servomotorček, následne si ukážeme rovnaký príklad cez knižnicu Servo.

Príklad – plynulý prechod farieb na 3-farebnom LED module

V kapitole o digitálnom vstupe/výstupe sme rovnaký LED modul ovládali len ako zapnuté/vypnuté (HIGH/LOW). Vďaka PWM vieme jas každej farby plynulo meniť, a tým vytvárať aj farby, ktoré modul priamo nemá (napr. plynulý prechod cez oranžovú, tyrkysovú...):

const int PIN_LED_R = 10; // uprav podla realneho zapojenia
const int PIN_LED_G = 11;
const int PIN_LED_B = 12;

void nastav_farbu(int r, int g, int b) {
  analogWrite(PIN_LED_R, r);
  analogWrite(PIN_LED_G, g);
  analogWrite(PIN_LED_B, b);
}

void setup() {
  pinMode(PIN_LED_R, OUTPUT);
  pinMode(PIN_LED_G, OUTPUT);
  pinMode(PIN_LED_B, OUTPUT);
}

void loop() {
  // plynuly prechod z cervenej do zelenej
  for (int i = 0; i <= 255; i++) {
    nastav_farbu(255 - i, i, 0);
    delay(5);
  }
  // zo zelenej do modrej
  for (int i = 0; i <= 255; i++) {
    nastav_farbu(0, 255 - i, i);
    delay(5);
  }
  // z modrej spat do cervenej
  for (int i = 0; i <= 255; i++) {
    nastav_farbu(i, 0, 255 - i);
    delay(5);
  }
}

analogWrite() tu v skutočnosti nastavuje duty cycle PWM signálu na každom pine samostatne (0 = stále LOW, 255 = stále HIGH) – aj keď názov funkcie znie ako analógový výstup.

Poznámka: rovnako ako pri digitálnom module – ak má tvoja LED spoločnú anódu (common anode), bude logika obrátená (255 = vypnuté, 0 = najjasnejšie).

Príklad – servomotorček cez ručný impulz

Pri LED sme videli, že analogWrite() v skutočnosti len nastavuje duty cycle – ako dlho je pin HIGH v rámci jednej periódy. Servo funguje na podobnom princípe, len namiesto "priemerného jasu" sa dĺžka HIGH impulzu prekladá priamo na uhol. Kým pri LED sme dĺžku impulzu nechali vyriešiť analogWrite(), tu si to skúsime napísať ručne, aby bolo vidieť, čo sa deje "pod kapotou":

  • impulz sa opakuje približne každých 20 ms (50 Hz)
  • dĺžka samotného HIGH impulzu (typicky 500–2500 μs) určuje uhol – kratší impulz = bližšie k 0°, dlhší = bližšie k 180°
const int PIN_SERVO = 13; // uprav podla realneho zapojenia

void poslat_impulz(int trvanie_us) {
  digitalWrite(PIN_SERVO, HIGH);
  delayMicroseconds(trvanie_us);
  digitalWrite(PIN_SERVO, LOW);
}

void setup() {
  pinMode(PIN_SERVO, OUTPUT);
}

void loop() {
  for (int t = 500; t <= 2500; t += 10) {
    poslat_impulz(t);
    delay(20);
  }
  for (int t = 2500; t >= 500; t -= 10) {
    poslat_impulz(t);
    delay(20);
  }
}

Poznámka: presné hraničné hodnoty (500/2500 μs) sa medzi servami mierne líšia – ak sa servo pri krajných hodnotách "trasie" alebo nedosiahne celý rozsah, uprav si čísla podľa konkrétneho kusu.

Jednoduchšia cesta – knižnica Servo.h

V praxi netreba impulzy generovať ručne – knižnica Servo.h robí presne to isté (a spoľahlivejšie, keďže časovanie beží nezávisle od zvyšku programu). Pri attach() vieme rovno zadať aj rozsah impulzu (min, max v μs), aby sme mohli použiť celý rozsah 500–2500 ako v ručnom príklade:

#include <Servo.h>

const int PIN_SERVO = 13;

Servo servo;

void setup() {
  servo.attach(PIN_SERVO, 500, 2500);
}

void loop() {
  for (int t = 500; t <= 2500; t += 10) {
    servo.writeMicroseconds(t);
    delay(15);
  }
  for (int t = 2500; t >= 500; t -= 10) {
    servo.writeMicroseconds(t);
    delay(15);
  }
}

Ak máš namiesto 180° serva 360° (kontinuálne otáčanie), impulz už neurčuje uhol, ale rýchlosť a smer – hodnota okolo 1500 μs zvyčajne znamená stop, kratšie/dlhšie impulzy otáčanie jedným alebo druhým smerom (presnú "stop" hodnotu si treba pre konkrétny kus odskúšať).