Schrittmotor ansteuern

Hallo an alle
ich möchte einen Schrittmotor auf zwei verschiedene arten laufen lassen.

  1. Ich drücke eine Taste dann soll der Motor so lange drehen bis er einen Sensor auf der Welle erreicht wird (Nullposition). Dan nach gebe ich im Seriellen Monitor "start" ein und dann nach möchte ich die Motordrehzahl mit einem Poti 10k steuern, wenn der Poti auf Position 0 ist soll sich der Motor nicht drehen. Der Motor soll immer linksrum laufen und so lange ich einen Taster drücke soll er rechtsrum laufen.
  2. Ich drücke eine Taste dann soll der Motor so lange drehen bis er einen Sensor auf der Welle erreicht wird (Nullposition). Dan nach gebe ich im Seriellen Monitor "start" ein und dann nach möchte ich die Motordrehzahl mit einem Poti 10k steuern, wenn der Poti auf Position 0 ist soll sich der Motor nicht drehen. Der Motor soll so lange Links rum laufen bis ein Sensor betätigt wird dann soll der Motor rechtsrum laufen

Ich habe mich mal versucht und bekomme es nicht wo wirklich hin selbst das 1 nicht. Motor drehen mit Drehzahl über Poti geht so naja und Drehrichtung ändern funktioniert.
Was Motoren angeht habe ich wenig Erfahrung. Habe den vor 2 Tagen bekommen und bin nun am probieren.

Board: Arduino Uno R4 Wifi
Treiber: Joy-it DM860H
Motor: Joy-it Nema 23-01

Mein Code wo ich aktuell am Probieren bin. Weiß aber nicht wie ich es machen soll. mit if else oder switch case da finde ich irgend wie nicht das richtige für mich.

// Konstante Werte
#define driverPUL 7      //
#define driverDIR 6      // Drehrichtung
#define driverENA 2      // Motortreiber Start / Stop (Serieller Monitor: 1 Start/ 0 Stop)
#define rechtslaufPin 3  // Rechtslaufpin HIGH = rechtslauf / LOW = linkslauf
#define nullpos 5        // Nullposition Motor über Sensor
#define sensor 4         // Sensor für Motor umkehren

#define potentiometer A0  // Drehzahl Poti

// Variable Werte
char sendeInhalt = ' ';  // Werte aus Seriellem Monitor
int rechtslaufPinState = 0;
int nullposState = 0;
int sensorState = 0;
int valueOld = 0, value = 0;
byte sensitivity = 10;

void setup() {
  // initialize serial:
  Serial.begin(115200);

  // initialize as a input
  pinMode(rechtslaufPin, INPUT_PULLUP);
  pinMode(nullpos, INPUT_PULLUP);
  pinMode(sensor, INPUT_PULLUP);

  // initialize as a output
  pinMode(driverPUL, OUTPUT);
  pinMode(driverDIR, OUTPUT);
  pinMode(driverENA, OUTPUT);

  // nach übertragung
  digitalWrite(driverENA, HIGH);
}

void loop() {

  // Motortreiber Start / Stop über Seriellen Monitor 
  if (Serial.available() > 0) {
    sendeInhalt = Serial.read();
    if (sendeInhalt == '0') {
      digitalWrite(driverENA, HIGH);
      Serial.println("Motortreiber: deaktiviert");
      Serial.println("------------------------");
    }
    if (sendeInhalt == '1') {
      digitalWrite(driverENA, LOW);
      Serial.println("Motortreiber: aktiv");
      Serial.println("------------------------");
    }
    Serial.flush();  //seriellen Puffer löschen
  }

  // Potentiometer auslesen
  value = analogRead(potentiometer);
  if (abs(valueOld - value) >= sensitivity) {
    valueOld = value;
    Serial.println(value);
  }

  // Drehrichtung Vorgabe
  rechtslaufPinState = digitalRead(rechtslaufPin);
  if (rechtslaufPinState == LOW) {
    digitalWrite(driverDIR, HIGH);
  } else {
    digitalWrite(driverDIR, LOW);
  }

  // Geschwindigkeit mit Poti
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(value);
  digitalWrite(driverPUL, LOW);
}

Würde mich freuen wenn mir jemand einen Tipp geben kann mit welcher Struktur ich da vorgehen kann.

Eventuell auch mehrere :joy:

  1. SPS ist schon etwas anders, da mußt Du ein paar Dinge "vergessen". SPS ist mehr "von oben nach unten", während es bei loop immer im Kreis geht, möglichst schnell sogar. Die blockadearme Programmierung ist Dein Freund.
  2. Hast Du schon mal was von "endlichen Automaten (=finite state machine; =Schrittkette) gehört? Mir hat das beim Einstieg in Arduino den Aha-Effekt gebracht.
  3. Mit "Struktur" meinst Du Ordnung, vermutlich nicht struct oder class, oder?
  4. Für Schrittmotoren empfehle ich Dir die Bibliothek MobaTools, gibt es in der Bibliotheksverwaltung der IDE. Die kann auch mechanische Kontakte wie Taster entprellen.

Bei Fragen bitte fragen :slightly_smiling_face:

Dein text fängt bei 1. und 2. mit "eine Taste" an. Ist das dieselbe?
Falls ja, sind beide Fälle doch identisch und entweder Sensor oder die Umschalt-Taste schaltet von "links rum" nach "rechts rum".

Wie lange übrigens?

Sehr gut an deinem bisherigen Versuch ist übrigens, dass auf der Seriellen Schnittstelle nicht auf "start" gewartet wird, sondern auf '0' oder '1' geprüft wird und der Rest ignoriert wird. Allerdings wird dieser Zustand noch nicht weiter ausgewertet.

Serial.flush macht übrigens nicht, was dein Kommentar behauptet. (Kann einfach weggelassen werden.)

Hallo,
Eigentlich ist für Deine Aufgabenstellung ein Gleichstrommotor besser geeignet. Schrittmotoren werden in der Regel zum Positionieren verwendet. Man gibt einen Fahrweg oder eine Position vor und der Motor fährt mit einer festgelegten Geschwindigkeit dahin.

Im Grunde ist es ja ganz gut wenn man zum lernen mal einen Schrittmotor mal selbst ansteuert und die Impulse manuell erzeugt. Leider führt das schnell dazu das das Programm in einer Schleife hängt und man letztlich nicht mehr im Stande ist auf einen Endschalter zu reagieren.

Wenn man die Funktion grundsätzlich verstanden hat sollte man sich allerdings auf die Verwendung eine Bibliothek umstellen. Die machen die Erzeugung der Impulse in der Regel im Hintergrund und Du musst Dich damit nicht beschäftigen. Letztlich suchst Du aus der Dokumentation zu der Lib die richtige "Methode" heraus und stellst die Parameter dazu ein.

  1. Das stimmt , SPS ist anders. Das habe ich schon gemerkt das mit dem loop als Kreis verstehe ich.
  2. endlichen Automaten noch nicht gehört, werde ich mir mal anschauen.
  3. Struktur ja genau Ordnung da es ja ein Kreis ist und wenn ich die Schritte ausgebe und ich da zu viel im loop habe würde das ja meine schritte beeinflussen da die ja in Microsekunden gehen. (denke ich zumindest)
  4. Die Bibliothek MobaTools werde ich mir auch mal anschauen.

Ja genau, ist die selbe Taste.
Identisch sind die ja das stimmt - beim ersten läuft der Motor immer in eine Richtung und ich kann in mit der Taste umkehren. Beim zweiten läuft er auch immer in eine Richtung und mit dem Sensor ändert er die Richtung. Während dessen kann ich allerdings mit dem Taster immer die Richtung ändern.

Wie kann ich das weiter auswerten bzw. was meinst du damit genau?
Serial.flush werde ich entfernen wenn es nicht benötigt wird.

Eventuell hilft Dir dies:

Sie erzeugt die Schrittimpulse "im Hintergrund" und läßt Deine Schleife geschmeidig im Kreis laufen, um beispielsweise Taster sicher zu erkennen.

ABER: Gerade erst gesehen, "Board: Arduino Uno R4 Wifi" ist problematisch! Da mußt Du lesen und probieren, welche Bibliotheken diese sehr spezielle Hardware unterstützen. MobaTools läuft auf UNO R3 und ESP32, aber auf Uno R4 wohl nicht. Sorry :flushed:

Vielen dank schon einmal für die Tipps.
Das mit der Bibliotheken stimmt, es laufen nicht alle richtig auf dem Uno R4.
Ich werde es dann einfach mal weiter probieren.

Habe auch mal versucht die "Null Position" anzufahren. Irgend wie möchte das aber nicht so wie ich.
Mein Gedanke war Motor soll drehen bis Sensor erreicht ist oder maximal 1 Umdrehung damit es nicht unendlich läuft. Allerdings funktioniert das mit dem Sensor Signal nicht.
Muss ich den nullposState = digitalRead(nullpos); in den case machen oder passt das schon wenn das im loop steht?

/*
Treiber:
SW1 on; SW2 off; SW3 on; SW4 off; SW5 on; SW6 off; SW7 on; SW8 on
Motor: 200 Schritte/Umdrehung; 1,8° Schrittwinkel; 4,2A Nennstrom
*/

// Konstante Werte
#define driverPUL 7      //
#define driverDIR 6      // Drehrichtung
#define driverENA 2      // Motortreiber Start / Stop (Serieller Monitor: 1 Start/ 0 Stop)
#define rechtslaufPin 3  // Rechtslaufpin HIGH = rechtslauf / LOW = linkslauf
#define nullpos 5        // Nullposition Motor über Sensor
#define sensor 4         // Sensor für Motor umkehren

#define potentiometer A0  // Potentiometer 10k für Drehzahl

// Variable Werte
char sendeInhalt = ' ';      // Werte aus Seriellem Monitor
int rechtslaufPinState = 0;  // Rechtslaufpin HIGH = rechtslauf / LOW = linkslauf
int nullposState = 0;        // Nullposition Motor über Sensor
int sensorState = 0;         // Sensor für Motor umkehren
int nullposcounter = 0;      // Zähler für Nullfahrt Umdrehungen
int valueOld = 0, value = 0;
byte sensitivity = 20;  // Potentiometer 10k Schrittweite

void setup() {
  // initialize serial:
  Serial.begin(115200);
  while (!Serial) {};

  // initialize as a input
  pinMode(rechtslaufPin, INPUT_PULLUP);
  pinMode(nullpos, INPUT_PULLUP);
  pinMode(sensor, INPUT_PULLUP);

  // initialize as a output
  pinMode(driverPUL, OUTPUT);
  pinMode(driverDIR, OUTPUT);
  pinMode(driverENA, OUTPUT);

  // nach übertragen Motortreiber deaktivieren
  digitalWrite(driverENA, HIGH);
}

void loop() {
  nullposState = digitalRead(nullpos);

  // Motortreiber ansteueren über Seriellen Monitor
  if (Serial.available() > 0) {
    sendeInhalt = Serial.read();
    switch (sendeInhalt) {
      case '0':
        digitalWrite(driverENA, HIGH);
        Serial.println("Motortreiber: deaktiviert");
        Serial.println("----------------------------------");
        break;
      case '1':
        digitalWrite(driverENA, LOW);
        Serial.println("Motortreiber: aktiv");
        Serial.println("Motor: linkslauf");
        Serial.println("----------------------------------");
        break;
      case '2':
      // Nullposition anfahren entweder Sensorsignal oder maximal 1 Umdrehung  
      // ca. 830 Impulse/Umdrehung 
        while (nullposcounter < 830 && nullposState != LOW) {
          digitalWrite(driverENA, LOW);
          digitalWrite(driverDIR, LOW);
          digitalWrite(driverPUL, HIGH);
          delayMicroseconds(400);
          digitalWrite(driverPUL, LOW);
          delayMicroseconds(400);
          nullposcounter++;
          Serial.println(nullposcounter);
        }
        digitalWrite(driverENA, HIGH);
        nullposcounter = 0;
        break;
      default:
        digitalWrite(driverENA, HIGH);
        break;
    }
  }

  // Drehrichtung Vorgabe
  rechtslaufPinState = digitalRead(rechtslaufPin);
  if (rechtslaufPinState == LOW) {
    digitalWrite(driverDIR, HIGH);  // rechtslauf
  } else {
    digitalWrite(driverDIR, LOW);  // linkslauf
  }

  // Potentiometer 10k auslesen
  value = analogRead(potentiometer);
  if (abs(valueOld - value) >= sensitivity) {
    valueOld = value;
    Serial.println(value);
  }

  // Geschwindigkeit mit Poti
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(value);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(value);
}

Seit V2.6 laufen die MobaTools auch auf UNO R4 ( Minima und WiFi ). Schon seit V2.5 auf Nano Every und UNO WiFi Rev2.

Da Du das Suchen der Nullposition in einer (blockierenden ) while-schleife machst, musst Du den nullpos-Schalter auch innerhalb der Schleife abfragen. sonst wird nullposState während des Suchlaufs nie aktualisiert.
Besser wäre es, das mit der FSM nicht-böockierend zu machen.

Das war mir entgangen, Du bist Klasse :clap:

Danke für die Blumen :blush: :blush:

Zumindest laut Doku kann die Bibliothek mit dem Uno R4 verwendet werden…

Wer lesen kann und die aktuelle Version verwendet, ist klar im Vorteil :innocent:

Ich frage mich, warum Du diese Hardware nutzt. Willst Du mal was mit einer Webseite machen? Dann wäre das Beispiel UNO-R4WiFi-Web.ino der MobaTools eventuell ein guter Einstieg. Ich habe das mal auf meinem ESP32 mit kleinen Anpassungen laufen gelassen:

Mich interessiert das nur perspektivisch, weil Du sicherlich nicht "start" eintippen möchtest und ein Uno R4 ohne Funk rausgeworfenes Geld bedeutet.

Webseite habe ich noch gar nicht in Betracht gezogen.
Da kenne ich mich zu wenig aus. Habe überlegt es evtl. über Excel zu machen oder Touch da das glaube ich etwas einfacher ist.

Am Anfang möchte ich mit Seriellen Monitor starten bevor ich das DIsplay oder Excel nutze.
Auf dem Display soll es die zwei "Modis" geben welche ich dort auswählen kann. (Also nur laufen ohne Sensor und das mit Sensor und Umkehrung.) Zusätzlich möchte ich da auch einen Start Button und evtl. einen Stopp Button nutzen. Das Poti bleibt ein "Analoges Poti".
Der Taster für Drehrichtung Umkehr bin ich noch nicht sicher ob über Touch oder mechanisch.
Was evtl. noch schön wäre wenn man die Umdrehungen anzeigen lassen könnte. Das ist aber alles noch Zukunft. Erst mal klein anfangen.

Der Uno R4 habe ich weil ich den bekommen habe. Und nochmals einen kleinen kaufen ist auch blöd wenn ich den habe.

Ich werde mir das Beispiel auf jeden fall mal anschauen ob ich das verstehe.

Verstehe, da steckt also keine Strategie deinerseits dahinter.

Davon möchte ich Dich keinesfalls abbringen!

Damit Du das leichter nachvollziehen kannst, habe ich mal auf alle Knöpfe geklickt.

Der Browser schickt Text an den Server, den dieser zerlegt und interpretiert.

IP Address: 192.168.178.27
signal strength (RSSI): -33 dBm
To see this page in action, open a browser to http://192.168.178.27
GET / HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&setRamp=Set+ramp&speed=800 HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&speed=444&setSpeed=Set+speed HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&speed=444&links=1+rev+left HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&speed=444&contl=Cont.+left HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&speed=444&rechts=1+rev.+right HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&speed=444&contr=Cont.+right HTTP/1.1
GET /favicon.ico HTTP/1.1
GET /stepper?ramp=55&speed=444&stop=Stopp HTTP/1.1
GET /favicon.ico HTTP/1.1

Das ist vergleichbar dem, was Du im seriellen Monitor eintippen möchtest. Abschauen ist erlaubt :wink:

Habe mir das ganze Thema mit Browser mal angeschaut und denke das das nichts für mich ist.
Möchte es lieber über ein Touch Display lösen.
Wahrscheinlich über den Arduino Giga mit dem passenden Display. (Ist aber noch offen)

Mache meinen Code aktuell auch nochmals neu und habe mal ganz unten versucht zu beschreiben was ich eigentlich mit dem Code machen möchte. (Code ist nicht als Code zu betrachten sondern eher als Info was er machen soll)

/*
Board: Arduino Uno R4 Wifi
Treiber: Joy-it DM860H
SW1 on; SW2 off; SW3 on; SW4 off; SW5 on; SW6 off; SW7 on; SW8 on
Motor: Joy-it Nema 23-01
200 Schritte/Umdrehung; 1,8° Schrittwinkel; 4,2A Nennstrom
*/

// Eingänge
#define driverZero 3  //Sensor Motor Nullposition
#define scaleZero 4   // Messskala Nullposition
#define scaleMax 5    // Sensor Messskala Maximalposition
#define potiSpeed A0  //Potentiometer Drehzahl
// Später über Touch Display
#define start 6     // Taster Start
#define stopp 7     // Taster Stop
#define rotation 8  // Taster Drehrichtung
#define transfer 9  // Taster Werte / Varablen Übertragen

// Ausgänge
int driverENA = HIGH;    // Motortreiber ENA
int driverDIR = LOW;     //  Motortreiber DIR
int driverPUL = LOW;     //  Motortreiber PUL
int LEDscaleZero = LOW;  //  LED Messskala Nullposition

// Variable Werte
int Modus = 0;                // Modus 1-5
int Länge = 0;                // Länge 0-1000mm (benötigt für berechnung von Umdrehungen auf 1000mm)
int Umdrehungen = 0;          //Anzahl Umdrehungen 0-9999
int Gewicht = 0;              // Gewicht auf Messskala
int LEDscaleZeroState = LOW;  //Status LED Messskala Nullposition
int valueOld = 0, value = 0;  // Potentiometer 10k auslesen
char SDrehung = 'S';          // S-Drehung = Rechtsdrehung
char ZDrehung = 'Z';          // Z-Drehung = Linksdrehung
char serial = ' ';            // Werte aus Seriellem Monitor
byte sensitivity = 10;        // Potentiometer 10k Schrittweite

void setup() {
  // initialize serial:
  Serial.begin(115200);
  while (!Serial) {};

  // initialize as a input
  pinMode(driverZero, INPUT_PULLUP);
  pinMode(scaleZero, INPUT_PULLUP);
  pinMode(scaleMax, INPUT_PULLUP);

  pinMode(start, INPUT_PULLUP);
  pinMode(stopp, INPUT_PULLUP);
  pinMode(rotation, INPUT_PULLUP);
  pinMode(transfer, INPUT_PULLUP);

  // initialize as a output
  pinMode(driverENA, OUTPUT);
  pinMode(driverDIR, OUTPUT);
  pinMode(driverPUL, OUTPUT);
  pinMode(LEDscaleZero, OUTPUT);
}

void loop() {
  // Seriellen Moitor auslesen falls benötigt wird
  if (Serial.available() > 0) {
    serial = Serial.read();
    switch (serial) {
      case '':

        break;
      case '':

        break;
      default:

        break;
    }
  }
  // Potentiometer 10k auslesen und auf Seriellen Monitor schreiben
  value = analogRead(potiSpeed);
  if (abs(valueOld - value) >= sensitivity) {
    valueOld = value;
    Serial.println(value);
  }
  // Geschwindigkeit mit Potentiometer Vorgabe
  digitalWrite(driverPUL, HIGH);
  delayMicroseconds(value);
  digitalWrite(driverPUL, LOW);
  delayMicroseconds(value);
}



/*
Funktion allgemein, unabhängig von Modus: 
1. über Touch Display auswählen welchen Modus (Touchdisplay zeigt nur Auswahl von 4x Modus an)
2. über Touch Display  eingeben "Länge", "Gewicht", "S oder Z Drehung" (Touchdisplay zeigt an welcher Modus ausgewählt und eingabefelder für ... und Start Taste)
3. Start drücken auf Touch Display, Motor dreht sich mit Linksdrehung bis "driverZero" erreicht ist, Motor bleibt stehen (Touchdisplay zeigt gleiche an wie davor)
4. ausgewählten modus ausführen und Umdrehungen vom Motor Zählen (Touchdisplay zeigt gleiche an wie davor zusätlich Stopp Taste und Anzahl Umdrehungen)
5. Stopp drücken auf Touch Display (Touchdisplay zeigt gleiche an wie davor, aus Start und Stopp Taste wird Taste "transfer" oder abbrechen und man springt auf 2 zurück)
6. nach drücken von Taste "transfer" "Länge", "Gewicht", "S oder Z Drehung", "Anzahl Umdrehungen" an Excel schicken über Datenstreamer 
7. Touch Display zeigt nur noch zwei Tasten an "Zurück auf Start" (gehe zu 1) oder "Wiederholen" (gehe zu 2)

Modus 1: 
Motor steht auf Nullposition 
Poti für Geschindigkeit drehen - Motor dreht sich mit Rechtslauf bis Poti auf 0 gestellt wird oder auf Touch Display Stopp gedrückt wird 
Wen sich der Motor dreht und man die Taste "rotation" drückt soll sich der Motor so lange wie gedrpckt wird in die andere Richtung drehen 

Modus 2: 
Motor steht auf Nullposition 
Poti für Geschindigkeit drehen - Motor dreht sich mit Rechtslauf bis Poti auf 0 gestellt wird oder auf Touch Display Stopp gedrückt wird
Wen sich der Motor dreht und man die Taste "rotation" drückt soll sich der Motor so lange wie gedrpckt wird in die andere Richtung drehen 
Wird der Sensor "scaleMax" erreicht dreht sich der Motor mit Linkslauf bis Poti auf 0 gestellt wird oder auf Touch Display Stopp gedrückt wird
Wen sich der Motor dreht und man die Taste "rotation" drückt soll sich der Motor so lange wie gedrpckt wird in die andere Richtung drehen 

Modus 3: 
Motor steht auf Nullposition 
Poti für Geschindigkeit drehen - Motor dreht sich mit Linkslauf bis Poti auf 0 gestellt wird oder auf Touch Display Stopp gedrückt wird 
Wen sich der Motor dreht und man die Taste "rotation" drückt soll sich der Motor so lange wie gedrpckt wird in die andere Richtung drehen 

Modus 4:
Motor steht auf Nullposition 
Poti für Geschindigkeit drehen - Motor dreht sich mit Linkslauf bis Poti auf 0 gestellt wird oder auf Touch Display Stopp gedrückt wird
Wen sich der Motor dreht und man die Taste "rotation" drückt soll sich der Motor so lange wie gedrpckt wird in die andere Richtung drehen 
Wird der Sensor "scaleMax" erreicht dreht sich der Motor mit Rechtslauf bis Poti auf 0 gestellt wird oder auf Touch Display Stopp gedrückt wird
Wen sich der Motor dreht und man die Taste "rotation" drückt soll sich der Motor so lange wie gedrpckt wird in die andere Richtung drehen

*/

Eine Schrittkette realisiere ich gerne mittels switch/case, aber nicht jedes switch/case ist eine Schrittkette.

Das nenne ich Referenzpunkt und entsprechend Referenzpunkttaster an refPin. Referenzpunkt und Nullposition müssen nicht übereinstimmen, mache ich aber erstmal so.

Das wäre schade. Mein Beitrag hat sich leider mit Deinem überschnitten, weshalb ich das Bibliotheksbeispiel mit Browsernutzung um eine Schrittkette in loopManuell() erweitert habe.

Da mein ESP32 andere Pins als der Uno R4 benötigt, verwende ich bedingte Compilierung.

Drückt man auf tasterPin, dreht der Motor maximal eine Umdrehung. Wird der refPin erreicht, bleibt der Motor stehen und die Bibliothek speichert diese Position als Nullposition.

Programm
/*
  WiFi Web Server to control a stepper ( for UNO R4 WiFi )

  A simple web server that lets control a stepper via the web.
  This sketch will print the IP address of your WiFi module (once connected)
  to the Serial Monitor. From there, you can open that address in a web browser
  to control a stepper.

  An extension of the AP_SimpleWebServer example for UNO R4 WIFI
*/

// One of the following 2 defines must be active:
//#define DEBUG_P( x, ... ) {char dbgBuf[80]; snprintf_P( dbgBuf, 80, PSTR( x ), ##__VA_ARGS__ ) ; Serial.println( dbgBuf ); }
#define DEBUG_P(...)  // no debug printing

#if defined ARDUINO_ARCH_ESP32
#include "WiFi.h"
#else
#include "WiFiS3.h"
#endif
#include <MobaTools.h>  // min version 2.6.1: https://github.com/MicroBahner/MobaTools

#include "zugangsdaten.h"  // "arduino_secrets.h"
/*/////please enter your sensitive data in the newly created tab 'arduino_secrets.h'
  e.g.:
  #define SECRET_SSID "your-ssid"
  #define SECRET_PASS "your-passwd"
*/
const char* ssid = STA_SSID;              // your network SSID (name)
const char* pass = STA_PASSWORD;          // your network WPA  password

// change pin numers to your needs
#if defined ARDUINO_ARCH_ESP32
const int dirPin    = 25;
const int stepPin   = 26;
const int enaPin    = 27;
const int tasterPin = 12;
const int ledPin    = 13;
const int refPin    = 32;
#else
const int dirPin    =  5;
const int stepPin   =  6;
const int enaPin    =  7;
const int tasterPin =  2;
const int ledPin    = 13;
const int refPin    =  3;
#endif

const int STEPS_REVOLUTION = 800;                         // 1/4 Microstep -> 800 steps/rev
MoToStepper myStepper( STEPS_REVOLUTION, STEPDIR );       // create stepper instance

uint32_t htSpeed = 8000;    // steps/10 sec
uint32_t htRamp = 100;      // ramp length in steps

int status = WL_IDLE_STATUS;
WiFiServer server(80);
#include "website.h"

void setup() {
  Serial.begin(115200);                             // initialize serial communication
  // initialize stepper
  myStepper.attach( stepPin, dirPin );              // assign step/dir pins
  myStepper.attachEnable( enaPin, 10, LOW );        // attach enable in ( LOW=active )
  myStepper.setSpeedSteps( htSpeed );               // initial value of speed
  myStepper.setRampLen( htRamp );                   // initial ramp length


#if defined ARDUINO_ARCH_ESP32
  // nicht relevant
#else
  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }
#endif

  // attempt to connect to WiFi network:
  Serial.print("Attempting to connect to Network named: ");
  Serial.println(ssid);                   // print the network name (SSID);
  WiFi.begin(ssid, pass);                     // <-- agmue
  while (WiFi.status() != WL_CONNECTED) {     // <-- agmue
    delay(200);
    Serial.print(".");
  }
  server.begin();                           // start the web server on port 80
  printWifiStatus();                        // you're connected now, so print out the status

  setupManuell();
}

void loop() {
  handleWiFi();
  loopManuell();
}

void handleWiFi() {
  // text buffer receiving from connected browser
  constexpr uint8_t lineBufLen = 80;
  char lineBuf[lineBufLen];
  uint8_t bufIx = 0;

  WiFiClient client = server.available();   // listen for incoming clients
  if (client) {                             // if you get a client,
    DEBUG_P("new client");                  // print a message out the serial port
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        //Serial.write(c);                    // print it out to the serial monitor
        if (c == '\n') {                    // if the byte is a newline character
          lineBuf[bufIx] = '\0';          // terminate string

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (bufIx == 0) {
            char htmlTemp[sizeof(HTMLTEXT) + 15]; // Size of website+some extra bytes for 2 variable fields
            DEBUG_P("Send website, speed=%d, ramp=%d", htSpeed, htRamp)
            snprintf( htmlTemp, sizeof(htmlTemp), HTMLTEXT, htRamp, htSpeed / 10 );
            client.print( htmlTemp);
            DEBUG_P("---------------Send HTTP-Page --------------------");
            break;
          } else {
            // We got a complete line. Test if we got a GET line and process it if so
            handleStepper(  lineBuf );
            bufIx = 0;
          }

        } else if (c != '\r') {
          // If you got anything else but a carriage return character,
          // write it into the buffer, but pay attention to the buffer length!
          if ( bufIx < (lineBufLen - 1) ) {      // leave space for a terminating \0
            lineBuf[bufIx++] = c;
          }
        }

      }
    } // End 'while connected'
    // close the connection:
    client.stop();
    DEBUG_P("client disconnected");
  }
}

void handleStepper( char* GETcom ) {
  // Field commands from the browser
  enum : uint8_t {SPEED, RAMP, SETSPEED_RAMP, SETSPEED, SETRAMP, LINKS, RECHTS, CONTL, CONTR, STOP}; // actions
  const char * keyWords[] = { "speed=", "ramp=", "setSpeedRamp=", "setSpeed=", "setRamp=", "links=", "rechts=", "contl=", "contr=", "stop=" };
  constexpr uint8_t keyIxMax = sizeof(keyWords) / sizeof(keyWords[0]);
  uint8_t keyIx;
  char *keyP, *valP;
  //check for GET command from client
  char* strGET = strstr( GETcom, "GET" );
  if ( strGET != NULL ) {
    // It's a GET line - process it
    uint32_t tmpSpeed = 8000, tmpRamp = 100;    // Default values for ramp and speed field - will usually been overwritten.
    Serial.println(GETcom);
    strGET = strstr( strGET, "stepper?" );
    if ( strGET != NULL ) {
      strGET += strlen("stepper?");
      strGET = strtok( strGET, " &" );
      DEBUG_P("vvvvvvvvvvvvvvvvvvvvvvv");
      while ( strGET != NULL ) {
        // DEBUG_P( strGET );
        // check for keywords - separate keyword from value
        valP = strchr(strGET, (int)'=');
        if ( valP ) valP++;
        for ( keyIx = 0; keyIx < keyIxMax; keyIx++ ) {
          keyP = strstr( strGET, keyWords[keyIx] );
          if ( keyP != NULL ) {
            DEBUG_P("Keyword: % s, Ix: % d", keyP, keyIx);
            // found keyword
            switch (keyIx) {
              case SPEED:
                tmpSpeed = 10 * atoi(valP);
                DEBUG_P("Speedval = %d", tmpSpeed);
                break;
              case RAMP:
                tmpRamp = atoi(valP);
                DEBUG_P("Rampval = % d", tmpRamp);
                break;
              case SETSPEED:
                htSpeed = tmpSpeed;
                htRamp = myStepper.setSpeedSteps(htSpeed, htRamp);
                DEBUG_P("set Speed = % d, actRamp = % d", htSpeed, htRamp);
                break;
              case SETSPEED_RAMP:
                htSpeed = tmpSpeed;
                htRamp = myStepper.setSpeedSteps(htSpeed);
                DEBUG_P("setSpeed + ramp = % d, actRamp = % d", htSpeed, htRamp);
                break;
              case SETRAMP:
                htRamp = tmpRamp;
                htRamp = myStepper.setRampLen(htRamp);
                break;
              case LINKS:
                myStepper.doSteps(-STEPS_REVOLUTION);
                DEBUG_P("One rev. CCW");
                break;
              case RECHTS:
                myStepper.doSteps(STEPS_REVOLUTION);
                DEBUG_P("one rev. CW");
                break;
              case CONTL:
                myStepper.rotate( -1 );
                DEBUG_P("rotate CCW");
                break;
              case CONTR:
                myStepper.rotate( 1 );
                DEBUG_P("rotate CW");
                break;
              case STOP:
                myStepper.rotate( 0 );
                DEBUG_P("Stop the stepper");
                break;
            }
            break; // Exit for loop, we found the keyword.
          }
        }
        strGET = strtok( NULL, " &" );
      }
      DEBUG_P("^^^^^^^^^^^^^^^^^^^^^^^^^");
    }
  }

}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI): ");
  Serial.print(rssi);
  Serial.println(" dBm");
  // print where to go in a browser:
  Serial.print("To see this page in action, open a browser to http://");
  Serial.println(ip);
}

void setupManuell()
{
  pinMode(tasterPin, INPUT_PULLUP);
  pinMode(refPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
}

void loopManuell()
{
  enum struct Schritt : byte {WARTEN, REFERENZ, WEITER};
  static Schritt schritt = Schritt::WARTEN;

  switch (schritt)
  {
    case Schritt::WARTEN:
      if (!digitalRead(tasterPin))
      {
        Serial.println(F("Start Referenzsuche"));
        myStepper.setZero( );
        myStepper.write( 360 );
        schritt = Schritt::REFERENZ;
      }
      break;
    case Schritt::REFERENZ:
      if (!digitalRead(refPin))
      {
        myStepper.setZero( );
        myStepper.stop( );
        Serial.println(F("Referenz gefunden"));
        schritt = Schritt::WEITER;
      }
      if (!myStepper.moving())
      {
        Serial.println(F("Referenz nicht gefunden"));
        schritt = Schritt::WEITER;
      }
      break;
    case Schritt::WEITER:
      schritt = Schritt::WARTEN;
      break;
    default:
      Serial.println(F("Fehler: In der Schrittkette falsch abgebogen!"));
      break;
  }
}

Die Datei website.h bleibt unverändert.

Ich freue mich über eine Rückmeldung :slightly_smiling_face: