Mehrere bipolar Schrittmotoren Ansteuern, aber wie ????

MicroBahner:
Dann haben wir 2 schöne Beispiele - ein einfaches, und ein komplexes :wink: .

Aller guten Dinge sind drei, also noch ein Beispiel mit OOP für die Referenzfahrt. Ich habe mehrere Varianten durchdacht und mich nun für eine Mischung aus prozeduraler Schrittkette und einer Schrittkette in der Referenz-Methode entschieden. Vermutlich wird das nicht auf ungeteiltes Echo stoßen. Was meinst Du?

#include <MobaTools.h>
MoToTimer Pause;
class Achse {
    enum {REFVERLASSEN, REFERREICHEN, NULLERREICHEN};
    const byte pinRef;	// Pin Referenzsensor Achse
    const byte IN1, IN2, IN3, IN4;	// Treiberpins
    byte schritt;
  public:
    MoToStepper Step;

    Achse(const byte pinRef, const byte IN1, const byte IN2, const byte IN3, const byte IN4)
      : pinRef(pinRef), IN1(IN1), IN2(IN2), IN3(IN3), IN4(IN4), schritt(REFVERLASSEN), Step(4096) {}
    void init() {
      pinMode(pinRef, INPUT_PULLUP);             // gedrückt = LOW
      Step.attach( IN1, IN2, IN3, IN4 );         // IN1, IN2, IN3, IN4 des Treibers
    }
    bool referenzfahrt() {
      switch (schritt) {
        case REFVERLASSEN:
          Step.setSpeed( 50 );                   // = 5 U/Min (motorspezifisch) Schleichfahrt
          Step.setRampLen( 5 );                  // Beschleunigung (motorspezifisch)
          Step.rotate(1);                        // vom Referentpunkt runterbewegen
          if (digitalRead(pinRef)) {             // Referenzsensor nicht (mehr) betätigt
            Step.doSteps(100);                   // mit etwas Entfernung anhalten
            schritt++;
          }
          break;
        case REFERREICHEN:
          if ( !Step.moving() ) {                // warten bis die Bewegung abgeschlossen ist
            Step.rotate(-1);                     // Richtung Referentpunkt bewegen
            schritt++;
          }
          break;
        case NULLERREICHEN:
          if (!digitalRead(pinRef)) {            // Ref_X betätigt
            Step.setZero(100);                   // setze Nullpunkt 100 Schritte von Referenzpunkt entfernt
            Step.writeSteps(0);                  // zum Nullpunkt bewegen
            schritt++;
          }
          break;
        default:
          schritt = REFVERLASSEN;
          return true;
      }
      return false;
    }
};

Achse achsen[] = {
  //pinRef, IN1, IN2, IN3, IN4
  {A0, 12, 11, 10, 9},
  {A1, 5, 4, 3, 2}
};

MoToStepper Step_Z(200, STEPDIR);            // Z-Achse, bipolarer Schrittmotor mit Treiber wie A4988, DRV8825 oder vergleichbare

void setup() {
  for (Achse &a : achsen) a.init();

  Step_Z.attach( 7, 8 );                     // STEPpin, DIRpin des Treibers
  Step_Z.setSpeed( 800 );                    // = 80 U/Min (motorspezifisch)
  Step_Z.setRampLen( 50 );                   // Beschleunigung (motorspezifisch)
  Step_Z.write(360);                         // Winkel 360 Grad drehen
  Pause.setTime( 2500 );                     // Dreh- und Pausenzeit
}

void loop() {
  enum {X_ACHSE, Y_ACHSE};
  enum {REFFAHRT, BEWEGUNG_VORWAERTS, BEWEGUNG_RUECKWAERTS};
  static byte schritt_X = REFFAHRT;          // Schrittkettenstatus X-Achse
  static byte schritt_Y = REFFAHRT;          // Schrittkettenstatus Y-Achse
  static int16_t winkel = 360;

  //-- X-Achse
  switch (schritt_X) {
    case REFFAHRT:
      if (achsen[X_ACHSE].referenzfahrt()) {
        schritt_X = BEWEGUNG_VORWAERTS;
      }
      break;
    case BEWEGUNG_VORWAERTS:
      if ( !achsen[X_ACHSE].Step.moving() ) {              // warten bis die Bewegung abgeschlossen ist
        achsen[X_ACHSE].Step.setSpeed( 200 );              // = 20 U/Min (motorspezifisch)
        achsen[X_ACHSE].Step.setRampLen( 100 );            // Beschleunigung (motorspezifisch)
        achsen[X_ACHSE].Step.writeSteps(4096);
        schritt_X = BEWEGUNG_RUECKWAERTS;
      }
      break;
    case BEWEGUNG_RUECKWAERTS:
      if ( !achsen[X_ACHSE].Step.moving() ) {              // warten bis die Bewegung abgeschlossen ist
        achsen[X_ACHSE].Step.writeSteps(-4096);
        schritt_X = BEWEGUNG_VORWAERTS;
      }
      break;
  }
  //-- Y-Achse
  switch (schritt_Y) {
    case REFFAHRT:
      if (achsen[Y_ACHSE].referenzfahrt()) {
        schritt_Y = BEWEGUNG_VORWAERTS;
      }
      break;
    case BEWEGUNG_VORWAERTS:
      if ( !achsen[Y_ACHSE].Step.moving() ) {              // warten bis die Bewegung abgeschlossen ist
        achsen[Y_ACHSE].Step.setSpeed( 150 );              // = 20 U/Min (motorspezifisch)
        achsen[Y_ACHSE].Step.setRampLen( 100 );            // Beschleunigung (motorspezifisch)
        achsen[Y_ACHSE].Step.writeSteps(4096);             // Bewegung starten
        schritt_Y = BEWEGUNG_RUECKWAERTS;
      }
      break;
    case BEWEGUNG_RUECKWAERTS:
      if ( !achsen[Y_ACHSE].Step.moving() ) {              // warten bis die Bewegung abgeschlossen ist
        achsen[Y_ACHSE].Step.writeSteps(-4096);            // Bewegung starten
        schritt_Y = BEWEGUNG_VORWAERTS;
      }
      break;
  }
  //-- Z-Achse
  if ( !Step_Z.moving() ) {                  // warten bis die Bewegung abgeschlossen ist
    if ( !Pause.running() ) {                // warten bis Ablauf der Zeit
      Pause.setTime( 5000 );                 // Zeit für Bewegung und Pause
      winkel *= -1;                          // andere Richtung
      Step_Z.write(winkel);                  // Bewegung starten
    }
  }
}

MicroBahner:
... muss ich noch untersuchen ).

Dann halte ich die Füße still.