Tutorial · Intermedio · 18 min de lectura
Controla servos con el PCA9685 (driver PWM por I2C)
Cómo controlar muchos servos con un PCA9685 por I2C: ajusta la frecuencia PWM, convierte un ángulo en un pulso calibrado y alimenta los servos con seguridad.
Un microcontrolador solo tiene un puñado de canales PWM por hardware. Eso basta para uno o dos servos, pero un brazo robótico tiene cuatro, un hexápodo tiene dieciocho, y el Arduino se queda sin temporizadores mucho antes de que te quedes sin articulaciones. El PCA9685 lo resuelve: una placa pequeña genera dieciséis señales PWM independientes por hardware, y las mandas todas por solo dos cables I2C. Así es como controlas cada articulación del simulador de brazo robótico en hardware real.
¿Por qué no cablear los servos directamente al Arduino?
Dos razones. La primera, los pines: el Uno tiene temporizadores suficientes para unos pocos objetos Servo antes de que la librería empiece a pelearse consigo misma. La segunda, y más importante, la alimentación: un servo puede consumir 500-700 mA cuando se bloquea, y cuatro moviéndose a la vez pueden demandar varios amperios. Esa corriente no puede salir del pin de 5 V del Arduino: hunde la placa y la reinicia a mitad de movimiento. El PCA9685 arregla ambas cosas. Descarga la generación de PWM en un chip dedicado y encamina la corriente de los servos desde su propio borne V+, manteniendo la corriente alta por completo lejos de tu lógica.
Ajusta la frecuencia PWM
Todo servo de aficionado espera una señal de control de 50 Hz, un pulso cada 20 ms. El PCA9685 fija una frecuencia para todo el chip, así que la ajustas una vez en setup():
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40); // direccion I2C por defecto
void setup() {
pwm.begin();
pwm.setPWMFreq(50); // 50 Hz: la frecuencia de refresco estandar de los servos
}
Los dieciséis canales pulsan ahora a 50 Hz. El ángulo que mantiene cada servo lo fija la anchura de su pulso, no la frecuencia: esa es la parte que controlas canal por canal.
De ángulo a anchura de pulso: la calibración que importa
Un servo lee la anchura del pulso como una orden de posición: aproximadamente 1 ms para 0°, 1,5 ms para el centro y 2 ms para 180°, repetido cincuenta veces por segundo. Es el mismo código de anchura de pulso como ángulo que usa el SG90; el PCA9685 solo lo genera por hardware.
El PCA9685 no acepta milisegundos directamente. Divide cada periodo de 20 ms en 4096 cuentas (resolución de 12 bits) y tú le dices cuántas cuentas permanece alto el pulso. A 50 Hz, un periodo completo son 4096 cuentas = 20 ms, así que:
- 1 ms ≈ 205 cuentas (0°)
- 1,5 ms ≈ 307 cuentas (90°)
- 2 ms ≈ 410 cuentas (180°)
Esos son los números nominales. Los servos reales varían: el mismo SG90 puede tocar fondo en 130 y llegar al tope en 490. Este es el número que debes calibrar. Guarda un mínimo y un máximo por servo y mapea tu ángulo a ese rango:
// Calibra estos dos valores por servo a ojo: mira "Trampas" mas abajo.
const int SERVO_MIN = 130; // cuentas en el tope mecanico de 0° del servo
const int SERVO_MAX = 490; // cuentas en el tope mecanico de 180° del servo
int angleToCount(int deg) {
return map(deg, 0, 180, SERVO_MIN, SERVO_MAX);
}
Saltarse la calibración es la razón de que una orden de “90°” acabe en 78° en una articulación y en 96° en otra, y de que un brazo construido con servos sin calibrar nunca alcance del todo la pose que pidió el solucionador de cinemática inversa.
Cableado: dos rieles de alimentación, una masa
- Lógica:
VCC,GND,SDAySCLdesde el Arduino. Esto alimenta solo al chip. - Alimentación de los servos: una fuente independiente de 5-6 V al borne de tornillo V+, dimensionada para la corriente de bloqueo de todos los servos a la vez, no para su consumo en reposo.
- Masa común: la masa de la fuente y la del Arduino deben estar unidas, o la señal PWM no tendrá referencia y los servos temblarán o te ignorarán. Lo mismo se aplica a las líneas I2C que llevan las órdenes.
Añade un condensador en V+ para absorber el pico de corriente cuando los servos empiezan a moverse; la placa del PCA9685 tiene un hueco reservado justo para eso.
El código: mover una articulación
#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)); // encendido en la cuenta 0, apagado en la cuenta del angulo
}
void setup() {
pwm.begin();
pwm.setPWMFreq(50);
setServo(0, 90); // base al centro
setServo(1, 45); // hombro
setServo(2, 120); // codo
setServo(3, 10); // pinza abierta
}
void loop() {}
Cada setPWM(channel, 0, count) dice “enciende este canal al principio del periodo y apágalo tras count cuentas”. Barre una articulación incrementando el ángulo en un bucle con un delay() corto entre pasos, para que el servo tenga tiempo de moverse en lugar de saltar de golpe.
Trampas
- Calibra
SERVO_MIN/SERVO_MAXpor servo. Ordena 0°, anota dónde queda realmente el brazo y ajusta la cuenta hasta que coincida. Haz lo mismo a 180°. Diez minutos aquí ahorran todas las poses posteriores. - Nunca alimentes V+ desde el Arduino. Un servo puede sobrevivir a ello; cuatro hundirán la placa y la reiniciarán.
- Dimensiona la fuente para el bloqueo, no para el reposo. Una fuente escasa se hunde cuando varios servos se mueven juntos y toda la placa tiembla.
- Comprueba la dirección. La de fábrica es
0x40. Puentea los puentes de soldadura para encadenar placas y pasa la nueva dirección al constructor. - Mueve con suavidad. Ir paso a paso hacia un objetivo es mejor que saltar a él: reduce el pico de corriente y es más amable con los engranajes de plástico.
- El canal de la pinza es el que se cocina. Cualquier otra articulación alcanza su ángulo y se queda en reposo; una pinza que sujeta un objeto es un servo bloqueado contra él, consumiendo medio amperio de forma continua. Ábrela en el momento en que dejes la pieza y consulta fuerza, bloqueo y flexibilidad en pinzas con servo para entender por qué una resolución PWM más fina no te compra una fuerza más fina.
Cuando cada articulación responda a un ángulo, el brazo está listo para la geometría: convertir un punto objetivo en los ángulos articulares que lo alcanzan, que es exactamente para lo que sirven la cinemática inversa de un brazo de dos eslabones y el simulador de brazo robótico.
Explora el grafo
Forma parte de estos montajes
Proyectos y rutas de aprendizaje que incluyen este tutorial.
Lecturas adicionales