PCA9685 12 Bit PWM Controller

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

Hinweis kann nach Kenntnisnahme deaktiviert werden!

  • Der PCA9685 ist ein 16Kanal I2C PWM Controller mit 12 Bit Auflösung, geeignet für LED und oft auch für Servo Ansteuerung benutzt da das Servo Signal an sich ja nichts anderes als ein PWM Signal ist.
    Ein Blick ins Datenblatt wird noch mehr Features als meine Beispiele hier zeigen. Auch sind die eingestellten Werte eher als grober Startwert zu sehen, z.b. ist der Oszillator nicht der genaueste, ich benötige z.b. den Vorteiler von 133 um auf 50 Hz zu kommen um mein Servo hat auch einen wesentlich grösseren Verstellbereich als 2ms. Man kann den IC aber auch mit maximal 50MHz externem Signal genauer und/oder schneller machen.
    Manche Servos funktionieren auch mit 100Hz wiederholrate ohne Probleme, dann hat man meinen Verstellbereich nochmals verdoppelt und erreicht noch mehr Auflösung bzw. Genauigkeit. Dem besseren Verständnis wegen bleiben meine Beispiele bei den standard Signalen.

    Zuerst muss man dem IC den zur Ausgangsfrequenz passenden Vorteiler/Prescaler einstellen, standardmäßig läuft er sonst auf 200Hz Ausgangsfrequenz. Möglich sind werte von 24 bis 1625Hz. Leider lässt sich die Frequenz nur einstellen wenn der Interne 25MHz Oszillator im Sleep Mode (also aus) ist. Das automatische Hochzählen der I2C Adressen ist auch nicht automatisch eingeschaltet, das wird gleich mit erledigt, ansonsten müsste man jede Adresse einzeln anwählen anstatt aufeinanderfolgende Adressen einfach nacheinander schreiben zu können:

    Quellcode

    1. 'Prescalerregister setzen, dafür muss das Oszillator bit5 von Mode 1ausgeschaltet sein sein
    2. 'Auto increment der Adressregister ist per default aus, einschalten mit bit6 vom Mode 1
    3. I2cstart
    4. I2cwbyte adressPCA9685_write
    5. I2cwbyte &H00
    6. I2cwbyte &B0011_0000 '&H21, auto increment on, sleep mode on
    7. I2cstop
    8. 'Servo signal 20MS=50Hz, impulslänge 1-2ms, verstellbereich min/max demnach 205 schritte;bereich min/max= 205-410
    9. I2cstart
    10. I2cwbyte adressPCA9685_write
    11. I2cwbyte &B1111_1110 '&HFE = set to PRE_SCALE register
    12. I2cwbyte &B0111_1001 '50 hz Osc_CLK=( 25000000/(4096*50)-1 = 121) set prescale, sleep mode must be 1 to set scaler
    13. I2cstop
    14. I2cstart
    15. I2cwbyte adressPCA9685_write
    16. I2cwbyte &H00
    17. I2cwbyte &B0010_0000 'auto increment on, sleep mode off
    18. I2cstop
    Alles anzeigen





    Der PCA9685 hat einen internen 25MHz Oszillator, die Ausgangsfrequenz berechnet sich nach dem Vorteiler und der Auflösung von 12Bit: =( 25000000/(4096*50)-1 für 50Hz welche die Servos benötigen also einen Vorteiler von 121.


    Jetzt muss noch eingestellt werden welche Art von Last am IC hängt, er kann nämlich FETs direkt schalten sowie auch LEDs bis 20mA pro Kanal direkt Versorgen. In diesem Fall stellen wir Servo ein:

    Quellcode

    1. I2cstart
    2. I2cwbyte adressPCA9685_write
    3. I2cwbyte &H01
    4. 'I2cwbyte &B0001_0000 'ausgang definieren INV=1 /outdrv =0 for direct led connection
    5. I2cwbyte &B0000_0100 'ausgang definieren INV=0 /outdrv =1 for direct servo connection
    6. I2cstop
    servo1.jpg
    Ausgangsfrequenz und Ausgangscharakteristik können leider nur global pro IC eingestellt werden. Das bedeutet alle Ausgänge laufen mit der gleichen Frequenz und theoretisch nur LEDs oder nur Servos. Wenn man die ein und ausschaltpunkte neu anpasst läuft das Servo aber auch mit einem Pullup unter der LED Einstellung, in dieser Einstellung ist das Signal ja invertiert und das Servo würde in den mechanischen Anschlag fahren.


    Ein Servo Signal ist zwischen 1ms und 2 ms lang und kommt mit 50 Hz (20ms Wiederholung), ein durchlauf (signalperiode) des PCA9685 hat 12 Bit bzw. 4095 Takte. 1 Millisekunde sind also knapp 205 Takte womit das Servosignal zwischen 205 und 410 Takten für mix/max liegt.
    pic2.jpg
    Der PCA hat zwei Schaltpunkte pro Kanal, den Einschaltpunkt und Ausschaltpunkt.
    pic1.jpg

    Beide werden durch eine Word-Variable gesetzt, zuerst wird das niedrigwertigere Byte übertragen, dann das höherwertige jedes Punktes. Im Beispiel hier wird bei Zählerstand 0 eingeschaltet und bei 205 wieder ausgeschaltet und somit ein 1ms Signal erzeugt. Auch werden in diesem Beispiel hier werden gleichzeitigallen 16 Kanäle mit den gleichen Werten eingestellt:


    Quellcode

    1. 'Alle 16 kanäle gleichzeitig ansprechen ab adresse FA servo minimalwert
    2. PCFword_on =0
    3. PCFword_off= 205 'beginn des signals immer bei 0
    4. I2cstart
    5. I2cwbyte adressPCA9685_write
    6. I2cwbyte &HFA
    7. I2cwbyte LOW(PCFword_on)
    8. I2cwbyte High(PCFword_on)
    9. I2cwbyte LOW(PCFword_off)
    10. I2cwbyte High(PCFword_off)
    11. I2cstop
    12. wait 5
    13. 'Alle 16 kanäle gleichzeitig ansprechen ab adresse FA servo maximalwert
    14. PCFword_on =0
    15. PCFword_off= 410 'beginn des signals immer bei 0
    16. I2cstart
    17. I2cwbyte adressPCA9685_write
    18. I2cwbyte &HFA
    19. I2cwbyte LOW(PCFword_on)
    20. I2cwbyte High(PCFword_on)
    21. I2cwbyte LOW(PCFword_off)
    22. I2cwbyte High(PCFword_off)
    23. I2cstop
    24. Wait 5
    Alles anzeigen
    Sieht dann so aus:
    2nd.jpg

    Wenn man alle Kanäle gleichzeitig ein oder ausschalten will kann man statt den 4 Bytes für ON und OFF auch einfach das 5te Bit aus dem höheren Byte schreiben:



    Quellcode

    1. 'vor dem nächsten test alle ausgänge abschalten, 100% on or off funktioniert auch über h-bit5:
    2. I2cstart
    3. I2cwbyte adressPCA9685_write
    4. I2cwbyte &HFD
    5. I2cwbyte &B0001_0000
    6. I2cstop

    Das vorherige Beispiel hat den nachteil das alle Signale zur gleichen Zeit beginnen, für die Stromversorgung ist so etwas eine sehr hohe Belastung. Besser wäre es wenn man das Signal an jeden Kanal etwas zeitverzögert ausgibt:

    Quellcode

    1. 'default werte damit Servo nicht in Anschlag fährt
    2. PCFword_on=0
    3. PCFword_off= 307
    4. do
    5. PCFword_on_add = PCFword_on + 255
    6. PCFword_off_add = PCFword_off + 255
    7. 'Ausgänge einzeln ansprechen, Ausgang 0:
    8. I2cstart
    9. I2cwbyte adressPCA9685_write
    10. I2cwbyte Aus0
    11. I2cwbyte LOW(PCFword_on)
    12. I2cwbyte HIGH(PCFword_on)
    13. I2cwbyte Low(PCFword_off)
    14. I2cwbyte High(PCFword_off)
    15. I2cstop
    16. 'Ausgänge einzeln ansprechen, Ausgang 1:
    17. I2cstart
    18. I2cwbyte adressPCA9685_write
    19. I2cwbyte AUS1
    20. I2cwbyte LOW(PCFword_on_add)
    21. I2cwbyte High(PCFword_on_add)
    22. I2cwbyte Low(PCFword_off_add)
    23. I2cwbyte High(PCFword_off_add)
    24. I2cstop
    25. ' Ausgänge kontinuierlich schreiben Ausgang 2-3:
    26. I2cstart
    27. I2cwbyte adressPCA9685_write
    28. I2cwbyte AUS2
    29. I2cwbyte LOW(PCFword_on)
    30. I2cwbyte HIGH(PCFword_on)
    31. I2cwbyte Low(PCFword_off)
    32. I2cwbyte High(PCFword_off)
    33. I2cwbyte LOW(PCFword_on_add) 'Hier beginnt Speicherbereich Ausgang 3
    34. I2cwbyte High(PCFword_on_add)
    35. I2cwbyte Low(PCFword_off_add)
    36. I2cwbyte High(PCFword_off_add)
    37. I2cstop
    38. 'Hochzählen bis zum maximum, Wenn erreicht zählrichtung umkehren
    39. if direction = 0 then
    40. incr PCFword_off
    41. if PCFword_off = 440 then direction = 1
    42. end if
    43. 'Runterzählen bis zum minimum, wenn erreicht zählrichtung umkehren
    44. if direction = 1 then
    45. decr PCFword_off
    46. if PCFword_off = 209 then direction = 0
    47. end if
    48. waitms 500
    49. loop
    Alles anzeigen
    Dadurch das man Start und Stopp Punkte pro Kanal setzen kann ist ein Versatz ohne Probleme möglich. Im vorherigen Beispiel fährt das Servo langsam hin und her. Das Signal vom zweiten Kanal wird um ca 1,2ms später (wert 255) ausgegeben.
    3rd.jpg
    Zur Erreichung einer Position muss man die Signalwerte aber nicht wie eben gezeigt hochzählen, das Servo vergleicht ja selber Soll-wert vom Signal und Ist-Stellung und fährt dann automatisch in die Soll- Position.


    Das vom mir eingesetzte Modul:

    PCA9685.jpg

    Alle Adresseingänge liegen per Default auf logisch null somit ist der
    PCA9685 unter der schreibdresse Hex 80 zu erreichen. Spannungsversorgung
    der Servo Stiftleisten über PIN „V+“ oder die Schraubklemme. Spannungsversorgung vom PCA über PINVCC“.


    Alle Ausgänge sind über 220Ohm Widerstände herausgeführt. SDA und SCL haben 10K Pullups.


    Im Gegensatz zum ähnlichen Modulen wurde an diesem hier die Verpolschutzschaltung an „V+“ eingespart.
    Dateien

    5.674 mal gelesen