Schrittmotor 28BYJ48 am Arduino

Seit einiger Zeit werden bei Ebay kleine Getriebe-Schrittmotoren vom Typ 28BYJ48 mitsamt einem ULN2003 Treibermodul aus China für unter drei Euro angeboten. Ohne zusätzliche Versandkosten! Keine Ahnung, wie sich das rechnet. Das gleiche Paket aus Schrittmotor und Treibermodul gibt es aber auch bei inländischen Anbietern für unter fünf Euro. (Zum Beispiel hier über Amazon).

28BYJ48, ULN2003, Arduino

28BYJ48, ULN2003, Arduino

Getriebe Übersetzung

Diese keinen Schrittmotoren werden offenbar eigentlich eingesetzt, um Steuerungsklappen in Klimaanlagen hin und her zu bewegen. Den Herstellern war es also egal, welche Übersetzung das Getriebe ganz genau hat. Zumindest bei meinem Modell stimmt die angegebene Übersetzung von 1:64 nicht genau. Es hat ebenfalls die hier berechnete Übersetzung von 1:63,68395. Das bedeutet, dass nicht 4096 Steps pro Umdrehung nötig sind, sondern nur 4075,772… Steps. Für viele Anwendungen ist das wohl egal, aber wenn der Motor fortlaufend in eine Richtung drehen soll (z.B. als Sekundenzeiger einer Uhr), muss dieser Umstand berücksichtigt werden.

Anschluss an den Arduino

ULN2003

ULN2003

Ich habe hier die digitalen Pins 8, 9, 10,11 des Arduino zum Anschluss des Motor-Treibers verwendet. Für die ersten Versuche reichte die Versorgung aus dem USB-Port. Für ernstzunehmende Anwendungen ist natürlich eine externe Quelle nötig.

Der Jumper auf dem Schrittmotor-Treiber (rechts neben dem VCC-Pin) muss gesteckt bleiben. Wenn ich es richtig verstehe, dann kann man durch entfernen dieses Jumpers die Stromversorgung zum Motor unterbrechen.

Betrieb am Arduino

Ich habe gar nicht versucht die Arduino Stepper-Library zu verwenden. Offenbar gab (gibt?) es mit der bei diesem Motor Probleme. Außerdem wollte ich genauer verstehen, wie man mit so einem Schrittmotor umgeht.Prinzipiell habe ich bei meinen Versuchen auf die Lösung von Benutzer celem im Arduino Forum aufgebaut.

Laut Datenblatt soll der Motor in folgender Sequenz angesteuert werden:

In 1 In 2 In 3 In 4
0 0 0 1
0 0 1 1
0 0 1 0
0 1 1 0
0 1 0 0
1 1 0 0
1 0 0 0
1 0 0 1

Ein einfacher Sketch zum Testen sieht zum Beispiel so aus:

const int motorPin1 = 8;  // Blue   - In 1
const int motorPin2 = 9;  // Pink   - In 2
const int motorPin3 = 10; // Yellow - In 3
const int motorPin4 = 11; // Orange - In 4
                          // Red    - pin 5 (VCC)

unsigned int lowSpeed  = 10000; // Notabene: nicht über 16000
unsigned int highSpeed =  1000;

void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
}

void loop()
{ unsigned long n = millis() / 3000; // 3 Sekunden

  switch(n % 8)
  { case 0: stop();               break;
    case 1: rechtsrum(lowSpeed);  break;
    case 2: stop();               break;
    case 3: linksrum(lowSpeed);   break;
    case 4: stop();               break;
    case 5: rechtsrum(highSpeed); break;
    case 6: stop();               break;
    case 7: linksrum(highSpeed);  break;
  }
}

void rechtsrum(unsigned int motorSpeed)
{ // 1
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(motorSpeed);

  // 2
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(motorSpeed);

  // 3
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(motorSpeed);

  // 4
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(motorSpeed);

  // 5
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, LOW);
  delayMicroseconds(motorSpeed);

  // 6
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(motorSpeed);

  // 7
  digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(motorSpeed);

  // 8
  digitalWrite(motorPin4, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, HIGH);
  delayMicroseconds(motorSpeed);
}

void linksrum(unsigned int motorSpeed)
{ // 1
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(motorSpeed);

  // 2
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(motorSpeed);

  // 3
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(motorSpeed);

  // 4
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(motorSpeed);

  // 5
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, LOW);
  delayMicroseconds(motorSpeed);

  // 6
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(motorPin4, HIGH);
  delayMicroseconds(motorSpeed);

  // 7
  digitalWrite(motorPin1, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delayMicroseconds(motorSpeed);

  // 8
  digitalWrite(motorPin1, HIGH);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin4, HIGH);
  delayMicroseconds(motorSpeed);
}

void stop()
{ digitalWrite(motorPin4, LOW);
  digitalWrite(motorPin3, LOW);
  digitalWrite(motorPin2, LOW);
  digitalWrite(motorPin1, LOW);
}

Werbung:

Weblinks:


14 comments to Schrittmotor 28BYJ48 am Arduino

  • Deine Definition der Sequenz als Array macht die Sache viel übersichtlicher. Ich hatte auch schon daran gedacht, die Sequenz gleich als Bitmuster abzulegen und in einem Schritt an den Ausgang zu übertragen. Da muss man aber sehr aufpassen, dass man nicht an Pin 0 und 1 herum fummelt, weil die für die serielle Kommunikation zuständig sind.

    Inzwischen habe ich meinen Motor zu einer Äquatoriale Montierung verarbeitet. Da hat er schwer zu arbeiten und bleibt bei ungünstiger Lage auch mal stehen. Werde mir wohl mal einen stärkeren Motor anschaffen müssen.

    • Gunther

      Hallo Heiner,
      super Beschreibung! Hat mir sehr geholfen.Vielen Dank dafür!
      Hier meine Kurzversion eines Testprogs mit Assembler :-)
      /* Schrittmotor Anschluss:
      * IN1 an Pin 0
      * IN2 an Pin 1
      * IN3 an Pin 2
      * IN4 an Pin 3
      * Servomotor läuft vorwärts
      */

      void setup()
      {
      DDRD=255;//Alle Pins des PORTD(Pin 0-7 des Arduinos) werden Ausgang
      PORTD=0;// Pin 0-7 werden auf Null gesetzt

      }

      void loop()
      {

      PORTD=1;// Ansteuerung des Motors, Schritt 1,2,3 usw.
      delay(2);
      PORTD=3;
      delay(2);
      PORTD=2;
      delay(2);
      PORTD=6;
      delay(2);
      PORTD=4;
      delay(2);
      PORTD=12;
      delay(2);
      PORTD=8;
      delay(2);
      PORTD=9;
      delay(2);

      }

  • Stefan

    hallo heiner,

    hier noch eine überarbeitete Version, bei welcher die Auflösung noch viel höher ist, da man die einzelnen “Schritte” ansteuern kann.

    Ich werde als nächstes einen Bipolar Schrittmotor mit einem L293D ansteuern und noch eine programmierte Stromabsenkung einabuen. Du kannst den Code oben löschen, da er noch Fehler enthält…

    Hast Du Bilder von deinem Projekt?

    Mfg

    Stefan

    //Schrittmotorsteuerung für 28BYJ-48 5VDC mit ULN2003A

    #define NrOfMotorOutputs 4 //Anzahl der Ausgänge zur Ansteuerung des Motors
    #define NrOfPatternsOneStep 8 //Anzahl der Muster zur Ansteuerung eines Schritts

    //Variabeln für Drehrichtung definieren
    const byte MotorOff = 0;
    const byte DirMotorRight = 1;
    const byte DirMotorLeft = 2;

    unsigned int ActStepNr = 0; //Aktueller Schritt

    //Schrittmuster definieren
    byte StepPattern[NrOfPatternsOneStep][NrOfMotorOutputs] =
    {
    { 0, 0, 0, 1 },
    { 0, 0, 1, 1 },
    { 0, 0, 1, 0 },
    { 0, 1, 1, 0 },
    { 0, 1, 0, 0 },
    { 1, 1, 0, 0 },
    { 1, 0, 0, 0 },
    { 1, 0, 0, 1 },
    } ;

    //Motor Pins für Ausgänge 1-4 definieren
    byte MotorOutputPin[NrOfMotorOutputs] = {10,11,12,13};

    void setup()
    {
    //Alle Pins als Ausgänge setzen und auf LOW schalten
    for (byte i=0; i < NrOfMotorOutputs; i++)
    {
    pinMode((MotorOutputPin[i]), OUTPUT);
    digitalWrite(MotorOutputPin[i], LOW);
    }
    }

    // the loop routine runs over and over again forever:

    void loop()
    {

    //Beispielprogramm zur Ansteuerung
    MotorMove(DirMotorRight,1, 2048); // MotorMove(Drehrichtung, MotorSpeed, Anzahl Schritte)
    delay(1000);
    MotorMove(DirMotorLeft,1, 2084);
    MotorMove(MotorOff,0, 0); //Motor stromlos Pin 1-4 = LOW
    delay(1000);

    }

    /////////////// Funktion für Motoransteuerung Anfang //////////////////
    void MotorMove(byte MotorDir, unsigned int MotorSpeed, unsigned int StepsToGo)
    {

    //Motor Stop alle Ausgänge auf LOW schalten
    if (MotorDir == MotorOff)
    {
    for (byte i=0; i < NrOfMotorOutputs; i++)
    {
    digitalWrite(MotorOutputPin[i], LOW);
    }
    }

    //Motor Rechtsdrehung
    else if (MotorDir == DirMotorRight)
    {
    for (int i=0; i < StepsToGo; i++)
    {
    ActStepNr++;
    if (ActStepNr == NrOfPatternsOneStep) ActStepNr = 0;
    for (byte j=0; j < NrOfMotorOutputs; j++)
    {
    digitalWrite(MotorOutputPin[j], StepPattern[ActStepNr][j]);
    }
    delay(MotorSpeed); //Verweilzeit um die Geschwindigkeit zu beeinflussen, für schnellere Ansteuereung ev. delayMicroseconds
    }
    }

    //Motor Linksdrehung
    else if (MotorDir == DirMotorLeft)
    {
    for (int i=0; i < StepsToGo; i++)
    {
    if (ActStepNr == 0) ActStepNr = NrOfPatternsOneStep-1;
    else ActStepNr–;
    for (byte j=0; j < NrOfMotorOutputs; j++)
    {
    digitalWrite(MotorOutputPin[j], StepPattern[ActStepNr][j]);
    }
    delay(MotorSpeed);
    }
    }
    }
    /////////////// Funktion für Motoransteuerung Ende //////////////////

  • John

    Geil,
    endlich läuft mein Motor vorwärts und rückwärts.
    Laut dieser Information ” http://rn-wissen.de/wiki/index.php/Schrittmotoren ” kann der Motor keine Halbschritte.
    Hab nen ganzen Tag zugebracht wegen einem Motor für 1,34€ aus China.
    ich beabsichtige ein Thermometer mit analoger Anzeige zu bauen.
    Bin Rentner und hab den ganzen Tag Zeit.

  • Rico

    Hallo Heiner

    Ich habe direkt mal Stefans Code ausprobiert und er läuft. Als Spannungsversorgung habe ich eine 9V Blockbatterie angeschlossen. Irgendwie hab ich mir den Motor aber etwas kraftvoller vorgestellt. Ist er wirklich gerade mal ausreichend um etwa einen kleinen Zeiger zu bewegen oder habe ich etwas falsch angeschlossen?

  • Andreas

    Hallo.

    Ein super Beitrag. Der Code ist klasse, funktioniert super. Vielen Dank!

  • Martin

    Danke an Alle,

    hat mir viel Zeit erspart! Habe den Motor von Pollin. Mit Platine S-SPSM-5V. Der macht 4096 Schritte pro U. Ich kann mit
    delayMicroseconds(MotorSpeed); bis 850 runter, schneller mag er nicht, und dann bleibt machmal hängen. Mit 900 ist er recht Stabil.
    Bei Stefan’s Code ist fast am Ende ein kleiner Fehler:
    else ActStepNr–; ich habe es in ActStepNr-=1; geändert. Dann läuft es.
    Der Motor ist nicht sehr stark, kommt auch davon das er durchdreht, wenn zu viel Last dran hängt.

  • Hier kurz ein Hinweis auf ein Projekt von Vulcaman bei instructables.com. Er hat es tatsächlich geschafft mit vier 28byj-48 Steppermotoren einen funktionierenden 3D-Drucker zu bauen. Die Gesamtkosten beliefen sich auf ca. 60 Euro.
    Hier der Link: Cherry- 60€ 3D-Printer

  • Cyp

    Hallo,
    habe so einen Motor geöffnet und die Zähnezahlen des Getriebes abgezählt. Der Motor selbst hat 64 Steps/Rev, das Getriebe hat ein Untersetzungsverhältnis von 8910 : 567424 = 63,68395062.. Dadurch kommt der Motor insgesamt auf 4075,7728395 Schritte je Umdrehung und nicht wie öfters behauptet 4096.

  • Maxi

    Danke, du hast mir endlich einfach aber genau erklärt wie ich meinen Stepper verwenden muss #anfänger

  • Tom

    Hallo noch eine Sache im Code ist ein Zahlendreher
    ungefähr Zeile 45 einmal hast du 2048 und anders rum dann 2084 geschrieben
    dreht sich bei mir auch nur in eine Richtung
    mal schauen wo noch ein Fehler ist

    • Ich habe den Code von Stefan nicht noch mal ausprobiert, aber ich denke das müsste trotz dieses Zahlendrehers funktionieren. Die 2048 beziehen sich soweit ich es sehe auf die Anzahl Steps. Für diesen Test ist es aber eher unerheblich, ob der Motor 2048 oder 2084 Steps dreht.

  • Sven

    Hallo,
    vielen Dank für die super Beschreibung!
    Ich habe eine andere Frage: der Motor dreht sich ja relativ “langsam”. Falls ich einen schnelleren brauche, zum Beispiel um ein kleines Auto oder sonstiges anzutreiben, welche Art Motor würde sich hierfür anbieten?

    Vielen Dank und viele Grüße
    Sven

    • Wenn die maximale Geschwindigkeit von Schrittmotoren nicht ausreicht würde ich einen stärkeren Motor mit einer passenden Übersetzung/Getriebe wählen.
      Für Autos etc. sind aber vermutlich normale Elektromotoren (falls nötig kombiniert mit einem Encoder) besser geeignet.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>