Tutorial · Intermedio · 18 min di lettura
Controlla i servomotori con PCA9685 (driver PWM I²C)
Controlla più servomotori con un PCA9685 via I²C: imposta la frequenza PWM, calibra la larghezza d'impulso dagli angoli e alimentali in sicurezza.
Un microcontrollore dispone soltanto di pochi canali PWM hardware. Va bene per uno o due servomotori, ma un braccio robotico ne ha quattro, un esapodo ne ha diciotto e Arduino esaurisce i timer molto prima che tu esaurisca le articolazioni. Il PCA9685 risolve il problema: una piccola scheda genera sedici segnali PWM indipendenti in hardware e tu controlli tutti questi segnali mediante soltanto due cavi I²C. Ecco come azioni ogni articolazione del simulatore di braccio robotico su hardware reale.
Perché non collegare direttamente i servomotori all’Arduino?
Per due motivi. Primo, i pin: la scheda Uno dispone di timer sufficienti per pochi oggetti Servo prima che la libreria inizi a litigare con sé stessa. Secondo, e più importante, l’alimentazione: un servomotore può assorbire 500–700 mA quando è bloccato e quattro in movimento possono assorbire diversi ampere. Questa corrente non può provenire dal pin da 5 V dell’Arduino: causa il brown-out della scheda e la riavvia a metà movimento. Il PCA9685 risolve entrambi i problemi. Delega la generazione PWM a un chip dedicato e instrada la corrente dei servomotori dal proprio morsetto V+, tenendo la corrente elevata completamente lontana dalla logica.
Imposta la frequenza PWM
Ogni servomotore hobbistico prevede un segnale di controllo a 50 Hz, cioè un impulso ogni 20 ms. Il PCA9685 imposta una sola frequenza per tutto il chip, quindi impostala una volta in 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
}
Ora tutti e sedici i canali emettono impulsi a 50 Hz. L’angolo mantenuto da ciascun servomotore è determinato dalla larghezza del suo impulso, non dalla frequenza: questa è la parte che controlli per ogni canale.
Dall’angolo alla larghezza d’impulso: la taratura che conta
Un servomotore interpreta la larghezza dell’impulso come comando di posizione: circa 1 ms per 0°, 1.5 ms per il centro, 2 ms per 180°, ripetuto 50 volte al secondo. Questo è lo stesso codice che converte la larghezza dell’impulso in angolo usato dallo SG90; il PCA9685 si limita a generarlo in hardware.
Il PCA9685 non accetta direttamente i millisecondi. Divide ogni periodo di 20 ms in 4096 conteggi (risoluzione a 12 bit) e tu gli indichi per quanti conteggi l’impulso resta alto. A 50 Hz, un periodo completo è 4096 conteggi = 20 ms, quindi:
- 1 ms ≈ 205 conteggi (0°)
- 1.5 ms ≈ 307 conteggi (90°)
- 2 ms ≈ 410 conteggi (180°)
Questi sono i valori nominali. I servomotori reali variano: lo stesso SG90 potrebbe fermarsi a 130 e raggiungere 490. Questo è l’unico valore che devi tarare. Memorizza un minimo e un massimo per ogni servomotore e mappa il tuo angolo in questo intervallo:
// 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);
}
Saltare la taratura è il motivo per cui un comando di «90°» raggiunge 78° su un’articolazione e 96° su un’altra, e il motivo per cui un braccio costruito con servomotori non tarati non raggiunge mai esattamente la posa richiesta dal risolutore di cinematica inversa.
Cablaggio: due linee di alimentazione, una massa
- Logica —
VCC,GND,SDA,SCLdall’Arduino. Questo alimenta soltanto il chip. - Alimentazione dei servomotori — un’alimentazione separata da 5–6 V collegata al morsetto a vite V+, dimensionata per la corrente di stallo di tutti i servomotori contemporaneamente, non per il loro assorbimento a riposo.
- Massa comune — la massa dell’alimentazione e quella dell’Arduino devono essere collegate insieme, altrimenti il segnale PWM non ha riferimento e i servomotori si muovono a scatti oppure ignorano i comandi. Lo stesso vale per le linee I²C che trasportano i comandi.
Monta un condensatore tra V+ e massa per assorbire il picco di corrente all’avvio dei servomotori; la scheda di sviluppo PCA9685 dispone di un’esposizione predisposta esattamente a questo scopo.
Il codice: muovi un’articolazione
#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() {}
Ogni setPWM(channel, 0, count) significa «attiva questo canale all’inizio del periodo e disattivalo dopo count scatti temporali». Fai scorrere un’articolazione aumentando l’angolo in un anello e inserisci un breve delay() tra i passi, così il servomotore ha tempo di muoversi invece di spostarsi di scatto.
Inconvenienti
- Tarala
SERVO_MIN/SERVO_MAXper ogni servomotore. Comanda 0°, osserva dove si trova effettivamente il braccetto e modifica leggermente il conteggio finché non corrisponde. Ripeti a 180°. Dieci minuti qui ti risparmiano ogni problema di posa a valle. - Non alimentare mai V+ dall’Arduino. Un servomotore potrebbe sopravvivere; quattro causeranno il brown-out e il riavvio della scheda.
- Dimensiona l’alimentazione per lo stallo, non per il funzionamento a riposo. Un’alimentazione sottodimensionata cala di tensione quando più servomotori si muovono insieme e l’intera scheda vibra.
- Controlla l’indirizzo. L’indirizzo predefinito è
0x40. Collega i ponticelli di saldatura per concatenare le schede e passa il nuovo indirizzo al costruttore. - Muoviti con delicatezza. Avvicinarti a un obiettivo a incrementi è preferibile rispetto a spostarti su di esso di scatto: riduce il picco di corrente e fa risparmiare agli ingranaggi in plastica.
- Il canale della pinza è quello che si surriscalda. Ogni altra articolazione raggiunge il proprio angolo e resta a riposo; una pinza che trattiene un oggetto è un servomotore bloccato contro l’oggetto e assorbe continuamente circa mezzo ampere. Aprila appena hai posizionato il pezzo e consulta forza, stallo e cedevolezza del servomotore della pinza per capire perché una risoluzione PWM più fine non ti dà una forza più precisa.
Una volta che ogni articolazione risponde a un angolo, il braccio è pronto per la geometria: trasformare un punto di destinazione negli angoli delle articolazioni che lo raggiungono, che è esattamente ciò per cui servono la cinematica inversa di un braccio a due link e il simulatore di braccio robotico.
Esplora il grafo
Fa parte di queste costruzioni
Progetti e percorsi di apprendimento che includono questo tutorial.
Per approfondire