3.16. Szervó vezérlése

Egy hobbi (RC) szervó egy kis fogaskerekes motor zárt házban, beépített zárthurkú pozícióvezérléssel. A házban egy egyenáramú motor, egy lassító hajtómű, egy a kimeneti tengelyhez kapcsolt potméter, valamint egy kis meghajtópanel ül, amely összehasonlítja a potméter értékét egy kívülről érkező alapjellel. A meghajtó abba az irányba forgatja a motort, amerre a hiba csökken, és megáll, amikor a pozíció megegyezik az alapjellel. A kamera oldaláról mindebből semmi sem látszik – egyszerűen csak megmondod a szervónak, hová menjen.

3.16.1. A PWM-jel

Egy szervó az alapjelét rögzített 50 Hz-es képkockasebességű PWM-jelként kapja, ahol az impulzusszélesség választja meg a pozíciót:

  • Egy 1,0 ms-os impulzus a tengelyt a mozgástartomány egyik végállásába hajtja.

  • Egy 1,5 ms-os impulzus a tengelyt középre állítja.

  • Egy 2,0 ms-os impulzus a tengelyt a másik végállásába hajtja.

A közötte lévő bármilyen érték egy köztes pozícióhoz rendelődik.

Három sornyi négyszögjel-görbe egymás fölött elrendezve. Minden sor egy 50 Hz-es PWM 20 ms-os periódusát mutatja egy keskeny, magas impulzussal az elején: 1,0 ms a felső sorban, 1,5 ms a középsőben, 2,0 ms az alsóban.

A szervó PWM-képkockája 20 ms hosszú; az impulzusszélesség (1,0 – 2,0 ms) választja meg a pozíciót.

A LED-ekkel és motorokkal ellentétben a szervó nem átlagolja a PWM-et. Maga az impulzusszélesség a parancs: a szervó belső logikája megméri az egyes impulzusokat, ennek megfelelően állítja be a célértékét, és addig járatja a motort, amíg a kimenet meg nem egyezik. A kitöltési tényező mint arány (a teljes tartományban 5% és 10% között) csak mellékes – az abszolút impulzusszélesség számít, és ezt kell a szoftvernek vezérelnie.

3.16.2. Bekötés

A hobbi szervók háromvezetékes csatlakozót használnak:

  • Táp (általában piros): a szervó saját tápellátása, jellemzően 4,8 V és 6 V között. Ne tápláld a szervót a kamera 3,3 V-os tápvonaláról – az nem tudja szolgáltatni a megállási (stall) áramot, és a tápvonal feszültsége leesik.

  • Föld (általában fekete vagy barna): a szervó tápellátásának visszatérő útvonala, a kamera földjéhez kötve, hogy a jelnek is közös referenciája legyen.

  • Jel (általában fehér, sárga vagy narancssárga): a PWM-vonal a kamera GPIO-járól.

3.16.3. Kód

A duty_u16() működne, de a kitöltést a periódus arányaként állítja be – ami kényelmetlen egy olyan jelnél, ahol az abszolút impulzusszélesség számít, és a periódus rögzített. A duty_ns() az impulzusszélességet közvetlenül nanoszekundumban állítja be:

from machine import PWM, Pin

servo = PWM(Pin("P7"), freq=50, duty_ns=1_500_000)  # centre

A vivőfrekvencia 50 Hz (20 ms-os periódus); az egyes ciklusok magas ideje pontosan 1500 µs. Egy kis segédfüggvény teszi explicitté a pozíció-impulzus megfeleltetést:

def set_position(angle):
    # angle: 0..180 degrees mapped to 1.0..2.0 ms
    pulse_us = 1000 + (angle * 1000) // 180
    servo.duty_ns(pulse_us * 1000)

set_position(0)      # full one way
set_position(90)     # centre
set_position(180)    # full the other way

Egy lassú végigfuttatás a tartományon:

import time

for angle in range(0, 181, 5):
    set_position(angle)
    time.sleep_ms(20)
for angle in range(180, -1, -5):
    set_position(angle)
    time.sleep_ms(20)

Az 1,0 – 2,0 ms-os tartomány a szabványos, de sok szervó szélesebb tartományt is elfogad (gyakran 500 µs-tól 2500 µs-ig) a teljes mozgástartományhoz. A szervó adatlapja megadja a pontos impulzusszélesség-határokat; az ezen kívül eső értékek a motort a mechanikai ütközőibe csaphatják.

Nem szabványos tartományú szervó esetén emeld ki a határokat konstansokba, és paraméterezd a megfeleltetést:

PULSE_MIN_US = 500     # full one way (from the data sheet)
PULSE_MAX_US = 2500    # full the other way

def set_position(angle):
    span_us = PULSE_MAX_US - PULSE_MIN_US
    pulse_us = PULSE_MIN_US + (angle * span_us) // 180
    servo.duty_ns(pulse_us * 1000)