Forum: Mikrocontroller und Digitale Elektronik I2C für Servo Controller PCA9685


von Pascal Chevron (Gast)


Lesenswert?

Hi

Ich versuche mich gerade das erste mal an I2C um eine Servo anzusteuern.
Es wird ein PCA9685 verwendet, denn ich mit einem Arduino Uno über GND, 
SDAm und SCL verbunden habe.

Datenblatt: https://cdn-shop.adafruit.com/datasheets/PCA9685.pdf

Ich möchte also nun die PWM Frequenz auf 50Hz setzen und den duty cycle
zwischen 0.8ms bis 2.2ms. Aus dem Datenblatt habe ich entnommen, dass
das Bit SLEEP im MODE1 Register(#0x00) auf 1 gesetzt werden muss um den 
Prescaler zu setzen.

Bei der Berechnung des Prescalers fehlt mir die osc_clock, wo kann ich 
die finden (ich verwende die interne clock)? Die Berechnung ist dann auf 
S.25 des Datenblattes.

Ich habe noch nicht ganz verstanden, wie man die PWM der einzelnen
Outputs setzen kann; Die einzelnen Register für die Ausgänge sind ja 12 
bit und daher mit Low/High adressierbar. Ist der Wert denn ich dort 
reinschreibe direkt die Limite für den Counter? Also wenn ich jetzt z.B
500 reinschreibe ist der duty cycle 500/4096?

Hier noch den Code, denn ich implementiert habe:
1
//Test PCA9685 Servo Driver
2
3
#include <Wire.h>
4
5
void setup() {
6
  // Start I2C
7
    Wire.begin(); 
8
  
9
  // Set Sleep Flag in MODE1 Regsiter to 1 to activate Prescaler
10
    //Access MODE1 Register
11
    Wire.beginTransmission(0x00);
12
    //Write Sleep Flag to 1 (Bit 4)
13
    Wire.write(byte(0x04));
14
    Wire.endTransmission;
15
16
  // Set Prescaler 
17
    //Access PRE_SCALE Register -> FEh
18
    Wire.beginTransmission(0xFE);
19
    //We want 50Hz, 12bit Register
20
    Wire.write(byte(0x??)); //osc_clock benoetigt
21
    Wire.endTransmission;
22
    
23
  //PIN4 Set Value to 307
24
    Wire.beginTransmission(0x16);
25
    .....
26
27
}
28
29
void loop() {
30
  // put your main code here, to run repeatedly:
31
32
}

Grüsse Pascal

von Pascal Chevron (Gast)


Lesenswert?

Gerade gesehen, das die interne clock 25Mhz ist.

von Pascal Chevron (Gast)


Lesenswert?

Ich habe das ganze mal folgendermassen versucht, jedoch gibt es kein PWM 
Signal aus. Zusätzlich habe ich noch VCC des Arduino mit VDD des PCA9685 
verbunden.
1
#include <Wire.h>
2
3
#define Out4_L 0x16
4
#define Out4_H 0x17
5
6
void setup() {  
7
  // Start I2C
8
    Wire.begin(); 
9
  
10
  // Set Sleep Flag in MODE1 Regsiter to 1 to activate Prescaler
11
    //Access MODE1 Register
12
    Wire.beginTransmission(0x00);
13
    //Write Sleep Flag to 1 (Bit 4)
14
    Wire.write(byte(0x04));
15
    Wire.endTransmission();
16
17
  // Set Prescaler 
18
    //Access PRE_SCALE Register -> FEh
19
    Wire.beginTransmission(0xFE);
20
    //We want 50Hz, 12bit Register
21
    Wire.write(byte(0x79)); //121 -> 50Hz
22
    Wire.endTransmission();
23
24
  //PIN4
25
    //LED4_ON_L
26
      Wire.beginTransmission(Out4_L);  
27
      // Write Value between 204 and 409
28
      Wire.write(byte(300));
29
      Wire.endTransmission();
30
    //LED4_ON_H
31
      Wire.beginTransmission(Out4_H);  
32
      // Write Value between 204 and 409
33
      Wire.write(byte(300>>8));
34
      Wire.endTransmission();
35
}

von Pascal Chevron (Gast)


Lesenswert?

Ich habe noch einige Fehler entdeckt, beispielsweise das mit der ON/OFF 
Time. Diese sollten nun korrekt gesetzt sein, doch leider passiert immer 
noch nichts an PIN4.
1
#include <Wire.h>
2
3
#define Out4_ON_L 0x16
4
#define Out4_ON_H 0x17
5
#define Out4_OFF_L 0x18
6
#define Out4_OFF_H 0x19
7
8
9
10
//global Variables
11
uint16_t pwm_val[3]={300,300,300}; //Holds the actual Values for PWM
12
13
void setup() {
14
  //Serial
15
  Serial.begin(9600);
16
  Serial.setTimeout(50);
17
  
18
  // Start I2C
19
    Wire.begin(); 
20
  
21
  // Set Sleep Flag in MODE1 Regsiter to 1 to activate Prescaler
22
    //Access MODE1 Register
23
    Wire.beginTransmission(0x00);
24
    //Write Sleep Flag to 1 (Bit 4)
25
    Wire.write(byte(0x04));
26
    Wire.endTransmission();
27
    
28
    delay(1);
29
    
30
  // Set Prescaler 
31
    //Access PRE_SCALE Register -> FEh
32
    Wire.beginTransmission(0xFE);
33
    //We want 50Hz, 12bit Register
34
    Wire.write(byte(0x79)); //121 -> 50Hz
35
    Wire.endTransmission();
36
37
    delay(1);
38
    
39
  //Deactivate Sleep Mode after Prescaler set:
40
    //Access MODE1 Register
41
    Wire.beginTransmission(0x00);
42
    //Write Sleep Flag to 1 (Bit 4)
43
    Wire.write(byte(0x00));
44
    Wire.endTransmission();
45
46
  //Init LED4 ON Time
47
  //LED4_ON_L
48
      Wire.beginTransmission(Out4_ON_L);  
49
      Wire.write(byte(0));
50
      Wire.endTransmission();
51
    //LED4_ON_H
52
      Wire.beginTransmission(Out4_ON_H);  
53
      Wire.write(byte(0));
54
      Wire.endTransmission();
55
    //LED4_OFF_L
56
      Wire.beginTransmission(Out4_OFF_L);  
57
      // Write Value between 204 and 409
58
      Wire.write(byte(pwm_val[0]));
59
      Wire.endTransmission();
60
    //LED4_OFF_H
61
      Wire.beginTransmission(Out4_OFF_H);  
62
      // Write Value between 204 and 409
63
      Wire.write(byte(pwm_val[0]>>8));
64
      Wire.endTransmission();
65
}

von Pascal Chevron (Gast)


Lesenswert?

Ich habe das mit der Adressierung falsch verstanden. Der PCA9865 hat 
anscheinden eine eigene Adresse und dann hat noch jedes Register eine 
Adresse. Zugriff also in etwa so:
1
void write8Bits(uint8_t reg, uint8_t val){
2
    Wire.beginTransmission(address);  
3
    Wire.write((uint8_t)reg);
4
    Wire.write((uint8_t)val);
5
    Wire.endTransmission();
6
}

Doch was ist die Adresse des PCA9865?

von Paul A. (wandkletterer)


Lesenswert?

Warum nimmst du nicht die Adafruit Libary?

von Pascal Chevron (Gast)


Lesenswert?

Habe ich nun genommen, doch manchmal scheint die Library einen Bug zu 
haben und die Servos werden nicht angesteuert. Auch scheint mir das 
ganze sehr träge zu sein. Vielleicht sollte ich besser einfach die Timer 
des Arduinos benützen und selbst was schreiben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.