Not-halter funktion bei Schrittmotor

Hallo, ich habe ein schrittmotor auf eine linearführung. an der linearfuhrung sind drei sensoren. sensor 1( startposition), sensor2(mitte), und sensor3. Ein ganzer ablauf läuft so: startsignal aktiv, sensor 1 aktiv, dann fährt er zu sensor 2 bleibt stehen dann zu sensor 3 bleibt stehen und dann zurück zu sensor 1. ich bekomme es einfach nicht hin ein nothalter einzubauen so das er richtig funktioniert. Nothalter anschluss: gnd/pin 40. wenn der not halter aktiv ist muss alles sofort stoppen und die position merken. Beim auslassen muss er von dere selbenstelle ohne weiteres startsignal den ablauf fertig ausführen ohne den ablauf zu behindern. hat wer eine ahnung was ich machen kann, wäre mir sehr hilfreich!
mfg. florin
hier wäre mein code:

#include <AccelStepper.h>

// Pin Definitionen
#define ENA_PIN 10
#define DIR_PIN 11
#define STEP_PIN 12
#define START_PIN A1
#define SIGNAL_PIN A0
#define EMERGENCY_STOP_PIN A7
#define SENSOR1 46
#define SENSOR2 48
#define SENSOR3 52
#define EMERGENCY_STOP_5V_PIN 40 // Not-Halt 5V Pin

#define MAX_SPEED 19000  // Maximalgeschwindigkeit (Schritte pro Sekunde)
#define ACCELERATION 10000  // Beschleunigung (Schritte pro Sekunde^2)
#define PAUSE_DURATION 500  // Wartezeit in Millisekunden zwischen Bewegungen
#define HALF_SECOND 200 // Halbe Sekunde in Millisekunden

// Anzahl der Schritte pro Zentimeter (anpassen je nach Motor und Mechanik)
#define SCHRITTE_PRO_CM_SENSOR2 400 // Schritte pro Zentimeter für Bewegung zu SENSOR2
#define SCHRITTE_PRO_CM_SENSOR3 400 // Schritte pro Zentimeter für Bewegung zu SENSOR3

AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);

bool emergencyStop = false;
bool startSignalDetected = false;
int currentPosition = 0; // Aktuelle Position des Schrittmotors
int stepsToMove = 0; // Schritte zur Bewegung
bool motionPaused = false; // Flag zur Anzeige, ob die Bewegung pausiert ist
int currentSensor = 0; // Der aktuelle Sensor, zu dem der Motor sich bewegt
int nextSensor = SENSOR2; // Nächster Sensor, zu dem der Motor sich bewegen soll

void setup() {
  pinMode(ENA_PIN, OUTPUT);
  digitalWrite(ENA_PIN, LOW);

  pinMode(START_PIN, INPUT);
  pinMode(SIGNAL_PIN, OUTPUT);
  pinMode(EMERGENCY_STOP_PIN, INPUT_PULLUP);
  pinMode(EMERGENCY_STOP_5V_PIN, INPUT);
  pinMode(SENSOR1, INPUT);
  pinMode(SENSOR2, INPUT);
  pinMode(SENSOR3, INPUT);

  stepper.setMaxSpeed(MAX_SPEED);
  stepper.setAcceleration(ACCELERATION);

  Serial.begin(9600);
}

void checkEmergencyStop() {
  if (digitalRead(EMERGENCY_STOP_PIN) == LOW || digitalRead(EMERGENCY_STOP_5V_PIN) == HIGH) {
    emergencyStop = true;
    stepper.stop();
    currentPosition = stepper.currentPosition(); // Aktuelle Position speichern
    stepsToMove = stepper.distanceToGo(); // Schritte bis zum Ziel speichern
    Serial.println("Emergency Stop Activated");
    while (digitalRead(EMERGENCY_STOP_PIN) == LOW || digitalRead(EMERGENCY_STOP_5V_PIN) == HIGH) {} // Warten bis der Not-Aus zurückgesetzt ist
    emergencyStop = false;
    Serial.println("Emergency Stop Released");

    // Bestimme den nächsten Sensor basierend auf der aktuellen Position
    if (currentPosition == 0) {
      nextSensor = SENSOR2;
    } else if (currentPosition == stepsToMove) {
      nextSensor = SENSOR1;
    } else {
      nextSensor = SENSOR3;
    }

    // Fortsetzen der Bewegung von der aktuellen Position
    if (!startSignalDetected) {
      motionPaused = true;
      moveToSensor(nextSensor);
      motionPaused = false;
    }
  }
}

void moveToSensor(int sensorPin) {
  digitalWrite(SIGNAL_PIN, HIGH); // Signal senden
  delay(HALF_SECOND); // Halbe Sekunde warten
  digitalWrite(SIGNAL_PIN, LOW); // Signal stoppen

  int stepsToMove = 0;

  if (sensorPin == SENSOR2) {
    stepsToMove = SCHRITTE_PRO_CM_SENSOR2 * 15; // 15 cm bis zu SENSOR2
  } else if (sensorPin == SENSOR3) {
    stepsToMove = SCHRITTE_PRO_CM_SENSOR3 * 15; // 15 cm bis zu SENSOR3
  } else if (sensorPin == SENSOR1) {
    stepsToMove = -SCHRITTE_PRO_CM_SENSOR3 * 30; // Zurück zu SENSOR1 (negativer Wert für Rückwärtsbewegung)
  }

  stepper.move(stepsToMove); // Schritte entsprechend der Entfernung bewegen
  currentSensor = sensorPin; // Speichern, zu welchem Sensor wir uns bewegen

  while (stepper.distanceToGo() != 0) {
    stepper.run(); // Stepper kontinuierlich laufen lassen
    checkEmergencyStop(); // Während der Bewegung auf Not-Halt prüfen
    if (motionPaused) return; // Bewegung pausieren, wenn Not-Halt betätigt wird
  }

  digitalWrite(SIGNAL_PIN, HIGH); // Signal senden
  delay(HALF_SECOND); // Halbe Sekunde warten
  digitalWrite(SIGNAL_PIN, LOW); // Signal stoppen
}

void loop() {
  checkEmergencyStop();

  if (!emergencyStop && !startSignalDetected && motionPaused) {
    // Fortsetzen der Bewegung von der gemerkten Position
    motionPaused = false;
    moveToSensor(nextSensor);
  }

  if (!emergencyStop) {
    if (digitalRead(SENSOR1) == HIGH && digitalRead(START_PIN) == HIGH) {
      startSignalDetected = true;
    }

    if (startSignalDetected) {
      moveToSensor(SENSOR2);
      moveToSensor(SENSOR3);
      moveToSensor(SENSOR1);
      startSignalDetected = false; // Ablauf 1 beendet, auf neues Startsignal warten
    }
  }
}

Der nächste Sensor ist doch vorher bekannt, der zu dem der Motor hinfährt.

Was genau meinst du damit? Verstehe es nicht ganz

Beim Aufruf von moveToSensor() ist der nächste anzufahrende Sensor bekannt. Nach einem Nothalt muß genau dieser Sensor wieder (immer noch) angefahren werden.

Benutzen Sie einen Schrittmotor-Treiber? Hat er einen Enable-Pin? Wenn ja, könnten Sie den Knopf mit dem Enable-Pin verbinden, so dass das Drücken des Knopfes den Treiber deaktiviert. Das würde Ihnen einen Not-Aus ohne jeglichen Code ermöglichen.

ja habe ich, wie genau sollte ich das verbinden und geht der ablauf verloren nach dem betätigen?

Das mit dem Enable-Eingang des Motortreibers ist zwar eine sehr einfache und funktionierende lösung, es ist aber zu bedenken, dass der Schrittmotor dann aber , während er im Nothalt ist, die Posotion nicht halten kann, da der Motorstrom komplett abgeschaltet wird. Wenn die Linear-Schine also senkrecht steht, fällt der bewegte schlitten je nach gewicht, mehr oder weniger schnell in die untere endposition, falls das nicht durch eine Spindel verhindert wird.

Außerdem geht die aktuelle Motorposition verloren da die Ansteuerung vom stop des Treibers nichts erfährt.
Grüße Uwe

Ja richtig. gut dies wäre noch lösbar, wenn der Notschalter (entweder auch) an nen Arduino Eingang geführt wirde, oder der norschalter an nen Arduino Eingang und Enable vom Treiber an nen Ausgang vom Arduino. Bei diesen arianten muss allerdingst die Software so geschrieben sein, dass der Nothalt bei jedem Step überprüft wird, falls die lib nicht in der Lage ist, jederzeit die aktuelle Motorposition zurückzugeben, was ja oft bei 'Move to'-Funktionen nicht geht.

Hallo @florin345

herzlich willkommen im Arduino-Forum.
Was du sehr gut gemacht hast ist, den Code als Code-Section zu posten.

Es ist gibt aber auch noch etwas zu verbessern:
Du hast eine Detailfrage gestellt wie man den "Nothalter" programmiert.

Das Wort "Nothalter" ist etwas unüblich. Deshalb ist es um so wichtiger sehr genau und mit noch viel mehr Details zu beschreiben was dein Linearantrieb macht.

Du hast noch keinen Überblick gegeben was der letztendliche Zweck des Linearantriebs ist.
Wie man das ganze am besten programmiert hängt mit davon ab was die eigentliche Gesamtfunktion des Linearantriebs ist.

Auch dein Grundkonzept einen Schrittmotor zu benutzen und dann trotz Schrittmotors bestimmte Positionen mit Sensoren abzufragen ist ungewöhnlich. Es gibt aber möglicherweise sehr gute Gründe dafür. Auch deshalb ist es wichtig, dass du einen Überblick durch eine detaillierte Beschreibung gibst.

Vermutlich lässt sich das alles einfacher Programmieren, weil dein Programm die Position auch ohne die Sensoren schon weiß.

AccelStepper zählt in einer internen Variable mit auf welcher Schrittposition sich der Schrittmotor befindet. AccelStepper zählt IMMER mit. Und das bedeutet dein Programm weiß zu jedem Zeitpunkt wo sich der Schrittmotor befindet.

Einen echten Not-Aus programmiert man nicht. Den verdrahtet man auf aller direktestem Wege mit der Stromversorgung.
Wie der Name schon sagt "NOT"-Aus. Es funktioniert etwas nicht richtig und deshalb soll das Ding jetzt möglichst zuverlässig gestoppt werden. Wenn dein Programm spinnt und den Notaus nicht korrekt abfragt - aus was für Gründen auch immer - dann wird nicht gestoppt.

Aus diesem Grunde wird ein Not-Aus so realisiert:
Nur wenn ALLE Details funktionieren wie sie sollen dann mache keinen Not-Aus.
Wenn irgendein Detail nicht stimmt dann halte an!

Mit diesem Konzept muss man seine Maschine tip-top in Ordnung halten sonst steht die Maschine.

Hardwareseitig realisiert man das dadurch, dass der der Notaus-Schalter als Öffner-Kontakt in der Plusleitung der Stromversorgung eingebaut wird.

Not-Aus betätigt => kein Strom Motor kann erst gar nicht losfahren. Ganz egal was das Programm macht.
Verkabelung zum Not-Aus ist unterbrochen => gleicher Effekt: Stromzufuhr unterbrochen Motor kann erst gar nicht losfahren. Ganz egal was das Programm macht.

Was du oben beschrieben hast ist aber kein klassischer Not-Aus.

Wie man jetzt Position merken und dann ohne Sensor-Signal weiterfährt hängt sehr stark von deiner Anwendung ab.

Möglicherweise macht es auch Sinn neben der echten Not-Aus eine Funktion
manueller "Extra-Halt" einzubauen.

Spätestens wenn der Strom ausgefallen ist muss dein Linearatrieb eine sogenannte Referenzfahrt machen damit das Programm wieder "weiß" auf welcher Position sich dein Linearantrieb befindet.

Möglicherweise lässt sich das Problem dadurch lösen, dass nach einem Notaus einfach eine neue Referenzfahrt gemacht wird. Eventuell geht es aber auch nicht.

Deshalb beschreibe bitte das Gesamtprojekt damit man auch das Nachvollziehen kann.

Ja hatte nicht bedacht. Ein NOTAUS schaltet aus und da ist es egal was die Maschiene gerade macht. Ein NOTAUS ist nicht für ein wiederstarten gedacht. Eine Angefangene Arbeit wird ziemlich sicher wegzuschmeisen sein. Notaus ist da auch gedacht wenn Gefahr von Leben eines Menschen oder eines großen Schadens der Maschine besteht und das abzuwenden. Ein materieller und finanzieller Schaden durch unterbrechen der Arbeit wird in kauf genommen da immernoch kleiner als ein Arbeiter.

Ein Notaus ist wirkungsvoller und verläßlicher wenn er die Versorgung der motoren unterbricht als mittels Enable die Treiber ausschaltet.

Grüße Uwe

Ja Das ergibt total Sinn