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.
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.
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,SDAeSCLdo 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_MAXpor 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.
- ProjetoConstrua um braço robótico de 4 DOF: PCA9685, servos e cinemática
- ProjetoConstrua um robô de coleta e colocação que sabe quando falhou
- Caminho de aprendizagemCinemática de braços robóticos: do PWM à cinemática inversa
- Caminho de aprendizagemPreensão e efetuadores finais: como realmente pegar o objeto
Leitura complementar