Forum: Mikrocontroller und Digitale Elektronik Schrittmotor macht was er nicht soll


von Roth (Gast)


Lesenswert?

Guten Abend Gemeinde.

Habe den ganzen Nachmittag damit verbracht, wie ein Schrittmotor 
zuverlässig eine bestimmte Position anfahren kann. Jeder Versuch ist 
gescheitert.

Als Treiber-Chip verwende ich einen DRV8825
Als Motor einen Schrittmotor 91255008 für VDO Tacho
http://www.xenone.de/Schrittmotoren/Schrittmotor-91255008-fuer-VDO-Kombiinstrument-VW-Audi-Seat-Skoda::1153.html
Der Motor hat vier Anschlüsse und pro Spule 150 Ohm.

Das kleine Sketch ist selbstgestrickt, siehe unten.

Die Parameter habe ich rauf und runter probiert. Mal geht es -eine Zeit 
lang- und "plötzlich" stimmt die Position nicht mehr.

Völlig absurd ist eine unerklärliche Abhängigkeit von delay(). Gegen 
delay's ist die Motorsteuerung scheinbar allergisch. Bei bestimmten 
Werten läuft der Motor sogar rückwärts, obwohl er vorwärts laufen soll.

Völlig absurd: Bei einner Einstellung hatte ich den Effekt, dass der 
Motor erst richtig lief, und dann - nach Ausführung des Codes - lief 
er wieder rückwärts. Ich habe Serial.print's eingebaut und kann 
ausschließen, dass noch Code ausgeführt wurde, als der Motor zurück 
lief. Die Steps beim Rücklauf sind willkürlich und in der Anzahl nicht 
reproduzierbar. Manchmal - bei derselben Einstellung - läuft er auch gar 
nciht zurück.

Ich meine fast, dass der Chip nicht ok ist. Aber weil das mein erster 
Kontakt mit Schrittmotoren ist, wird der Fehler eher bei mir liegen. 
Aber WO ??

Die Einstellung des Potis auf dem DRV8825 ist (fast) egal, weil der 
Motor auf 12V ausgelegt ist und die Motorspannung auch 12V beträgt.
1
long StepperPosition;
2
3
/****************************************************************/
4
/* Motor drehen lassen                                          */
5
/* iSteps: Anzahl der Schritte                                  */
6
/* Die Drehrichtung ergibt sich aus dem Vorzeichen von 'iSteps' */
7
/****************************************************************/
8
void Step(long iSteps) {
9
  if (iSteps) {
10
11
     // Drehrichtung einstellen
12
     if (iSteps > 0) 
13
        {digitalWrite(51, HIGH);}         // forwärts
14
     else
15
        {digitalWrite(51, LOW);}          // rückwärts
16
17
     // Steps ausführen
18
     for (long n=0; n<abs(iSteps); n++) {
19
       digitalWrite(52, HIGH);            // HIGH-Pegel auf Step-Pin
20
       delay(1);                          // kurz warten
21
       digitalWrite(52, LOW);             // LOW-Pegel
22
       delay(5);                          // nochmal warten
23
     }  
24
25
     // Neue Position merken
26
     StepperPosition += iSteps;
27
  }
28
}
29
30
31
/************************************************/
32
/* Motor auf eine bestimmte Position ausrichten */
33
/* iPosition: Gewünschte Motorposition          */
34
/************************************************/
35
void StepTo(long iPosition) {
36
  if (iPosition != StepperPosition) {
37
     Step(iPosition - StepperPosition);
38
  } 
39
}
40
41
42
void setup() {
43
  Serial.begin(9600);
44
  pinMode(51, OUTPUT);  // DIR
45
  pinMode(52, OUTPUT);  // STEP
46
}
47
48
49
void loop() {
50
  StepTo(random(10,135));
51
}

von Wolfgang (Gast)


Lesenswert?

Roth schrieb:
> Völlig absurd ist eine unerklärliche Abhängigkeit von delay().

Völlig absurd ist, dass du von dem Schrittmotor erwartest, dass er von 
jetzt auf plötzlich mit voller Schrittfrequenz läuft. Ein Schrittmotor 
hat eine drehende Masse und die muss erst beschleunigt werden. Sonst 
verliert er Schritte, i.e. seine Position stimmt nicht mehr oder er 
bleibt gar brummend...pfeifen stehen.

Lies dir mal etwas über Beschleunigungs- und Bremsrampen durch, z.B. in 
der Atmel AppNote AVR446 - Linear speed control of stepper motor 
(MicroChip AN_8017)
http://ww1.microchip.com/downloads/en/AppNotes/doc8017.pdf

von Roth (Gast)


Lesenswert?

@Wolfgang Hast du gelesen, dass ich die Einstellungen rauf-und-runter 
getestet habe? Insbesondere die Pusdauer bei HIGH und auch bei LOW. Dass 
zu kurze Pulslänge irgendwann nicht mehr geht, ist schon klar. Aber zu 
lange Dauer hat ebenfalls negativen Effekt.

Wolfgang schrieb:
> Völlig absurd ist, dass du von dem Schrittmotor erwartest, dass er von
> jetzt auf plötzlich mit voller Schrittfrequenz läuft. Ein Schrittmotor
> hat eine drehende Masse und die muss erst beschleunigt werden.

Ganau dazu habe ich ja testweise delay's eingebaut - um die Schritte zu 
verlangsamen. Je länger die Verzögerung nach jedem LOW-HIGH-LOW, desto 
unruhiger lief manchmal der Motor. Am besten lief er völlig ohne 
Verzögerung, also bei voller Geschwindigkeit. Er läuft nicht sauberer, 
wenn er langsamer läuft, denn bei dem Projekt muss er nicht schnell 
laufen. Nur Genauigkeit erwarte ich. Ich habe aber keine einstellung 
gefunden, egal wie langsam, wo der Motor zuverlässig das tat, was ich 
von einem Schrittmotor erwarte: Positionsgenauigkeit.

von Pat P. (tsag)


Lesenswert?

Nutze doch die Accelstepper Lib, oder willst Du es komplett selber 
bauen?

von Maik S. (yellowbird)


Lesenswert?

Roth schrieb:
> @Wolfgang Hast du gelesen, dass ich die Einstellungen rauf-und-runter
> getestet habe? Insbesondere die Pusdauer bei HIGH und auch bei LOW. Dass
> zu kurze Pulslänge irgendwann nicht mehr geht, ist schon klar. Aber zu
> lange Dauer hat ebenfalls negativen Effekt.
>
> Wolfgang schrieb:
>> Völlig absurd ist, dass du von dem Schrittmotor erwartest, dass er von
>> jetzt auf plötzlich mit voller Schrittfrequenz läuft. Ein Schrittmotor
>> hat eine drehende Masse und die muss erst beschleunigt werden.
>
> Ganau dazu habe ich ja testweise delay's eingebaut - um die Schritte zu
> verlangsamen. Je länger die Verzögerung nach jedem LOW-HIGH-LOW, desto
> unruhiger lief manchmal der Motor. Am besten lief er völlig ohne
> Verzögerung, also bei voller Geschwindigkeit. Er läuft nicht sauberer,
> wenn er langsamer läuft, denn bei dem Projekt muss er nicht schnell
> laufen. Nur Genauigkeit erwarte ich. Ich habe aber keine einstellung
> gefunden, egal wie langsam, wo der Motor zuverlässig das tat, was ich
> von einem Schrittmotor erwarte: Positionsgenauigkeit.

Hast du dir das manual des DRV8825 durchgelesen ?
Die Pulslänge die zu zu verwenden hast, wenn du eine korrekte Ausführung 
erwartest ist festgelegt.

Und zu den delays.. vergiss nicht dass "delay" nicht der einzige 
Einfluss auf die Pulsform- / Dauer ist, sondern auch die Schritte 
zwischen zwei Ausführungen.

: Bearbeitet durch User
von Roth (Gast)


Lesenswert?

Danke erstmal für die Anteilnahme. Ich bin weiter gekommen, aber als 
"zuverlässig" würde ich meine Schaltung nicht verkaufen. Davon bin ich 
leider noch weit weg. Obwohl der Testlauf schon seit Stunden läuft und 
der Motor immer noch korrekt positioniert. Das noch vorliegende Problem 
ist das gelegentliche "Zurückprallen" (wie eine Billardkugel) beim 
Nullstellungslauf, siehe unten im Text.

Patrick B. schrieb:
> Nutze doch die Accelstepper Lib, oder willst Du es komplett selber
> bauen?

Die Lib kenne ich noch nicht. Ich sehe mir die nachher mal an.

Maik S. schrieb:
> Hast du dir das manual des DRV8825 durchgelesen ?
> Die Pulslänge die zu zu verwenden hast, wenn du eine korrekte Ausführung
> erwartest ist festgelegt.

Auch das werde ich mir dann nochmal ansehen.

> Und zu den delays.. vergiss nicht dass "delay" nicht der einzige
> Einfluss auf die Pulsform- / Dauer ist, sondern auch die Schritte
> zwischen zwei Ausführungen.

Ja genau. Wie ich dann allerdings die Berechnung von Beschleunigung und 
Abbremsung durchführen soll, die ja zwischen den Schritten durchgeführt 
werden muss, ist mir schleierhaft.

Nach Wolfgangs berechtigtem Einwand habe ich mir meine Steuerung nochmal 
angesehen und diese nochmal langsamer gemacht. Eine vorher eingebaute 
Beschleunigung und Abbremsung der Geschwindigkeit zu Beginn und am Ende 
der Steps ist völlig gescheitert. Der Motor hat nur noch gezuckt und ist 
wild hin und her gefahren. Ich habe dafür keine Erklärung und habe 
wirklich alle mir eingefallenen Kombinationen getestet.

Für mich sieht es so aus, als würde Motor und/oder Chip nicht jede 
Step-Frequenz mögen. Das komische ist dabei, dass auch eine 
Verlangsamung der Frequenz negativ zu Buche schlägt. Ich habe die Steps 
z.B. mit delay(10) verlangsamt. delay(11), also noch langsamer, 
funktioniert dann nicht. delay(9) dann schon und delay(14) auch wieder.

Etwas fremdartig finde ich: Wenn ich delay(11) durch 
delayMicroseconds(11000) ersetze, funktioniert es, dafür andere Werte 
aber nicht mehr. Ich bin völlig ratlos, was da los ist :(

Aktuell habe ich eine Kombination gefunden, die scheinbar funktioniert. 
Die Frage ist nur, wie lange diese empfindliche Balance funktioniert und 
ob Temperatur- oder andere Schwankungen später zu Problemen führen. Das 
kanns doch eigentlich nicht sein, oder? Irgendwas mache ich falsch oder 
einer der Chips hat eine Mache. Das Problem an meiner "lauffähigen" 
Konfiguration ist nach wie vor die Initialisierung. Da der Motor als 
VDO-Instrument zwischen zwei Anschlägen läuft, er kann max. 320° und 
stößt dann vor eine mechanische Begrenzung, stelle ich ihn in setup() in 
null-Position. Da er dabei fast immer an den Schschlag stößt, passiert 
es (sehr selten), dass er von dort "zurückhüpft" und in einer Position > 
null zum stehen kommt. Das ist natürlich auch Käse, aber was soll ich 
tun. Beim noch langsameren Lauf passiert das übrigens auch.

Aktuell sieht die Prozedur so aus, also fast unverändert. Man achte auf 
die abwechselnde Verwendung von delayMicroseconds und delay.
1
/**************************************************************/
2
/* MM: Motor drehen lassen                                    */
3
/* iSteps: Anzahl der Schritte                                */
4
/* Die Drehrichtung ergibt sich aus dem Vorzeichen von iSteps */
5
/**************************************************************/
6
void MM_Step(long iSteps) {
7
  if (iSteps) {
8
9
     // Treiberchip aktivieren
10
     digitalWrite(EnablePin, LOW);        // Treiber einschalten
11
     delay(100);                          // einen Moment warten
12
13
     // Drehrichtung einstellen
14
     if (iSteps > 0) 
15
        {digitalWrite(DirPin, HIGH);}     // vorwärts
16
     else
17
        {digitalWrite(DirPin, LOW);}      // rückwärts
18
19
     // Motor drehen lassen
20
     for (long n=0; n<abs(iSteps); n++) {
21
       digitalWrite(StepPin, HIGH);       // HIGH-Pegel auf Step-Pin
22
       delayMicroseconds(1000);           // kurz warten
23
       digitalWrite(StepPin, LOW);        // LOW-Pegel
24
       delayMicroseconds(5000);           // nochmal warten
25
26
       // Nach jeden Schritt warten
27
       delayMicroseconds(9000);           // Steuerung der Motorgeschwindigkeit
28
     }  
29
30
     // Treiberchip deaktivieren (auch 2,5 Watt werden irgendwann heiß)
31
     delay(100);                          // einen Moment warten
32
     digitalWrite(EnablePin, HIGH);       // Treiber ausschalten
33
34
     // Neue Position merken
35
     Position += iSteps;
36
37
   }
38
}

von Johannes S. (Gast)


Lesenswert?

Wie ist denn der Mode eingestellt? Wenn M0..M2 offen sind ist das 
Vollschrittbetrieb, besser ist die Mikroschritte zu nutzen.
Stromversorgung für den Motor ausreichend? Nicht das durch 
Spannungseinbrüche der µC in den Reset geht, sowas gabs hier auch schon. 
Kann mit Meldungsausgabe oder blinken in setup() kontrollieren.
Die schon angesprochenen Beschleunigungs- und Bremsrampen sind wichtig, 
besonders wenn du einen Richtungswechsel hast.
Die Zeiten mit delay() sind nicht präzise, Interrupts können das Timing 
verändern. Die AccelStep Lib arbeitet da hoffentlich mit einem HW Timer, 
das ist besser.
Wenn Enable ausgeschaltet wird dann ist der Motor stromlos und hat kein 
Haltemoment mehr, wenn der Motor belastet wird hält er seine Position 
nicht.
Hier ist eine gute Beschreibung zu dem Treiber: 
https://www.pololu.com/product/2133

von Roth (Gast)


Lesenswert?

Johannes S. schrieb:
> Wie ist denn der Mode eingestellt? Wenn M0..M2 offen sind ist das
> Vollschrittbetrieb, besser ist die Mikroschritte zu nutzen.

Aktuell Vollschrittmodus. Bis 8 Mikroschritte läuft der Motor sauber 
mit.

Johannes S. schrieb:
> Stromversorgung für den Motor ausreichend? Nicht das durch
> Spannungseinbrüche der µC in den Reset geht, sowas gabs hier auch schon.
> Kann mit Meldungsausgabe oder blinken in setup() kontrollieren.

Ja, die Spannung ist gut versorgt. Das war das erste, das ich geprüft 
habe

Johannes S. schrieb:
> Wenn Enable ausgeschaltet wird dann ist der Motor stromlos und hat kein
> Haltemoment mehr, wenn der Motor belastet wird hält er seine Position
> nicht.

Der VDO-Motor ist getriebeuntersetzt. Die Achse lässt sich von Hand 
nixht bewegen.

---

Ich werde mir jetzt den Nullstellungslauf in setup() vornehmen. Der wird 
ja eigentlich nicht wirklich gebraucht. Beim Ausschalten der Zündung 
(ich rede jetzt vom Auto) muss der Motor in Zeiger-Nullposition fahren. 
Die Zeiger-Nullposition ist nicht die Anschlag-Nullposition. Da der 
Zeiger da stehen bleibt, bist die Zündung wieder an ist, ist die 
Motorposition bekannt und ein Nullstellungslauf nicht nötig. Dieser wäre 
nur erforderlich, wenn bei eingeschalteter Zündung die Batterie 
abgeklemmt würde, so dass der Motor nicht mehr in Zeiger-Nullposition 
fahren kann. Um das zu realisieren, brauche ich aber Zugriff zum EEPROM. 
Mal sehen, wie das beim Arduino gemacht wird.

von MOSFET (Gast)


Lesenswert?

macht nicht was er soll !!!!

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.