Forum: Mikrocontroller und Digitale Elektronik Programm zur Ansteuerung von Schrittmotor 28BYJ-48 5V Arduino


von Stefan G. (silentforce)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe soeben ein Programm zur Ansteuerung von dem oben genannten 
Schrittmotor geschrieben und möcht es mit euch teilen. Ev. werde ich es 
später noch ausbauen und z.B. Startrampen einbauen usw...

Für Tips und konstruktive Kritik bin ich sehr dankbar.....
1
//Schrittmotorsteuerung für 28BYJ-48 5VDC mit ULN2003A
2
3
4
//Befehle für Drehrichtung definieren
5
byte MotorStop    =   0; //wird automatisch am Ende nach Ausführung der Schritte aufgerufen
6
byte MotorRechts   =  1; //Definition von Rechts und Linksdrehung, bei Bedarf vertauschen
7
byte MotorLinks    =  2;
8
9
//Schrittabfolge definieren 1 Muster ergibt einen Schritt Vorwärts
10
byte StepValues[][4] =  { 
11
                        { 0, 0, 0, 1 }, 
12
                        { 0, 0, 1, 1 }, 
13
                        { 0, 0, 1, 0 }, 
14
                        { 0, 1, 1, 0 }, 
15
                        { 0, 1, 0, 0 }, 
16
                        { 1, 1, 0, 0 }, 
17
                        { 1, 0, 0, 0 }, 
18
                        { 1, 0, 0, 1 },       
19
                        } ; 
20
21
//Motor Pins für Ausgänge 1-4 definieren  (auf ->> Eingänge ULN2003A)
22
byte Motor_Ausgaenge[] = {10, 11, 12, 13};
23
 
24
25
// the setup routine runs once when you press reset:
26
27
void setup() { 
28
  
29
  //Alle Pins als Ausgänge setzen und auf LOW schalten
30
  for (byte i=0; i <= 3; i++){
31
      pinMode((Motor_Ausgaenge[i]), OUTPUT);
32
      digitalWrite(Motor_Ausgaenge[i], LOW);
33
      }      
34
 
35
}
36
37
// the loop routine runs over and over again forever:
38
39
void loop() {
40
  
41
  //Beispielprogramm zur Ansteuerung
42
  delay(1000);
43
  MotorMove(MotorRechts, 1000, 256); // MotorMove(Drehrichtung, Speed, Anzahl Schritte)
44
  delay(1000);
45
  MotorMove(MotorLinks, 1000, 256);
46
  MotorMove(MotorLinks, 2000, 256);
47
  MotorMove(MotorLinks, 3000, 256);
48
  MotorMove(MotorLinks, 5000, 256);
49
  delay(1000);
50
51
}
52
53
54
55
/////////////// Funktion für Motoransteuerung Anfang //////////////////
56
57
//MotorMove(byte Direction, int Speed, int Steps)
58
//Werte für Direction --> MotorRechts, MotorLinks, MotorStop (Motor Stop wird bei Rechts und Linksdrehung am Schluss aufgerufen)
59
//Werte für Speed --> kleinster Wert c.a. 1000 (Verweilzeit in Mikrosekunden) je kleiner desto schneller
60
//Werte für Anzahl Steps --> beliebig im Rahmen der int Variable
61
62
void MotorMove(byte Direction, int Speed, int Steps){ 
63
  
64
  //Motor Stop alle Ausgänge auf LOW schalten
65
  if (Direction == 0){  
66
    for (byte i=0; i <= 3; i++){
67
      digitalWrite(Motor_Ausgaenge[i], LOW);
68
    }      
69
         
70
  }
71
  
72
  //Motor Rechtsdrehung
73
  if (Direction == 1){  
74
    for (int i=0; i <= Steps; i++){     //Schleife für Anzahl Schritte
75
      for (int j=0; j <= 7; j++){       //Schleife für Anzahl Ansteuerungsmuster pro Schritt
76
          for (int k=0; k <= 3; k++){   //Schleife um alle Ausgänge zu setzen
77
            digitalWrite(Motor_Ausgaenge[k], StepValues[j][k]);
78
          }
79
          delayMicroseconds(Speed); //Verweilzeit um die Geschwindigkeit zu beeinflussen
80
      }
81
    }
82
  MotorMove(MotorStop, 0, 0); //nach beendigung aller Schritte Motor abschalten
83
  }
84
  
85
  //Motor Linksdrehung
86
  if (Direction == 2){  
87
    for (int i=0; i <= Steps; i++){     //Schleife für Anzahl Schritte
88
      for (int j=0; j <= 7; j++){       //Schleife für Anzahl Ansteuerungsmuster pro Schritt
89
          for (int k=0; k <= 3; k++){   //Schleife um alle Ausgänge zu setzen
90
            digitalWrite(Motor_Ausgaenge[k], StepValues[j][3-k]); //3-K Muster wird umgedreht
91
          }
92
          delayMicroseconds(Speed); //Verweilzeit um die Geschwindigkeit zu beeinflussen
93
      }
94
    }
95
  MotorMove(MotorStop, 0, 0); //nach beendigung aller Schritte Motor abschalten
96
  }
97
} //Ende Funktion Motoransteuerung
98
99
/////////////// Funktion für Motoransteuerung Ende //////////////////

: Bearbeitet durch User
von Sabine (Gast)


Lesenswert?

Die erreichbare Auflösung ist nicht so besonders, wenn man den Motor 
immer nur um ein Vielfaches dieser 8 Sub-Schritte ansteuern kann.
Was willst du denn selber mit diesem Motor noch so anstellen? Einfach 
nur so mal drehen lassen ist doch etwas langweilig.
(Mein eigenes Projekt mit 2 dieser Motoren: 
Beitrag "Plotter aus Billig-Steppern ( 28BYJ-48)")

von Public (Gast)


Lesenswert?

Stefan Geheim schrieb:
> Stepper.jpg
> 2 MB, 18 Downloads

Auf den ersten Blick würde ich sagen: "Arduino mit simplem Treiber, 
einem Stepper und ein paar Kabeln".

Was sollen mir diese 2MB sonst noch sagen?

von Karl H. (kbuchegg)


Lesenswert?

Gewöhn dir for Schleifen in der Form
1
   for( variable = 0; variable <= Ausdruck; variable++ )
2
                                ^
3
                                |
4
                                |

wieder ab.
Wenn du hier ein <= siehst, musst du hellhörig werden. In mehr als 80% 
aller Fälle ist das ein Fehler.

Ein Array mit 8 Elementen
1
int a[8];

bearbeitet man so in einer for-Schleife
1
   for( i = 0; i < 8; i++ )
2
     mach was mit a[i]

das hat nämlich den Vorteil, dass an beiden Stellen im Code dieselbe 8 
vorkommt. Wodurch man die beiden Teile im Code per #define auch 
zusammenfassen und damit vereinheitlichen kann
1
#define NR_WERTE 8
2
3
int a[NR_WERTE];
4
5
..
6
7
  for( i = 0; i < NR_WERTE; i++ )
8
    mach was mit a[i]
Nachdem der Präprozessor dann die Textersetzung von 'NR_WERTE' mit dem 
Text '8' gemacht hat, steht damit automatisch an beiden Stellen immer 
der gleiche Wert. Selbst dann wenn sich dieser Wert mal ändert
1
#define NR_WERTE 15
sorgt dann der Präprozessor dafür, dass die beiden Werte wieder 
zusammenstimmen. Er ersetzt ja beide Vorkommen von NR_WERTE durch 15. So 
etwas reduziert Fehler und erleichter Anpassungen.


Oder man kann auch so arbeiten
1
int a[] = { 0, 1, 2, 3 }
2
3
#define ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0])
4
5
...
6
7
   for( i = 0; i < ARRAY_SIZE(a); i++ )
8
     mach was mit a[i]
dann rechnet der Compiler selber aus, wie groß er das Arrya aufgrund der 
Initialisierung dimensioniert hat. Voraussetzung ist allerdings, das er 
das Array auch als Array zu Gesicht bekommt.


Du hast zwar an fast allen Stellen in deinem Programm dieses 
berücksicht, wenn du an die Arrays gegangen bist, aber nicht hier
1
...
2
    for (int i=0; i <= Steps; i++){     //Schleife für Anzahl Schritte
3
...
deine Funktion macht einen 'Schritt' zu viel. Wenn du die Funktion 
aufrufst mit
1
  MotorMove(MotorLinks, 1000, 256);
macht sie keine 256 Schritte, sondern 257.
Mal ganz davon abgesehen, dass deine 'Schritte' nicht das sind, was man 
gemeinhin unter 'Schritte' eines Schrittmotors versteht.

: Bearbeitet durch User
von Stefan G. (silentforce)


Lesenswert?

Sabine schrieb:
> Die erreichbare Auflösung ist nicht so besonders,

Nunja bei 512 Schritten/Umdrehung ergibt sich ja ein Schrittwinkel von 
c.a. 0.7 Grad. Mit einer Spindel von z.B. 2mm Steigung eine Auflösung 
von knapp 0,004 mm. Meiner ansicht nach für die allermeisten Projekte im 
Hobbybereich  absolut brauchbar.

Mir geht es hier darum die Grundlagen der Mikrokontrollerprogrammierung 
ein bisschen zu erforschen und kennenzulernen. Ich möchte dann erstmal 
ein kleines Solarpanel damit automatisch ausrichten...

Vielen Dank für den Link, werde mir das mal anschauen, sieht interessant 
aus. Ich habe vor Jahren eine komplette 4 Achsen CNC gebaut, gesteuert 
durch Mach 3...

von Stefan G. (silentforce)


Lesenswert?

Karl Heinz:

vielen  herzlichen Dank für deine sehr konstruktive und hilfreiche 
Kritik! Solche Kommentare wünscht man sich :-D


1
for( i = 0; i < 8; i++ )
2
     mach was mit a[i]

Klar da hast du recht, macht für mich auch mehr Sinn...


1
#define NR_WERTE 8
2
3
int a[NR_WERTE];

auch dies ein sehr nützlicher Hinweis. Ich habe jetzt die Anzahl der 
Ausgänge und die Anzahl der Muster so definiert. Das macht den Code 
flexibler und besser anpassbar... zudem noch übersichtlicher.. :-)


1
for (int i=0; i <= Steps; i++)



uups... das war ein Flüchtigkeitsfehler. Nach 2 Stunden Programmieren 
und lernen.. wohl schon etwas müde ;-)

1
Mal ganz davon abgesehen, dass deine 'Schritte' nicht das sind, was man gemeinhin unter 'Schritte' eines Schrittmotors versteht.

Wäre schön wenn du mir das noch genauer erläutern könntest?

Vielen Dank erstmal!!!

Und hier erstmal den korrigierten Code:
1
//Schrittmotorsteuerung für 28BYJ-48 5VDC mit ULN2003A
2
3
#define AnzAusgange 4 //Anzahl der Ausgänge zur Ansteuerung des Motors
4
#define AnzMuster 8 //Anzahl der Muster zur Ansteuerung eines Schritts
5
6
7
//Befehle für Drehrichtung definieren
8
byte MotorStop    =   0; //wird automatisch am Ende nach Ausführung der Schritte aufgerufen
9
byte MotorRechts   =  1; //Definition von Rechts und Linksdrehung, bei Bedarf vertauschen
10
byte MotorLinks    =  2;
11
12
//Schrittabfolge definieren 1 Muster ergibt einen Schritt Vorwärts
13
byte StepValues[AnzMuster][AnzAusgange] =  { 
14
                        { 0, 0, 0, 1 }, 
15
                        { 0, 0, 1, 1 }, 
16
                        { 0, 0, 1, 0 }, 
17
                        { 0, 1, 1, 0 }, 
18
                        { 0, 1, 0, 0 }, 
19
                        { 1, 1, 0, 0 }, 
20
                        { 1, 0, 0, 0 }, 
21
                        { 1, 0, 0, 1 },       
22
                        } ; 
23
24
//Motor Pins für Ausgänge 1-4 definieren  (auf ->> Eingänge ULN2003A)
25
byte Motor_Ausgaenge[AnzAusgange] = {10, 11, 12, 13};
26
 
27
28
// the setup routine runs once when you press reset:
29
30
void setup() { 
31
  
32
  //Serial.begin(9600);  //zu Testzwecken Debuggen
33
  
34
  //Alle Pins als Ausgänge setzen und auf LOW schalten
35
  for (byte i=0; i < AnzAusgange; i++){
36
      pinMode((Motor_Ausgaenge[i]), OUTPUT);
37
      digitalWrite(Motor_Ausgaenge[i], LOW);
38
      }      
39
 
40
}
41
42
// the loop routine runs over and over again forever:
43
44
void loop() {
45
  
46
  //Beispielprogramm zur Ansteuerung
47
  MotorMove(MotorRechts, 1000, 256); // MotorMove(Drehrichtung, Speed, Anzahl Schritte)
48
  delay(1000);
49
  MotorMove(MotorLinks, 1000, 256);
50
  delay(1000);
51
52
}
53
54
55
56
/////////////// Funktion für Motoransteuerung Anfang //////////////////
57
58
//MotorMove(byte Direction, int Speed, int Steps)
59
//Werte für Direction --> MotorRechts, MotorLinks, MotorStop (Motor Stop wird bei Rechts und Linksdrehung am Schluss aufgerufen)
60
//Werte für Speed --> kleinster Wert c.a. 1000 (Verweilzeit in Mikrosekunden) je kleiner desto schneller
61
//Werte für Anzahl Steps --> beliebig im Rahmen der int Variable
62
63
void MotorMove(byte Direction, int Speed, int Steps){ 
64
  
65
  //Motor Stop alle Ausgänge auf LOW schalten
66
  if (Direction == 0){  
67
    for (byte i=0; i < AnzAusgange; i++){
68
      digitalWrite(Motor_Ausgaenge[i], LOW);
69
    }      
70
         
71
  }
72
  
73
  //Motor Rechtsdrehung
74
  if (Direction == 1){  
75
    for (int i=0; i < Steps; i++){     //Schleife für Anzahl Schritte
76
      for (int j=0; j < AnzMuster; j++){       //Schleife für Anzahl Ansteuerungsmuster pro Schritt
77
          for (int k=0; k < AnzAusgange; k++){   //Schleife um alle Ausgänge zu setzen
78
            digitalWrite(Motor_Ausgaenge[k], StepValues[j][k]);
79
          }
80
          delayMicroseconds(Speed); //Verweilzeit um die Geschwindigkeit zu beeinflussen
81
          //Serial.print(i); 
82
          //Serial.print("\n");
83
      }
84
    }
85
  MotorMove(MotorStop, 0, 0); //nach beendigung aller Schritte Motor abschalten
86
  }
87
  
88
  //Motor Linksdrehung
89
  if (Direction == 2){  
90
    for (int i=0; i < Steps; i++){     //Schleife für Anzahl Schritte
91
      for (int j=0; j < AnzMuster; j++){       //Schleife für Anzahl Ansteuerungsmuster pro Schritt
92
          for (int k=0; k < AnzAusgange; k++){   //Schleife um alle Ausgänge zu setzen
93
            digitalWrite(Motor_Ausgaenge[k], StepValues[j][3-k]); //3-K Muster wird umgedreht
94
          }
95
          delayMicroseconds(Speed); //Verweilzeit um die Geschwindigkeit zu beeinflussen
96
      }
97
    }
98
  MotorMove(MotorStop, 0, 0); //nach beendigung aller Schritte Motor abschalten
99
  }
100
} //Ende Funktion Motoransteuerung
101
102
/////////////// Funktion für Motoransteuerung Ende //////////////////

von Stefan G. (silentforce)


Lesenswert?

> Auf den ersten Blick würde ich sagen: "Arduino mit simplem Treiber,
> einem Stepper und ein paar Kabeln".
>

Genau! Das hast du richtig erkannt :-)


> Was sollen mir diese 2MB sonst noch sagen?

Ich denke das reicht doch oder? Ist ja schon eine ganze Menge....

von Public (Gast)


Lesenswert?

Stefan Geheim schrieb:
> Ich denke das reicht doch oder? Ist ja schon eine ganze Menge....

Dafür, dass die Datenmenge 20000 mal so groß ist, wie der 
zusammenfassende Satz, würde ich doch noch etwas mehr Information 
erwarten.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Geheim schrieb:

>
1
Mal ganz davon abgesehen, dass deine 'Schritte' nicht das sind, 
2
> was man gemeinhin unter 'Schritte' eines Schrittmotors versteht.
3
>
>
> Wäre schön wenn du mir das noch genauer erläutern könntest?

Dein Schrittmotor macht ja immer 8 Schritte auf einmal, wenn ich ihn 
anweise 1 Schritt zu machen. Muss ja nicht sein. Du verschenkst dadurch 
ja Auflösung des Motors für nichts.
1
byte stepNr = 0;
2
3
void oneStepRechts()
4
{
5
  stepNr++;
6
  if( stepNr == 8 )
7
    stepNr = 0;
8
9
  for (byte k=0; k < 4; k++)
10
    digitalWrite( Motor_Ausgaenge[k], StepValues[stepNr][k]);
11
}
12
13
void oneStepLinks()
14
{
15
  if( stepNr == 0 )
16
    stepnr = 7;
17
  else
18
    stepNr--;
19
20
  for (byte_t k=0; k < 4; k++)
21
    digitalWrite( Motor_Ausgaenge[k], StepValues[stepNr][k]);
22
}
23
24
void MotorMove(byte Direction, int Speed, int Steps)
25
{ 
26
  if (Direction == MotorStop)
27
  {  
28
    for (byte i=0; i < 4; i++)
29
      digitalWrite( Motor_Ausgaenge[i], LOW );
30
  }
31
  
32
  else if (Direction == MotorRechts)
33
  {  
34
    for (int i=0; i < Steps; i++)
35
    {
36
      oneStepRechts();
37
      delayMicroseconds(Speed);
38
    }
39
  }
40
  
41
  else if (Direction == MotorLinks)
42
  {  
43
    for (int i=0; i < Steps; i++)
44
    {
45
      oneStepLinks();
46
      delayMicroseconds(Speed);
47
    }
48
  }
49
}

und achte ein wenig mehr auf deine Codekommentare. Die Hälfte deiner 
Kommentare im Code sind sinnlose Kommentare
1
    for (int i=0; i < Steps; i++){     //Schleife für Anzahl Schritte
das das eine Schleife ist, sehe ich im Code auch so. Und wenn die 
Schelifenvariable Step heisst, dann brauchst du mir im Kommentar auch 
nicht dazu schreiben, dass es sich um die Schleife für die Anzahl der 
Schritte handelt. Das kann ich "zur Not" auch so noch in 2 Sekunden 
erraten.

Als Ausgleich sollst du aber anstatt
1
  //Motor Rechtsdrehung
2
  if (Direction == 1){
was besseres schreiben. Du hast dir sooooo schöne Wertedefinitionen 
dafür gemacht (ein const davor würde noch guttun)
1
const byte MotorStop    =   0;
2
const byte MotorRechts   =  1;
3
const byte MotorLinks    =  2;
warum benutzt du sie denn nicht?
1
  if (Direction == MotorRechts){
dann brauchst du auch den Kommentar nicht. Denn das was mir der 
Kommentar erzählt, steht sowieso schon im Code mehr oder weniger im 
Klartext. Da steht "Wenn Richtung gleich Rechts". Noch ein paar 
Füllwörter dazu gedacht und fertig ist der komplette Satz. Ganz ohne 
Kommentar und nur durch Code ausgedrückt.


PS: Einen Schrittmotor brauchst du nicht im eigentlichen Sinne 
'Stoppen'. Wenn du keine Schritte machst, dann bewegt sich der auch 
nicht. Was du maximal tun kannst, ist alle Spulen stromlos schalten. Das 
will man aber meistens nicht wirklich. Denn dann hält der Motor nichts 
mehr - er lässt sich dann ganz leicht drehen. Und das will man dann ja 
meistens nicht, dass die vom Motor angetriebene Last den Motor 
verstellt, weil der keine Kraft hat, die Last an Ort und Stelle zu 
halten. Wenn schon, dann willst du das aber ganz sicher dem 
Anwendungscode überlassen, ob er das tun möchte oder nicht. 
Basisroutinen sollten eine derartig schwerwiegende Entscheidung nicht 
für sich selber treffen. Vor allen Dingen dann nicht, wenn es für den 
Anwendungscode keine Möglichkeit gibt, das zu umgehen. Ein
1
...
2
  MotorMove( MotorMove, 0, 0 );
3
...
kann der Anwendungscode immer aufrufen, wenn er die Spulen stromlos 
schalten will. Aber die Umkehrung kann er nicht erreichen. Er kann 
keinen
1
  MotorMove( MotorRechts, 1, 1000 );
aufrufen und nach vollzogener Bewegung den Motor unter Strom halten, 
damit der die Liftkabine, die er gerade hochgezogen hat, auch in der 
Station halten kann ohne dass die Kabine mit ihrem Eigengewicht den 
Motor in die andere Richtung zurückdreht.

: Bearbeitet durch User
von Stefan G. (silentforce)


Lesenswert?

Karl Heinz schrieb:
> Dein Schrittmotor macht ja immer 8 Schritte auf einmal, wenn ich ihn
> anweise 1 Schritt zu machen. Muss ja nicht sein. Du verschenkst dadurch
> ja Auflösung des Motors für nichts.

Genau da hast du natürlich Recht. Da dieser Motor aber stark untersetzt 
ist, würde dies immer noch lange reichen für mein gedachtes Projekt. Da 
ich aber jetzt ein Programm erstellen möchte welches universell ist, 
werde ich das entsprechend abändern.

Vielen Dank für deine Lösung für dieses "Problem". Ich habe mir den Code 
durchgeschaut und soweit verstanden.

Elegante Lösung um einen Minuswert zu verhindern... da brauchte ich eine 
Weile :)

> if( stepNr == 0 )
>     stepnr = 7;
>   else
>     stepNr--;

Kann es sein dass hier das "byte_t" ein Fehler ist?

> for (byte_t k=0; k < 4; k++)

Würde etwas dagegen sprechen die "oneStepRechts" und "oneStepLinks" 
Funktion direkt in die "MotorMove" Funktion einzubauen? Oder hat dies 
Nachteile?


Auch was die Kommentare angeht, bin ich mit dir einverstanden. Ich habe 
das so aufgebaut, weil ich mit den Kommentaren zuerst ein Gerüst 
erstellt habe und dann den Code eingefügt habe... Anfängermethode halt 
:-) Ist sicher mit kommender Routine und gut gewählten Namen völlig 
überflüssig..

> Als Ausgleich sollst du aber anstatt  //Motor Rechtsdrehung
>   if (Direction == 1){
> was besseres schreiben.

Klar ein weiterer Flüchtigkeitsfehler... Ich werde den Code nochmals 
überarbeiten und die Namen noch klarer und besser definieren.

> Einen Schrittmotor brauchst du nicht im eigentlichen Sinne
> 'Stoppen'. Wenn du keine Schritte machst, dann bewegt sich der auch
> nicht.

Das ist mir schon klar, ich habe auch schon eine 4 achsen NC mit 
Schrittmotoren gebaut und arbeite seit 20 Jahren als Feinmechaniker. Das 
Wort Stop ist hier natürlich ein bisschen unglücklich gewählt. 
Eigentlich dient es nur dazu die Motoren Stromlos zu schalten 
(Überhitzung/Stromverbruach). Das war auch der Hintergedanke für mein 
Projekt "Solarpanel ausrichten". Da macht es natürlich Sinn den Strom 
noch für das halten eines Motores zu verpuffen. Da es ein "stark" 
übersetzter Getriebemotor ist, reicht das Haltemoment allemal aus... Ev. 
könnte man das auch noch über ein Schneckengetriebe verbessern. Aber 
eben, der Code soll ja universeller werden. Deshalb stimme ich dir auch 
hier wieder zu...

Wahrscheinlich werde ich dies über einen Parameter lösen, wo man diese 
Funktion ein und auschalten kann.

Bei der Schrittmotorsteuerung die ich für die NC Fräse verwendet habe, 
gab es eine "Stromabsenkungsfunktion" damit die Motoren "halten" und 
doch nicht zu heiss werden. Wie wäre dies realisierbar?

Dann bedanke ich mich erneut bei dir für dein Mühe, ich weiss das sehr 
zu schätzen... ich habe viel dazu gelernt :-)

von mike (Gast)


Lesenswert?

Stefan Geheim schrieb:
> Bei der Schrittmotorsteuerung die ich für die NC Fräse verwendet habe,
> gab es eine "Stromabsenkungsfunktion" damit die Motoren "halten" und
> doch nicht zu heiss werden. Wie wäre dies realisierbar?

Mit einem Schrittmotortreiber, bei dem es die Möglichkeit gibt, den 
Sollwert für den Strom durch ein Steuersignal zu ändern, z.B. indem man 
die Referenzspannung für den Stromsollwert per PWM (mit TP-Filter) 
vorgibt.

von Stefan G. (silentforce)


Lesenswert?

Hier erstmal der überarbeitete Code. Ich habe für die Variabeln noch 
klarere Namen verwendet und alles in Englisch gemacht:
1
//Schrittmotorsteuerung für 28BYJ-48 5VDC mit ULN2003A
2
3
4
#define NrOfMotorOutputs 4 //Anzahl der Ausgänge zur Ansteuerung des Motors
5
#define NrOfPatternsOneStep 8 //Anzahl der Muster zur Ansteuerung eines Schritts
6
7
8
//Variabeln für Drehrichtung definieren
9
const byte MotorOff        =  0; 
10
const byte DirMotorRight   =  1; 
11
const byte DirMotorLeft    =  2;
12
13
byte ActStepNr = 0; //Aktueller Schritt
14
15
//Schrittmuster definieren
16
17
byte StepPattern[NrOfPatternsOneStep][NrOfMotorOutputs] =  
18
{ 
19
{ 0, 0, 0, 1 }, 
20
{ 0, 0, 1, 1 }, 
21
{ 0, 0, 1, 0 }, 
22
{ 0, 1, 1, 0 }, 
23
{ 0, 1, 0, 0 }, 
24
{ 1, 1, 0, 0 }, 
25
{ 1, 0, 0, 0 }, 
26
{ 1, 0, 0, 1 },    
27
} ; 
28
29
30
//Motor Pins für Ausgänge 1-4 definieren
31
byte MotorOutputPin[NrOfMotorOutputs] = {10,11,12,13};
32
33
34
void setup() 
35
{  
36
  //Alle Pins als Ausgänge setzen und auf LOW schalten
37
  for (byte i=0; i < NrOfMotorOutputs; i++)
38
  {
39
      pinMode((MotorOutputPin[i]), OUTPUT);
40
      digitalWrite(MotorOutputPin[i], LOW);
41
  } 
42
}
43
44
45
void loop() 
46
{
47
  
48
  //Beispielprogramm zur Ansteuerung
49
  MotorMove(DirMotorRight,1, 2048); // MotorMove(Drehrichtung, MotorSpeed, Anzahl Schritte)
50
  delay(1000);
51
  MotorMove(DirMotorLeft,1, 2084); 
52
  MotorMove(MotorOff,0, 0); //Motor stromlos Pin 1-4 = LOW
53
  delay(1000);
54
55
}
56
57
58
/////////////// Funktion für Motoransteuerung Anfang //////////////////
59
void MotorMove(byte MotorDir, unsigned int MotorSpeed, unsigned int StepsToGo)
60
{ 
61
  
62
  //Motor Stop alle Ausgänge auf LOW schalten
63
  if (MotorDir == MotorOff)
64
  {  
65
    for (byte i=0; i < NrOfMotorOutputs; i++)
66
    {
67
      digitalWrite(MotorOutputPin[i], LOW);
68
    }            
69
  }
70
  
71
  //Motor Rechtsdrehung
72
  else if (MotorDir == DirMotorRight)
73
  {  
74
    for (int i=0; i < StepsToGo; i++)
75
    {
76
      ActStepNr++;
77
      if (ActStepNr == NrOfPatternsOneStep) ActStepNr = 0;
78
      for (byte j=0; j < NrOfMotorOutputs; j++)
79
      {
80
        digitalWrite(MotorOutputPin[j], StepPattern[ActStepNr][j]);
81
      }
82
      delay(MotorSpeed); //Verweilzeit um die Geschwindigkeit zu beeinflussen, für schnellere Ansteuereung ev. delayMicroseconds
83
    }
84
  }
85
  
86
  //Motor Linksdrehung
87
  else if (MotorDir == DirMotorLeft)
88
  {  
89
    for (int i=0; i < StepsToGo; i++)
90
    {  
91
      if (ActStepNr == 0) ActStepNr = NrOfPatternsOneStep-1;
92
      else ActStepNr--;
93
      for (byte j=0; j < NrOfMotorOutputs; j++)
94
      {
95
        digitalWrite(MotorOutputPin[j], StepPattern[ActStepNr][j]);
96
      }
97
      delay(MotorSpeed);
98
    }
99
  }
100
}
101
/////////////// Funktion für Motoransteuerung Ende //////////////////

Jetzt habe ich noch einen Bipolar Stepper vom Betrieb bekommen und werde 
diesen mit einem L293D ansteuern und ein paar neue Funktionen einbauen 
wie: Stromabsenkungsfunktion, mehrere Motoren, Anfahr/Stop Rampe.

von Stefan G. (silentforce)


Lesenswert?

mike schrieb:

> Mit einem Schrittmotortreiber, bei dem es die Möglichkeit gibt, den
> Sollwert für den Strom durch ein Steuersignal zu ändern, z.B. indem man
> die Referenzspannung für den Stromsollwert per PWM (mit TP-Filter)
> vorgibt.


Dies wäre also mit dem L293D möglich und dem Bipolarstepper. Ich nehme 
an der TP Filter ist da um die Spannung zu glätten? Wie müsste ich 
diesen berechnen? Würde sich ohne TP-Filter ev. die Position des Motors 
ändern oder würde es auch ohne gehen?

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Lesenswert?

Ohne wirst du ein starkes Rauschen hören, weil sich der Strom in den 
Motorwicklungen ständig leicht ändert. Es geht aber auch ohne PWM, in 
dem man einen Spannungsteiler aufbaut, den man über einen Transistor 
umschalten kann. So z.B.:
http://www.mechapro.de/pdf/3D-Step_Doku_20120915.pdf (Schaltplan S. 7)
Oder einfacher:
http://www.mechapro.de/pdf/tinystep_doku.pdf (Schaltplan auf S. 4)

Mit freundlichen Grüßen
Thorsten Ostermann

von Stefan G. (silentforce)


Lesenswert?

Thorsten Ostermann schrieb:
> Ohne wirst du ein starkes Rauschen hören, weil sich der Strom in
> den
> Motorwicklungen ständig leicht ändert.


Hallo Thorsten,

vielen Dank für deinen Hinweis. Ich habe vor Jahren bei dir Bausätze für 
die 3d Step, HP Step und Tiny Step gekauft als ich meine NC Maschinen 
gebaut habe, welche ich inzwischen leider wieder verkauft habe. Damals 
hiess es glaube ich noch NC-Step... Von daher kenne ich auch diese 
Stromabsenkungsfunktion. Schön dass es deinen Shop immer noch gibt. Ich 
war sehr zufrieden mit den Produkten und dem super Support.

Ich werde mir die Schaltpläne mal anschauen... auf die Idee bin ich gar 
nicht gekommen. Ich habe den Motor mit dem L293D mittlerweilen mal 
angeschlossen und das Rauschen ist deutlich zu hören... :-)

Ich könnte mir natürlich einfach eine professionelle Karte von dir 
kaufen, aber ich möchte ja etwas mehr über Elektronik lernen... (arbeite 
als Mechaniker auf NC-Maschinen)

von Sabine W. (sabine_w)


Lesenswert?

Lässt sich eigentlich mit entsprechend angepassten Strömen auch jeder 
beliebige Zwischenwinkel erzeugen, um z.B. einen weicheren Lauf oder 
eine höhere Auflösung zu bekommen?

von Karl H. (kbuchegg)


Lesenswert?

Sabine W. schrieb:
> Lässt sich eigentlich mit entsprechend angepassten Strömen auch jeder
> beliebige Zwischenwinkel erzeugen,

das nennt sich dann 'Microstepping'

von Mike (Gast)


Lesenswert?

Sabine W. schrieb:
> Lässt sich eigentlich mit entsprechend angepassten Strömen auch jeder
> beliebige Zwischenwinkel erzeugen, um z.B. einen weicheren Lauf oder
> eine höhere Auflösung zu bekommen?

Ja, das nennt sich dann Mikroschrittbetrieb. Die Genauigkeit mit der die 
Winkelunterteilung stattfindet, hängt sehr vom Aufbau des Motor ab. Der 
Lauf wird auf jeden Fall ruhiger.

von Marcel O. (marcel_o)


Lesenswert?

Hallo,

bin neu hier und absoluter Noob was Programmieren angeht .
Demzufolge fand ich die anfänglichen Codekommentare einfach klasse auch 
wenn für viele überflüssig.

mit dem Code Läuft mein Stepper jetzt , anstatt dieses "  delay(1000);"
möchte ich den Befehl mit Tastern ausführen.

Taster an Pin 2,3,4
Pin 2 Start Motor rechts
Pin 3 Stop
Pin 4 Start Motor links.

Die anzahl der Steps kann ich im Sketch ändern und diese soll er per 
Tastendruck ablaufen lassem.


Gruß Marcel.

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.