Wemos D1 Mini – Schrittmotor 28BYJ-48 ruckelt, bleibt stehen

Hallo,
ich habe leider ein Problem mit meinem Projekt, bei dem ich trotz Recherche seit einigen Wochen nicht weiter komme.

Ich möchte mit einem Wemos D1 Mini einen Schrittmotor 28BYJ-48 mit Treiberplatine ULN2003 antreiben.
Der Motor läuft, allerdings ruckelt und stoppt er ständig, so dass sich eine neue Endposition ergibt.

Der Motor soll eine volle Umdrehung in eine Richtung machen, kurz warten und dann eine volle Umdrehung zurück fahren.

Als Anleitung habe ich mich hier bedient:

Ich verwende die selbe Hard- und Software (Sektch und Bibliothek) die dort beschrieben ist.

An einem Punkt, musste ich allerdings von dieser Anleitung abweichen.
Damit der Wemos nach einem Reset startet, musste ich an den Pin D8 einen 10k Widerstand anbringen. Da der Wemos sonst in einen speziellen Modus bootet. Was auch der Dokumentation des Wemos entspricht.
Umso mehr ist es verwunderlich, dass das in dieser, und in anderen, Anleitung offenbar nicht notwendig ist.

Als Stromversorgung habe ich drei verschiedene Methoden ausprobiert, da ich gelesen hatte, dass es daran liegen könnte. Was mir aber leider nicht weiter geholfen hat.

Laptop USB → Wemos
5V des Wemos→ Schrittmotor

Laptop USB → Wemos
Steckernetzteil 5V; 2,5A → Schrittmotor

Steckernetzteil 5V; 2,0A → Wemos
Steckernetzteil 5V; 2,5A → Schrittmotor

Außerdem habe ich den Wemos und den Schrittmotor inkl. Treiberplatine ausgetauscht, um möglichst einen Hardware Defekt auszuschließen.

Hier nochmal der Code des Sketchs, der auch oben in der Anleitung angegeben ist.

#include <StepperMotor.h> //Einbinden der Bibliothek StepperMotor.h

StepperMotor motor(D5,D6,D8,D7); // IN1, IN2, IN3, IN4

//Die maximale Geschwindigkeit bei 5Volt ist 15 RPM (RoundsPerMinute)
//Je größer der Wert ist desto langsamer wird der Motor. 
//Mit einem langsamen Motor kann man größere Kräfte erzeugen!
int motorSpeed = 1; 

//Es benötigt 4096 Schritte für eine volle Umdrehung.
int motorSteps = 4096; 

//Wert für die Pause zwischen den Schritten.
int motorDelay = 1000;

void setup(){
  motor.setStepDuration(motorSpeed);
}

void loop(){
  //Erst eine volle Umdrehung entgegen des Uhrzeigersinns durchführen.
  motor.step(motorSteps); 
  delay(motorDelay); //Eine kleine Pause einlegen.

  //Danach eine volle Umdrehung im Uhrzeigersinn durchführen.
  motor.step(-motorSteps);
  delay(motorDelay); //Eine kleine Pause einlegen.
}

Anbei noch die Fotos zu meinem Aufbau.
→ Sry der Bild Upload funktioniert, laut Forum, aus “Sicherheitsgründen” nicht.

Ich hoffe es kann mir jemand weiterhelfen.
Vielen Dank schon einmal im Voraus!

Bitte Link zur Bibliothek
Grüße Uwe

rydepier / Arduino-and-ULN2003-Stepper-Motor-Driver

Hallo,

versuch mal die beiden mittleren Anschlüsse zu tauschen

Beim Uno wäre normal pin

2,3,4,5 auf IN1,IN2,IN3,IN4 Hardware

in der Software hab ich´s aber so verwendet

Stepper myStepper(stepsPerRevolution, 2, 4, 3, 5);

Heinz

hansdampff:
Ich möchte mit einem Wemos D1 Mini einen Schrittmotor 28BYJ-48 mit Treiberplatine ULN2003 antreiben.
Der Motor läuft, allerdings ruckelt und stoppt er ständig, so dass sich eine neue Endposition ergibt.

Einen Wemos D1 Mini habe ich nicht und die verwendete Bibliothek ist mir unbekannt, daher teste ich mit einem ESP32 und AccelStepper:

#include <AccelStepper.h>

// Motor 28BYJ-48 Windungen: Pins 1-5-3, 2-5-4. 5:VDD; IN1 = /IN3, IN2 = /IN4
#define IN1  32
#define IN2  33
#define IN3  25
#define IN4  26

const uint16_t schritteProUmdrehung = 4096;
AccelStepper stepper(AccelStepper::HALF4WIRE, IN1, IN3, IN2, IN4);

void setup()
{
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(4000);
}

void loop()
{
  const uint32_t pause = 1000;
  static bool hin = true;
  stepper.run();

  if (stepper.distanceToGo() == 0)
  {
    if (hin) {
      stepper.moveTo(schritteProUmdrehung);
    } else {
      stepper.moveTo(0);
    }
    hin = !hin;
    delay(pause);
  }
}

Nach meiner Beobachtung läuft das ohne jegliche Unterbrechung, auch mit OTA:

#include <ArduinoOTA.h>
#include <AccelStepper.h>

// Motor 28BYJ-48 Windungen: Pins 1-5-3, 2-5-4. 5:VDD; IN1 = /IN3, IN2 = /IN4
#define IN1  32
#define IN2  33
#define IN3  25
#define IN4  26

const uint16_t schritteProUmdrehung = 4096;
AccelStepper stepper(AccelStepper::HALF4WIRE, IN1, IN3, IN2, IN4);

void setup() {
  const char *ssid = "Esp32AP";             // << kann bis zu 32 Zeichen haben
  const char *password = "12345678";        // << mindestens 8 Zeichen jedoch nicht länger als 64 Zeichen
  WiFi.mode(WIFI_AP);
  WiFi.softAP(ssid, password);
  ArduinoOTA.begin();

  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(4000);
}

void loop() {
  ArduinoOTA.handle();
  bewegung();
}

void bewegung()
{
  const uint32_t pause = 1000;
  static bool hin = true;
  stepper.run();

  if (stepper.distanceToGo() == 0)
  {
    if (hin) {
      stepper.moveTo(schritteProUmdrehung);
    } else {
      stepper.moveTo(0);
    }
    hin = !hin;
    delay(pause);
  }
}

Vielen Dank für die Antworten!
@Rentner

Das wäre dann eine Änderung die in meinem Fall wie folgt aussieht:
Vorgabe laut Anleitung

IN 1 2 3 4
PIN 5 6 8 7

Änderung nach deiner Empfehlung

IN 1 2 3 4
PIN 5 8 6 7

Das Ergebnis sieht leider nicht gut aus. Der Motor dreht mit dieser Konfiguration gar nicht mehr und brummt nur vor sich hin.

@agmue
Ich habe hier noch einen ESP32 herumliegen und werde es einfach mal damit ausprobieren.

Für weitere Hinweise, wäre ich trotzdem dankbar!

hansdampff:
@Rentner

Das wäre dann eine Änderung die in meinem Fall wie folgt aussieht:
Vorgabe laut Anleitung

IN 1 2 3 4
PIN 5 6 8 7

Änderung nach deiner Empfehlung

IN 1 2 3 4
PIN 5 8 6 7

Das Ergebnis sieht leider nicht gut aus. Der Motor dreht mit dieser Konfiguration gar nicht mehr und brummt nur vor sich hin.

War mal einen Versuch wert, denn das gilt für die AccelStepper-Bibliothek. Da Du aber eine spezielle Bibliothek für diesen Motor verwendest, ist Deine ursprüngliche Konfiguration wohl richtig.

hansdampff:
Ich habe hier noch einen ESP32 herumliegen und werde es einfach mal damit ausprobieren.

Gute Idee!

Könntest Du auch die vermutlich bessere AccelStepper-Bibliothek verwenden?

Ich habe mich getäuscht, ich habe hier noch einen Lolin NodeMCU v3.
Der hat offenbar andere Pinbelegungen als in deinem Code verlangt werden.

Hättest du eventuell die passende Pinbelegung für den Anschluß des Schrittmotors?
Ich habe leider erst morgen Zeit zur Recherche.

Mit dem ES8266 beschäftige ich mich nur sehr am Rande, da möchte ich keine falschen Informationen in die Welt setzen. Für des ESP32 habe ich eine Seite gefunden, welche Pins man unbedenklich nutzen kann, da verwende ich dann die grünen.

Gibt es auch für den ESP8266: ESP8266 Pinout Reference: Which GPIO pins should you use?

Morgen ist auch ein schöner Tag!

Ich habe nun noch etwas herum gespielt und konnte zwei Probleme identifizieren und beheben.

  1. Das Treiberboard (ULN2003) des Schrittmotors scheint defekt zu sein. Mit einem neuen Board und deinem Quellcode und der AccelStepper Bibliothek lief es.

  2. “Mein” Code zur StepperMotor Bibliothek musste bei der Zuordnung der Anschlüsse zur Motortreiberboard angepasst werden. Den Code hatte ich von einer Vorlage (siehe mein erster Beitrag) kopiert.

Diese Reihenfolge funktioniert für mich:

StepperMotor motor(D5,D6,D7,D8); // IN4, IN3, IN2, IN1

Der Motor läuft nun mit dem neuen Motortreiberboard und der StepperMotor bzw. der AccelStepper Bibliothek.
Auch der Wemos D1 Mini und der Lolin NodeMCU funktionieren.

Damit ist das Problem also endlich gelöst! Auch wenn ich es nicht verstehe, warum der vorgegebene Code mit den vorgegebenen Bauteilen für mich nicht funktioniert. Vielleicht liegt das ja einem veränderten Aufbau z.B. des Motors.

Da ich nun einen schönen Vergleich zwischen den Bibliotheken (StepperMotor - Accelstepper) habe, fällt mir auf, dass der Motor mit der StepperMotor Bibliothek in einer Situation ruhiger läuft.
Vielleicht gibt es dafür nun auch noch eine Lösung, auch wenn ich dieses Thema evtl. in ein neues “Ticket” packen sollte. Aber vielleicht liest hier ja schon jemand mit, der eine Lösung parat hat.

Unter Verwendung StepperMotor Bibliothek und des Codes, den ich hier unten noch einmal angebe, klingt es so, als würde der Motor nach Vollendung der ersten Umdrehung blockieren.

Auf dem Treiberboard flackert dann die LED D3. Soweit ich das sehe fährt der Motor aber korrekt seine volle Umdrehung und findet auch immer korrekt seine Endposition wieder.

Das ist also vielleicht nur ein kleiner Schönheitsfehler.
Aber da es mit der AccelStepper Bibliothek problemlos funktioniert, müsste das mit der StepperMotor Bibliothek doch auch funktionieren. Oder es hat eher mit dem Code des Sketchs zu tun.

Sketch für StepperMotor Bibliothek, Hier klingt der Motor nach der ersten Umdrehung so als würde er blockieren, bevor er dann wie gewünscht in die Gegenrichtung fährt und am Endpunkt korrekt “ruhig” stehen bleibt.

#include <StepperMotor.h> //Einbinden der Bibliothek StepperMotor.h

StepperMotor motor(D5,D6,D7,D8); // IN4, IN3, IN2, IN1

//Die maximale Geschwindigkeit bei 5Volt ist 15 RPM (RoundsPerMinute)
//Je größer der Wert ist desto langsamer wird der Motor. 
//Mit einem langsamen Motor kann man größere Kräfte erzeugen!
int motorSpeed = 1; 

//Es benötigt 4096 Schritte für eine volle Umdrehung.
int motorSteps = 4096; 

//Wert für die Pause zwischen den Schritten.
int motorDelay = 1000;

void setup(){
  motor.setStepDuration(motorSpeed);
}

void loop(){
  //Erst eine volle Umdrehung entgegen des Uhrzeigersinns durchführen.
  motor.step(motorSteps); 
  delay(motorDelay); //Eine kleine Pause einlegen.

  //Danach eine volle Umdrehung im Uhrzeigersinn durchführen.
  motor.step(-motorSteps);
  delay(motorDelay); //Eine kleine Pause einlegen.
}

Zugehörige StepperMotor.cpp

#include <Arduino.h>
#include <StepperMotor.h>

StepperMotor::StepperMotor(int In1, int In2, int In3, int In4){
    // Record pin numbers in the inputPins array
    this->inputPins[0] = In1;
    this->inputPins[1] = In2;
    this->inputPins[2] = In3;
    this->inputPins[3] = In4;

    // Iterate through the inputPins array, setting each one to output mode
    for(int inputCount = 0; inputCount < 4; inputCount++){
        pinMode(this->inputPins[inputCount], OUTPUT);
    }
    duration = 50;
}

void StepperMotor::setStepDuration(int duration){
    this->duration = duration;
}

void StepperMotor::step(int noOfSteps){
    /*
        The following 2D array represents the sequence that must be
        used to acheive rotation. The rows correspond to each step, and
        the columns correspond to each input. L
    */
    bool sequence[][4] = {{LOW, LOW, LOW, HIGH },
                          {LOW, LOW, HIGH, HIGH},
                          {LOW, LOW, HIGH, LOW },
                          {LOW, HIGH, HIGH, LOW},
                          {LOW, HIGH, LOW, LOW },
                          {HIGH, HIGH, LOW, LOW},
                          {HIGH, LOW, LOW, LOW },
                          {HIGH, LOW, LOW, HIGH}};
                      
    int factor = abs(noOfSteps) / noOfSteps;    // If noOfSteps is +, factor = 1. If noOfSteps is -, factor = -1 
    noOfSteps = abs(noOfSteps);    // If noOfSteps was in fact negative, make positive for future operations

    /* 
        The following algorithm runs through the sequence the specified number 
        of times
    */
    for(int sequenceNum = 0;  sequenceNum <= noOfSteps/8; sequenceNum++){
        for(int position = 0; ( position < 8 ) && ( position < ( noOfSteps - sequenceNum*8 )); position++){
            delay(duration);
            for(int inputCount = 0; inputCount < 4; inputCount++){
                digitalWrite(this->inputPins[inputCount], sequence[(int)(3.5 - (3.5*factor) + (factor*position))][inputCount]);
            }
        } 
    }
}

Zugehörige StepperMotor.h

#ifndef Stepper_h
#define Stepper_h

class StepperMotor {
public:
    StepperMotor(int In1, int In2, int In3, int In4);    // Constructor that will set the inputs
    void setStepDuration(int duration);    // Function used to set the step duration in ms
    void step(int noOfSteps);    // Step a certain number of steps. + for one way and - for the other

    int duration;    // Step duration in ms
    int inputPins[4];    // The input pin numbers
};

#endif

hansdampff:
Ich habe nun noch etwas herum gespielt und konnte zwei Probleme identifizieren und beheben.

Sehr schön :slight_smile:

hansdampff:
Aber da es mit der AccelStepper Bibliothek problemlos funktioniert, müsste das mit der StepperMotor Bibliothek doch auch funktionieren.

Was veranlaßt Dich zu dieser Annahme? "Wenn ich die Strecke mit meinem Porsche in zwei Stunden schaffe, dann muß das mit einem Käfer doch auch gehen!"

Die AccelStepper Bibliothek verwendet Rampen zum Beschleunigen und Bremsen, bei der StepperMotor Bibliothek, die ich in der Praxis nicht kenne, kann ich das nicht finden.

Warum greifst Du nicht zum Porsche, also zur funktionierenden Lösung?

agmue:
Was veranlaßt Dich zu dieser Annahme?

Da war der Wunsch Vater des Gedanken :slight_smile:

Ich habe noch ein anderes Projekt im Auge, das auf der StepperMotor Bibliothek aufbaut.
Dort müsste ich den Code anpassen, was mir als Anfänger vermutlich nicht leicht fallen wird.

Ich fang einfach mal an. Die Performance der AccelStepper Bibliothek hat ja spontan überzeugt.
Vielen Dank für die Hilfe und den Hinweis auf diese Bibliothek!

hansdampff:
Ich habe noch ein anderes Projekt im Auge, das auf der StepperMotor Bibliothek aufbaut.
Dort müsste ich den Code anpassen, was mir als Anfänger vermutlich nicht leicht fallen wird.

Du könntest in einem Forum Deines Vertrauens nach Hilfe fragen :wink:

Die Beispiele der AccelStepper Bibliothek überzeugen mich nicht immer, daher habe ich mit ein paar Grundübungen angefangen. Da kann auch ein kleines Funktionsmodell helfen, sieht für ein anderes Thema so aus:

Mit diesem Modell und einem ESP32 habe ich auch für dieses Thema probiert.