3.16. Servon ohjaus

Harrastelija- eli RC-servo on pieni hammaspyörävälitteinen moottori suljetussa kotelossa, jossa on sisäänrakennettu suljetun silmukan asennon ohjaus. Kotelon sisällä on tasavirtamoottori, alennusvaihteisto, lähtöakseliin kytketty potentiometri ja pieni ohjainlevy, joka vertaa potentiometrin lukemaa ulkopuolelta tulevaan asetusarvoon. Ohjain ajaa moottoria siihen suuntaan, joka pienentää virhettä, ja pysähtyy kun asento vastaa asetusta. Kameran näkökulmasta mikään tästä ei näy – kerrot vain servolle minne mennä.

3.16.1. PWM-signaali

Servo ottaa asetusarvonsa PWM-signaalina kiinteällä 50 Hz:n kehystaajuudella, jossa pulssin leveys valitsee asennon:

  • 1,0 ms:n pulssi ajaa akselin liikealueensa toiseen ääripäähän.

  • 1,5 ms:n pulssi pysäköi akselin keskelle.

  • 2,0 ms:n pulssi ajaa akselin toiseen ääripäähän.

Mikä tahansa siltä väliltä kuvautuu välissä olevaan asentoon.

Kolme riviä neliöaaltokuvaajia pinottuna pystysuoraan. Kukin rivi näyttää yhden 50 Hz:n PWM:n 20 ms:n jakson, jossa on kapea korkea pulssi alussa: 1,0 ms ylimmällä rivillä, 1,5 ms keskellä ja 2,0 ms alimmalla.

Servon PWM-kehys on 20 ms pitkä; pulssin leveys (1,0 – 2,0 ms) valitsee asennon.

Toisin kuin LEDit ja moottorit, servo ei keskiarvoista PWM:ää. Pulssin leveys itsessään on komento: servon sisäinen logiikka mittaa kunkin pulssin, asettaa kohteensa sen mukaan ja ajaa moottoria kunnes lähtö vastaa asetusta. Pulssisuhde murto-osana (5 %:n ja 10 %:n välillä koko alueella) on satunnaista – merkitystä on absoluuttisella pulssin leveydellä, jota ohjelmiston on ohjattava.

3.16.2. Kytkentä

Harrastelijaservot käyttävät kolmijohtimista liitintä:

  • Käyttöjännite (yleensä punainen): servon oma syöttö, tyypillisesti 4,8 V – 6 V. Älä syötä servoa kameran 3,3 V:n jännitetasosta – se ei pysty syöttämään jumitusvirtaa, ja jännitetaso romahtaa.

  • Maa (yleensä musta tai ruskea): servon käyttöjännitteen paluureitti, sidottuna kameran maahan, jotta signaalilla on myös yhteinen vertailutaso.

  • Signaali (yleensä valkoinen, keltainen tai oranssi): PWM-linja kameran GPIO:sta.

3.16.3. Koodi

duty_u16() toimisi, mutta se asettaa pulssisuhteen jakson murto-osana – hankalaa signaalille, jossa merkitystä on absoluuttisella pulssin leveydellä ja jakso on kiinteä. duty_ns() asettaa pulssin leveyden suoraan nanosekunteina:

from machine import PWM, Pin

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

Kantoaalto on 50 Hz (20 ms:n jakso); korkea aika kullakin jaksolla on tarkalleen 1500 µs. Pieni apufunktio tekee asento-pulssi-kuvauksen näkyväksi:

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

Hidas pyyhkäisy koko alueen yli:

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)

1,0 – 2,0 ms:n alue on vakio, mutta monet servot hyväksyvät leveämmän alueen (usein 500 µs – 2500 µs) täyttä liikealuetta varten. Servon datalehti luettelee tarkat pulssin leveyden rajat; tuon alueen ulkopuoliset arvot voivat lyödä moottorin mekaanisia rajoittimiaan vasten.

Servolle, jolla on epästandardi alue, nosta rajat vakioiksi ja parametroi kuvaus:

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)