Stepper Probleme mit der AccelStepper Bibliothek

Hallo,

ich brauche eure Hilfe!!

Ich habe seit einem Jahr in meinem Projekt einen funktionierenden Sketch zum Öffnen einer Tür mittels NEMA 17 Stepper, TB6600, verwende die AccelStepper Bibliothek.

Mich stört darin, dass der StepperMotor an den Endstops "über das Ziel hinaus schießt".
Das wollte ich abstellen und ich habe mich in AccelStepper.h orientiert und versucht, einige Anpassungen vorzunehmen.

Das Problem ist:

verwende ich den "alten Code" wie in den Funktionen im Beispiel Tuer1Auf(); und Tuer2Auf();, dann klappt alles gut bis auf das Problem, dass der Stepper über das Ziel an den Endstops hinausfahren will. Bedeutet: trifft der Schlitten auf die Endstops, dann stoppt der Motor nicht sofort, sondern dreht sich weiter.

Mein Ziel ist es, dass der Stepper nicht eine vorher definierte Strecke bis zum Endstop zurücklegt, sondern

step für step bewegt wird,
wenn er Endstop auslöst, sich um wie hier 50 Steps zurückbewegt
und stoppt.

Das habe ich in der Funktion TuerAuf() versucht, indem ich die Zeilen

digitalWrite(enablePin, LOW);
while (digitalRead(endSchalterAuf)) {
stepper.run();
stepper.setCurrentPosition(0);
...

zu realisieren mit der Folge, dass der Motor nur kurz "anruckt" und dann leicht pfeifende Töne von sich gibt und blockiert.

Worin liegt der Fehler?
Ich bitte um eure Unterstützung.

Gruß, Gerhard


Hier der Code:

```cpp
#include <AccelStepper.h>
// PINBELEGUNG Stepper-Motor NEMA 17
const int enablePin = 8;
const int stepPin = 9;
const int dirPin = 10;
// PINBELEGUNG für die Endschalter der Linearführung
#define endSchalterAuf 7
#define endSchalterZu 6

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup() {
  pinMode(6, INPUT_PULLUP);  // Tür auf
  pinMode(7, INPUT_PULLUP);  // Tür zu
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, HIGH);
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(500);
  Serial.begin(9600);
}

void loop() {
  Tuer1Auf();
  delay(5000);
  Tuer1Zu();
  delay(5000);
  TuerAuf();
  delay(5000);
  TuerZu();
  delay(5000);
}

// Definieren der Funktion TUER AUF
void TuerAuf() {
  digitalWrite(enablePin, LOW);
  while (digitalRead(endSchalterAuf)) {
    stepper.run();
    stepper.setCurrentPosition(0);
   }
  digitalWrite(enablePin, LOW);

  stepper.moveTo(stepper.currentPosition() - 30);  // Entprellen
  stepper.runToPosition();
  digitalWrite(enablePin, HIGH);
}

// Definieren der Funktion TUER 1 ZU
void Tuer1Zu() {
  digitalWrite(enablePin, LOW);
  stepper.moveTo(-30000);
  while (digitalRead(endSchalterZu)) {
    stepper.run();
    stepper.currentPosition() == 0;
  }
  digitalWrite(enablePin, HIGH);
  digitalWrite(enablePin, LOW);
  stepper.moveTo(stepper.currentPosition() + 30);
  stepper.runToPosition();
  digitalWrite(enablePin, HIGH);
}

// Definieren der Funktion TUER 2 AUF
void Tuer1Auf() {
  digitalWrite(enablePin, LOW);
  stepper.moveTo(30000);
  while (digitalRead(endSchalterAuf)) {
    stepper.run();
    stepper.currentPosition() == 0;
  }
  digitalWrite(enablePin, HIGH);
  digitalWrite(enablePin, LOW);
  stepper.moveTo(stepper.currentPosition() - 30);
  stepper.runToPosition();
  digitalWrite(enablePin, HIGH);
}


// Definieren der Funktion TUER ZU
void TuerZu() {
  Serial.println("Zeile01");
  digitalWrite(enablePin, LOW);
  digitalWrite(dirPin, LOW);
  stepper.move(1);
  stepper.run();
  while (digitalRead(endSchalterZu)) {
    stepper.run();
    stepper.setCurrentPosition(0);
  }
  //digitalWrite(enablePin, LOW);
  stepper.moveTo(stepper.currentPosition() + 30);  // Entprellen
  stepper.runToPosition();
  digitalWrite(enablePin, HIGH);
}

Deine max. Beschleunigung ist zu niedrig, mach den Wert um den Faktor 10 größer. Wenn du Schritte verlierst reduzier' die Beschleunigung.

Ja, das hat zumindest im "alten" Code funktioniert. Vielen Dank.
Ich habe mit 79 Jahren angefangen, damit das Gehirn nicht einrostet, mir Arduino- Projekte auszudenken. Mein Ziel ist es, zum Flugsimulator MS 2020 Garmin Displays mit "richtigen" Knobs, Tastern, Poti usw. zu bauen. Alle 3D Druckteile sind fertg, Raspberry pi für Display und Webinterface. Jetzt warte ich noch auf die Veröffentlichung von MS 2024, dann gehts los. MobiFlight steht schon in den Startlöchern.

Nur mit den Schrittmotoren in Verbindung mit AcelStepper tu ich mich schwer. Standard ja, aber wenn es etwas eleganter zugehen soll, dann klemmts.

Das Problem mit der festen Anzahl der Schritte bis zum Endstop ist noch immer vorhanden.
Wie kann man das ändern, dass der Schrittmotor wie hier im Beispiel nicht die 30000 Schritte bis zum Endstop zurücklegen soll, sondern, dass die steps so lange erhöht werden (steps ++ ???), bis der Endstop erreicht ist?

Der auf das Wesentliche verkürzte Sketch hier noch einmal gepostet:

#include <AccelStepper.h>
// PINBELEGUNG Stepper-Motor NEMA 17
const int enablePin = 8;
const int stepPin = 9;
const int dirPin = 10;
// PINBELEGUNG für die Endschalter der Linearführung
#define endSchalterAuf 7
#define endSchalterZu 6

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup() {
  pinMode(6, INPUT_PULLUP);  // Tür auf
  pinMode(7, INPUT_PULLUP);  // Tür zu
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, HIGH);
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(1500);
  Serial.begin(9600);
}

void loop() {
  Tuer1Auf();
  delay(5000);
 TuerAuf();
}

// Definieren der Funktion TUER AUF
void TuerAuf() {
  digitalWrite(enablePin, LOW);
  while (digitalRead(endSchalterAuf)) {
    stepper.run();
    stepper.setCurrentPosition(0);
  }
  Serial.println("Zeile04");
  digitalWrite(enablePin, LOW);

  stepper.moveTo(stepper.currentPosition() - 30);  // Entprellen
  stepper.runToPosition();
  digitalWrite(enablePin, HIGH);
}


// Definieren der Funktion TUER 2 AUF
void Tuer1Auf() {
  digitalWrite(enablePin, LOW);
  stepper.moveTo(30000);
  while (digitalRead(endSchalterAuf)) {
    stepper.run();
    stepper.currentPosition() == 0;
  }
  digitalWrite(enablePin, HIGH);
  digitalWrite(enablePin, LOW);
  stepper.moveTo(stepper.currentPosition() - 30);
  stepper.runToPosition();
  digitalWrite(enablePin, HIGH);
}

Du braucht immer eine Referenz, also entweder Endschalter, Lichtschranke ... und beim Eischalten fährst du den an. Alternative sind Absolutencoder oder Poti, kommt halt auf deine Mechanik an was du nehmen kannst. Ah ja, und ganz brutale Menschen faren einfach bis zum mechanischen Anschlag und dann ein bischen zurück, also ohne Schalter dfrür mit Tickgeräusch.

Zeig mal bitte, wie deine Hardware aufgebaut ist. Türmechanik und die Position der Endschalter. Evtl auch ein Foto wo man das erkennen kann.
Du verwendest die Accelstepper sehr 'eigenwillig' ;).
Welcher Sinn steckt hinter den jeweils 2 Varianten von Auf und Zu? Was soll da unterschiedlich sein (von der Funktionalität her)?
[Edit] Habs jetzt verstanden - sind alte und neue Version.

Kanns momentan nur beschreiben:
Für eine automatisierte Türöffnung habe ich einen Steppermotor, einen Schlitten auf einer 1m 20x20 Alu Schiene, an deren Enden 2 Endstops befestigt sind.
In Abhängigkeit von Innen- und Aussentemperatur, Feuchte und Niederschlag öffnet sich die Tür prozentual, bis sie vollständig geschlossen oder vollständig geöffnet wird.
Zu diesem Projekt habe ich mir eigens ein kleines Tomatenhäusschen gebastelt, Bewässerung, Lüftung und alles andere ebenfalls durch Arduino.

Habe nun ein bissel gebastelt und bin momentan bei diesem, funktionierenden Code gelangt, beantwortet aber nicht mein eigentliches "Problemchen".
Habe ihn mal kommentiert:

#include <AccelStepper.h>
// PINBELEGUNG Stepper-Motor NEMA 17
const int enablePin = 8;
const int stepPin = 9;
const int dirPin = 10;
// PINBELEGUNG für die Endschalter der Linearführung
#define endSchalterAuf 6
#define endSchalterZu 7

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup() {
  pinMode(endSchalterZu, INPUT_PULLUP);  // Endschalter Zu
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, LOW);  // Aktivieren des Steppers
  stepper.setMaxSpeed(500);
  stepper.setAcceleration(1500);
  Serial.begin(9600);
}

void loop() {
  TuerZuBisEndschalter();
  delay(5000);

  //break;
}

void TuerZu() {
  digitalWrite(enablePin, LOW);  // Aktivieren des Steppers
  // Schleife, die den Stepper schrittweise bewegt, bis der Endschalter erreicht ist
  while (digitalRead(endSchalterZu) == HIGH) {  // Solange der Endschalter nicht ausgelöst ist
    stepper.move(100);  // Einen Schritt vorwärts
    stepper.runToPosition();  // Bewegung ausführen
    //delay(10);  // Kurze Pause zwischen den Schritten, um den Motor nicht zu überlasten
  }
  stepper.stop();  // Stoppen des Steppers, wenn der Endschalter ausgelöst wird
  delay(1000);  // 1 Sekunde Pause
  stepper.move(-50);  // 50 Steps zurück
  stepper.runToPosition();  // Zurück zur neuen Position bewegen
}

void TuerZu() {
  digitalWrite(enablePin, LOW);  // Aktivieren des Steppers
  stepper.setMaxSpeed(1000);  // Maximale Geschwindigkeit setzen
  stepper.setAcceleration(2000);  // Beschleunigung setzen

  // Bewegung in Richtung Endschalter starten
  stepper.moveTo(stepper.currentPosition() + 500000);  // Großer Wert, um sicherzustellen, dass der Endschalter erreicht wird

  // Schleife, die den Stepper kontinuierlich bewegt, bis der Endschalter erreicht ist
  while (stepper.distanceToGo() > 0) {  // Solange noch Distanz zum Ziel vorhanden ist
    stepper.run();  // Führt die Bewegung aus
    if (digitalRead(endSchalterZu) == LOW) {  // Prüfung, ob Endschalter ausgelöst wurde
      stepper.stop();  // Stoppen des Steppers
      break;  // Verlassen der Schleife
    }
  }

  delay(1000);  // 1 Sekunde Pause
  stepper.move(-50);  // 50 Steps zurück
  while(stepper.distanceToGo() != 0) {
    stepper.run();  // Zurück zur neuen Position bewegen
  }
}



Hallo @Eibenger
hast du mal die Doku zu den AccelStepper-Befehlen gelesen?

Ich vermute mal nicht.
function move() und function runToPosition()

while (digitalRead(endSchalterZu) == HIGH) {  // Solange der Endschalter nicht ausgelöst ist
    stepper.move(100);  // Einen Schritt vorwärts
    stepper.runToPosition();  // Bewegung ausführen
    //delay(10);  // Kurze Pause zwischen den Schritten, um den Motor nicht zu überlasten
  }

move() : setze eine Zielposition
runToPosition() fahre gnadenlos bis an die Zielposition
erst dann wenn die Zielposition erreicht IST wird der nächste Befehl begonnen.

Um das mit etwas abgewandeltem Code besser zu verdeutlichen

while (digitalRead(endSchalterZu) == HIGH) {  // Solange der Endschalter nicht ausgelöst ist
    stepper.move(100);  // Einen Schritt vorwärts
    Serial.print("Starte Motor fahre AUF JEDEN FALL 100 Schritte");
    stepper.runToPosition();  // Bewegung ausführen
    Serial.print("Position erreicht");
  }

Du fährst also IMMER 100 Schritte egal ob schon nach einem Schritt dein Schalter namens
endSchalterZu LOW liefert oder nicht.

Das nächste Einlesen des Schalter "endSchalterZu" findert immer erst dann statt wenn der
Schrittmotor 100 Schritte gemacht hat.

runToPosition() ist eine blockierende function. Die arbeitet das Schritte ausgeben IMMER vollständig ab.

Wenn man das nicht haben möchte dann muss man jeweils nur einen Schritt ausgeben
und dann schon wieder erneut abfragen also so

while (digitalRead(endSchalterZu) == HIGH) {  // Solange der Endschalter nicht ausgelöst ist
    stepper.move(1);  // WIRKLICH nur EINEN Schritt vorwärts und nicht 100 
    Serial.print("Starte Motor fahre EINEN Schritt)
    stepper.runToPosition();  // Bewegung ausführen
    Serial.print("Position erreicht");
  }

Es gibt aber eine viel bessere Lösung:

Die MobaTools. Es ist geradezu budhistische Bescheidenheit das der Autor Microbahner die MobaTools nicht selbst vorschlägt.

Die Befehle in den MobaTools heißen ein Stück weit anders. Aber wenn du sie gelernt hast wird das Programmieren sehr viel leichter. Weil die MobaTools die Schrittimpulse-Erzeugung im Hintergrund machen und man IMMER nebenher weitere Befehle ausführen kann. Beliebig schnell oder langsam wie immer sich das ergeben mag.

Außerdem gibt es einen STOP-Befehl der immer sofort wirkt.

Im Gegensatz zum .stop() der Accelstepper. Der macht nämlich nicht das was Du offensichtlich denkst:

stepper.stop() ist letztendlich auch nur ein spezieller moveTo Befehl. Er setzt ein neues Ziel, dass mit der aktuellen Beschleunigung/Bremsung gerade so erreicht werden kann.

P.S. So wie Du den Stepper nutzt, wäre ein DC-Motor wahrscheinlich effektiver und einfacher.

Ich habe das für die MobaTools gemeint. Da es nicht ausdrücklich dabeistand kann man es natürlich auch auf AccelStepper beziehen.

Danke für eure Unterstützung!
Wo sind die MobaTools zu finden?
Das interessiert mich schon, zumal ich das Projekt (nur des Lernens wegen, die wenigen zu erntenden Tomaten sind um das hundertfache billiger als die verbaute Hardware :wink: ) erweitern möchte.

Auf alle Fälle nehme ich mir jetzt noch einmal gründlich die AccelStepper.h vor, da habe ich doch noch sehr viel Nachholebdarf.

Deine Erklärung hat jedenfalls schon mal geholfen.

Ja, ist schon klar. Mein Post war auch an @Eibinger gerichtet - hätte ich deutlicher machen sollen.

Die kannst Du über den Bibliotheksmanger installieren. Im Suchfeld 'MobaTools' eingeben, dann findest Du die. Bei dem Eintrag einfach auf 'installieren' drücken, fertig.

Danke, ist jetzt installiert.
Habe die Doku runtergeladen und damit ist der Sonntag gerettet!
Wenn ich durch bin, dann stelle ich den überarbeiteten Sketch zur Überprüfung vor.

Hätte ich früher wissen sollen, dass es die Tools gibt, hatte nur zum Lernen eine Modelleisenbahnanlage Spur N aufgebaut, hatte gebrauchte Loks gekauft und alle 15 digitalisiert. Auf drei Etagen fuhren bis zu 10 Züge gleichzeitig, 42 Weichen u.a.
Habe fast 2 Jahre damit zugebracht, als alles fertig war, habe ich verkauft, habe keinen in der Familie, der sich dafür interessierte. Ich hatte aber eine schöne Zeit. Nun das neue Projekt, etwas bescheidener!

Gruß, Gerhard

Ja, ursprünglich habe ich die MobaTools mal für Aufgaben bei einer Moba-Steuerung entwickelt. Daher auch der Name. Inzwischen werden sie wahrscheinlich für andere Anwendungen häufiger eingesetzt als für die Moba ... :smile: :wink: Aber jetzt bleibt der Name so.

Nach den ersten Fehlversuchen mit den MobaTools habe ich jetzt meinen Stepper zum Laufen gebracht.
Ziel ist es, in meinem kleinen Versuchsaufbau "Tomatenhäuschen" die Aufgabe:

Türöffnung prozentual entsprechend der Innentemperatur und Niederschlag

erst einmal für die Innentemperatur zu realisieren. Ein Schrittmotor NEMA 17 kommt zur Anwendung.
Eine Hysterese wird eingebunden, um das "Türpendeln" an den Grenzwerten zu verhindern.

Praktisch funktioniert der Sketch mit dem Stepper und den MobaTools recht gut.

Ich komme nur noch nicht zurecht, wenn ich vor dem ersten Anfahren der temperaturabhängigen Positionen den Schlitten erst einmal zu einer noch zu definierten Position TuerZu fahren will.
Die Schritte wären m.E.

TuerZu:

  1. Egal, wo du bist, fahre den Schlitten in Richtung Endstop Zu
  2. Entprelle um 55 steps
  3. Stop

Ob es nötig ist, bei jeder temeraturabh. Türöffnung TuerZu davorzusetzen, wird sich durch die MobaTools wohl erübrigen, da die aktuelle Position nicht die neue Startposition wäre?

Ihr könnt mir bestimmt helfen und den Codeschnipsel die Funktion TuerZu schreiben anhand meiner Parameter und zeigen, an welche Stelle er eingebunden werden muss.

Danke schon mal im voraus und liebe Grüße,

Gerhard

Hier der Code:

#include <OneWire.h>
#include <DallasTemperature.h>
#include <MobaTools.h>

// Motor Pin-Definitionen
#define STEP_PIN 9
#define DIRECTION_PIN 10
#define ENABLE_PIN 8

// Endschalter Pin-Definitionen
#define Auf 6
#define Zu 7

// Temperatursensor Pin
#define ONE_WIRE_BUS 46

// Positionen in Steps
const int POSITION_CLOSED = 0;
const int POSITION_QUARTER = 2500;
const int POSITION_HALF = 5000;
const int POSITION_FULL = 14000;

// Hysterese
const float HYSTERESIS = 0.8;

// Entprellung für den Schlitten
const int DEBOUNCE_STEPS = 55;

// Initialisiere den OneWire-Bus und den Temperatursensor
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Initialisiere den Schrittmotor
MoToStepper motor(400, STEPDIR);  // 400 Schritte pro Umdrehung, Betriebsart STEPDIR

bool motorIsActive = false;  // Variable zur Verfolgung des Motorstatus

void setup() {
  // Initialisiere serielle Kommunikation
  Serial.begin(9600);

  // Konfiguriere die Motor-Pins
  motor.attach(STEP_PIN, DIRECTION_PIN);
  motor.setSpeedSteps(5000);  // Geschwindigkeit des Motors in Schritten pro Sekunde

  // Aktiviere den Motor
  pinMode(ENABLE_PIN, OUTPUT);
  digitalWrite(ENABLE_PIN, LOW);  // Aktiviere den Motor
  pinMode(Zu, INPUT_PULLUP);
  pinMode(Auf, INPUT_PULLUP);

  // Starte den Temperatursensor
  sensors.begin();

  // Konfiguriere die Endschalter-Pins
  pinMode(Auf, INPUT_PULLUP);
  pinMode(Zu, INPUT_PULLUP);

  // Führe die Entprellung für die Startposition "TuerZu" durch
  motor.write(POSITION_CLOSED + DEBOUNCE_STEPS);


  // Führe die Initialisierung zur Position "TuerZu" durch
  while (digitalRead(Zu) == LOW) {
    motor.rotate(-1);  // Bewege den Schlitten in Richtung "Zu"
  }
  motor.write(POSITION_CLOSED);  // Setze die Position "TuerZu"
}

void loop() {

  // Aktuelle Temperatur auslesen und auf dem Ser. Monitor zur Kontrolle der temp. Abfrage ausgeben. Später im LCD Display.
  sensors.requestTemperatures();
  float tempnow = sensors.getTempCByIndex(0);
  Serial.print("Die Temperatur beträgt  ");
  Serial.println(tempnow);
  delay(500);

  // Temperaturabhängige Türposition ermitteln - Hysterese 0,8° berücksichtigt, damit die Tür an den Grenzwerten nicht "pendelt"
  int targetPosition;
  if (tempnow < 20 - HYSTERESIS) {
    targetPosition = POSITION_CLOSED;
  } else if (tempnow >= 20 && tempnow < 25) {
    targetPosition = POSITION_QUARTER;
  } else if (tempnow >= 25 && tempnow < 30) {
    targetPosition = POSITION_HALF;
  } else if (tempnow >= 30) {
    targetPosition = POSITION_FULL;
  }

  // #####################  HIER HABE ICH EIN PROBLEM ODER EINEN LOGISCHEN FEHLER??? ########
  /*
  // Bewege den Motor zur Position "TuerZu" VOR! den temperaturabhängigen Bewegungen
  if (targetPosition != POSITION_CLOSED) {
    motor.write(POSITION_CLOSED);
    while (digitalRead(Zu) == HIGH) {
      motor.rotate(-1); // Bewege den Schlitten in Richtung "Zu"
    }
    motor.write(POSITION_CLOSED + DEBOUNCE_STEPS); // Entprellung
  }
*/
  // #######################################################################################

  // Bewege den Motor zur Zielposition
  motor.write(targetPosition);

  // Überprüfe die Endschalter und führe die Entprellung durch
  if (digitalRead(Auf) == HIGH) {
    // Endschalter "Auf" erreicht
    motor.write(targetPosition - DEBOUNCE_STEPS);  // Bewege den Schlitten weg vom Endschalter
  }
  if (digitalRead(Zu) == HIGH) {
    // Endschalter "Zu" erreicht
    motor.write(targetPosition + DEBOUNCE_STEPS);  // Bewege den Schlitten weg vom Endschalter
  }

  // Motor abschalten, wenn in Ruhestellung
  if (targetPosition == POSITION_CLOSED && motorIsActive) {
    digitalWrite(ENABLE_PIN, HIGH);  // Motor abschalten
    motorIsActive = false;
  } else if (targetPosition != POSITION_CLOSED && !motorIsActive) {
    digitalWrite(ENABLE_PIN, LOW);  // Motor einschalten
    motorIsActive = true;
  }

  // Ein bissel warten, während die Temperatur erneut geprüft wird. Erübrigt sich, wenn der nächste Code danach folgt.
  delay(1000);
}

Das verstehe ich nicht. Wenn Du den Stepper richtig ansteuerst, gibt es kein Türpendeln.

Naja, so etwa stimmt das schon. Meinst Du mit 'Entprellen, den Endschalter wieder freizufahren? Was noch fehlt, ist nach dem Stop den Referenzpunkt auf 0 zu setzen.
Wenn Du das einmal gemacht hast ( im Setup ), kannst Du von da an jede beliebige Türposition anfahren, ohne dich um die Endschalter kümmern zu müssen ( höchstens als 'Notstop' wenn mal was schief geht. ). NotStop sollte aber eigentlich immer per HW realisert werden.

Hast Du die Beispiele angeschaut? Da sind auch welche mit Referenzfahrt dabei.

Da verstehe ich nicht, was Du damit bezwcken willst. Du musst auch zwischen .write() und .moveTo() unterscheiden. .write gibt die Zielposition in Winkelgeraden vor (ähnl. wie ein Servo, nur ohne die dort vorhandene Begrenzung ). Bei deiner Tür macht das aber wenig Sinn. .moveTo gibt die Zielposition in Steps vom Referenzpunkt aus an. Da musst Du einmal bestimmen, wieviele Steps Du von 'ZU' bis 'AUF' brauchst. Dann sollte sich das ja nie mehr ändern.

Habe noch ein bisschen mit den MobaTools "gespielt" und bin wohl auf einem guten Weg.
Ich muss sagen, dass die Programmierung mit den Moba's viel effizienter zu sein scheint.

Komme nur ein bisschen durcheinander mit den Befehlen.

verwende ich
myStepper.doSteps(-5); // 5 Schritt zurück
in Verbindung mit
MoToStepper myStepper(400, STEPDIR);
// Initialisiere den Stepper
myStepper.attach(STEP_PIN, DIRECTION_PIN);
oder
motor.rotate(-5); // 5 Schritt zurück
in Verbindung mit z.B
motor.attach(STEP_PIN, DIRECTION_PIN); und
MoToStepper motor(400, STEPDIR);

Ist wohl nur eine Bezeichnungssache.

Ich glaube jedoch, vom Prinzip her kann ich den Post als erledigt betrachten und danke allen Experten dafür, dass sie mal drübergeschaut haben.

motor.rotate() ist für das dauerhafte drehen des Motors, und kennt nur die Parameter 1 ( vorwärts ), -1 (rückwärts) und 0 (anhalten).
motor.doSteps() bewegt den Motor die angegebene Zahl von Steps von der momentanen Position aus und hält dort an. Das gilt auch, wenn der Motor momentan bereits in Bewegung ist.
motor.moveTo() fährt zu einer absoluten Position, gerechnet vom Referenzpunkt aus, und ist mMn der richtige Befehl für die Positionierung deiner Tür. Die Drehrichtung wird dabei automatisch entsprechend der momentanen Position berechnet. Wenn der gesamte Bewegungsbereich der z.B. 5000 Schritte sind, und Du die Referenzposition bei 'ZU' auf o gesetzt hast ( im setup ), dann wird moveTo(2500) die Tür halb aufmachen - egal wo sie gerade steht.

"Da musst Du einmal bestimmen, wieviele Steps Du von 'ZU' bis 'AUF' brauchst. Dann sollte sich das ja nie mehr ändern."

Die Steps zwischen TuerZu und TuerAuf werden aus den Temperaturen ermittelt:
a) wenn temp < 18° -> Tür zu
b) wenn 18° < temp < 21° 1/4 öffnen
c) wenn 21° < temp < 24° 1/2 öffnen
d) wenn temp >24° vollständig öffnen
Hysterese von 0,8°

Codeschnipsel:

float tempnow = readTemperature();
if (abs(currentTemp - lastTemp) > HYSTERESIS) {
    resetPosition();
    moveToPositionBasedOnTemp(currentTemp);
    lastTemp = currentTemp;
  }
void moveToPositionBasedOnTemp(float temp) {
  if (temp < 18) {
    stepper.moveTo(POSITION_CLOSED);
  } else if (temp >= 18 && temp < 21) {
    stepper.moveTo(POSITION_QUARTER);
  } else if (temp >= 21 && temp < 24) {
    stepper.moveTo(POSITION_HALF);
  } else if (temp >= 24) {
    stepper.moveTo(POSITION_FULL);
  }
  while (stepper.distanceToGo() != 0) {
    stepper.run();
  }
}
tempnow = sensors.getTempCByIndex(0);

Vollständig öffnen wird erreicht bei z.B. 20000 Steps. Dies wäre die Entfernung zwischen den beiden Endstops. Eine kleine Routine errechnet den Mittelwert der Schritte zwischen 2 Bewegungen Hin und Her, dieser Wert wird dann in eine Variable zum Programmstart eingetragen und jedesmal neu ermittelt, Riemenspannung etc.!

Schaue mir nun doch noch mal nach deinen Hinweisen und nach gründlichem Studieren des genannten Beispiels meinen Code an.

Hier der Code für TuerZU am Anfang

#include <MobaTools.h>

// Motor Pin-Definitionen
#define STEP_PIN 9
#define DIRECTION_PIN 10
#define ENABLE_PIN 8
// Endschalter Pin-Definitionen
#define Auf 6
#define Zu 7

MoToStepper myStepper(400, STEPDIR);  // 200 Schritte pro Umdrehung
int schritteZaehler = 0;              // Variable zum Zählen der Schritte

void setup() {
  Serial.begin(9600);  // Starte die serielle Kommunikation
  // Initialisiere die Pins
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIRECTION_PIN, OUTPUT);
  pinMode(ENABLE_PIN, OUTPUT);
  pinMode(Auf, INPUT_PULLUP);
  pinMode(Zu, INPUT_PULLUP);

  // Initialisiere den Stepper
  myStepper.attach(STEP_PIN, DIRECTION_PIN);
  myStepper.setSpeed(5000);  // 1000 Schritte pro Sekunde
  myStepper.setRampLen(10);  // Rampenlänge auf 10 Schritte setzen

  // Motor aktivieren
  digitalWrite(ENABLE_PIN, LOW);

  // Bewege den Motor zur Position "Zu"
  while (digitalRead(Zu) == HIGH) {
    myStepper.doSteps(-5);  // 5 Schritte
    while (myStepper.moving());
  }
  myStepper.doSteps(100);  // 100 Schritte zurück
  while (myStepper.moving()); 

  delay(5000);  // Warte 1 Sekunde
  /*
  }
void loop() {
}

Kurz und knackig im Vergleich zu AccelStepper.

Wieviel Schritte macht dein Motor denn wirklich?
Und einen Schrittzähler brauchst Du nicht, das machen die MobaTools

Welche Geschwindigkeit soll dein Stepper machen? mit setSpeed setzt Du die Umdrehungsgeschwindigkeit. Bei 400 Steps/Umdr. wären das in diesem Fall 3333 Steps/Sek ( was MobaTools auf einem AVR 'out of the box' nicht schafft).
Um 1000 Steps/sek einzustellen musst Du

myStepper.setSpeedSteps(1000*10);  // 1000 Schritte pro Sekunde

einstellen.

Ich glaube, Du denkst immer noch zuviel mit AccelStepper. Mit MobaTools geht das einfacher:

  // Bewege den Motor zur Position "Zu"
  myStepper.doSteps(-20000);  // so viele Schritte, dass der Endstop sicher erreicht wird.
  while (digitalRead(Zu) == HIGH) ; // Warten bis Endstop anspricht
  myStepper.doSteps(100);  // 100 Schritte zurück
  while (myStepper.moving()); // warten bis Bewegungsende
  myStepper.setZero(); // Referenzpunkt setzen


// Motor aktivieren
  digitalWrite(ENABLE_PIN, LOW);

Du könntest das Aktivieren/Deaktivieren des Motors auch komplett den MobaTools überlassen ( mit attachEnable ).