Tutorial · Intermediário · 18 min de leitura

Acione servos com o PCA9685 (driver PWM I²C)

Acione muitos servos com PCA9685 via I²C: defina a frequência PWM, calibre a largura de pulso e alimente os servos com segurança.

Um microcontrolador tem apenas alguns canais de PWM por hardware. Isso basta para um ou dois servos, mas um braço robótico tem quatro, um hexápode tem dezoito, e o Arduino fica sem temporizadores muito antes de você ficar sem juntas. O PCA9685 resolve isso: uma pequena placa gera dezesseis sinais PWM independentes em hardware, e você comanda todos eles por apenas dois fios de I²C. É assim que se aciona todas as juntas do simulador de braço robótico em circuitos reais.

Diagrama rotulado de uma placa de driver PWM/servo PCA9685 de 16 canais: dezesseis cabeçalhos de servo de três pinos ao longo da parte superior, o chip PCA9685 no centro, um cabeçalho de controle I²C de cinco pinos à esquerda, jumpers de solda para configuração de endereço e um terminal de parafusos V+ à direita para a alimentação dos servos.
Dezesseis canais PWM dedicados, comandados por dois pinos I²C; a corrente dos servos vem do terminal V+ separado, nunca do microcontrolador. Baixar SVG

Por que não ligar os servos diretamente ao Arduino?

Dois motivos. Primeiro, os pinos: o Uno tem temporizadores suficientes para alguns objetos Servo antes de a biblioteca começar a lutar consigo mesma. Segundo, e mais importante, a alimentação: um servo pode consumir 500–700 mA quando trava, e quatro se movendo ao mesmo tempo podem consumir vários ampères. Essa corrente não pode vir do pino de 5 V do Arduino — ela causa queda de tensão na placa e a reinicia no meio do movimento. O PCA9685 resolve os dois problemas. Ele transfere a geração do PWM para um chip dedicado e encaminha a corrente dos servos de seu próprio terminal V+, mantendo as correntes elevadas completamente longe da sua lógica.

Defina a frequência PWM

Todo servo de hobby espera um sinal de controle de 50 Hz — um pulso a cada 20 ms. O PCA9685 define uma frequência para o chip inteiro, portanto você a define uma vez em setup():

#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);  // default I²C address

void setup() {
  pwm.begin();
  pwm.setPWMFreq(50);   // 50 Hz — the standard servo refresh rate
}

Agora todos os dezesseis canais pulsam a 50 Hz. O ângulo que cada servo mantém é definido pela largura de seu pulso, não pela frequência — essa é a parte que você controla por canal.

Ângulo para largura de pulso — a calibração essencial

Um servo lê a largura do pulso como um comando de posição: aproximadamente 1 ms para 0°, 1,5 ms para o centro, 2 ms para 180°, repetidos 50 vezes por segundo. Este é o mesmo mapeamento de largura de pulso para ângulo que o SG90 usa; o PCA9685 apenas o gera no hardware.

Diagrama de controle de servo: um sinal PWM de 50 Hz cuja largura de pulso define o ângulo do servo. Um pulso de 1 milissegundo comanda 0 graus, 1,5 milissegundos comanda 90 graus e 2 milissegundos comanda 180 graus, mostrados em mostradores de transferidor.
O servo lê a largura do pulso, não a tensão: 1 ms é 0°, 1,5 ms é o centro e 2 ms é todo o curso — repetidos 50 vezes por segundo. Baixar SVG

O PCA9685 não recebe milissegundos diretamente. Ele divide cada período de 20 ms em 4096 contagens (resolução de 12 bits), e você informa quantas contagens o pulso permanece alto. A 50 Hz, um período completo tem 4096 contagens = 20 ms, portanto:

  • 1 ms ≈ 205 contagens (0°)
  • 1,5 ms ≈ 307 contagens (90°)
  • 2 ms ≈ 410 contagens (180°)

Esses são os números nominais. Servos reais variam — o mesmo SG90 pode chegar a 130 no mínimo e 490 no máximo. Estes são os valores que você deve calibrar. Armazene um mínimo e um máximo por servo e mapeie seu ângulo para essa faixa:

// Calibrate these two per servo by eye — see "Gotchas" below.
const int SERVO_MIN = 130;   // counts at the servo's 0° hard stop
const int SERVO_MAX = 490;   // counts at the servo's 180° hard stop

int angleToCount(int deg) {
  return map(deg, 0, 180, SERVO_MIN, SERVO_MAX);
}

Pular a calibração é a razão de um comando de “90°” terminar em 78° em uma junta e 96° em outra — e por que um braço construído com servos não calibrados nunca chega exatamente à postura que o solucionador de cinemática inversa solicitou.

Ligação: dois trilhos de alimentação, uma massa

  • Lógica — VCC, GND, SDA e SCL do Arduino. Isso alimenta apenas o chip.
  • Alimentação dos servos — uma fonte separada de 5–6 V para o terminal de parafusos V+, dimensionada para a corrente de travamento de todos os servos ao mesmo tempo, não para o consumo ocioso.
  • Massa comum — a massa da fonte e a massa do Arduino precisam ser ligadas, ou o sinal PWM não terá referência e os servos tremerão ou ignorarão você. O mesmo vale para as linhas I²C que transportam os comandos.

Adicione um capacitor entre V+ e a massa para absorver o pico de corrente quando os servos começarem a se mover; a placa adaptadora PCA9685 tem uma área exatamente para isso.

O código: movendo uma junta

#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

const int SERVO_MIN = 130;
const int SERVO_MAX = 490;

int angleToCount(int deg) {
  return map(deg, 0, 180, SERVO_MIN, SERVO_MAX);
}

void setServo(uint8_t channel, int deg) {
  pwm.setPWM(channel, 0, angleToCount(deg));  // on at count 0, off at the angle count
}

void setup() {
  pwm.begin();
  pwm.setPWMFreq(50);
  setServo(0, 90);   // base to centre
  setServo(1, 45);   // shoulder
  setServo(2, 120);  // elbow
  setServo(3, 10);   // gripper open
}

void loop() {}

Cada setPWM(channel, 0, count) significa “ligue este canal no início do período e desligue-o após count contagens”. Mova uma junta em passos, incrementando o ângulo dentro de um laço e usando um pequeno delay() entre os passos, para que o servo tenha tempo de se mover em vez de saltar.

Armadilhas

  • Calibre SERVO_MIN / SERVO_MAX por servo. Comande 0°, observe onde o braço do servo realmente fica e ajuste a contagem até ela corresponder. Faça o mesmo em 180°. Dez minutos aqui economizam cada postura posterior.
  • Nunca alimente o V+ pelo Arduino. Um servo pode sobreviver; quatro causarão queda de tensão e reiniciarão a placa.
  • Dimensione a fonte para o travamento, não para o repouso. Uma fonte subdimensionada sofre queda quando vários servos se movem juntos, e a placa inteira fica instável.
  • Verifique o endereço. O padrão é 0x40. Ligue os jumpers de solda para encadear placas e passe o novo endereço ao construtor.
  • Mova suavemente. Chegar a um alvo em passos é melhor do que saltar para ele — reduz o pico de corrente e é mais gentil com as engrenagens de plástico.
  • O canal da garra é o que mais aquece. Todas as outras juntas alcançam seu ângulo e ficam ociosas; uma garra segurando um objeto é um servo travado contra ele, consumindo cerca de meio ampere continuamente. Abra-a assim que colocar a peça e veja força, travamento e complacência da garra para entender por que uma resolução PWM mais fina não proporciona um controle mais fino da força.

Depois que cada junta responder a um ângulo, o braço está pronto para a geometria: transformar um ponto-alvo nos ângulos das juntas que o alcançam, que é exatamente para que servem a cinemática inversa de um braço de dois elos e o simulador de braço robótico.

Explore o grafo

Faz parte destas montagens

Projetos e caminhos de aprendizagem que incluem este tutorial.

Leitura complementar

Referências