Usando um Servomotor com a Raspberry Pi Pico Deixe um comentário

O servomotor é um tipo de motor bastante utilizado em aplicações de microcontrolador. Vamos ver neste artigo como conectá-lo e controlá-lo com uma Raspberry Pi Pico.

Introdução

O servomotor é um motor cuja posição do eixo pode ser controlada através de um sinal elétrico.Isto pode ser visto prendendo um ponteiro neste eixo, o que vamos controlar é o ângulo deste ponteiro em relação a uma referência.

Os servomotores normalmente usados pelos makers são capazes de variar a posição em cerca de 180 graus (meia volta). O sinal de controle é um conjunto de pulsos com intervalo de aproximadamente 20 ms (50 Hz); a largura (duração) do pulso determina o ângulo.Os valores nominais são 1ms para posicionar o eixo em um extremo e 2ms para posicionar no outro, mas existe grande variação de um servo para outro (no meu servo obtive 180 graus com os valores 0.54 e 2.44 ms).

Atenção que o servo demora um certo tempo até atingir a posição (a especificação fala em 0,3s para ir de um extremo ao outro). Se você comandar outra posição antes dele atingir a anterior, ele passará imediatamente a se dirigir à nova posição. Se você parar os pulsos antes dele atingir a posição, ele parará onde estiver.

Material Utilizado

Para reproduzir o exemplo que vamos montar você vai precisar de:

Preparação da Raspberry Pi Pico

O software que vamos usar será escrito em MicroPyhon e executado na placa através da IDE Thonny. Para instalar o MicroPython na placa e a IDE Thonny no seu micro siga os passos detalhados neste artigo.

Ligando o Servomotor à Raspberry Pi Pico

O micro servo que vamos usar tem um conector fêmea de três pinos, a cor do fio indica a sua função:

  • marrom: terra (negativo da alimentação e referência para o sinal de controle)
  • vermelho: positivo da alimentação
  • laranja: sinal de controle

O servo necessita de uma alimentação de 5V, porém aceita um sinal de controle de 3,3V. Na nossa montagem a alimentação vai ser obtida do conector USB da Pi Pico (Vbus) e o sinal de controle será ligado diretamente a um pino de GPIO.

O Software

Para gerar os pulsos vamos usar o recurso de PWM (pulse width modulation). A versão do MicroPython para a Pi Pico possui uma classe para controlar o PWM, vamos usar no nosso código os seguintes métodos:

servo = PWM(Pin(pino))     # Constrói um objeto PWM
                           # para controlar o pino ‘pino’
servo.freq(50)             # configura uma frequência de 50Hz
servo.duty_u16(val)        # configura o duty cycle para val/65535

Este último método merece um pouco mais de detalhe. Para gerar um pulso de PWM a Raspberry Pi Pico utiliza um contador de 16 bits, dividindo o período em 65535. O valor definido através de duty_u16(val) indica por quantas contagens o sinal vai ficar alto. Um valor de 0 faz com que o sinal fique sempre baixo e um valor de 65535 faz com o sinal fique sempre alto. No nosso caso o período será 20 ms portanto cada contagem corresponde a 20/65535 ms (aproximadamente 0,3 microsegundos).

Para simplificar o código, fiz uma classe Servo que internamente usa a classe PWM (veja o código abaixo).

O programa que eu escrevi tem duas partes:

  • Controle manual e calibração: usando o console do Thonny você pode digitar uma largura de pulso (entre 0.5 e 2.5 ms) e observar a movimentação do eixo. Se o valor for muito alto ou muito baixo, você perceberá que a movimentação do eixo é limitada internamente (não force muito o motor e as engrenagens para não danificar o servo). Digitando A, o último valor digitado será considerado como o valor para 0 graus. Digitando Z, o último valor será considerado o valor para 180 graus.
  • Controle automático: digitando G o programa passará a mover continuamente o eixo entre o mínimo e o máximo.

Segue abaixo o programa completo:

from machine import Pin
from machine import PWM
from time import sleep

# Classe para controle de servomotor
class Servo:

    # Iniciação
    def __init__(self, pino):
        self.FREQ = 50
        self.pwm = PWM (Pin(pino))
        self.pwm.freq(self.FREQ)
        self.ultpos = 0
        self.duty = 0
        self.pwm.duty_u16(0)
        self.min = 1
        self.max = 2

    # Envia n pulsos com tempo t em ms
    def enviaPulsos(self, t, nPulsos=20):
        self.duty = int(t*65.535*self.FREQ)
        self.pwm.duty_u16(self.duty)
        sleep (nPulsos/self.FREQ)
        self.pwm.duty_u16(0)
        #print ("-> "+str(t)+" "+str(self.duty))
        
    # Informa/Muda posição
    # angulo deve estar entre 0 e 180 graus
    def pos(self, ang = None):
        if ang is None:
            return self.ultpos
        elif (ang >= 0) or (ang <= 180):
                self.ultpos = ang
                t = self.min + (180 - ang)*(self.max-self.min)/180
                self.enviaPulsos(t)
                
    # Informa/muda tempo (em ms) para colocar na posição 180 graus
    def tempoFim (self, val = None):
        if (val == None):
            return self.min
        else:
            self.min = val

    # Informa/muda tempo (em ms) para colocar na posição 0 graus
    def tempoInicio(self, val = None):
        if (val == None):
            return self.max
        else:
            self.max = val
            
print ('Demonstração do controle de servomotor')
print ('* Entre com um valor entre 0.5 e 2.5 para posicionar')
print ('* A para definir o tempo para 0 graus')
print ('* Z para definir o tempo para 180 graus')
print ('* G para mover automaticamente')
servo = Servo(0)
tempo = 0.0
while True:
    val = input('Comando: ')
    if ((val == 'A') or (val == 'a')) and (tempo != 0.0) and \
       (tempo > servo.tempoFim()):
        servo.tempoInicio(tempo)
        print ('Novo tempo para 0 graus: '+str(tempo))
    elif ((val == 'Z') or (val == 'z')) and (tempo != 0.0) and \
       (tempo < servo.tempoInicio()):
        servo.tempoFim(tempo)
        print ('Novo tempo para 180 graus: '+str(tempo))
    elif ((val == 'G') or (val == 'g')):
        break
    else:
        try:
            tempo = float(val)
            if (tempo >= 0.5) and (tempo <= 2.5):
                servo.enviaPulsos(tempo)
            else:
                print ('Tempo precisa estar entre 0.5 e 2.5')
        except:
            print('Valor inválido')
print ('Entrando em modo automático')
while True:
    for angulo in range(0, 180, 10):
        servo.pos(angulo)
    for angulo in range(180, 0, -10):
        servo.pos(angulo)

Conclusão

O vídeo abaixo mostra o programa em funcionamento com o controle automático:

YouTube video

Neste artigo aprendemos um pouco sobre os servomotores e vimos como controlar um usando a Raspberry Pi Pico. Conte para gente nos comentários se gostou do artigo e quais os seus planos para usar um servomotor com uma Pi Pico.

Faça seu comentário

Acesse sua conta e participe