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.

Gelabeld diagram van een PCA9685 16-kanaals PWM-/servodriverbord: langs de bovenzijde een rij van zestien driepins servo-headers (PWM, V+, GND) in een zwarte behuizing, in het midden de PCA9685-chip en passieve componenten, links een vijfpins I²C-besturingsheader (OE, SCL, SDA, GND, VCC), adresjumpers en rechts een V+-schroefaansluiting voor de servovoeding.
Zestien PWM-kanalen in hardware, bestuurd via twee I²C-pinnen; de servostroom komt van de afzonderlijke V+-aansluiting en niet van de microcontroller. SVG downloaden

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

Bronnen