Schrittmotor Drehrichtung

Gast #3612380
Lesenswert?

Hallo,

ich möchte mittels eines ATMEGA8 und des Schrittmotortreibers von Pollin 
einen Schrittmotor ansteuern.

Auf der Platine von Pollin ist wirklich nur der Treiber L298n Montiert 
und kein weiterer Controller.

Ich versuche die Schrittabfolge ich mit dem ATMEGA8 zu erzeugen.

Ich versuche für einem Richtungswechsel einfach die Schrittfolge 
entgegengesetzt durchzulaufen aber ich komme dabei einfach nicht mehr 
zum Startpunkt zurück.

Schrittfolge:
volatile char stepArray_Vorwaertz_8[8] = 
{0x01,0x05,0x04,0x06,0x02,0x0A,0x08,0x09};

Schrittmotor:
Bipolarer, PSM57BYGHM201 Pollin

Ich würde mich sehr freuen wenn mir jemand erklären könnte was ich 
falsch mache.

Ich hoffe ich habe ausreichende Infos geschrieben.

Vielen Dank

Grüße Hans
Gast #3612663
Lesenswert?

Hallo Spess,

vielen Dank das du dich meiner annehmen willst!!!!!

Anbei der Code in dem zwischen den Laufrichtungen gewechselt wird.
1
  
2
volatile char stepArray_Vorwaertz_8[8] = {0x01,0x05,0x04,0x06,0x02,0x0A,0x08,0x09};
3

4
if (directionState == STATE_RIGHT_DIRECTION_ON)/*(PINB & 0x10) == 0x00*/
5
  {
6
    if (stepp > 412)
7
    {
8
      directionState = STATE_LEFT_DIRECTION_ON;
9
    }
10
    else
11
    {
12
      /********************************/
13
      PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[stepp%MODULO_TEILER];
14
      /********************************/
15
      stepp++;
16
    }
17
  }
18
  else if (directionState == STATE_LEFT_DIRECTION_ON)/*(PINB & 0x20) == 0x00*/
19
  {
20
    if (stepp < 0)
21
    {
22
      directionState = STATE_RIGHT_DIRECTION_ON;
23
    }
24
    else
25
    {
26
      /********************************/
27
      PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[stepp%MODULO_TEILER];
28
      /********************************/
29
      stepp--;
30
    }
31
  }

Vielen Dank

Grüße Hans
#3612723
Lesenswert?

hans schrieb:

wenn hier

>       /********************************/
>       PORTB = (PORTB & 0xF0)|
> stepArray_Vorwaertz_8[stepp%MODULO_TEILER];
>       /********************************/
>       stepp++;

Die Reihenfolge
* zuerst ausgeben
* dann erhöhen
ist

dann ist die exakte UMkehrung davon

* zuerst erniedrigen
* dann ausgeben

das hier
>       PORTB = (PORTB & 0xF0)|
> stepArray_Vorwaertz_8[stepp%MODULO_TEILER];
>       /********************************/
>       stepp--;
ist daher die falsche Reihenfolge.

Aber selbst dann stimmt es noch nicht, weil du dann immer einen Schritt 
Rückwärts brauchst, um die letzte Erhöhung durch step++ wieder 
rückgängig zu machen. Es ist grundsätzlich besser, zuerst die Sache mit 
dem step zu erledigen und erst dann die Stepnummer am Port tatsächlich 
zu realisieren. Auf die Art stimmt die aktuell am Port vorliegende 
Motorposition dann auch tatsächlich mit der internen Repräsentierung 
durch step überein.


Im übrigen würde ich die absolute Schrittposition von einem internen 
laufenden Zähler trennen.

Zum einen sparst du dir dann die laufende Modulo-Division, zum anderen 
wirst du das sowieso machen müssen, wenn du irgendwann mal in der Lage 
sein musst zu sagen: Motor fahr mal an eine Endposition und dann 
definiere ich, dass diese Endposition die Schrittnummer 0 hat.


Also so
1
unsigned char stepArray_Vorwaertz_8[8] = {0x01,0x05,0x04,0x06,0x02,0x0A,0x08,0x09};
2
unsigned char currentStep;
3

4
void StepForward()
5
{
6
  currentStep++;
7
  if( currentStep == MODULO_TEILER )
8
    currentStep = 0;
9

10
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
11
}
12

13
void StepBackward()
14
{
15
  if( currentStep == 0 )
16
    currentStep = MODULO_TEILER - 1;
17
  else
18
    currentStep--;
19

20
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
21
}
22

23
...
24
if (directionState == STATE_RIGHT_DIRECTION_ON)/*(PINB & 0x10) == 0x00*/
25
  {
26
    if (stepp > 412)
27
    {
28
      directionState = STATE_LEFT_DIRECTION_ON;
29
    }
30
    else
31
    {
32
      step++;
33
      StepForward();
34
    }
35
  }
36
  else if (directionState == STATE_LEFT_DIRECTION_ON)/*(PINB & 0x20) == 0x00*/
37
  {
38
    if (stepp < 0)
39
    {
40
      directionState = STATE_RIGHT_DIRECTION_ON;
41
    }
42
    else
43
    {
44
      stepp--;
45
      stepBackward();
46
    }
47
  }
Gast #3613055
Lesenswert?

Hallo,

vielen Dank für die Hilfe. Ich muss gestehen ich versuche noch deine 
Lösung nach zu vollziehen.
1
void StepBackward()
2
{
3
  if( currentStep == 0 )
4
    currentStep = MODULO_TEILER - 1; <--
5
  else
6
    currentStep--;
7

8
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
9
}

Die Markierte Zeile habe ich aber bis jetzt nicht verstanden, könntest 
du mir diese bitte einmal kurz erklären.

Vielen Dank & ich hoffe ich stell mich nicht zu doof an.

Grüße Hans
Gast #3613096
Lesenswert?

Hallo,

die oben markierte Zeile habe ich jetzt verstanden. Ich denke man hat 
den "Groschen" fallen hören. ;-)

Nun habe ich aber leider ein verständnisproblem mit der Funktion 
stepForward().

Wenn currentStep beim Aufruf der Methode den Wert 0 hat, also der 1. 
Schritt durchlaufen werden soll, wird als 1. der currentStep einen 
hochgezählt und somit der 2. step durchgeführt. Richtig?

Ist das gewollt?

Gruß Hans
Gast #3613120
Lesenswert?

Hallo,

ich noch mal. ;-(

Nee geht leider nicht. Ich habe noch mal mein Code hier abgebildet.
1
volatile char stepArray_Vorwaertz_8[8] = {0x01,0x05,0x04,0x06,0x02,0x0A,0x08,0x09};
2

3

4
volatile signed int step=0;
5
volatile unsigned char currentStep=0;
6

7
volatile int sendMSGflag=0;
8
volatile int EEPROM eepromStepcounter = 0;
9
volatile char directionState = STATE_RIGHT_DIRECTION_ON;
10

11
void stepUP();
12
void stepDOWN();
13

14

15
ISR(TIMER0_OVF_vect)
16
{
17
  TCCR0  = 0x00;//Start the Timer counting
18
  TCNT0 = TIMER0_RELOAD_VALUE;//256-157 = 99 ==> 0x63
19

20
  if (directionState == STATE_RIGHT_DIRECTION_ON)/*(PINB & 0x10) == 0x00*/
21
  {
22
    if (step > 112)
23
    {
24
      directionState = STATE_LEFT_DIRECTION_ON;
25
    }
26
    else
27
    {
28
      /********************************/
29
      step++;
30
      stepUP();
31
      sendMSGflag=1;
32
      /********************************/
33
    }
34
  }
35
  else if (directionState == STATE_LEFT_DIRECTION_ON)/*(PINB & 0x20) == 0x00*/
36
  {
37
    if (step < 0)
38
    {
39
      directionState = STATE_RIGHT_DIRECTION_ON;
40
    }
41
    else
42
    {
43
      /********************************/
44
      step--;
45
      stepDOWN();
46
      sendMSGflag=1;
47
      /********************************/
48
    }
49
  }
50
  //_delay_ms(500);
51
  TCCR0  = 0x05;//Start the Timer counting
52
}
53

54
void stepUP()
55
{
56
  if( currentStep == MODULO_TEILER )
57
  {
58
    currentStep = 0;
59
  }
60
  else
61
  {
62
    currentStep++;
63
  }
64
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
65
}
66
void stepDOWN()
67
{
68
  if( currentStep == 0 )
69
  {
70
      currentStep = MODULO_TEILER - 1;
71
  }
72
  else
73
  {
74
    currentStep--;
75
  }
76
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
77
}

Ich hab echt keine Ahnung warum es nicht funktionieren will.


Bitte noch mal helfen.

Grüße Hans
#3613571
Lesenswert?

hans schrieb:

>
> Ich hab echt keine Ahnung warum es nicht funktionieren will.
>

Warum WAS nicht funktioniert?

Zu deinem anderen Problem

Es ist grundsätzlich ja egal wo du in der Tabelle anfaengst. So ein 
Schrittmotor ist ja rund. Der hat keine Vorzugsrichtung und auch keinen 
irgendwie speziell ausgeprägten Schritt 0.

in deinem Programm ist das wichtigste, das du gleich viele physikalische 
Schritte vor und zurück machst. Das wirst du eben nicht tun, zumindest 
hat das deine erste Version nicht getan, wenn man sich mal die Ausgaben 
auf den Port ansieht
Gast #3613694
Lesenswert?

Hallo,

ich habe ein stk papier an der Welle befästigt und laß den Motor dann 15 
mal vor und zurück bewegen (MAX 123; MIN 0). Nach dem 15ten mal stopt 
der Motor automatisch und ich kann an der Stellung des Papierstückes 
ablesen ob er genau an der Pos angehalten hat wo er gestartet ist.

Und er scheint immer etwas weiter zurück gefahren zu sein. ;-(

Und bevor ich es vergesse.Auch wenn es ich hier zu keiner Lösung kommen 
sollte, möchte ich mich auf jeden Fall bei euch allen bedanken!!!!!

Ich hoffe aber natürlich das mir jemand weiter helfen kann.

Anbei noch mal meine aktuelle Version:
1
volatile char stepArray_Vorwaertz_8[9] = {0x0A,0x02,0x06,0x04,0x05,0x01,0x09,0x08,0x0A};
2

3

4
volatile signed int step=0;
5
volatile unsigned char currentStep=CURRENT_STEP_START_POS;
6

7
volatile int sendMSGflag=0;
8
volatile int EEPROM eepromStepcounter = 0;
9
volatile char directionState = STATE_RIGHT_DIRECTION_ON;
10

11
void stepUP();
12
void stepDOWN();
13

14

15
ISR(TIMER0_OVF_vect)
16
{
17
  TCCR0  = 0x00;//Start the Timer counting
18
  TCNT0 = TIMER0_RELOAD_VALUE;//256-157 = 99 ==> 0x63
19

20
  if (directionState == STATE_RIGHT_DIRECTION_ON)/*(PINB & 0x10) == 0x00*/
21
  {
22
    if (step > MAX_UP_COUNT_VAL)
23
    {
24
      directionState = STATE_LEFT_DIRECTION_ON;
25
    }
26
    else
27
    {
28
      /********************************/
29
      step++;
30
      stepUP();
31
      sendMSGflag=1;
32
      /********************************/
33
    }
34
  }
35
  else if (directionState == STATE_LEFT_DIRECTION_ON)/*(PINB & 0x20) == 0x00*/
36
  {
37
    if (step == 0)
38
    {
39
      directionState = STATE_RIGHT_DIRECTION_ON;
40
      upDownCounter++;
41
      if (upDownCounter==15)
42
      {
43
        return;
44
      }
45
    }
46
    else
47
    {
48
      /********************************/
49
      step--;
50
      stepDOWN();
51
      sendMSGflag=1;
52
      /********************************/
53
    }
54
  }
55
  //_delay_ms(500);
56
  TCCR0  = 0x05;//Start the Timer counting
57
}
58

59
void stepUP()
60
{
61
  currentStep++;
62
  if( currentStep == MODULO_TEILER )
63
  {
64
    currentStep = 0;
65
  }
66
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
67
}
68
void stepDOWN()
69
{
70
  if( currentStep == 0 || currentStep == CURRENT_STEP_START_POS)
71
  {
72
      currentStep = MODULO_TEILER - 1;
73
  }
74
  else
75
  {
76
    currentStep--;
77
  }
78
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[currentStep];
79
}


Das verlieren der Schritte würde mich natürlich beruhigen da es bedeuten 
würde das ich nicht zu dumm bin. Aber das die Abweichung immer die selbe 
zu sein schein, glaube ich da leider nicht dran.

Noch mal vielen Dank!!!!

Grüße Hans
Gast #3613711
Lesenswert?

Hi

Mit welcher Frequenz wird denn deine ISR aufgerufen? Schrittmotoren 
besitzen eine sog. Start-Stop-Frequenz. Das ist die Frequenz, mit ein 
Schrittmotor Starten oder Stoppen kann ohne Schritte zu verlieren. Bei 
einer Drehrichtungsumkehr dürfte sich diese Frequenz noch halbieren. 
Leider gibt es dazu im 'Polln-Datenblatt' keine Angaben dazu.

MfG Spess
#3613730
Lesenswert?

hans schrieb:

> Und er scheint immer etwas weiter zurück gefahren zu sein. ;-(

Akkumuliert sich der Effekt, oder ist das nur beim ersten mal in jedem 
Programmlauf so.

Denn natürlich muss der Code beim starten den Motor erst mal einfangen. 
Der Code weiß ja nicht, bei welchem 'Schritt' der Motor gerade steht. 
Nur weil er als erstes 0b00000011 auf dem Port ausgibt, heißt das ja 
nicht, dass der Motor auch genau so steht. D.h. der wird da einen 
kleinen Sprung machen.

Nachdem der Motor aber erst mal 'eingefangen' ist, darf sich der Effekt 
nicht mehr akkumulieren.

> würde das ich nicht zu dumm bin. Aber das die Abweichung immer die selbe
> zu sein schein, glaube ich da leider nicht dran.

Mach halt dein erstes Programm einfacher, so dass du sicher sein kannst, 
keinen großen Fehler machen zu können. Das ist eigentlich die übliche 
Vorgehensweise. Irgendwie machen viele immer den gleichen Fehler: gleich 
mal mit einem relativ komplexen Programm anfangen, dass ein paar 
Fehlermöglichkeiten hat und dann kann man nicht mehr 
auseinanderklamüsern, wo der Fehler liegen könnte.
1
...
2
int main()
3
{
4
  int i;
5

6
  ...
7

8
  // den Motor mal einfangen, damit die externe Position mit der internen
9
  // übereinstimmt
10
  PORTB = (PORTB & 0xF0)| stepArray_Vorwaertz_8[0];
11
  stepUP();
12
  stepDOWN();
13

14
  _delay_ms( 1000 );
15

16
  while( 1 )
17
  {
18
    for( i = 0; i < 400; i++ )
19
    {
20
      stepUP();
21
      _delay_ms( 100 );
22
    }
23

24
    for( i = 0; i < 400; i++ )
25
    {
26
      stepDOWN();
27
      _delay_ms( 100 );
28
    }
29
  }
30
}

Das wäre mein erstes Testprogramm.
Durch die for-Schleifen hab ich erst mal alle möglichen Fehler 
ausgeschlossen, die ich durch die Umkehrsteuerung haben könnte, so dass 
ich hin und zurück unterschiedliche Schrittzahlen haben könnte. Hier hab 
ich auf jeden Fall erst mal gleiche Schrittzahlen - und das ist durcj 
die for-Schleifen garantiert und nicht davon abhängig ob ich die 
Inkrements und Dekrements bzw. die Schleifenabbruchbedingungen in der 
richtigen Reihenfolge habe.
Durch die vergleichsweise langen delays brauch ich auch keine Sorgen 
haben, dass ich ev. zu schnell fahren würde, so dass der Motor Schritte 
verliert.
Statt dessen kann ich mich ganz darauf konzentrieren, ob die stepUP bzw. 
stepDOWN Funktionen korrekt sind (was sie sein müssten). Wenn hier immer 
noch Schritte verloren gehen, dann kann der Fehler nur in einem Fehler 
in der Gleichbehandlung in diesen beiden Funktionen liegen (wie es in 
deinem Ursprungscode der Fall war - der erste Aufruf von stepDOWN machte 
tatsächlich einen Schritt nach oben)

Auch hab ich am Anfang, noch ehe die Hauptschleife beginnt, versucht 
dafür zu sorgen, dass der Motor gesichert auch tatsächlich in der 
Position steht, die der logischen Schrittposition 0 entspricht. Bestrome 
ich den Port mit einem Wicklungsmuster, dann richtet sich der Magnet im 
Motor ersmalig in diese Richtung aus. Durch Zufall könnte es jetzt sein, 
dass er genau um 180° verdreht zum Magnetfeld steht und sich nicht 
ausrichtet, also mach ich einmalig einmal hin und wieder zurück. Der 
Nettoeffekt ist, dass der Magnet im Motor tatsächlich genau so steht, 
wie es meiner SChrittposition 0 entspricht. Und erst dann kann ich 
sicher sein, dass 400 Schritte vorwärts auch physikalisch tatsächlich 
400 Schritte vorwärts sind.
Gast #3614148
Lesenswert?

Hallo,

meine Freq. ist ~140Hz. Und die Abweichung in die eine Richtung wird 
größer je mehr Wiederholungen man laufen läßt.

Aber der Ratschlag mit dem setzten der Startposition ist natürlich super 
richtig. Hab ich gleich eingebaut. ;-)

Leider hat es aber kleine Auswirkung auf mein Problem gehabt. An der 
Mechanik scheint es auch nicht zu liegen, da ich es bestimmt 10 mal mit 
jeweils 15 mal Vor- und zurück laufen ausprobiert habe und ich bin immer 
auf die selbe Abweichung gekomen.

Danke das ihr mich noch nicht aufgegeben habt. ;-)

Grüße Hans
Gast #3614165
Lesenswert?

Das ist doch schon mal gut eingekreist, Wenn er bei Durchlauf 400 
Schritte links und 399 rechts macht, sollte sich der Fehler im Programm 
doch finden lassen.

Als nächstes würde ich 2 Schitte rechts und 2 Schritte links machen. Mit 
10 Sekunden Abstand. Und an den 4 Pins messen, ob wirklich das das 
richtige Signal ausgegeben wird. Und ob am Ende wieder das selbe Signal 
anliegt, wie am Anfang.
Gast #3614328
Lesenswert?

Hallo,

ich habe nun eine Schrittzahl von 2 eingestellt und am Ossi die 
erwarteten Signale gemessen. da ich mir aber nicht 100%ig sicher war 
habe ich das Prog durch den Simulator gejagt.

Dabei ist raus gekommen das die Sequenz wie folgt aussieht.

Beginn:
0x01 start pos
0x01 1. Schritt
0x09 2. Schritt
0x01 3. Schritt
0x05 4. Schritt <--
0x01 5. Schritt
0x09 6. Schritt
0x01 7. Schritt

Bei der Startposition gibt es zwar eine kl. unregelmäßigkeit diese ist 
aber nur zu Beginn. bei weiteren Wiederholungen wechselt die folge 
zwischen

0x05 xx Schritt
0x01 xx Schritt
0x09 xx Schritt
0x01 xx Schritt
0x05 xx Schritt
...

diesen Schritten hin und her. Ich würde sagen also alles OK.

ich habe irgendwie das Gefühl das die Schritte unterschiedlich groß 
sind. Das kann aber ja eigentlich nicht sein das ich die selben Schritte 
ja vor- und zurück laufe.

Wie ist denn die Maximal Freq für die Änderung der Schrittfolge? Gibt es 
hierErfahrungen?

Noch mal Danke

Gruß Hans
Gast #3614342
Lesenswert?

hans schrieb:
> Wie ist denn die Maximal Freq für die Änderung der Schrittfolge? Gibt es
> hierErfahrungen?

Das hängt von deiner Motorspannung ab, weil der Stromanstieg in der 
Windung nach dem Umschalten des Treibers durch die Induktivität begrenzt 
wird. Und Strom bedeutet Magnetkraft und damit Drehmoment. Und das 
Drehmoment wird benötigt, um das Trägheitsmoment des Motor zu überwinden 
und auch noch die Last ohne Schrittverlust zu bewegen.
Gast #3614436
Lesenswert?

Zu viel Strom kann auch unregelmäßige Schritte ergeben. So ein 
Schrittmotor ist halt für Belastung und elastische Kupplung konstruiert. 
Wenn du nur eine Scheibe draufklemmst, solltest du ihn mit 1/10 des 
Nennstroms betreiben.

Allerdings bekommst du bei diesem Problem normalerweise unregelmäßige 
Fehler. Mal zu viel Schritte, mal zu wenig.
Gast #3614762
Lesenswert?

Hallo zusammen,

ich habe jetzt mal einen alten Schrittmotor aus der Schublade geholt und 
den angeschlossen. Ich es nun ein paar mal ausprobiert, mit 
unterschiedlichen freqenzen und unterschiedlicher Schrittzahl.

Und...

Es läuft einwandfrei. ;-)

Noch mal vielen vielen Dank an alle beteiligten!!!!!!!!!!

Eine letzte Frage:

Wie kann es sein das es bei dem einen Schrittmotor funktioniert und bei 
dem anderen nicht. Ich habe beide Motoren auf die gleiche weise 
angeschlossen.

Viele Grüße Hans
Gast #3614798
Lesenswert?

Je besser der Motor, desto mehr Probleme :-(
Wahrscheinlich hat dein alter Motor wenig Drehmoment und hohe 
Induktivität; läuft auch ohne Last ruhig. Der neue Motor hat so eine 
Kraft, dass er bei einem Schritt ein paar Raster weiter springt. Wie 
Mike schon sagte, erst einbauen und dann Strom und Beschleunigungsrampen 
ermitteln. Und hat schon seine Gründe, warum wir elastische Kupplungen 
für 10-20€ kaufen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren