3.16. Controlul servomotoarelor

Un servomotor de hobby (RC) este un mic motor cu reductor într-o carcasă etanșă, cu control de poziție în buclă închisă încorporat. În interiorul carcasei se află un motor de curent continuu, un reductor cu roți dințate, un potențiometru conectat la axul de ieșire și o mică placă driver care compară citirea potențiometrului cu o valoare de referință venită din exterior. Driverul rulează motorul în direcția care reduce eroarea și se oprește când poziția corespunde. Din partea camerei, nimic din toate acestea nu este vizibil – pur și simplu îi indici servomotorului unde să meargă.

3.16.1. Semnalul PWM

Un servomotor primește valoarea de referință sub forma unui semnal PWM cu o rată de cadre fixă de 50 Hz, unde lățimea impulsului selectează poziția:

  • Un impuls de 1,0 ms duce axul la unul dintre capetele cursei sale.

  • Un impuls de 1,5 ms poziționează axul la centru.

  • Un impuls de 2,0 ms duce axul la celălalt capăt.

Orice valoare intermediară corespunde unei poziții intermediare.

Trei rânduri de forme de undă dreptunghiulare stivuite pe verticală. Fiecare rând arată o perioadă de 20 ms a unui PWM de 50 Hz cu un impuls îngust la nivel înalt la început: 1,0 ms în rândul de sus, 1,5 ms la mijloc, 2,0 ms în rândul de jos.

Cadrul PWM al servomotorului are 20 ms; lățimea impulsului (1,0 – 2,0 ms) selectează poziția.

Spre deosebire de LED-uri și motoare, servomotorul nu mediază semnalul PWM. Lățimea impulsului în sine este comanda: logica internă a servomotorului măsoară fiecare impuls, își setează ținta în consecință și rulează motorul până când ieșirea corespunde. Factorul de umplere ca fracțiune (între 5 % și 10 % pe întregul interval) este incidental – contează lățimea absolută a impulsului, iar aceasta este ceea ce software-ul trebuie să controleze.

3.16.2. Cablare

Servomotoarele de hobby folosesc un conector cu trei fire:

  • Alimentare (de obicei roșu): alimentarea proprie a servomotorului, de regulă între 4,8 V și 6 V. Nu alimenta servomotorul de la șina de 3,3 V a camerei – aceasta nu poate furniza curentul de blocare, iar șina va ceda în tensiune.

  • Masă (de obicei negru sau maro): calea de retur pentru alimentarea servomotorului, legată la masa camerei astfel încât semnalul să aibă și o referință comună.

  • Semnal (de obicei alb, galben sau portocaliu): linia PWM de la GPIO-ul camerei.

3.16.3. Cod

duty_u16() ar funcționa, dar setează factorul de umplere ca fracțiune din perioadă – incomod pentru un semnal la care contează lățimea absolută a impulsului, iar perioada este fixă. duty_ns() setează lățimea impulsului direct în nanosecunde:

from machine import PWM, Pin

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

Purtătoarea este de 50 Hz (perioadă de 20 ms); timpul la nivel înalt al fiecărui ciclu este exact 1500 µs. O mică funcție auxiliară face explicită maparea poziție-impuls:

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

O variație lentă pe întregul interval:

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)

Intervalul de 1,0 – 2,0 ms este standardul, însă multe servomotoare acceptă un interval mai larg (adesea de la 500 µs la 2500 µs) pentru cursa completă. Foaia de date a servomotorului indică limitele exacte ale lățimii impulsului; valorile din afara acelui interval pot izbi motorul în opritoarele sale mecanice.

Pentru un servomotor cu un interval nestandard, mută limitele în constante și parametrizează maparea:

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)