3.16. Controlo de servos

Um servo de uso amador (RC) é um pequeno motor com engrenagens numa caixa selada com controlo de posição em malha fechada incorporado. No interior da caixa encontra-se um motor DC, uma caixa de redução, um potenciómetro ligado ao veio de saída e uma pequena placa controladora que compara a leitura do potenciómetro com um valor de referência proveniente do exterior. O controlador faz o motor rodar na direção que reduz o erro, e para quando a posição corresponde. Do ponto de vista da câmara, nada disso é visível – basta dizer ao servo para onde ir.

3.16.1. O sinal PWM

Um servo recebe o seu valor de referência como um sinal PWM a uma taxa de fotograma fixa de 50 Hz, onde a largura de pulso seleciona a posição:

  • Um pulso de 1,0 ms move o veio para uma extremidade da sua excursão.

  • Um pulso de 1,5 ms posiciona o veio no centro.

  • Um pulso de 2,0 ms move o veio para a outra extremidade.

Qualquer valor intermédio mapeia para uma posição intermédia.

Three rows of square-wave traces stacked vertically. Each row shows one 20 ms period of a 50 Hz PWM with a narrow high pulse at the start: 1.0 ms in the top row, 1.5 ms in the middle, 2.0 ms in the bottom.

O fotograma PWM do servo tem 20 ms de duração; a largura de pulso (1,0 – 2,0 ms) seleciona a posição.

Ao contrário dos LEDs e dos motores, o servo não integra o PWM. A largura de pulso em si é o comando: a lógica interna do servo mede cada pulso, define o seu objetivo em conformidade, e faz o motor rodar até a saída corresponder. O ciclo de trabalho como fração (entre 5 % e 10 % em toda a gama) é acessório – é a largura de pulso absoluta que importa, e é o que o software precisa de controlar.

3.16.2. Ligação elétrica

Os servos de uso amador usam um conector de três fios:

  • Alimentação (normalmente vermelho): a alimentação própria do servo, tipicamente 4,8 V a 6 V. Não alimente o servo com o nível de 3,3 V da câmara – ele não consegue fornecer a corrente de bloqueio, e o nível irá colapsar.

  • Massa (normalmente preto ou castanho): o caminho de retorno para a alimentação do servo, ligado à massa da câmara para que o sinal também tenha uma referência comum.

  • Sinal (normalmente branco, amarelo ou laranja): a linha PWM do GPIO da câmara.

3.16.3. Código

duty_u16() funcionaria, mas define o ciclo de trabalho como uma fração do período – pouco prático para um sinal onde a largura de pulso absoluta é o que importa e o período é fixo. duty_ns() define a largura de pulso diretamente em nanossegundos:

from machine import PWM, Pin

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

A portadora é 50 Hz (período de 20 ms); o tempo alto em cada ciclo é exatamente 1500 µs. Um pequeno auxiliar torna explícito o mapeamento de posição para pulso:

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

Uma varredura lenta por toda a gama:

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)

A gama de 1,0 – 2,0 ms é o padrão, mas muitos servos aceitam uma gama mais ampla (frequentemente 500 µs a 2500 µs) para excursão completa. A folha de dados do servo indica os limites exatos da largura de pulso; valores fora dessa gama podem forçar o motor contra os batentes mecânicos.

Para um servo com uma gama não padrão, eleve os limites para constantes e parametrize o mapeamento:

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)