A szervomotorokat igen széles körben használják a robotikában, különböző vezérlő és szabályzó rendszerekben, RC modellekben, elsősorban pozicionálási feladatokra. A szervo egy speciális motor, tengelye a hagyományos motorokkal szemben nem folyamatos, állandó vagy változtatható fordulatszámú forgást végez, hanem adott szöggel elfordul, és a tengelyére szerelt kar helyzetét változtatja meg. A kar, illetve a tengely által megtett elfordulást, illetve az elfordulás szögét egy impulzussorozattal határozhatjuk meg. A kar addig marad az adott pozícióban, amíg az impulzussorozat meg nem szűnik.
Ebben a leírásban azt fogom bemutatni, hogy egy kisméretű un. microszervo hogyan programozható és működtethető egy Raspberry Pi 3B+ segítségével.
A választott szervo típus a Tower Pro gyártmányú SG92R. A kis motor a népszerű SG90 9g változat utódja, kedvezőbb paraméterekkel illetve megerősített mechanikai tulajdonságokkal.
A szervo főbb paraméterei (SG92R):
- Tömeg: 9g
- Méretek: 23×12.2x27mm
- Fogaskerekek anyaga: szénszállal erősített műanyag
- Működési sebesség: 0.1sec/60fok (4.8V)
- Tartozékok: működtető kar és csavarok
Működtetés:
A szervo működtetését a gyakorlatban úgy valósíthatod meg, hogy vezérlő bemenetére egy un. változtatható kitöltési tényezőjű (dutycycle) impulzussorozatot küldesz a Raspberry Pi megfelelő kimenetéről. Ezt a vezérlési módot PWM-nek, azaz impulzus-szélesség modulációnak hívjuk. A megoldás lényege az, hogy olyan állandó periódusidejű (frekvenciájú) jeleket állítunk elő, ahol a szabályozás a jel kitöltési tényezőjének változtatásával történik. Néhány különböző kitöltési tényezőjű PWM jelet láthatsz a következő ábrán:
A kitöltési tényező az impulzusszélesség (azaz a bekapcsolt állapot ideje) és a periódusidő hányadosa. Ha százalákosan akarjuk megadni, akkor a hányadost még meg kell szorozni 100-al.
Ha a kitöltési tényezőt százalékosan akarjuk megadni, akkor a hányadost még meg kell szorozni 100-zal:
Az SG92R szervo karja 90 fokos elfordulást végezhet mindkét irányba, azaz a teljes elfordulás szöge 180 fok. A un. semleges helyzet az a pont, amelyből a tengely az óramutató járásával egyező, illetve ellenkező irányba is elmozdulhat. A szervo minden 20ms-os időközönként új impulzust vár, ami meghatározza az elfordulási szögét. Egy 1,5ms-os impulzus a szervot a 90 fokos pozícióba forgatja, amit semleges pozíciónak hívunk. Az 1ms-os impulzus 0 fokba, a 2ms-os impulzus pedig 180 fokos pozícióba forgatja a szervo tengelyét, illetve a rá szerelt kart. A pozícionáló impulzusoknak ismétlődniük kell, hogy a szervo tengelye stabilan tartsa a felvett pozíciót, akár külső erő ellenében is.
Bekötés:
A legtöbb mikrovezérlőn illetve egykártyás számítógépen találsz PWM kimenetet. A Raspberry Pi 3B+ két hardveres illetve több szoftveres kimenettel rendelkezik. Az alábbi példában a PI első PWM csatornáját használtam (GPIO 18 / 12) a microservo vezérlésére, a további GPIO bemenetek három nyomógomb lekezelését oldják meg, ezek szerepére a második mintaprogram ismertetésénél térek ki. ( A Pi másik „fizikai” PWM kimenete a GPIO 13 / 33)
A bekötésnél két alapvető biztonsági szempontra kell figyelemmel lenned! Ahogy a bekötési ábrán is látszik, a servo tápfeszültség ellátása a Pi 5V-os GPIO tüskéjéről történik, a nyomógombok 3,3V-ot kapnak. Ha erre a pontra 5V-ot kötsz, az a Pi tönkremeneteléhez vezethet!!
A másik szem előtt tartandó szempont a servo teljesítmény igénye. A mintakapcsolásban alkalmazott SG92R szervo csatlakoztatható a Pi 5V-os GPIO tüskéjére, de ebben az esetben biztosítani kell, hogy az alkalmazott tápegység képes legyen a megfelelő áramerősség szolgáltatására, mert alacsony teljesítményű tápegység használata esetén a szervo működésekor a Pi lefagyhat, vagy újraindul.
A teljes biztonságot adó megoldás a szervo független 5V-os tápegységről történő működtetése, ebben az esetben a táp negatív potenciálú pontját a GPIO port tetszőleges GND tüskéjével kell összekötnöd.
Vezérlés
Az előzőekben megbeszéltük, hogy a servo számára az impulzusokat ismételnünk kell, méghozzá 20ms-os gyakorisággal. Ez tudva, valamint, hogy a periódusidő a frekvencia reciproka ez 50Hz-es frekvenciát jelent. Így python programunkban a PWM modul meghívását ezzel az értékkel kell megtennünk.
p = GPIO:PWM(12,50) p.start (dc)
Ezek után be kell állítani a kitöltési tényezőt (dutycycle), amit az impulzus időtartamának és a szükséges impulzus szélességének az aránya határoz meg. 20ms-os periódusidővel a szükséges impulzusok időtartamát 0,5ms, 1,5ms, illetve 2,5ms-nak véve a következőképpen számolhatunk:
- dc1 = 0,5 / 20 x 100 = 2,5%
- dc2 = 1,5 / 20 x 100 = 2,5%
- dc3 = 2,5 / 20 x 100 = 2,5%
A kitöltési tényező beállítását az alábbi paranccsal tehetjük meg:
p.ChangeDutyCycle (dc)
Az impulzus sorozatot az alábbi parancs állítja le:
p.stop ()
Példaprogramok:
Az előzőekben elmondottakhoz két példaprogram, az első ciklikusan 0 – 90 – 180 fok között változtatja a szervo pozícióját, míg a másik három nyomógomb segítségével állítja be a kívánt szögelfordulást.
A programok alapján tetszőleges robot, vagy RC modell-vezérlő alkalmazást készíthetsz.
1. példaprogram:
# micro-servo teszt-1 program # szükséges library-k importálása import RPi.GPIO as GPIO import time #GPIO számozás beállítása GPIO.setmode (GPIO.BOARD) #12-es tüske beállítása kimenetnek GPIO.setup (12, GPIO.OUT) #PWM frekvencia beállít p = GPIO.PWM(12,50) #alaphelyzet p.start(0) dc1 = 7.5 dc2 = 2.5 dc3 = 12.5 try: while True: p.ChangeDutyCycle(dc1) #90 fok time.sleep(1) p.ChangeDutyCycle(dc2) #0 fok time.sleep(1) p.ChangeDutyCycle(dc3) #180 fok time.sleep(1) except KeyboardInterrupt: p.stop() GPIO.cleanup()
2. példaprogram:
# micro-servo teszt-2 program, szervo vezérlése gombokkal # szükséges library-k importálása import RPi.GPIO as GPIO import time #GPIO számozás beállítása GPIO.setmode (GPIO.BOARD) #12-es tüske beállítása kimenetnek GPIO.setup (12, GPIO.OUT) # 7,10,11-es tüske beállítása bemenetnek GPIO.setup (7, GPIO.IN) GPIO.setup (10, GPIO.IN) GPIO.setup (11, GPIO.IN) #PWM frekvencia beállít p = GPIO.PWM(12,50) #alaphelyzet p.start(0) try: while True: #gomb 1 if GPIO.input(10) == 1: p.ChangeDutyCycle(7.5) print("90 fok") time.sleep(1) #gomb 2 if GPIO.input(11) == 1: p.ChangeDutyCycle(2.5) print("0 fok") time.sleep(1) #gomb 3 if GPIO.input(7) == 1: p.ChangeDutyCycle(12.5) print("180 fok") time.sleep(1) except KeyboardInterrupt: pass p.stop() GPIO.cleanup()
A két forráskód letölthető:
A cikkben használt szervó megvásárolható a MálnaPC Webshopjában!