Component · Driver
PCA9685-servodriver
De PCA9685 bestuurt 16 servo's of PWM-uitgangen via I²C vanaf twee pinnen: standaard voor een robotarm of veel servo's, zonder de microcontroller te belasten.
Wat het is
De PCA9685 is een servoverbreider. Een microcontroller heeft maar een handvol hardware-PWM-kanalen, dus de zes servo’s van een robotarm aandrijven — laat staan de achttien van een hexapod — raakt je pinnen en timers snel op. Dit kleine bord neemt dat werk over: het genereert in hardware 16 onafhankelijke PWM-signalen, en je bestuurt ze allemaal via twee I²C-draden. Het is het bord achter de meeste robots met meerdere servo’s.
Hoe het werkt
Je praat met de PCA9685 via I²C—dezelfde twee pinnen (SCL/SDA) kunnen ook andere sensoren dragen. Je stelt voor de hele chip één PWM-frequentie in (50 Hz voor hobby-servo’s), en daarna de pulsbreedte van elk kanaal om de bijbehorende servo te positioneren. Omdat de chip alle 16 signalen in hardware vast houdt, stuurt de microcontroller alleen „kanaal 3 → 1,5 ms“ en gaat hij verder; hij hoeft de timing nooit zelf met bitbanging te doen. Zo blijft elke servo soepel, zelfs als alle 16 tegelijk bewegen. Het idee van pulsbreedte naar hoek staat uitgelegd op de pagina over de SG90-servo.
Wanneer je hem gebruikt
Kies een PCA9685 zodra een robot meer servo’s heeft dan de microcontroller PWM-pins heeft, of wanneer je de servo’s uiterst stabiel wilt laten werken:
- Robotarmen — meerdere gewrichtservo’s die tegelijk bewegen (combineer hem met inverse kinematica).
- Hexapoden / quadrupeden — genoeg servo’s voor een tiental poten.
- Pan-tilt- en camera-opstellingen — zo blijven de timers van de microcontroller vrij voor ander werk.
Voor één scanservo — zoals de ultrasone scanner op een obstakelvermijder — heb je hem niet nodig; de microcontroller kan één servo rechtstreeks aansturen.
Aansluiting en aandachtspunten
- Twee spanningsrails. Logica (VCC) vanaf de microcontroller; servovoeding vanaf de V+-aansluiting. Laat nooit de stroom van 16 servo’s door de 5 V van de Arduino lopen.
- Dimensioneer V+ op de vastloopstroom, niet op het verbruik in rust. Zestien servo’s kunnen samen meerdere ampères vragen; een te kleine voeding zakt in en het hele bord trilt.
- Stel unieke adressen in bij het doorkoppelen, via de soldeerjumpers.
- Plaats een condensator over V+ om stroompieken op te vangen wanneer servo’s gaan bewegen.
Pinindeling
Drie groepen verbindingen: een besturingsheader die je aan de microcontroller aansluit, zestien servo-headers en een voedingsaansluiting die je niet met de eerste mag verwarren.
| Groep | Pin | Functie |
|---|---|---|
| Besturing | VCC | Alleen logische voeding, 3,3 V of 5 V vanaf de microcontroller. Niet de voeding voor de servo’s |
| Besturing | GND | Ground — moet gemeenschappelijk zijn met zowel de microcontroller als de servovoeding |
| Besturing | SCL | I²C-klok |
| Besturing | SDA | I²C-data |
| Besturing | OE | Uitgangen inschakelen, actief laag. Als de pin zweeft, wordt hij laag getrokken en zijn de uitgangen ingeschakeld |
| Voeding | V+ (schroefaansluiting) | Servostroom. Tot 6 V op de gangbare breakout |
| Uitgangen | 0–15 | Per kanaal drie pinnen: PWM-signaal, V+, GND — standaardvolgorde voor servo’s |
| Adres | A0–A5 (soldeerpads) | Zes jumpers stellen het I²C-adres in, standaard 0x40 |
Het belangrijkste feit op dit bord is dat VCC en V+ verschillende rails zijn. VCC voedt de chip; V+ voedt de servo’s. Als je ze overbrugt, loopt de vastloopstroom van de servo’s door de regulator van de microcontroller. Daardoor zakt de spanning op de Arduino het snelst in en krijg je een brown-out.
Aansluiten op een Arduino
| PCA9685 | Arduino Uno | ESP32 | Opmerking |
|---|---|---|---|
| VCC | 5 V | 3,3 V | Een paar milliampères — alleen logica |
| GND | GND | GND | Ook gemeenschappelijk met de ground van de servovoeding |
| SDA | A4 | GPIO 21 | Op het bord zitten al 10 kΩ pull-ups |
| SCL | A5 | GPIO 22 | Hetzelfde |
| V+ | niet de Arduino | niet de ESP32 | Een aparte 5–6 V-voeding, gedimensioneerd op de vastloopstroom |
| OE | Open laten | Open laten | Of bestuur hem vanaf een pin om alle uitgangen tegelijk uit te schakelen |
OE is nuttiger dan het lijkt. Hoog trekken schakelt alle zestien uitgangen direct in hardware uit, zonder I²C-transactie. Bij een arm die door de zwaartekracht kan vallen is dat een echte noodstop, en het werkt zelfs als je code vastloopt.
De servovoeding dimensioneren
Hier gaan de meeste PCA9685-projecten mis, en de rekenkunde is niet moeilijk.
Een hobby-servo gebruikt ongeveer:
| Servo | In rust | In beweging, onbelast | Vastgelopen |
|---|---|---|---|
| SG90 (9 g) | ~10 mA | ~150–250 mA | ~650 mA |
| MG90S (metalen tandwielen) | ~10 mA | ~250–400 mA | ~800 mA |
| MG996R (standaard) | ~10 mA | ~500–900 mA | ~2,5 A |
Vier SG90’s op een kleine arm die allemaal tegelijk bewegen, vragen ruim 1 A en kunnen samen pieken op bijna 2,6 A als ze allemaal tegelijk vastlopen — en dat is precies wat er gebeurt wanneer de arm zijn eigen frame raakt. Een telefoonlader van 1 A is dus niet genoeg. Dimensioneer voor al je servo’s die tegelijk vastlopen, of minimaal voor allemaal in beweging plus één die vastloopt.
Het symptoom van een te kleine voeding is kenmerkend en verwarrend: de servo’s trillen, het bord kan herstarten en het lijkt op een I²C- of codeprobleem. Dat is het niet. Zet een multimeter op V+ terwijl de arm beweegt en bekijk de spanningsdaling.
Plaats een condensator over V+. Iets in het bereik 470–1000 µF, dicht bij de aansluiting. Hij kan geen langdurige vastloopstroom leveren — een condensator van 1000 µF die 1 A levert, verliest elke milliseconde een volt — maar vangt wel de scherpe stroompiek op het moment dat een servo start, en dat is wat de logica-rail beïnvloedt.
Hoe de PWM werkelijk wordt gegenereerd
Als je deze twee getallen begrijpt, wordt elk probleem met een servodriver makkelijker te diagnosticeren.
De chip draait op een interne 25 MHz-oscillator en deelt die met een prescaler:
prescale = round(25000000 / (4096 x frequency)) - 1
Voor de 50 Hz die hobby-servo’s gebruiken is dat round(25000000 / 204800) - 1 = 121.
Elke periode wordt vervolgens verdeeld in 4096 stappen (12 bits). Bij 50 Hz is de periode 20 ms, dus één stap is 20 ms / 4096 = 4.88 µs. Zo zet je de pulsbreedtes die je werkelijk nodig hebt om in de tellingen die je schrijft:
| Pulsbreedte | Betekenis | Tellingen bij 50 Hz |
|---|---|---|
| 1,0 ms | Eén uiteinde van de slag | 205 |
| 1,5 ms | Midden | 307 |
| 2,0 ms | Het andere uiteinde | 410 |
Daaruit volgen twee dingen. Ten eerste krijg je ongeveer 205 tellingen over de volledige 180° van een servo, dus iets minder dan één telling per graad — de 12-bits resolutie van de PCA9685 is niet de beperkende factor bij een hobby-servo, maar de eigen dode zone van de servo wel. Ten tweede kan de prescaler alleen worden geschreven wanneer de chip in slaapstand staat, en daarom schakelt elke bibliotheek MODE1 om bij een frequentiewijziging.
De oscillator is niet exact 25 MHz
Echte borden wijken een paar procent af van de nominale waarde, en dat is voor elk bord consistent. Als je servo’s aan beide uiteinden systematisch minder ver komen dan de opgegeven hoek, los je dat niet op door de pulsbreedtes bij te schuiven — meet en corrigeer de klok:
pwm.begin();
pwm.setOscillatorFrequency(26075000); // measured, not the 25 MHz nominal
pwm.setPWMFreq(50);
Meet dat door 50 Hz op te geven, een oscilloscoop of logische analyser op een uitgang te zetten en de werkelijke periode af te lezen. Schaal de nominale 25 MHz met de verhouding van opgegeven tot gemeten frequentie. Doe dit één keer per bord en schrijf het getal in een commentaar.
Minimaal werkende code
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
// Per-servo calibration. These are NOT universal — measure your own.
const int SERVO_MIN = 150; // counts at one end stop
const int SERVO_MAX = 600; // counts at the other
int countsFor(int degrees) {
return map(constrain(degrees, 0, 180), 0, 180, SERVO_MIN, SERVO_MAX);
}
void setup() {
pwm.begin();
pwm.setOscillatorFrequency(25000000); // replace with your measured value
pwm.setPWMFreq(50); // hobby servos want 50 Hz
delay(10);
}
void loop() {
for (int a = 0; a <= 180; a += 5) { // sweep, don't jump
pwm.setPWM(0, 0, countsFor(a));
delay(20);
}
for (int a = 180; a >= 0; a -= 5) {
pwm.setPWM(0, 0, countsFor(a));
delay(20);
}
}
De constanten SERVO_MIN en SERVO_MAX zijn de kalibratie, en ze verschillen per servo — zelfs tussen twee servo’s van hetzelfde model uit dezelfde zak. Vind ze door langzaam vanuit 307 naar buiten te stappen en te stoppen zodra de servo zoemt zonder te bewegen. Dat betekent dat hij tegen zijn eigen eindstop duwt en voor niets vastloopstroom trekt.
Let ook op de doorloop in plaats van een sprong. setPWM verandert de opgegeven positie meteen, en de servo zal die met volle snelheid proberen te bereiken — bij een arm betekent dat een heftige beweging en een stroompiek. De commando’s in stappen zetten is het eenvoudige bewegingsprofiel, en dat is de moeite waard, zelfs in testcode.
Borden aan elkaar koppelen
Elk bord heeft zes soldeerpads, A0 tot A5, waarmee je vanaf 0x40 64 adressen krijgt. Overbrug op elk bord een andere combinatie:
| Overbrugde jumpers | Adres |
|---|---|
| geen | 0x40 |
| A0 | 0x41 |
| A1 | 0x42 |
| A0 + A1 | 0x43 |
| A5 | 0x60 |
Het gedocumenteerde maximum is 62 borden: 0x70 is gereserveerd voor het algemene I²C-oproepadres, dus 64 borden zijn niet mogelijk. In de praktijk is 62 borden al 992 servo’s; de benodigde voeding is een veel groter technisch probleem dan de bus.
Eén ding om in de gaten te houden bij het koppelen: elk bord heeft zijn eigen 10 kΩ I²C-pull-ups, en die staan parallel. Tien borden geven 1 kΩ, wat al zwaar is voor een 5 V-bus. Bij meer dan een handvol borden knip je de pull-upjumpers op alle borden behalve één door.
Problemen oplossen
| Klacht | Waarschijnlijke oorzaak | Oplossing |
|---|---|---|
| Er beweegt helemaal niets | Geen servovoeding op V+ | V+ is een aparte rail; VCC voedt alleen de chip |
| Servo’s trillen voortdurend | Voeding zakt in onder belasting | Dimensioneer V+ op de vastloopstroom; plaats een condensator van 470–1000 µF |
| Servo’s trillen alleen als meerdere tegelijk bewegen | Hetzelfde, maar net op de grens | Doe hetzelfde — meet V+ met een meter tijdens het bewegen |
| Eén servo zoemt en wordt heet | Opgegeven voorbij zijn eindstop | Versmal de SERVO_MIN/SERVO_MAX van dat kanaal |
| Alle hoeken zijn consequent te klein | Oscillator is niet exact 25 MHz | Meet de werkelijke uitgangsfrequentie en roep setOscillatorFrequency aan |
| Bord niet gevonden op de bus | Verkeerd adres of geen logische voeding | Doorzoek de bus; controleer VCC en of de adresjumpers overeenkomen met je code |
| Twee borden, slechts één reageert | Beide op standaard 0x40 |
Overbrug adresjumpers zodat elk bord uniek is |
| Arduino herstart wanneer de arm beweegt | Servostroom loopt via het bord | V+ moet uit een eigen voeding komen, met alleen de ground gemeenschappelijk |
| Uitgangen dood terwijl I²C wel werkt | OE hoog vastgehouden |
Laat OE zweven of stuur hem laag |
PCA9685 of directe PWM van de microcontroller?
| Directe PWM-pins | PCA9685 | |
|---|---|---|
| Kanalen | 6 op een Uno, en de Servo-bibliotheek neemt een timer |
16 per bord, 62 borden op één bus |
| Gebruikte pinnen | Eén per servo | Twee in totaal voor allemaal |
| Timing | Gegenereerd door de microcontroller — trilt wanneer de lus bezet is | In hardware gegenereerd — stabiel ongeacht je code |
| Stroompad | Wat je ook aansluit, vaak verkeerd | Een eigen V+-aansluiting die het juiste antwoord duidelijk maakt |
| Extra kosten | Geen | Een paar dollar, plus een I²C-adres |
Het praktische omslagpunt: één of twee servo’s, bestuur ze rechtstreeks. Een sensorscankop op een obstakelvermijder heeft dit bord niet nodig. Drie of meer, of een servo waarvan de soepelheid belangrijk is, en de PCA9685 is zijn meerprijs meteen waard — niet vanwege het aantal pinnen, maar omdat de microcontroller niet langer verantwoordelijk is voor de timing. Een servo die door de Servo-bibliotheek wordt bestuurd, schokt zodra je lus blijft hangen; een servo die door een PCA9685 wordt bestuurd niet.
Verken de graaf
Gebruikt in deze bouwprojecten
Projecten, leerroutes en simulators waarin de PCA9685-servodriver voorkomt.
Vragen
FAQ over de PCA9685-servodriver
Wat is een PCA9685?
De PCA9685 is een 16-kanaals, 12-bits PWM-driver die je via I²C bestuurt. Hij wordt meestal als servodriver gebruikt—één klein bord bestuurt maximaal 16 servo's vanaf slechts twee microcontrollerpinnen. Daarom is dit de standaardkeuze voor robotarmen, hexapoden en pan-tiltopstellingen.
Hoeveel servo's kan een PCA9685 aansturen?
16 per bord, en je kunt tot 62 borden op één I²C-bus doorkoppelen voor 992 kanalen. De praktische grens is stroom, niet het aantal kanalen—16 servo's die tegelijk bewegen kunnen meerdere ampères vragen, en die moeten vanaf de afzonderlijke V+-aansluiting komen, niet vanaf de microcontroller.
Heeft de PCA9685 een aparte voeding nodig?
Ja, voor de servo's. De logica van de chip werkt op 3,3–5 V vanaf de microcontroller, maar de servo's halen hun stroom vanaf de aparte V+-aansluiting—verbind die met een voeding die de vastloopstroom van al je servo's tegelijk kan leveren, anders krijgen ze een brown-out en trillen ze.
Hoe sluit je een PCA9685 aan op een Arduino?
Sluit hem aan via I²C—SDA en SCL op de I²C-pins van de Arduino, plus VCC en GND voor de logische voeding van de chip. Verbind daarna een aparte voeding met de V+-aansluiting voor de servo's en steek elke servo in een kanaalheader. Een bibliotheek (zoals die van Adafruit) laat je in code de hoek van elk kanaal instellen.
Hoe koppel je PCA9685-borden aan elkaar?
Elk bord heeft zes soldeerjumpers die het I²C-adres instellen. Overbrug op elk bord een andere combinatie, zodat elk bord een uniek adres heeft, en verbind ze daarna allemaal met dezelfde twee I²C-lijnen—tot 62 borden en 992 kanalen op één bus.
Verder lezen