Forum: Mikrocontroller und Digitale Elektronik 8-Bit PWM für 2 DC Motoren


von muhmann (Gast)


Lesenswert?

hallo zusammen,

ich bin grad dabei das grundgerüst eines kleinen roboters mit 2 rädern 
aufzubauen. die beiden räder dienen sowohl als antrieb als auch zu 
lenkung. ähnlich diesem hier:

http://w3-o.cs.hm.edu/~mfischer/SS2006/Pioneer3DX.jpg

mein problem ist die PWM für die 2 motoren.
ich benutze einen ATmega88 und als treiber einen L6206N. datenblatt zum 
treiber gibts hier:

http://www.datasheetcatalog.net/de/datasheets_pdf/L/6/2/0/L6206N.shtml

soweit hab ich alles verbunden und es funktioniert auch. lediglich die 
PWM funktioniert nicht so wie ich mir das wünsche. ich habe, 
entsprechend dem treiber datenblatt, die pins wie folgt verbunden:

für motor 1:
IN1_A -> PD5
IN2_A -> PD0

für motor 2:
IN1_B -> PD6
IN2_B -> PD1

gewählt ist PWM mode 5, also phase correct. dieser funktioniert auch 
soweit, lediglich mit dem vorwärts und rückwärtslauf hab ich enorme 
probleme. in der main wird anfangs die PWM_init ausgeführt und in der 
hauptschleife die PWM_Speed funktion.

mit der funktion "PWM_Speed" möchte ich den gewünschten pwm-wert und die 
laufrichtug realisieren. wenn ich beide motoren in die gleiche richtung 
laufen lasse funktioniert alles soweit, aber wenn ich eine 
unterschiedliche laufrichtung vorgeb verhalten sie sie komplett anders 
und drehen plötzlich viel schneller.

irgendwo ist der wurm drin und ich hab absolut keine ahnung wo.

ich hoffe ihr könnt mir helfen.

gruß
1
int main(void)
2
{
3
...
4
  for(;;)
5
  {
6
    PWM_Speed(180,BACKWARD,180,BACKWARD);  // FORWARD = 0, BACKWARD = 1
7
8
  }
9
}
10
11
//---------------------------------------------------------------
12
// sets pwm settings 
13
void PWM_initialise (void)
14
{
15
  /* Form generation mode using WGM bits and Compare output mode using COM bits. Phase correct Mode 5*/
16
  TCCR0A =  _BV (WGM00) | _BV (COM0A1) | _BV(COM0B1);
17
  TCCR0B = _BV(WGM02);
18
19
  /* Set the Clock select bits to determine Clock frequency. Prescaler = 1*/
20
  TCCR0B = _BV (CS00);
21
22
  PORTD = !(_BV(OC0A_R)  | _BV(OC0B_R));  // Internal Pull-Ups low
23
24
  DDRD = _BV(OC0A) | _BV(OC0B) | _BV(OC0A_R)  | _BV(OC0B_R); // Enable OC0A and OC0B as output = 1
25
26
  /* Enable interrupts*/
27
  sei();
28
}
29
30
//---------------------------------------------------------------
31
// set motor speed an direction
32
void PWM_Speed(char SPD_M1, char DIR_M1, char SPD_M2, char DIR_M2)
33
{
34
  if(DIR_M1)          // BACKWARD
35
  {
36
    PORTD &= ~(1<<PD5);
37
    PORTD |= (1<<PD0);
38
    OCR0A = ~SPD_M1;
39
  }
40
  else            // FORWARD
41
  {
42
    PORTD |= (1<<PD5);
43
    PORTD &= ~(1<<PD0);
44
    OCR0A = SPD_M1;
45
  }
46
  if(DIR_M2)          // BACKWARD
47
  {
48
    PORTD &= ~(1<<PD6);
49
    PORTD |= (1<<PD1);
50
    OCR0B = ~SPD_M2;
51
  }
52
  else            // FORWARD
53
  {
54
    PORTD |= (1<<PD6);
55
    PORTD &= ~(1<<PD1);
56
    OCR0B = SPD_M2;
57
  }
58
59
  sei();
60
}

von Düsendieb (Gast)


Lesenswert?

Leg mal einen Schletplan bei. Der PWM Ausgang sollte auf Enable, die 
Richtung wird mit In 1 und IN2 gemacht.

Axel

von muhmann (Gast)


Angehängte Dateien:

Lesenswert?

ich hab mal den teil des L6206 beigfügt.

die beiden IN1 und IN2 leitungen sind direkt an die oben genannten pins 
angeschlossen.
ich benutze eine pwm frequenz von 36 kHz. prescaler ist 1, da meine cpu 
eine frequenz von 18,432 MHz hat.

diese 36 kHz liegen an den pins PD5 und PD6 an. je nachdem welchen wert 
ich an OCR0A und OCR0B ändere ich das tastverhältnis dieser frequenz. an 
den pins PD0 und PD1 liegt je nach vorwärts oder rückwärtslauf nur ein 
high- oder low-pegel an.

ich steh grad echt aufm schlauch :)

von Düsendieb (Gast)


Lesenswert?

36 kHz sind recht schnell, versuch mal kleiner 1kHz.

Wenn In1 und In2 gleiche Signallage haben, wird der Motor 
kurzgeschlossen und bremst mit vollem Moment. Daher sollte der PWM auf 
den Enable.


Axel

von muhmann (Gast)


Lesenswert?

"pfeift" der motor dann nicht wenn ich ihn bei 1 kHz betreibe?

auf enable, verstehe. aber gäbe es auch eine möglichkeit die motoren 
bzw. den treiberbaustein auf die art und weise zu benutzen wie ich ihn 
angeschlossen habe?

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Nein, das ist schon richtig so, dass die Motoren kurzgeschlossen werden 
müssen, das nennt man Zwangskommutierung.
Enable heißt deswegen so, weil man damit die Funktionseinheit 
einschaltet nicht weil man damit pulst. Einige Treiber haben auf dem 
Enable sogar Filter drin, so dass ein Pulsen hier nicht möglich ist.

Der Fehler ist schon im Quelltext...

Werd gleich mal in Ruhe drübersehen.

Grüße,

Peter

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Diese Zeile gefällt mit so garnicht:

  PORTD = !(_BV(OC0A_R)  | _BV(OC0B_R));  // Internal Pull-Ups low

"!" ist ein logischer operator, kein bitweiser.

aber vielleicht finde ich noch mehr...

Edit:

Abgesehen davon, sind die Richtungspins Ausgänge, da muss man keine 
Pullups setzen.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Ich würde da etwas ändern:
1
void PWM_Speed(unsigned char SPD_M1, unsigned char DIR_M1, unsigned char SPD_M2, unsigned char DIR_M2)
2
{
3
  if(DIR_M1)          // BACKWARD
4
  {
5
    PORTD |= (1<<PD0);
6
    OCR0A = 255 - SPD_M1;
7
  }
8
  else            // FORWARD
9
  {
10
    PORTD &= ~(1<<PD0);
11
    OCR0A = SPD_M1;
12
  }
13
  if(DIR_M2)          // BACKWARD
14
  {
15
    PORTD |= (1<<PD1);
16
    OCR0B = 255 - SPD_M2;
17
  }
18
  else            // FORWARD
19
  {
20
    PORTD &= ~(1<<PD1);
21
    OCR0B = SPD_M2;
22
  }
23
24
  sei();
25
}

Die komische Zeile (letzter Beitrag) einfach weglassen.

Grüße,

Peter

von muhmann (Gast)


Lesenswert?

bitte entschuldigt meine verspätete antwort, mein internet wollte 
gestern abend nicht so wie ich wollte :( konnte mich partout nicht mehr 
einloggen.

erstmal danke für eure hilfe :)

@Peter
ich hab deine vorschläge natürlich sofort umgesetzt und die drehrichtung 
funktioniert jetzt wunderbar. nur hab ich jetzt ein problem mit der 
geschwindigkeit.

wenn ich die motoren in die gleiche richtung drehen lasse:
z.b. beide vorwärts (rückwärts geht analog dazu) mit einem pwm-wert von 
180

also PWM_Speed(180,FORWARD,180,FORWARD);

drehen sie sich recht langsam.

wenn ich nun aber die drehrichtung umkehre:

also PWM_Speed(80,BACKWARD,80,FORWARD);

muss ich den pwm-wert von 180 auf 80 runtersetzen um eine ungefähr 
gleiche drehzahl zu erhalten.

irgendwie verwirrt mich das jetzt schon wieder :)

von muhmann (Gast)


Lesenswert?

edit:
edit geht nicht als gast, werd mich gleich mal registrieren.

ok, mein fehler, is klar warum ich die verschiedenen drehzahlen bekomme.
zum einen wird 180 an die funktion übergeben. dadruch ergeben sich die 
pwm-werte für vorwärts von 180 und rückwärts von 255-180=75
kein wunder das die sich dann unterschiedlich schnell drehen.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>ok, mein fehler, is klar warum ich die verschiedenen drehzahlen bekomme.

Nein, das ist eigentlich nicht klar.
Die Wirkrichtung vom PWM muss ja umgedreht werden, da der Motor umgepolt 
wird. So wie ich es geschrieben habe, sollte das beides die gleiche 
Geschwindigkeit liefern, nur das eine andersherum:

PWM_Speed(180,FORWARD,180,FORWARD);
PWM_Speed(180,BACKWARD,180,BACKWARD);

Läuft der Motor vorwärts, bedeutet das folgende, dass der Motor steht:
OCR0A/B = 0

Läuft der Motor vorwärts, bedeutet das folgende, dass der Motor mit 
maximaler Geschwindigkeit läuft:
OCR0A/B = 255

Läuft der Motor rückwärts, bedeutet das folgende, dass der Motor steht:
OCR0A/B = 255

Läuft der Motor rückwärts, bedeutet das folgende, dass der Motor mit 
maximaler Geschwindigkeit läuft:
OCR0A/B = 0

Damit die Eingabewerte von PWM_Speed in beiden Laufrichtungen der 
Geschwindigkeit entsprechen, habe ich im einen Fall den Sollwert von 255 
subtrahiert.

Warum das nicht funktioniert, ist mir momentan ohne den vollständigen 
Schaltplan und Quellcode nicht klar.

Grüße,

Peter

von muhmann (Gast)


Lesenswert?

ja genauso hatte ich das gemeint, hab mich nur etwas unglücklich 
ausgedrückt.

ich habe in diesem fall:
PWM_Speed(180,FORWARD,180,FORWARD);
eine bestimmte drehzahl am rad erhalte.

wenn ich ich nun die richtung auf rückwärts ändere, sprich:
PWM_Speed(180,BACKWARD,180,BACKWARD);
erhalte ich ungefähr dieselbe drehzahl, allerdings ist sie leicht 
niedriger. diese differenz, so nehme ich an, kommt höchstwahrscheinlich 
vom mechanischen aufbau der räder und getriebe. im vorwärtslauf läuft 
das getriebe deutlich runder als im rückwärtslauf. ist nicht ganz so 
schön gefertigt und zusammengebaut, geb ich zu :)

aber soweit passt alles ja noch. mein problem mit der stark veränderten 
drehzahl tritt dann auf, wenn ich 2 verschiedene laufrichtungen 
angegeben habe. also so:
PWM_Speed(180,FORWARD,180,BACKWARD);
oder grad umgekehrt ist es das gleiche. ich habe plötzlich eine deutlich 
höhere drehzahl am rad, trotz gleichbleibendem pwm-wert.

kann mir wirklich nicht vorstellen warum das so sein kann.

der quellcode den ich im ersten beitrag gepostet habe ist eigentlich 
alles. ich hatte noch eine ADC-wandlungsroutine und eine 
I2C-kommunikation drin, die ich aber alle auskommentiert habe. somit hab 
ich nur das was ich oben gepostet habe.

der schaltplan is soweit eigentlich auch vollständig. der L6206 treiber 
ist nur mit insgesamt 6 pins des atmegas verbunden. 2 davon dienen zur 
erfassung des motorstromes über einen shunt-wiederstand (links in dem 
geposteten schaltplan) und die restlichen 4 sind mit den oben genannten 
ports verbunden. der rest des schaltplans besteht nur noch aus dem 
atmega88 und dessen anschlüsse zur spannungsversorung und 
programmierleitungen.

kann mir nicht vorstellen das es da ein problem geben soll, zumal der µC 
ja alle sonstigen aufgaben problemlos erfüllt. also die genannte 
I2C-kommunikation und die ADC-wandlungsroutine.

von Peter D. (pdiener) Benutzerseite


Lesenswert?

>PWM_Speed(180,FORWARD,180,BACKWARD);
>oder grad umgekehrt ist es das gleiche. ich habe plötzlich eine deutlich
>höhere drehzahl am rad, trotz gleichbleibendem pwm-wert.

Ich denke mal, das liegt daran, dass die Motoren im einen Fall 
gleichzeitig die Stromversorgung belasten und im Problemfall durch die 
PWM immer abwechselnd. Dadurch ergibt sich eine höhere durchschnittliche 
Spannung zur Versorgung, was zu einer höheren Drehzahl an beiden Motoren 
führt.

Das müsste man sich mal auf Papier aufmalen, wie sich das genau mit der 
Pulsmustererzeugung auf die Belastung der Stromversorgung auswirkt.

Vielleicht kann man ja einen anderen PWM-Modus nehmen und damit etwas 
verbessern.

Grüße,

Peter

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.