Zwei Schrittmotoren MobaTools

Hallo,

ich versuche zwei Schrittmotoren (Nema 23 und Nema 17) mit einem Ramps 1.4 board und Pololu A4988 Treiber zu betreiben. Ich benutze die Bibliothek MobaTools

Der Nema 23 läuft die ganze Zeit und wenn der einen Winkel von 360*x (in einer for schleife), dann soll der kleinere Motor Nema 17 immer um einen bestimmten winkel weiter drehen. Bis er den wert der Variable “Wicklung” erreicht hat und dann soll er wieder das selbe Machen nur gegen den Uhrzeigersin und immer so weiter, bis er das ganze hin und her 25 mal gemacht hat.

Mein Problem ist das er die for schleife perfekt durch läuft, wenn Variable “Wicklung” nicht größer als 10 ist, ich muss jedoch den wert auf über 30 stellen. Wenn ich das mache dann überspringt dann läuft die schleife nicht x++ sondern x=x+2; oder dreht ganz durch.

Ich hoffe Ihr könnt mir da weiter helfen.

Vielen Dank

#include <MobaTools.h>

MoToStepper stepper1(3200, A4988);
MoToStepper stepper2(3200, A4988);

#define X_STEP_PIN         54
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38

#define Y_STEP_PIN         60
#define Y_DIR_PIN          61
#define Y_ENABLE_PIN       56


long wicklung =10;
int winkeld1;

int lagen = 25;
long x, y, z;
int vor, back;


void setup() {
  pinMode(X_STEP_PIN   , OUTPUT);
  pinMode(X_DIR_PIN    , OUTPUT);
  pinMode(X_ENABLE_PIN , OUTPUT);

  pinMode(Y_STEP_PIN   , OUTPUT);
  pinMode(Y_DIR_PIN    , OUTPUT);
  pinMode(Y_ENABLE_PIN , OUTPUT);

  digitalWrite(X_ENABLE_PIN    , LOW);
  digitalWrite(Y_ENABLE_PIN    , LOW);

  stepper1.attach(X_STEP_PIN, X_DIR_PIN);
  stepper2.attach(Y_STEP_PIN, Y_DIR_PIN);

  stepper1.setSpeed(300); //=60U/min
  stepper2.setSpeed(300); //60u/min

  Serial.begin(9600);
}


void loop()
{
  //winkeld1 = (1 / 1.75) * 360;
  winkeld1 = 105;


 

  for (x = 1; x <= wicklung; x++)
  {
    stepper2.doSteps(3600);
    if (stepper2.read() == 360 * x)   //Schrittmotor Schlitten hoch bewegen zu ende der Spule
    {
      stepper1.write(winkeld1 * x);
      Serial.print("1.stepper1:");
      Serial.println(stepper1.read());
      Serial.print("1.stepper2:");
      Serial.println(stepper2.read());

    }
    else if (stepper2.read() == (360 * wicklung) + (360 * x))  //Schlitten wieder zum Anfang der Spule
    {
      stepper1.write(-winkeld1 * x);
            Serial.print("2.stepper1:");
            Serial.println(stepper1.read());
            Serial.print("2.stepper2:");
            Serial.println(stepper2.read());
    }

    if ((stepper1.read() == (winkeld1 * wicklung)) && (stepper2.read() == (360 * wicklung) + 360))
    {
      stepper1.setZero();
      vor++;

      Serial.print("vor:");
      Serial.println(vor);
    }
    else if ((stepper1.read() == -winkeld1 * (wicklung - 1)) && (stepper2.read() == 360 * wicklung * 2))
    {
      stepper1.setZero();
      stepper2.setZero();
    }

//    if (vor == wicklung * lagen)
//    {
//      stepper1.setSpeed(0); //=60U/min
//      stepper2.setSpeed(0); //60u/min
//      digitalWrite(X_ENABLE_PIN    , HIGH);
//      digitalWrite(Y_ENABLE_PIN    , HIGH);
//    }
  }
}

oder kennt jemand eine andere Lösung, wie ich die Motoren betreiben kann?
Mit AccelStepper.h stottert der große Motor wenn der kleiner zu Position fährt. Die Bibliothek gefällt mir nicht :frowning:

Hallo,
um ehrlich zu sein, so ganz habe ich noch nicht verstanden, was das Programm machen soll. Wozu brauchst Du die for-Schleife? loop ist doch schon eine Schleife.

Vielleicht zeigst Du mal ein Bild von deinem Aufbau und erklärst was die Stepper machen sollen. Etwas mehr Kommentare im Sketch, was da jeweils passieren soll, wären auch nicht schlecht. Bisher bringe ich deine Beschreibung und den Sketch noch nicht zusammen.

Also die Motoren sollen anfangs wie eine Uhr laufen, der große Motor "stepper2"bewegt sich die ganze Zeit. (1) Der stepper1 nur dann wenn stepper2 sich um 360grad gedreht hat und zwar nur um einen bestimmten winkel “winkeld1”.
Das soll er so lange machen bis der winkel von stepper1 = winkeld1wicklung ist.
Wenn das der fall ist soll sich stepper1 wieder wie der kleine Zeiger von einer Uhr verhalten, jedoch diesmal in die andere richtung fahren, wenn er den winkel -winkeld1
wicklung erreicht hat, soll er wieder die andere Richtung fahren.
Während der ganzen Zeit dreht sich der stepper2 in eine Richtung, an dem verändert sich nicht.

Stepper1 soll so lange hin und her laufen bis er das 25mal gemacht und dann stehen bleiben.

Hier noch einmal mein Code mit paar Kommentaren:

#include <MobaTools.h>

MoToStepper stepper1(3200, A4988);
MoToStepper stepper2(3200, A4988);

#define X_STEP_PIN         54
#define X_DIR_PIN          55
#define X_ENABLE_PIN       38

#define Y_STEP_PIN         60
#define Y_DIR_PIN          61
#define Y_ENABLE_PIN       56


long wicklung =10;
int winkeld1;

int lagen = 25;
long x, y, z;
int vor, back;


void setup() {
  pinMode(X_STEP_PIN   , OUTPUT);
  pinMode(X_DIR_PIN    , OUTPUT);
  pinMode(X_ENABLE_PIN , OUTPUT);

  pinMode(Y_STEP_PIN   , OUTPUT);
  pinMode(Y_DIR_PIN    , OUTPUT);
  pinMode(Y_ENABLE_PIN , OUTPUT);

  digitalWrite(X_ENABLE_PIN    , LOW);
  digitalWrite(Y_ENABLE_PIN    , LOW);

  stepper1.attach(X_STEP_PIN, X_DIR_PIN);
  stepper2.attach(Y_STEP_PIN, Y_DIR_PIN);

  stepper1.setSpeed(300); //=60U/min
  stepper2.setSpeed(300); //60u/min

  Serial.begin(9600);
}


void loop()
{
  //winkeld1 = (1 / 1.75) * 360;
  winkeld1 = 105;


       
 //die for schleife ist dazu das der die winkel nach jeder Umdrehung immer dazu addiert werden und sich stepper1 vorwärts bewegen kann
  for (x = 1; x <= wicklung; x++)
  {
    stepper2.doSteps(3600);
    
    if (stepper2.read() == 360 * x)     
    {
      // 1. immer wenn die stepper2 360*x erreicht soll sich der stepper1 um winkeld*x bewegen bis x=wicklung
      stepper1.write(winkeld1 * x);
      Serial.print("1.stepper1:");
      Serial.println(stepper1.read());
      Serial.print("1.stepper2:");
      Serial.println(stepper2.read());

    }
    else if (stepper2.read() == (360 * wicklung) + (360 * x))  
    {
      //2. wenn der stepper2 den winkel (360 * wicklung) + (360 * x) erreicht, soll stepper2 sich in die andere Richtung bewegen wie bei 1. 
      stepper1.write(-winkeld1 * x);
            Serial.print("2.stepper1:");
            Serial.println(stepper1.read());
            Serial.print("2.stepper2:");
            Serial.println(stepper2.read());
    }

    if ((stepper1.read() == (winkeld1 * wicklung)) && (stepper2.read() == (360 * wicklung) + 360))    
    {
      //wenn der stepper1 den winkel "winkeld1*wicklung" erreicht hat, und der der stepper2 den winkel (360 * wicklung) + 360) erreicht hat 
      //setzte ich den jetzigen winkel von stepper1 auf 0 und wieder und bei 2. starten zu können, weile write zählt nicht direkt von 0 zurück 
      //sondern von dem Winkel an dem sich der Motor befindet deswegen diese ifanweisung 
      stepper1.setZero();
      vor++;

      Serial.print("vor:");
      Serial.println(vor);
    }
    else if ((stepper1.read() == -winkeld1 * (wicklung - 1)) && (stepper2.read() == 360 * wicklung * 2))
    {
      // hier setzte ich beide Winkel der Motoren auf null wenn der stepper1 einmal hoch (1) und einmal runter (2) gefahren ist. 
      // Hiermit startet ich dann wieder bei 1.
      stepper1.setZero();
      stepper2.setZero();
    }

//    if (vor == wicklung * lagen)
//    {
//      stepper1.setSpeed(0); //=60U/min
//      stepper2.setSpeed(0); //60u/min
//      digitalWrite(X_ENABLE_PIN    , HIGH);
//      digitalWrite(Y_ENABLE_PIN    , HIGH);
//    }
  }
}

Deine Beschreibung habe ich - glaube ich - verstanden. Den Zusammenhang mit deinem Sketch aber nicht wirklich. Ich denke, Du denkst da zu kompliziert, und das:

     //wenn der stepper1 den winkel "winkeld1*wicklung" erreicht hat, und der der stepper2 den winkel (360 * wicklung) + 360) erreicht hat
      //setzte ich den jetzigen winkel von stepper1 auf 0 und wieder und bei 2. starten zu können, weile write zählt nicht direkt von 0 zurück
      //sondern von dem Winkel an dem sich der Motor befindet deswegen diese ifanweisung
      stepper1.setZero();

habe ich garnicht verstanden. Mit write() gibst Du eine absolute Position vor. Du musst also immer nur einfach ausrechnen, wo Du gerade hin willst ( immer einen delta Winkel weiter bzw. wieder zurück ) und das gibst Du bei write an. Da musst Du nichts zu 0 setzen.

Ich habe das mal so umgesetzt, wie ich deine verbale Beschreibung verstanden habe:

#include <MobaTools.h>

MoToStepper stepper1(3200, A4988);
MoToStepper stepper2(3200, A4988);

#define X_STEP_PIN         6
#define X_DIR_PIN          5
#define X_ENABLE_PIN       7

#define Y_STEP_PIN         9
#define Y_DIR_PIN          8
#define Y_ENABLE_PIN       12


bool moveStepper1 = true;   // Flag, damit Stepper 1 nicht mehrfach gestartet wird
long wicklung = 10;
long winkeld1;
long winkel1Abs;
#define VORWAERTS true
#define RUECKWAERTS false
bool richtungStepper1 = VORWAERTS;   // true: forwärts, false rückwärts
int lagen = 25;
int lagenCnt = 0;   // Zähler für die lagen


void setup() {
  pinMode(X_STEP_PIN   , OUTPUT);
  pinMode(X_DIR_PIN    , OUTPUT);
  pinMode(X_ENABLE_PIN , OUTPUT);

  pinMode(Y_STEP_PIN   , OUTPUT);
  pinMode(Y_DIR_PIN    , OUTPUT);
  pinMode(Y_ENABLE_PIN , OUTPUT);

  digitalWrite(X_ENABLE_PIN    , LOW);
  digitalWrite(Y_ENABLE_PIN    , LOW);

  stepper1.attach(X_STEP_PIN, X_DIR_PIN);
  stepper2.attach(Y_STEP_PIN, Y_DIR_PIN);

  stepper1.setSpeed(300); //=60U/min
  stepper2.setSpeed(300); //60u/min



  Serial.begin(115200);
  // Bewegung starten:
  richtungStepper1 = VORWAERTS; // Richtung Stepper 1
  winkel1Abs = 0;               // Winkelposition Stepper1
  winkeld1 = 105;               // Winkelbewegung Stepper 1
  stepper2.rotate(1);
}

void loop()
{
  if ( ( (stepper2.read() % 360) == 0)  ) { 
    if ( moveStepper1 && lagenCnt<lagen) {
      // Stepper 2 hat eine Umdrehung gemacht. Da die modulo 360 während
      // mehrerer loop-Durchläufe 0 ist, muss mit dem Flag moveStepper1 sichergestellt
      // werden, dass der Stepper 1 nur einmal gestartet wird.
      moveStepper1 = false;
      if ( richtungStepper1 == VORWAERTS ) {
        // Stepper 1 eine Stufe weiter
        winkel1Abs += winkeld1;
        stepper1.write(winkel1Abs);
        Serial.print("1.stepper1:");
        Serial.println(stepper1.read());
        Serial.print("1.stepper2:");
        Serial.println(stepper2.read());
        if ( winkel1Abs >= wicklung * winkeld1 ) {
            //positiven Umkehrpunkt erreicht, rückwärts laufen
          Serial.print("Umkehr Rückwärts, winkelAbs = "); Serial.println( winkel1Abs );
          //Schlitten wieder zum Anfang der Spule
          richtungStepper1 = RUECKWAERTS;
        }
      }   else {
        // Stepper 1 eine Stufe zurück
        winkel1Abs -= winkeld1;
        stepper1.write(winkel1Abs);
        Serial.print("2.stepper1:");
        Serial.println(stepper1.read());
        Serial.print("2.stepper2:");
        Serial.println(stepper2.read());
        if (winkel1Abs <= -wicklung * winkeld1) {
          // negativen Umkehrpunkt erreicht, wieder vorwärts
          Serial.print("Umkehr Vorwäerts, winkelAbs = "); Serial.println( winkel1Abs );
          richtungStepper1 = VORWAERTS;
          lagenCnt++;
          Serial.print("Lagen = "); Serial.println( lagenCnt );
        }
      }
    }
  } else {
    moveStepper1 = true;
  }
}

Was Du aber noch brauchst ist eine Initiierung, bei der Du den Stepper an eine definierte Position fährst. Jetzt startet der da, wo er gerade steht als ‘Mitte’ und pendelt dann um diesen Punkt hin und her ( von +winkeld1wicklung bis -winkeld1wicklung ). Nach 25 mal bleibt er stehen - dann geht’s aber auch (ohne Reset) nicht mehr weiter.

Hi

Du willst Spulen wickeln.
Dazu dreht einer der Stepper die Spule, der Andere führt den zukommenden Draht so, daß Du saubere Lagen bekommst.
Korrekt?
Man müsste den Stepper abfragen können, WO Der gerade steht - und somit den Winkel des Servo (Ziel-Position von Stepper 2) festlegen.
Diese übergibst Du einfach den MoBaTools - Die kümmern sich darum, daß auch der Nema17 dahin rennt, wo Er hin soll.

Wickelmaschinen sah ich bisher mit Stepper + Servo.

MfG

Vielen Dank MicroBahner, du hast mir sehr geholfen.
Ich habe wirklich zu kompliziert gedacht.

Freut mich, wenn ich dich in die richte Richtung ‘schubsen’ konnte, und Du nun allein weiterkommst 8)
( Ansonsten - einfach nochmal fragen :wink: )

Ich stehe wieder auf dem schlauch.
Ich hab das Programm für die Schrittmotoren in einem separaten Programm aufgerufen.
Es hat alles super funktioniert.

Jetzt habe ich jedoch ein Display auf dem ich werte eingeben kann und somit mehre Seiten abbilde. Die Aufrufe für das Display führe ich im void loop() auf.

Jetzt möchte ich jedoch wenn ich auf dem Display auf einer bestimmten Seite bin und einen Taster drücke das der Motor los läuft und das Programm (wie oben) abläuft.
Jedoch sobald ich mehre Sachen mit void loop() aufrufe, fährt der Motor nicht mehr, bzw. führt das % nicht mehr aus.
Kommentiere ich die anderen Sachen aus der loop raus, läuft der Motor wieder einwandfrei.

Wie kann ich das mit der loop separat machen?

Aus deiner Beschreibung werde ich nicht wirklich schlau.
Da musst Du uns schon deinen Sketch zeigen, damit man helfen kann.