Schrittmotor Anwedung programmieren

Hallo Zusammen,

Ich bin kompletter Beginner und würde gerne einen Schrittmotor exakt steuern, mit sehr langsamen Drehzahlen. Es soll eine Spindel angetrieben werden

Der Plan wäre zb dass ich in 1 min 1.09 Umdrehungen mache. Nach x Umdrehungen soll die Drehzahl angepasst werden usw. Nach einer maximalen Anzahl Umdrehungen soll der Motor schnell in die andere Richtung drehen.

Kann ich exakte Schrittzahlen pro Umdrehung festlegen und die Zeit pro umdrehung definieren? Zudem müssten die Schritte gezählt werden, um zu wissen, wann die Drehzahl usw angepasst werden soll.

Ich habe einen 28BYJ-48 mit einer ULN2003 und einem Arduino UNO. Ich werde später den Motor wechseln, aber mit diesem Motor möchte ich das mal testen.

Danke für Eure Hilfe

Öhmmm....

Ja!
Vermutlich ja...

Das Wesen eines Schrittmotors ist, dass eine Umdrehung exakt mit n Schritten definiert ist.
Damit kannst Du also beliebig arbeiten.

Ja, davon gehe ich auch aus. Die Frage ist wie definiere ich

n Schritte in einer Zeiteinheit t?
Wie zähle ich die Anzahl der ausgeführten Schritten?

Hallo,

Wie zähle ich die Anzahl der ausgeführten Schritten?

Man gibt die Schritte selbst vor, deshalb kennt man sie. Außer man möchte die ausgeführten Schritte überwachen. Dafür muss ein Encoder an den Motor. Noch besser wäre an die angetriebene Welle. Dann kann man die Werte vergleichen und Rückschlüsse ziehen. Ob die Überwachung notwendig ist weiß ich nicht. Bei großer Untersetzung vermutlich nicht.

n Schritte in einer Zeiteinheit t?

n/t ist wie U/min. Eine Drehzahlangabe. Jede Formel kann man umstellen. :wink:

Schau dir einmal die MobaTools an, der Programmierer ist zufällig hier im Forum.

Mit
int SPU=200
Stepper Motor (SPU,....) gege ich ja die Schritte pro U an.
Motor.setSpeed die U/min. Und ich möchte 1.09 U/min.

Wie realisiere ich das konkret? Auf Dezimalzahken reagiert er nicht

Dein Schrittmotor hat aber 2048 Schritte/Umdrehung ( oder 4096 - je nach Ansteuerung ). Das ist schon ein gewaltiger Unterschied. ( Bei einigen ist das Getriebe auch nicht genau 1:64, da sind die Schritte / Umdr. etwas unterschiedlich - Versuch macht kluch :wink: )

Bei 2048 Schritten / Umdr. sind das 2048*1,09 = 2232,32 Schritte / min oder 26,877 µs / Schritt. Wobei jetzt noch die Frgae ist, wie genau Du das ganze haben willst ....

Zeig mal, was Du bisher versucht hast. Den Sketch bitte in Codetags.

Mach das doch einfach zu Fuß ohne Lib.
Du kannst den Motor einen Schritt machen lassen? Fein!
Dann berechnest Du die notwenigen Schritte pro Minute basierend auf den Angaben Deines Motors und Deiner Vorgabe.
Und dann machst Du eben alle x ms einen Schritt.

Microbahner war schneller :smile:

Die gibt es mit unterschiedlicher Schrittzahl pro Umdrehung, diese Zahl mußt Du zunächst ermitteln. Meiner hat 4096, das läßt sich nicht mit 1,09 Umdrehungen darstellen (1,09 * 4096 = 4464,64). Übliche Motoren 200 * 1,09 = 218 machen eine bessere Figur. Zusätzlich hängt es am Getriebe.

Ein Wechsel bringt neue Berechnungen, die solltest für Dich gut nachvollziehbar dokumentieren.

Die MobaTools sind auch meine Empfehlung.

Wahrscheinlich absichtlich :wink:

wie gesagt bin ich kompletter Anfänger und habe erst ein paar Zeilen. Konnte den Motor drehen lassen, aber noch nicht so präzise wie ich es brauche.

#include <Stepper.h> // Hinzufügen der Programmbibliothek.
int SPU = 2048; // Schritte pro Umdrehung. Ev 2048 x ca 1.09
Stepper Motor(SPU, 10,11,12,13); // Der Schrittmotor erhält die Bezeichnung "Motor" und es wird angegeben an welchen Pins der Motor angeschlossen ist.

void setup() //Hier beginnt das Setup.
{
Motor.setSpeed(1.09); // U/min - sollten 1.09 sein
}

void loop() {
//Motor.step(2048);  Der Motor macht 2048 Schritte, das entspricht einer Umdrehung.
//delay(6000); // Durch diese Pause bleibt der Motor nach der Drehung für eine Sekunde stehen.
}

Ich werde das genauer Anschauen sobald am Abend die Kinder im Bett sind :wink:

Dann habe ich noch was für Dich:

#include <MobaTools.h>
MoToStepper Step(4096);           // HALFSTEP ist default
MoToTimer   delayTime;

void setup() {
  Step.attach( 4, 5, 6, 7 ); // Anschluß an digitalen Ausgängen; Treiber IN1,IN2,IN3,IN4
  Step.setZero();            // Referenzpunkt für Motor 1 setzen
}

void loop() {
  const uint16_t GESCHW_V = 744;  // 4096 * 1,09 / 60 * 10 Schrittgeschwindigkeit in Steps/10sec
  const uint16_t GESCHW_R = 240;  // Rotationsgeschwindigkeit 24 U/Min
  const uint16_t RAMPE = 500;     // Rampenlänge in Steps.
  const uint16_t FAKTOR = 10;     // 1/10 Grad
  const uint16_t WINKEL = 3924;   // 1,09 * 360 in 1/10 Grad
  Step.setSpeedSteps( GESCHW_V, 0 );
  Step.write( WINKEL, FAKTOR );
  delay(65000);
  Step.write( 2 * WINKEL, FAKTOR );
  delay(65000);
  Step.write( 3 * WINKEL, FAKTOR );
  delay(65000);
  Step.setSpeed( GESCHW_R );
  Step.setRampLen(RAMPE);
  Step.write(0);                 // zurück
  delay(20000);
}

Das ist ein gruseliges Programm, aber der Motor dreht ungefähr so, wie Du es beschrieben hast :crazy_face:

Deine genaue Idee ist mir nicht klar, aber vermutlich benötigst Du eine Schrittkette und
if ( !Step.moving() ) ....

#include <MobaTools.h>
MoToStepper Step(4096);           // HALFSTEP ist default
MoToTimer   delayTime;

void setup() {
  Step.attach( 4, 5, 6, 7 ); // Anschluß an digitalen Ausgängen; Treiber IN1,IN2,IN3,IN4
  Step.setZero();            // Referenzpunkt für Motor 1 setzen
}

void loop() {
  const uint16_t GESCHW_V = 744;  // 4096 * 1,09 / 60 * 10 Schrittgeschwindigkeit in Steps/10sec
  const uint16_t GESCHW_R = 240;  // Rotationsgeschwindigkeit 24 U/Min
  const uint16_t RAMPE = 500;     // Rampenlänge in Steps.
  const uint16_t FAKTOR = 10;     // 1/10 Grad
  const uint16_t WINKEL = 3924;   // 1,09 * 360 in 1/10 Grad
  static uint8_t schritt = 0;

  switch (schritt)
  {
    case 0:
      Step.setSpeedSteps( GESCHW_V, 0 );
      Step.write( WINKEL, FAKTOR );
      schritt++;
      break;
    case 1:
      if ( !Step.moving() )
      {
        schritt++;
      }
      break;
    case 2:
      delay(2000);  // Hier könnte man was Sinnvolles tun
      Step.write( 2 * WINKEL, FAKTOR );
      schritt++;
      break;
    case 3:
      if ( !Step.moving() )
      {
        schritt++;
      }
      break;
    case 4:
      delay(2000);  // Hier könnte man was Sinnvolles tun
      Step.write( 3 * WINKEL, FAKTOR );
      schritt++;
      break;
    case 5:
      if ( !Step.moving() )
      {
        schritt++;
      }
      break;
    case 6:
      delay(2000);  // Hier könnte man was Sinnvolles tun
      Step.setSpeed( GESCHW_R );
      Step.setRampLen(RAMPE);
      Step.write(0);                 // zurück
      schritt++;
      break;
    case 7:
      if ( !Step.moving() )
      {
        schritt++;
      }
      break;
    case 8:
      delay(2000);  // Hier könnte man was Sinnvolles tun
      schritt = 0;
      break;
  }
}

Bilde den Kehrwert und rechne aus, wie groß die Zeit für einen Schritt sein soll.
Dann mach das einfach.

Wie man zählt, kriegst du bestimmt raus.
Hört sich so an, als solltest du das am besten (fast) ohne Libraries machen.

Da gehen die Informationen auseinander.
Der Motor 28BYJ-48 hat 32 Voll-Schritte pro Umdrehung. Daran ist ein Getriebe verbaut.
Die Angabe des Übertrgungsverhälnisses wird als 64:1, und 63,68:1 (genau gesagt 32/9 x 22/11 x 26/9 x 31/10 = 64 x 403/405 = 63.68:1) angegeben. Ich weiß nicht ob es den 1:64 Getriebe gibt oder ob das nur ein gerundeter Wert ist.
Normal ist, daß die Zahnradkombinationen so gewählt werden, daß kein ganzzahliges Verhältnis ergibt. Das hat zur Folge daß die Zähne des einen Zahnrad nicht immer auf die gleichen Zähne des anderen treffen. Das ist gewollt, damit die Zahnräder gleichmäßiger abgebraucht werden.
Es gibt auch eine Motor-Version mit 16:1 Getriebe ( gerundet oder nicht weiß ich nicht).

Es gibt den Motor als 5 und als 12V Version

Grüße Uwe

Also.. vorab mal danke allen die mir helfen. Ich habe meinen 28BYJ-48 5V aus einem Arduino starter set. Gibt es ein Code snippet, um zu testen wie viele Schritte er für eine Umdrehung braucht?

Wenn Du in meinem Programm die 3924 durch 3600 ersetzt, sollte sich der Motor genau einmal rumdrehen. Wenn Du das mehrmals machst, solltest Du Abweichungen erkennen können.

Hab das obere Programm genommen .. motor läuft schonmal :wink:
aber verstehe den void loop noch nicht ...
4096 * 1,09 / 60 * 10 warum noch mal 10
was ist die Rampenlänge usw

Wer mal den Code etwas anpassen um nur eine Umdrehung zu erhalten und dann stoppen und das dann langsam aufbauen :wink:

:smiley:

Die Bibliothek möchte Steps/10sec

Schau mal in die Bibliotheksdoku MobaTools-243-de.pdf

So ich habe mal ein wenig getestet und gerechnet :wink:

folgender Code: Motor soll Vorwärts laufen 4.36 U in 239.34 Sekunden. Danach schnell rückwärts. Zuerst mal den Code, danach die Probleme :wink:

#include <MobaTools.h>
MoToStepper Step(4096);           // HALFSTEP ist default
MoToTimer   delayTime;

//Variablen definieren
int Steps = 4096; //Schritte pro Umdrehung 
int Zeitsequenz = 86164/360; //Rotationszeit für ein Grad
int Gewindesteigung = 1; //Steigung in mm/U
int Hebel_Statisch = 250; // Länge Hebelarm in mm
int Hebel_Rotation = 250; // Länge Hebelarm in mm

void setup() {
  Step.attach( 10, 11, 12, 13 ); // Anschluß an digitalen Ausgängen; Treiber IN1,IN2,IN3,IN4
  Step.setZero();            // Referenzpunkt für Motor 1 setzen
}

//for a= 1 to 30 jedes Grad die Schritte berechnen
//if a==0 then 
//  Anzahl Schritte in Zeitsequenz = ((sqrt(Hebel_Statisch^2 + Hebel_Rotation^2 - 2*Hebel_Statisch*Hebel_Rotation*cos(a))) / Gewindesteigung) * Steps
//else
//  Anzahl Schritte in Zeitsequenz = ((sqrt(Hebel_Statisch^2 + Hebel_Rotation^2 - 2*Hebel_Statisch*Hebel_Rotation*cos(a)) - sqrt(Hebel_Statisch^2 + Hebel_Rotation^2 - 2*Hebel_Statisch*Hebel_Rotation*cos(a-1))) / Gewindesteigung) * Steps
//end if
//next a++
//wenn a>30 Motor stoppen und schnell zurückfahren zu Grad 0

void loop() {
  const uint16_t GESCHW_V = 747;  // 4096 * 4.363 / 239.34 * 10 Schrittgeschwindigkeit in Steps/10sec
  const uint16_t GESCHW_R = 4000;  // Rotationsgeschwindigkeit 24 U/Min
  const uint16_t RAMPE = 15000;     // Rampenlänge in Steps.
  const uint16_t FAKTOR = 10;     // 1/10 Grad
  const uint16_t WINKEL = 15708;   // 4.363 * 360 in 1/10 Grad
  Step.setSpeedSteps( GESCHW_V, 0 );
  Step.write( WINKEL, FAKTOR );
  delay(600);
  //Step.write( 2 * WINKEL, FAKTOR );
  //delay(65000);
  //Step.write( 3 * WINKEL, FAKTOR );
  //delay(65000);
  Step.setSpeed( GESCHW_R );
  Step.setRampLen(RAMPE);
  Step.write(0);                 // zurück
  delay(20000);
}

Also, ich habe zuerst mal den Motor nur vorwärts drehen lassen und getestet ob er die Soll Umdrehungen in der gewünschten Zeit zurück legt. Das funktionierte, zumindest ohne das er eine Drehmoment bewegen musste ;).
Nun wollte ich, dass der Motor kurz wartet und danach rückwärts fährt. Ich habe es ohne Rampe versucht sondern so:

Step.setSpeedSteps( GESCHW_R );
  Step.write( WINKEL, FAKTOR );
  delay(600);

Ging leider nicht.
Danach so wie es jetzt ist. Problem ist, dass der Motor zu schnell zurück dreht. Ich gehe davon aus, dass das Delay so gross sein muss, dass der Motor die Schritte zuvor ausführen kann. Das würde bedeuten, dass ich das Delay immer der Aktionsdauer der Aktion anpassen müsste ;/.

Ich müsste wahrscheinlich eine Schleife programmieren, da die Werte immer etwas ändern, in etwa so was

//for a= 1 to 30 jedes Grad die Schritte berechnen

//if a==0 then

// Anzahl Schritte in Zeitsequenz = ((sqrt(Hebel_Statisch^2 + Hebel_Rotation^2 - 2*Hebel_Statisch*Hebel_Rotation*cos(a))) / Gewindesteigung) * Steps

//else

// Anzahl Schritte in Zeitsequenz = ((sqrt(Hebel_Statisch^2 + Hebel_Rotation^2 - 2*Hebel_Statisch*Hebel_Rotation*cos(a)) - sqrt(Hebel_Statisch^2 + Hebel_Rotation^2 - 2*Hebel_Statisch*Hebel_Rotation*cos(a-1))) / Gewindesteigung) * Steps

//end if

//next a++

//wenn a>30 Motor stoppen und schnell zurückfahren zu Grad 0

Delay auf 239344 gesetzt, läuft nun besser

Wenn Du im Programm warten willst, bis der Motor die Schritte ausgeführt hast, kannst Du einfach abfragen, ob er noch dreht und solange warten:

while ( Step.moving() ) ; // Warten bis der Motor steht

Willst Du danach warten bis zur nächsten Bewegung kannst Du ein delay einfügen, dass dann nur noch die Wartezeit im Stillstand beinhaltet.