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.
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)