Problem bei Schrittkette

Hallo alle zusammen,

könntet ihr mir bitte kurz bei einem Problem mit der Schrittkette weiterhelfen ?

Meine Schrittkette hat sozusagen 2 Fälle:

Fall 1 :
Durchlauf von Case0 bis Case5 aber ohne case1 (den case 1 brauche ich dann später für den 2-ten Fall) .

Fall 2:
Wenn das Program so oft abgelaufen ist, sodas schlußendlich der Taster 2 gedrückt wird (das ist dann case 6) sollte bei case 1 gestartet werden.

Mein Problem ist, das ich aber mit dem Code gar nicht über den case 0 hinauskomme.
wie müsste der Code aussehen, damit die Schrittkette funktioniert ? => das ist mein erster Versuch eine Schrittkette zu programmieren.

#define MAX8BUTTONS                                                 
#include <MobaTools.h>

const int sensorpin = 22;               // Kapazitiver Näherungssensor

MoToTimer   Schleifverweilzeit;
MoToStepper S1(1600, STEPDIR);          // bipolarer Schrittmotor Längsschlitten => Verfahrweg: 0m bis 3m, stoppt ca. alle 10cm bei Klinge durch Kap. Sensor
MoToStepper S3(2000, STEPDIR);          // bipolarer Schrittmotor Vertikalschlitten

enum { Taster1, Taster2, Taster3, Taster4, Startknopf, Notaus} ;       // 4x Endschalter
const byte tasterPins[] = { 44, 45, 46, 47, 7, 6 };                             
MoToButtons taster( tasterPins, sizeof(tasterPins), 20, 500 );   


String Z_Start;
String Z_Schleifrichtung;

void setup()
{
  Serial.begin (115200);
 
  pinMode(sensorpin, INPUT);
 
  S1.attach( 53, 51 );                   // STEPpin, DIRpin
  S1.setSpeed( 300 );                    // = 80 U/Min (motorspezifisch)
  S1.setRampLen( 10 );                   // Beschleunigung (motorspezifisch)

  S3.attach( 52, 50 );                   // STEPpin, DIRpin
  S3.setSpeed( 300 );                    // = 80 U/Min (motorspezifisch)
  S3.setRampLen( 50 );                    // Beschleunigung (motorspezifisch)
  
  Z_Start = "aus";                       // Zustandsvarable für Start des Schleifvorganges
  Z_Schleifrichtung = "rechts";
}


void loop()
{

  taster.processButtons();                                   // Taster einlesen und bearbeiten
  int sensorstate = digitalRead(sensorpin);
  static byte status;                                        // Schrittkettenstatus    
  
 if (taster.pressed(Startknopf)) Z_Start = "ein";  // Um zu Starten muss linker Knopt gedrückt werden

  switch (status) {
   
   case 0:
   if ( sensorstate == 1  && Z_Start == "ein"  && Z_Schleifrichtung == "rechts")  {      // S1 fährt zu nächswter Klinge                                                       
    S1.rotate(1); 
    S3.rotate(0);  
    status++;
    }
   break;

   case 1:
    if ( sensorstate == 1  && Z_Start == "ein"  && Z_Schleifrichtung == "links") {       // S1 fährt zu nächswter Klinge                                                        
    S1.rotate(-1); 
    S3.rotate(0);  
    status++;
    }
   break;
    
   case 2:
    if ( sensorstate == 0 ){         // S1 stoppt bei Klinge, S3 beginnt nach unten zu drehen
    S1.rotate(0);
    S3.rotate(1);
    status++;
    }
   break;
   
   case 3:
    if (taster.pressed(Taster3)) {
    S1.rotate(0);
    S3.rotate(0);
    Schleifverweilzeit.setTime(1500);
    status++;
    }
    break;
    
    case 4:
     if ( !Schleifverweilzeit.running() ) {
     S1.rotate(0);
     S3.rotate(-1);
     status++;
     }
    break;


    case 5:
     if (taster.pressed(Taster4)) {
     S1.rotate(0);
     S3.rotate(0);
     status++;
     }
   break;

    case 6:
     if (taster.pressed(Taster2)) {
     Z_Schleifrichtung = "links";
     status = 1;
     }
   break;   
   
    default:
    status = 0;
  }
 
}

LG
Christian

Mein Problem ist, das ich aber mit dem Code gar nicht über den case 0 hinauskomme.

Dann wird vermutlich dein IF nie true.

Gib dir mal vor dem If aus

sensorstate
Z_Start
Z_Schleifrichtung

und kontrolliere deine Werte.

christian_auer_11:
Fall 1 :
Durchlauf von Case0 bis Case5 aber ohne case1 (den case 1 brauche ich dann später für den 2-ten Fall) .
Fall 2:
Wenn das Program so oft abgelaufen ist, sodas schlußendlich der Taster 2 gedrückt wird (das ist dann case 6) sollte bei case 1 gestartet werden.

Mein Problem ist, das ich aber mit dem Code gar nicht über den case 0 hinauskomme.

Hinweis:
Bei mir wird status als keyword markiert,.. Du solltest Dir Variablennamen suchen, die kein keyword sind!

Kurz aus Deinem Code mal was gebastelt - ohne Garantie, das es funktioniert, aber als Idee:

  static byte status;                                        // Schrittkettenstatus    
  static byte durchlauf=0;
  
 if (taster.pressed(Startknopf)) Z_Start = "ein";  // Um zu Starten muss linker Knopt gedrückt werden

  switch (status) {
   
   case 0:
   if ( sensorstate == 1  && Z_Start == "ein"  && Z_Schleifrichtung == "rechts")  {      // S1 fährt zu nächswter Klinge                                                       
    S1.rotate(1);
    S3.rotate(0);  
    status++;
    if (durchlauf<5) {status++; durchlauf++}; // addiert auf, solange keine x Anzahl Durchläufe...
    }
   break;

Warum verwendest Du 'String' für Zustandsvariablen? Umständlicher und ressourcenfressender geht wohl nicht.
Und wie noiasca schon schreibt, gib dir die entscheidenden Variablen auf dem seriellen Monitor aus. Dann kannst Du sehen, weshalb es nicht weiter geht.

Ach!
Ich hatte da ja noch übersehen, das Du einen TASTER bedienst.
Dann könnte das auch so aussehen:
[Nochmal editiert - für die Bedingung: schlußendlich [...] sollte bei case 1 gestartet werden]
Dein case 1 ist jetzt case 2.
ungetestet. Aber ich denke, das da noch Optimierungspotenzial besteht.

  static byte status = 0;                                       // Schrittkettenstatus
  static byte durchlauf = 0;
  switch (status)
  {
    case 0:
      if (taster.pressed(Startknopf)) Z_Start = "ein";  // Um zu Starten muss linker Knopt gedrückt werden
      {
        status++;
      }
      break;
    case 1:
      if (durchlauf < 5)
      {
        if ( sensorstate == 1  && Z_Schleifrichtung == "rechts")  {      // S1 fährt zu nächswter Klinge
          S1.rotate(1);
          S3.rotate(0);
          status++;
          status++;
          durchlauf++
        };
      }
      else
      {
        status++;
      }
      break;
    case 2:
      if ( sensorstate == 1  && Z_Schleifrichtung == "links") {       // S1 fährt zu nächswter Klinge
        S1.rotate(-1);
        S3.rotate(0);
        status++;
      }
      break;

enums sind hier eigentlich für Zustände gedacht. Damit kannst du sowas machen:

enum Richtung { links, rechts };
Richtung richtung = links;

...

if (richtung == links)
 ...

Und dir den Unsinn mit den Strings sparen

Bei dir sieht das hier etwas seltsam aus:

if (taster.pressed(Startknopf))

"Startknopf" hat den Wert 4. Vielleicht meinst du hier das:

if (taster.pressed(tasterPins[Startknopf]))

Serenifly:
Bei dir sieht das hier etwas seltsam aus:

Das ist schon richtig so. Die Umsetzung auf die Pinnummer und das lesen des Pins machen die MoToButtons.
Aber sind die Taster auch nach Gnd angeschlossen?

Guten Morgen,

Vielen Dank für eure Rückmeldungen.

MicroBahner:
Warum verwendest Du 'String' für Zustandsvariablen? Umständlicher und ressourcenfressender geht wohl nicht.

Das habe ich mir mal aus einem Code angeeignet, welchen ich hier im Forum gesehen habe, ich habe aber auch recht wenig Erfahrung mit dem Arduino.
Was wäre die bessere Lösung für Zustandsvariablen ?

Dann könnte das auch so aussehen:

Vielen Dank für deine Ergänzung.
Ich habe deinen Code bei mir implementiert, dann hat zwar ein Durchlauf funktioniert, aber ich kam nicht mehr zum Startpunkt zurück => Beim Drücken dest Taster 4 war Ende:

Ich habe nun meinen Code nochmal überarbeitet, jetzt funktioniert der Durchlauf schon einmal :).
Was jedoch nicht funktioniert, ist der Richtungswechsel, welcher Hervorgerufen werden sollte wenn ich den Taster2 gedrückt halte => das wäre bei mir der case 1.
Dieser funktioniert nur dann wenn ich de Taster2 gedrückt halte, während ich den Arduino neu starte (also der taster funktioniert).

Bei meinem Aufbau wird der Taster 2 dann gedrückt wenn der Schrittmotor S1 vom case0 irgendwann einmal dagegenfährt. Der Schrittmotor S1 ist für eine Linearantrieb verantwortlich.

#define MAX8BUTTONS                                                 
#include <MobaTools.h>

const int sensorpin = 22;               // Kapazitiver Näherungssensor

MoToTimer   Schleifverweilzeit;
MoToStepper S1(1600, STEPDIR);          // bipolarer Schrittmotor Längsschlitten => Verfahrweg: 0m bis 3m, stoppt ca. alle 10cm bei Klinge durch Kap. Sensor
MoToStepper S3(2000, STEPDIR);          // bipolarer Schrittmotor Vertikalschlitten

enum { Taster1, Taster2, Taster3, Taster4, Startknopf, Notaus} ;       // 4x Endschalter
const byte tasterPins[] = { 44, 45, 46, 47, 7, 6 };                             
MoToButtons taster( tasterPins, sizeof(tasterPins), 20, 500 );   


String Z_Start;
String Z_Schleifrichtung;

void setup()
{
  Serial.begin (115200);
 
  pinMode(sensorpin, INPUT);
 
  S1.attach( 53, 51 );                   // STEPpin, DIRpin
  S1.setSpeed( 300 );                    // = 80 U/Min (motorspezifisch)
  S1.setRampLen( 10 );                   // Beschleunigung (motorspezifisch)

  S3.attach( 52, 50 );                   // STEPpin, DIRpin
  S3.setSpeed( 300 );                    // = 80 U/Min (motorspezifisch)
  S3.setRampLen( 50 );                    // Beschleunigung (motorspezifisch)
  
  Z_Start = "aus";                       // Zustandsvarable für Start des Schleifvorganges
  Z_Schleifrichtung = "rechts";
}


void loop()
{

  taster.processButtons();                                   // Taster einlesen und bearbeiten
  int sensorstate = digitalRead(sensorpin);
  static byte status = 0;                                       // Schrittkettenstatus

  

      if (taster.pressed(Startknopf))  // Um zu Starten muss linker Knopt gedrückt werden
      {
        Z_Start = "ein";
      }

 switch (status)
  {


    
    case 0:

        if ( sensorstate == 1  && Z_Start == "ein" && Z_Schleifrichtung == "rechts")  {      // S1 fährt zu nächswter Klinge
          S1.rotate(1);
          S3.rotate(0);
          status++;
        }     
      else
      {
        if ( sensorstate == 1 && Z_Schleifrichtung == "links"){
        S1.rotate(-1);
        S3.rotate(0);
        status++;
      };
      }
      break;
      
      case 1:
     if (taster.pressed(Taster2))
     {
     Z_Schleifrichtung = "links";
     status--;
     }
      else
     {
     status++;
     } 
     break;  
    
   case 2:
    if ( sensorstate == 0 ){         // S1 stoppt bei Klinge, S3 beginnt nach unten zu drehen
    S1.rotate(0);
    S3.rotate(1);
    status++;
          
    }
   break;
   
   case 3:
    if (taster.pressed(Taster3)) {
    S1.rotate(0);
    S3.rotate(0);
    Schleifverweilzeit.setTime(1500);
    status++;
           
    }
    break;
    
    case 4:
     if ( !Schleifverweilzeit.running() ) {
     S1.rotate(0);
     S3.rotate(-1);
     status++;
             
     }
    break;


    case 5:
     if (taster.pressed(Taster4)) {
     S1.rotate(0);
     S3.rotate(0);
     status = 0;
              
     }
   break;


   
    default:
    status = 0;
  }
 
}

Das Problem mit den Taster 2 konnte ich so lösen, indem ich abfrage ob der Schrittmotor S1 läuft :slight_smile:

   case 1:
    if (S1.moving() && taster.pressed(Taster2) )
     {
     Z_Schleifrichtung = "links";
     status--;
     }
   else
   {
    if ( sensorstate == 0 ){         // S1 stoppt bei Klinge, S3 beginnt nach unten zu drehen
    S1.rotate(0);
    S3.rotate(1);
    status++;
    };     
    }
   break;

Jetzt würde ich aber noch gerne wissen, wie ich meine Zustandsvariablen anstelle von string lösen sollte ?

LG
Christian

christian_auer_11:
Das habe ich mir mal aus einem Code angeeignet, welchen ich hier im Forum gesehen habe,

Dann war das eine sehr schlechte Vorlage. Sowas mit String zu mache ist wirklich die schlechteste aller denkbaren Möglichkeiten. Serenifly hat dir in #5 doch schon gezeigt, wie sowas geht.

boolean Z_Start;
enum richtung_t { LINKS, RECHTS };
richtung_t Z_Schleifrichtung;

Setzen und Abfragen dann mit

Z_Start = true;
Z_Schleifrichtung = RECHTS;
...
...
if ( sensorstate == 1  && Z_Start && Z_Schleifrichtung == RECHTS)

Du könntest deinen Code auch wesentlich übersichtlicher machen ( und damit die Hilfe erleichtern ) wenn Du deinen Variablen sinnvolle Namen gibst. 'sensorstate' ist so allgemein, allgemeiner geht's ja garnicht. Was macht der sensor, wann spricht er an - das sollte aus dem Namen hervorgehen.

christian_auer_11:
Der Schrittmotor S1 ist für eine Linearantrieb verantwortlich.

Dann benenn ihn doch aus so. Dann weis man gleich was Sache ist.
Auch eine vernünftige Formatierung ( Einrückung hilft ungemein ( ctrl-T hilft dir dabei ).
Ein Kommentar bei jedem case, wozu der ist, und wann er erreicht werden soll, würde die Hilfe auch ungemein erleichtern - und auch Du weist das nicht mehr so genau, wenn Du den Sketch mal später wieder vornimmst.

P.S. noch ein Hinwies zu den Tastern: 'pressed' erkennt den Zeitpunkt des Drückens, also die Flanke am Eingang. Wenn Du den statischen[/] Zustand des Tasters abfragen willst, musst Du 'state' verwenden.

Zwei Tipps:

  • Gib dir auf der Seriellen Schnittstelle aus in welchem Case du bist und wie deine Variablen aussehen (habe ich dir schon mal geraten oder?), damit du selber siehst was dein Sketch mach (oder nicht macht)
  • Zeichne dir ein Zustandsübergangsdiagramm und visualisiere was in welchem Zustand passieren soll, was die Aktionen sind, um von einem Zustand in den anderen zu kommen!

Jeder Zustand kann bis zu 4 Spezifikationen haben. Das sind sozusagen deine Kontrollfragen die du jedem Zustand stellen kannst:

4buzzer4m.png

auch würde ich mich im Case wenn möglich an diese Reihenfolge halten:
entry
doActivity
eventBehaviour
exit

4buzzer4m.png

christian_auer_11:
Das Problem mit den Taster 2 konnte ich so lösen, indem ich abfrage ob der Schrittmotor S1 läuft :slight_smile:

Kann man machen.

Jetzt würde ich aber noch gerne wissen, wie ich meine Zustandsvariablen anstelle von string lösen sollte ?

Das mit enum{} war ja schon oben.
Zudem würde ich das inhaltlich mit den Switch/cases nochmal angehen.
Auflösen: -> Richtung1 wird ein Ablauf / Richtung 2 ein neuer.

Was wirds eigentlich? EIn (Horizontal-)Nasschleif-Bearbeitungszentrum?

Vielen Dank für eure Rückmeldungen, ich werde eure Anmerkungen beherzigen und denn Ablauf im Code etwas genauer zu beschreiben versuchen, sowie auch die Zustandsvariablen neu angehen.

Da ich erst ein paar Sketche gemacht habe, möchte ich hierzu noch einmal kurz nachhaken, ob ich das richtig interpretiere ?

boolean
verwende ich wenn ich einen Zustand habe (z.B Start),

und enum
wenn ich mehrere Zustände haben kann (z.B links oder rechts) ?

Jeder Zustand kann bis zu 4 Spezifikationen haben. Das sind sozusagen deine Kontrollfragen die du jedem Zustand stellen kannst:

4buzzer4m.png

auch würde ich mich im Case wenn möglich an diese Reihenfolge halten:
entry
doActivity
eventBehaviour
exit

Vielen Dank, dass erleichtert mir den Ablauf und werde ich auch so befolgen

Auflösen: -> Richtung1 wird ein Ablauf / Richtung 2 ein neuer.

Das Klingt sehr gut mit dem Auflösen, da ich das in späterer Folge noch des öfterern brauchen werde.

Wie könnte so ein Praxisbeispiel aussehen ? Ich bin bis jetzt nur das Programmieren in einer fortlaufenden Wurst gewöhnt.
Gestern habe ich mich zum ersten mal an eine Schrittkette rangewagt, vorher habe ich diesen Ablauf mit sehr vielen If Abfragen bzw Zustände gelöst, da ist der Ablauf im Code dann wirklich extremst unübersichtlich. => wie gesagt ich habe im Grunde noch überhaupt keine Programmierkentnisse. Das ist mein erstes Projekt mit dem Arduino, mit Ausnahme der LED-Licht Beispiele für Anfänger.

my_xy_projekt:
Was wirds eigentlich? EIn (Horizontal-)Nasschleif-Bearbeitungszentrum?

Es sollte ein automatischer Schleifapparat für Balkenmähermesser werden.
Jetzt über die Weihnachtszeit hatte ich nun wieder etwas Zeit daran zu Arbeiten, sodass ich hoffe damit bis zum Mai oder Juni fertig zu werden.
Am meisten freut mich, dass ich den Drehstrommotor doch recht einfach mittels FU ansteuern kann, davor hatte ich die meiste Bange.

Zu deinen Fragen:

boolean ist ein Typ der ein ja oder nein aufnehmen kann, 1 oder 0, True oder False.

ein enum - eine Enumeration - ist eine Aufzählung. Der Compiler vergibt intern dafür 0, 1, 2, ...

bei

enum richtung_t { LINKS, RECHTS };

ist LINKS also 0 und RECHTS 1.

Eine Variable zugeordnet wird es aber erst durch den Typ richtung_t. Also in der Zeile

richtung_t Z_Schleifrichtung;

Schleifrichtung kann nur LINKS oder RECHTS binhalten (0 oder 1).

Zur Finite State Machine habe ich noch nicht wirklich was geschrieben, aber die Grafik ist von hier: Arduino: Buzzer-Buttons für 4 Spieler - Finite State Machine und ich erkläre dort anhand eines Beispiels wie man zunächst einen einfachen Ablauf gestaltet und den dann in einer FSM umsetzt. Vieleichts hilfts. Eine enum findest dort auch, genauer eine enum class.

christian_auer_11:
boolean
verwende ich wenn ich einen Zustand habe (z.B Start),

und enum
wenn ich mehrere Zustände haben kann (z.B links oder rechts) ?

Boolean kann genau 2 Zustande haben: Wahr (true) und Falsch ( false ). Kann man schön verwenden, wenn aus dem Namen bereits hervorgeht, was 'wahr' und was 'falsch ist'. Z_Start: ist wahr, wenn gestartet werden soll.

Enum verwendet man, wenn mehrere Zustände möglich sind, denen man dann Namen zuordnen kann. Würde sich auch für deinen 'status' der Schrittkette anbieten, wobei man dann jedem case eine sprechenden Namen zuordnet. Das ist wesentlich übersichtlicher als die reinen Zahlen in deinen cases.

Z_Richtung hat zwar auch nur 2 Zustände, aber aus dem Namen kann man nicht erkennen, was 'true' oder 'false' bedeuten würde. Deshalb biete sich hier auch ein enum an, um den beiden Zuständen sprechende Namen ( RECHTS, LINKS ) zuordnen zu können.

N.B. Es ist zwar nicht zwingend, aber weit verbreitet solche konstanten Werte in Großbuchstaben zu schreiben, um sie auf einen Blick von normalen Variablen unterscheiden zu können.

Edit: noiasca war schneller :wink: - aber doppelt hält besser 8)

christian_auer_11:
boolean verwende ich wenn ich einen Zustand habe (z.B Start),

naja eher ob Start ausgelöst oder eben nicht.
der Wert des bool wird in genau einem bit gespeichert. Das Ding kann nur 0 oder 1 haben.
Wie das nachher benannt wird, ist erstmal egal.
Als Vorgabewerte gibt es false/true, LOW/HIGH.
Selbst benennen könntes z.B. an/aus oder Links/Rechts.
Da wären wir dann bei

und enum
wenn ich mehrere Zustände haben kann (z.B links oder rechts) ?

Das sind zwei - die lassen sich als bool ansetzen.
Kommt noch ein dritter dazu, z.B. halt, sieht es schon anders aus.
aus enum {links, halt, rechts} werden dann intern 0,1,2
Du musst dann aber nicht in Deinem switch Zustand mit case 0, case 1, case 2 arbeiten, sondern sagst:
case links, case halt, case rechts.
Und jetzt kommst an die Schrittkette, dann geht:
enum {start, halt1, links, halt2, rechts, halt3, end}

Wie könnte so ein Praxisbeispiel aussehen ? Ich bin bis jetzt nur das Programmieren in einer fortlaufenden Wurst gewöhnt.

In dem Du Stift und Papier nimmst und aufschreibst, was nacheinander passieren soll.
Wenn sich irgendetwas wiederholt, dann kannst Du daraus eine Funktion machen und die immer wieder aufrufen und musst später nicht ständig den gleichen Code schreiben.

Am meisten freut mich, dass ich den Drehstrommotor doch recht einfach mittels FU ansteuern kann, davor hatte ich die meiste Bange.

Buuuh! :wink: Frequenzumrichter anbammeln ist ja nu kein Hexenwerk.
Und ich hatte die Hoffnung, das Du Deine Erfolge am Arduino festmachst. ;(

Nichts desto trotz, weil ich das die letzten Tage immer wieder hatte, auch für Dich:
So und Literatur für Nachts zum lesen:
https://www.arduinoforum.de/code-referenz
dort das pdf runterladen und einfach nur drüber lesen - nicht auswendig lernen.

Da steht alles drin und schön erklärt für Einsteiger richtig passend gemacht....

Hallo,

ich habe nun meinen Code nach den mir gegebenen Vorschlägen überarbeitet, und bin soweit ganz zufrieden damit.

An einer Stelle hakt es derzeit jedoch etwas.
Wenn ich den Ablauf mit dem Startknopf Starte funktioniert dies Problemlos.
Wenn ich danach den Notaus drücke funktioniert auch das.

Wenn ich nun wieder den Startknopf drücke, fährt das System jedoch nicht mehr an.
Den Z_Start habe ich mir im seriellen Monitor auslesen lassen, dort schaltet er aber richtig (es wird von Zustand 0 = welcher von Notaus kommt auf Zustand 1 => welcher vom Startknopf kommt geschalten)

Was eigenartig ist, der Knopf "Man_Betrieb" funktioniert nach dem Notaus schon.

Habt ihr eine Idee, woran das liegt ?

Ich bekomme gerade die Fehlermeldung das der Code zu viele zeichen hat deshalb Teile ich diesen auf 2 Teile in 2 Posts auf.

#define MAX32BUTTONS
#include <MobaTools.h>

const int Klingensensor_2_Pin = 22;      // Kapazitiver Näherungssensor 6V      => derzeit keine Verwendung da die 24V Variante getestet wird
const int Klingensensor_Pin = 26;        // Kapazitiver Näherungssensor 24V
int DSM_Rechtslauf = 34;                 // Anschluß X1 am FU  => Drehstrommotor dreht rechts
int DSM_Linkslauf = 36;                  // Anschluß X2 am FU  => Drehstrommotor dreht links

MoToTimer   Schleifverweilzeit;
MoToStepper S1(1600, STEPDIR);          // bipolarer Schrittmotor Längsschlitten => Verfahrweg: 0m bis 3m, stoppt ca. alle 10cm bei Klinge durch Kap. Sensor
MoToStepper S3(2000, STEPDIR);          // bipolarer Schrittmotor Vertikalschlitten

enum { Taster1, Taster2, Taster3, Taster4, Startknopf, Notaus, Manueller_Betrieb} ;       // 4x Endschalter
const byte tasterPins[] = { 44, 45, 46, 47, 7, 6, 24 };
MoToButtons taster( tasterPins, sizeof(tasterPins), 20, 500 );


enum ZUSTAENDE { LS_faehrt_rechts, LS_Endschalter_rechts, LS_findet_Klinge_rechts, VS_faehrt_runter, VS_faehrt_hoch, VS_oben_angekommen, Schleifumkehr, LS_faehrt_links, LS_Endschalter_links, LS_findet_Klinge_links, };
byte Zustand = LS_faehrt_rechts;

enum Maschinenzustand { AUS, EIN, Man_Betrieb };
Maschinenzustand    Z_Start;

enum Richtung_LS { LINKS, RECHTS };      // Fahrrichtung vom Längsschlitten
Richtung_LS   Z_Schleifrichtung;

void setup()
{
  Serial.begin (115200);

  pinMode(Klingensensor_2_Pin, INPUT);   // im Moment nicht belegt, da der 24V IFM Sensor getestet wird
  pinMode(Klingensensor_Pin, INPUT);       // Kapazitiver Näherungsensor 24V Fa. IFM
  pinMode(DSM_Rechtslauf, OUTPUT);       // Rechtslauf des Drehstrommotors
  pinMode(DSM_Linkslauf, OUTPUT);        // Linksslauf des Drehstrommotors

  S1.attach( 53, 51 );                   // STEPpin, DIRpin
  S1.setSpeed( 300 );                    // = xxx U/Min (motorspezifisch)
  S1.setRampLen( 10 );                   // Beschleunigung (motorspezifisch)

  S3.attach( 52, 50 );                   // STEPpin, DIRpin
  S3.setSpeed( 300 );                    // = xxx U/Min (motorspezifisch)
  S3.setRampLen( 50 );                   // Beschleunigung (motorspezifisch)

  Z_Start = AUS;                         // Zustandsvarable für Start des Schleifvorganges
  Z_Schleifrichtung = RECHTS;

}


void loop()
{

  //Serial.println(Zustand);
  //Serial.println(Z_Schleifrichtung);
  Serial.println(Z_Start);

  taster.processButtons();                                         // Taster EINlesen und bearbeiten
  int Z_Klingensensor_2 = digitalRead(Klingensensor_2_Pin);        // 6V Sensor
  int Z_Klingensensor   = digitalRead(Klingensensor_Pin);          // 24V IFM-Sensor
  static byte status = 0;                                          // Schrittkettenstatus



  if (taster.pressed(Notaus))             // Notausfunktion
  {
    S1.stop();                            // im Gegensatz zu S1.rotate(0) führt S1.stop(0) zu einem sofortigen anhalten ohne Rampe  => Stop vom Längsschlitten
    S3.stop();                            // Stop vom Vertikalschlitten
    digitalWrite(DSM_Rechtslauf, LOW);    // Stop vom Drehstrommotor im Fall eines Rechtslauf
    digitalWrite(DSM_Linkslauf, LOW);     // Stop vom Drehstrommotor im Fall eines Linkslauf
    Z_Start = AUS;
  }


  if (Z_Start == AUS && taster.pressed(Startknopf))           // Um zu Starten muss linker Knopf gedrückt werden => das ist der Startknopf
  {
    Z_Start = EIN;
  }



  /***********************************************/
  /*                 Handbetrieb                 */
  /***********************************************/



  if (taster.pressed(Manueller_Betrieb) && Z_Start == AUS)   //Wenn der Knopf für manuelle Steuerung gedrückt wird sollte mit den Tasten 1 bis 4 der Längsschlitten (S1) sowie Vertikalschkitten (S3) bewegt werden
  {
    Z_Start = Man_Betrieb;
  }


  if (Z_Start == Man_Betrieb && taster.pressed(Taster4)) {
    S1.rotate(1);
  }

  if (Z_Start == Man_Betrieb && taster.released(Taster4)) {
    S1.rotate(0);
  }

  if (Z_Start == Man_Betrieb && taster.pressed(Taster3)) {
    S1.rotate(-1);
  }

  if (Z_Start == Man_Betrieb && taster.released(Taster3)) {
    S1.rotate(0);
  }

  if (Z_Start == Man_Betrieb && taster.pressed(Taster2)) {
    S3.rotate(1);
  }

  if (Z_Start == Man_Betrieb && taster.released(Taster2)) {
    S3.rotate(0);
  }

  if (Z_Start == Man_Betrieb && taster.pressed(Taster1)) {
    S3.rotate(-1);
  }

  if (Z_Start == Man_Betrieb && taster.released(Taster1)) {
    S3.rotate(0);
  }

Hier der Teil 2

  switch (Zustand)
  {


    /***********************************************/
    /*      Schleifrichtung erfolgt nach Rechts    */
    /***********************************************/


    case LS_faehrt_rechts:  // Der Längsschlitten angetrieben von S1 faehrt solange nach RECHTS, solange kEIN Sensorsignal ankommt

      if ( Z_Klingensensor == 1  && Z_Start == EIN && Z_Schleifrichtung == RECHTS)  {
        S1.rotate(1);
        S3.rotate(0);
        digitalWrite(DSM_Rechtslauf, HIGH);    // Drehstrommotor zum Schleifen der Klingen wird im Rechtslauf gestartet
        digitalWrite(DSM_Linkslauf, LOW);      // der Linkslauf des Drehstrommotor zum Schleifen der Klingen wird deaktiviert
        Zustand = LS_Endschalter_rechts;       // Endschalter rechts vom Längsschlitten wird ereicht nachdem die letzte Klinge im Rechtslauf angefahren wurde => aktiviert die Schleifumkehr
      }
      break;


    case LS_Endschalter_rechts:                // nach der letzten Klinge fährt der Längsschlitten S1 solange nach RECHTS bis er an den Endschalter Taster 2 kommt
      if (S1.moving() && taster.pressed(Taster2))
      {
        Z_Schleifrichtung = LINKS;
        Zustand = Schleifumkehr;
      }
      else                                     // Wenn der Längsschlitten angetrieben durch S1 vom Sensor EIN Signal bekommt, stoppt S1 und der Schleifvorgang wird eingeleitet
      {
        if ( Z_Klingensensor == 0 ) {
          Zustand = LS_findet_Klinge_rechts;
        };
      }
      break;


    case LS_findet_Klinge_rechts:              // wenn der Klingensensor eine Klinge gefunden hat stoppt der Längsschlitten, und der Schleifvorgang beginnt
      if ( Z_Klingensensor == 0 ) {            // Klingensensor hat Klinge gefunden
        S1.rotate(0);                          // Längsschlitten stoppt
        S3.rotate(1);                                     // Vertikaler Schlitten fährt runter zur Klinge
        Zustand = VS_faehrt_runter;
      }
      break;


    case VS_faehrt_runter:                     // Vertikaler Schlitten fährt runter zur Klinge
      if (taster.pressed(Taster3)) {           // Endschalter zur Deaktivierung der fahrt des Vertikalschlittens nach unten
        S1.rotate(0);
        S3.rotate(0);
        Schleifverweilzeit.setTime(1500);      // aufziehen des timmers für die Schleifzeit
        Zustand = VS_faehrt_hoch;

      }
      break;


    case VS_faehrt_hoch:                       // Vertikaler Schlitten fährt runter zur Klinge
      if ( !Schleifverweilzeit.running() ) {   // Wenn der Timer der Schleifzeit abgelaufen ist fährt der Längsschlitten andem der Schleifmotor befestigt ist wieder hoch
        S1.rotate(0);
        S3.rotate(-1);
        Zustand = VS_oben_angekommen;
      }
      break;


    case VS_oben_angekommen:                    // Wenn der Vertikalschlitten (S3) oben angekommen ist, betätigt dieser den Endschalter Taster 4 und S3 stoppt
      if (taster.pressed(Taster4)) {
        S1.rotate(0);
        S3.rotate(0);
        Zustand = LS_faehrt_rechts;             // Ein neuer Schleifvorgang beginnt indem eine neue Klinge vom Längsschlitten angefahren wird
      }
      break;


    /***********************************************/
    /*          Schleifrichtungsumkehr             */
    /***********************************************/


    case Schleifumkehr:                        // nach der letzten Klinge fährt der Längsschlitten S1 solange nach RECHTS bis er an den rechten Endschalter Taster 2 kommt.
      if (  Z_Schleifrichtung == LINKS) {
        S1.rotate(0);
        digitalWrite(DSM_Rechtslauf, LOW);     // der Rechtslauf des Drehstrommotor zum Schleifen der Klingen wird deaktiviert
        digitalWrite(DSM_Linkslauf, HIGH);     // der Linkslauf des Drehstrommotor zum Schleifen der Klingen wird aktiviert
        Zustand = LS_faehrt_links;
      }
      break;



    /***********************************************/
    /*     Schleifrichtung erfolgt nach Links      */
    /***********************************************/


    case LS_faehrt_links:                        // Nach dem Umschalten der Schleifrichtung werden die Klingen auf der zweiten Seite nach links geschliffen
      if ( Z_Klingensensor == 1  && Z_Schleifrichtung == LINKS)  {   // Der Längsschlitten angetrieben von S1 faehrt solange nach Links, solange kEIN Sensorsignal ankommt
        S1.rotate(-1);
        S3.rotate(0);
        Zustand = LS_Endschalter_links;
      }
      break;



    case LS_Endschalter_links:                   // nach der letzten Klinge fährt der Längsschlitten S1 solange nach Links bis er an den Endschalter Taster 1 kommt => dadurch wird der Schleifvorgang beendet und alles wird ausgeschalten
      if (S1.moving() && taster.pressed(Taster1))
      {
        S1.rotate(0);
        S3.rotate(0);
        digitalWrite(DSM_Rechtslauf, LOW);
        digitalWrite(DSM_Linkslauf, LOW);
        Z_Start = AUS;
      }
      else
      {
        if ( Z_Klingensensor == 0 ) {            // sollte der Klingensensor eine Klinge finden beginnt wieder ein Schleifvorgang
          Zustand = LS_findet_Klinge_links;
        };
      }
      break;



    case LS_findet_Klinge_links:                 // wenn der Klingensensor eine Klinge gefunden hat stoppt der Längsschlitten, und der Schleifvorgang beginnt
      if ( Z_Klingensensor == 0 ) {              // Klingensensor hat Klinge gefunden
        S1.rotate(0);                            // Längsschlitten stoppt
        S3.rotate(1);                            // Vertikaler Schlitten fährt runter zur Klinge
        Zustand = VS_faehrt_runter;
      }
      break;

  }

}

christian_auer_11:
Ich bekomme gerade die Fehlermeldung das der Code zu viele zeichen hat ...

Jo mei, warum löschst Du dann nicht überflüssige Zeichen?!

Schon durch das Entfernen überflüssiger Leerzeilen und übersichtliche Formatierung kannst Du einiges sparen. Lesbarkeit ist jedenfalls etwas Anderes ...

Nur mal so ein Vorschlag zur Lektüre: Ein Länzchen für die Schönheit.

Gruß

Gregor

christian_auer_11:
Wenn ich danach den Notaus drücke funktioniert auch das.

Wenn ich nun wieder den Startknopf drücke, fährt das System jedoch nicht mehr an.

Wo steht denn der Status zu dem Zeitpunkt?

Und: Wenn ich das richtig sehe, würde das drücken des Startknopfes den Notaus überschreiben.
Dann verdient der Notaus aber den Namen nicht.

if (taster.pressed(Notaus))             // Notausfunktion
  {
    S1.stop();                            // im Gegensatz zu S1.rotate(0) führt S1.stop(0) zu einem sofortigen anhalten ohne Rampe  => Stop vom Längsschlitten
    S3.stop();                            // Stop vom Vertikalschlitten
    digitalWrite(DSM_Rechtslauf, LOW);    // Stop vom Drehstrommotor im Fall eines Rechtslauf
    digitalWrite(DSM_Linkslauf, LOW);     // Stop vom Drehstrommotor im Fall eines Linkslauf
    Z_Start = AUS;
  }


  if (Z_Start == AUS && taster.pressed(Startknopf))           // Um zu Starten muss linker Knopf gedrückt werden => das ist der Startknopf
  {
    Z_Start = EIN;
  }

Davon abgesehen, das ich durch den Code noch nicht durchgestiegen bin, wäre das meine Zeile als Versuch für den Start:

if ((Z_Start == AUS) && (taster.pressed(Startknopf)) && (!taster.pressed(Notaus)))