// https://wokwi.com/projects/414023680218511361
// for 

//Modified from 
////////// Example Reference for MoToStepper - attaching a bipolar stepper with step/dir and enable ////////////
// https://github.com/MicroBahner/MobaTools/blob/master/examples/_Stepper/Stepper_Reference/Stepper_Reference.ino
// https://wokwi.com/projects/410122241449166849
// for https://forum.arduino.cc/t/wokwi-simulations-for-arduino-built-in-examples/1304754/6


/*  Beispiel für die Ansteuerung eines bipolaren Steppers
   über 4 Taster und ein Poti ( für die Geschwindigkeit )
   In diesem Beispiel werden neben der Stepperklasse (MoToStepper), auch die MoToButtons
   und der MoToTimebase genutzt.
   Jedem Taster ist eine Position zugeordnet, die bei einem Klick auf den Taster
   angefahren wird.
   Ein Doppelklick führt zu endlosen Bewegungen:
        Taster1: vorwärts
        Taster2  rückwärts
        Taster3  stop

   Wird Taster4 lang gedrückt, wird eine Referenzfahrt ausgelöst.
   In diesem Beispiel ist die Referenzfahrt als einfache blockierende Funktion ausgeführt.

   Die interne LED wird angesteuert, wenn der Referenzschalter aktiv ist.
*/
/* Example for the control of a bipolar stepper with 4 buttons and a potentiometer (for speed)
   In this example, besides the stepper class (MoToStepper), also the MoToButtons and the MoToTimebase are used.
   A position is assigned to each button, which is approached when the stepper is clicked.
   A double click leads to endless movements:
        Button1: forward
        Button2: backward
        Button3: stop

   If button4 is pressed and held down, a reference run is initiated.
   In this example, the reference run is a simple blocking function.

   The internal LED lights up when the reference switch is active.
*/


#define MAX8BUTTONS // spart Speicher, da nur 4 Taster benötigt werden
#include <MobaTools.h>

const int STEPS_UMDREHUNG = 800;
//Stepper einrichten ( 800 Schritte / Umdrehung - 1/4 Microstep )
MoToStepper myStepper( STEPS_UMDREHUNG, STEPDIR );
MoToStepper myStepperRev( STEPS_UMDREHUNG, STEPDIR );
const byte dirPin = 5;
const byte stepPin = 6;
const byte enaPin = 7;
const byte dirPinRev = 8;
const byte stepPinRev = 9;

// Taster einrichten ( die Taster müssen gegen Gnd schalten, keine Widerstände notwendig )
enum { Taster1, Taster2, Taster3, Taster4 } ; // Den Tasternamen die Indizes 0...3 zuordnen
const byte tasterPins[] = {A1, A2, A3, A4 }; // muss als byte definiert sein, damit ein enfaches sizeof funktioniert
const byte tasterZahl = sizeof(tasterPins);
const long tasterPos[] = { 1600, 3200, 6400, 7600 };
MoToButtons taster( tasterPins, tasterZahl, 20, 500 );



// Referenzschalter
const byte refPin = A5;         // Input für Referenzpunktschalter
const byte atRefpoint = HIGH;   // Einganspegel, wenn Refpunkt erreicht

MoToTimebase speedIntervall;      // Zeitinterval zum Auslesen des Speedpotentiometers

const byte potiPin = A0;        //Poti fuer Geschwindigkeit
int vspeed = 0;                 //Steppergeschwindigkeit in U/min*10
int oldSpeed = 0;               // Zur Erkennung von Geschwindigkeitsänderungen

void toRefPoint() {
  // Stepper zum Referenzpunkt bewegen, und Position auf 0 setzen
  Serial.println("Referenzpunkt anfahren");
  // Im Schnellgang Richtung Refpunkt fahren ...
  if ( digitalRead( refPin ) != atRefpoint ) {
    // ... nur wenn der Stepper nicht schon dort steht
    myStepper.setSpeedSteps( 20000, 100 );
    myStepperRev.setSpeedSteps( 20000, 100 );
    myStepper.rotate(-1);
    myStepperRev.rotate(1);
    while ( digitalRead( refPin ) != atRefpoint );
  }
  digitalWrite( LED_BUILTIN, digitalRead( refPin ) );
  // Refschalter erreicht, anhalten
  myStepper.rotate(0);
  myStepperRev.rotate(0);
  while ( myStepper.moving() );     // Bremsrampe abwarten;
  
  // Langsam und ohne Rampe zurück zum Schaltpunkt des Refpunktes fahren
  myStepper.setSpeedSteps( 1000 );
  myStepperRev.setSpeedSteps( 1000 );
  myStepper.setRampLen(0);
  myStepperRev.setRampLen(0);
  myStepper.rotate( 1 );
  myStepperRev.rotate( -1 );
  while ( digitalRead( refPin ) == atRefpoint );
  
  digitalWrite( LED_BUILTIN, digitalRead( refPin ) );
  Serial.println("Referenzpunkt erreicht");
  myStepper.rotate(0);
  myStepperRev.rotate(0);
  while (myStepper.moving() );
  myStepper.setZero();
  myStepper.setSpeed( 200 );
  myStepper.setRampLen( 100 );        // Rampenlänge 100 Steps bei 20U/min
  oldSpeed = 0;                       // Damit Speedwert vom Poti wieder übernommen wird
  myStepperRev.setZero();
  myStepperRev.setSpeed( 200 );
  myStepperRev.setRampLen( 100 );        // Rampenlänge 100 Steps bei 20U/min
  oldSpeed = 0;                       // Damit Speedwert vom Poti wieder übernommen wird
  Serial.println("Ende Reffahrt");
}

void setup()
{ Serial.begin(115200); while (!Serial);
  myStepper.attach( stepPin, dirPin );
  myStepperRev.attach( stepPinRev, dirPinRev );
  myStepper.attachEnable( enaPin, 10, LOW );        // Enable Pin aktivieren ( LOW=aktiv )
  myStepper.setSpeed( 200 );
  myStepperRev.setSpeed( 200 );
  vspeed = 200;
  myStepper.setRampLen( 100 );                       // Rampenlänge 100 Steps bei 20U/min
  myStepperRev.setRampLen( 100 );                       // Rampenlänge 100 Steps bei 20U/min
  speedIntervall.setBasetime( 100 );                  // 100ms Tickerzeit
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(refPin, INPUT_PULLUP );
  toRefPoint();
}

void loop() {
  taster.processButtons();          // Taster einlesen und bearbeiten

  digitalWrite( LED_BUILTIN, digitalRead( refPin ) );

  // Speed alle 100ms neu einlesen und setzen
  if ( speedIntervall.tick() ) {
    // wird alle 100ms aufgerufen ( Tickerzeit = 100ms im setup() )
    vspeed = map((analogRead(potiPin)), 0, 1023, 20, 1800);  //Poti mappen auf 2 ... 180 Umdr/Min
    //min speed =2 and max speed =180 rpm
    if ( abs( oldSpeed - vspeed ) > 5 ) {
      myStepper.setSpeed( vspeed );
      myStepperRev.setSpeed( vspeed );
      oldSpeed = vspeed;
    }
  }

  // Referenzfahrt auslösen
  if ( taster.longPress( Taster4 ) ) toRefPoint();

  //
  for ( byte tastIx = 0; tastIx < tasterZahl; tastIx++ ) {
    // die 4 Taster auf Click/Doppelclick abfragen
    byte clickTyp = taster.clicked(tastIx);
    if ( clickTyp == SINGLECLICK ) {
      //Taste wurde einfach gedrückt
      Serial.print("Fahre zu Pos "); Serial.println( tasterPos[tastIx] );
      myStepper.writeSteps(tasterPos[tastIx]);
      myStepperRev.writeSteps(-tasterPos[tastIx]);
    } else if ( clickTyp == DOUBLECLICK ) {
      // ein Doppelclick wurde erkannt
      switch ( tastIx ) {
        case Taster1:
          myStepper.rotate(1);
          myStepperRev.rotate(-1);
          break;
        case Taster2:
          myStepper.rotate(-1);
          myStepperRev.rotate(1);
          break;
        case Taster3:
          myStepper.rotate(0);
          myStepperRev.rotate(0);
          break;
        default:
          ;
      }
    }
  }
}
A4988
Tasker 1 and Tasker 2
Reference
Tasker 3 and Tasker 4
Speed
A4988