GERMAN Verbesserung Vorschläge | Schrittkettensteuerung | ?

Hallo zusammen :) ,

in diesem Sketch habe ich versucht eine Arduino Schrittketten-Steuerung zu erstellen. Orientiert habe ich mich an meinen FUP Kenntnissen mit Siemens LOGO! und S7.

Gibt es bessere/effizientere Lösungswege als eine switch case Kette mit einem Schrittzähler?

Und wie würdet Ihr Verzögerungen zwischen den Schritten einbauen (natürlich ohne delay)? [u]Mein Versuch:/u (if (millis() - vorherige_Zeit == TON_Schritt_2) Bedingung für Schritt 2)

Dann noch eine Sache, und zwar mit der Freigabe: Wenn die Freigabe bei einer FUP Steuerung nicht mehr gegeben ist, werden alle Ausgänge in der Kette rückgesetzt. Bei Arduino bleiben die letzten Werte ja erhalten. Gibt es da eine Möglichkeit ALLE Pins einmalig mit LOW zu belegen?

Besten Dank Max

//Taster
const int S0 = 2; // Start_Taster
//Sensoren 
const int mag_leer = 3;
const int B1_1 = 4;  const int B1_2 = 5; 
const int B2_1 = 8;  const int B2_2 = 9; 
//Ventile
const int V1_1 = 6;  const int V1_2 = 7;
const int V2_1 = 10; const int V2_2 = 11;
//Meldeleuchten
const int P0 = 12; //Betrieb
const int P1 = 13; //Magazin leer
//Merker
bool M_Freigabe = false;
int M_mag_leer = 0;
int Zaehler = 0;

void setup() {

//6 Eingaenge
pinMode(S0 ,INPUT);
pinMode(mag_leer ,INPUT);
pinMode(B1_1 ,INPUT); pinMode(B1_2 ,INPUT); //eingefahren/ausgefahren
pinMode(B2_1 ,INPUT); pinMode(B2_2 ,INPUT);

//6 Ausgaenge
pinMode(P0 , OUTPUT);  pinMode(P1 , OUTPUT);
pinMode(V1_1 ,OUTPUT); pinMode(V1_2 ,OUTPUT); //ausfahren/einfahren
pinMode(V2_1 ,OUTPUT); pinMode(V2_2 ,OUTPUT);

Serial.begin(19200); //Baudrate = 19200 Bit/s
delay(100);
 Serial.println(" ");
 Serial.println("************************START************************");
 Serial.println("*  Steuerung fuer Auswurfmodell          (Arduino)  *");
 Serial.println("*  Version 1.0            08.06.2017 Max Buschhorn  *");
 Serial.println("*---------------------------------------------------*");
 Serial.println("* INPUT:   S0   =  2     mag_leer =  3              *");
 Serial.println("*          B1_1 =  4         B1_2 =  5              *");
 Serial.println("*          B2_1 =  6         B2_2 =  7              *");
 Serial.println("*---------------------------------------------------*");
 Serial.println("* OUTPUT:  V1_1 =  8         V1_2 =  9              *");
 Serial.println("*          V2_1 = 10         V2_2 = 11              *");
 Serial.println("*          P0   = 12         P1   = 13              *");
 Serial.println("*************************END*************************");
 Serial.println(" ");
delay(100);
}

void loop() {

Start:

if (digitalRead(mag_leer) == HIGH && M_mag_leer == 0) {
  Serial.println("Warnung!  Magazin LEER");
  M_mag_leer = 1;
}

if (digitalRead(mag_leer) == HIGH) {
  digitalWrite(P1, HIGH);
 }
 else {
  digitalWrite(P1, LOW);
}

if (digitalRead(S0) == HIGH && digitalRead(mag_leer) == LOW && Zaehler == 0) {
   digitalWrite(P0, HIGH);
   M_Freigabe = true;
   M_mag_leer = 0;
   Zaehler = 1;
 }
else {
   digitalWrite(P0, LOW);
   M_Freigabe = false;
   digitalWrite(V1_1, LOW);
   digitalWrite(V1_2, LOW);
   digitalWrite(V2_1, LOW);
   digitalWrite(V2_2, LOW);
   goto Start;
} 

if (M_Freigabe == true) 

switch (Zaehler) {
  case 1:
    digitalWrite(V1_2, HIGH);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  break;
  case 2:
  if (Zaehler == 2 && digitalRead(B1_2) == LOW && digitalRead(B1_1) == HIGH) {
    digitalWrite(V1_2, LOW);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  }
  break;
  case 3:
    digitalWrite(V1_1, HIGH);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  break;
  case 4:
  if (Zaehler == 4 && digitalRead(B1_1) == LOW && digitalRead(B1_2) == HIGH) {
    digitalWrite(V1_1, LOW);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  }
  break;
  case 5:
    digitalWrite(V2_1, HIGH);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  break;
  case 6:
  if (Zaehler == 6 && digitalRead(B2_1) == LOW && digitalRead(B2_2) == HIGH) {
    digitalWrite(V2_1, LOW);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  }
  break;
  case 7:
    digitalWrite(V2_2, HIGH);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Zaehler++;
  break;
  case 8:
  if (Zaehler == 8 && digitalRead(B2_2) == LOW && digitalRead(B2_1) == HIGH) {
    digitalWrite(V2_2, LOW);
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
    Serial.println(" ");
    Zaehler = 0;
    Serial.print("Zaehlerstand = ");
    Serial.println(Zaehler);
  }
  break;
 }
}
switch (Zaehler) {
  ...
  case 2:
  if (Zaehler == 2 ...

Bist Du unsicher daß SWITCH funktioniert weil Du Zaehler nochmals kontrollierst?

Benutze das F() Makro bei den Serial.print("TEXT");

if (digitalRead(S0) == HIGH && digitalRead(mag_leer) == LOW && Zaehler == 0) {
   ...
 }
else {
   ...
   goto Start;
}

Zu was goto? Schreib den switch-Teil ins if und das ist dann das gleiche.

if (M_Freigabe == true)

switch (Zaehler) {

Das if ist so ohne Funktion (für die Katz).

grüße Uwe

Max_Beginner: Gibt es bessere/effizientere Lösungswege als eine switch case Kette mit einem Schrittzähler?

Für kleine Programme mit ein paar Zuständen ist es das einfachste.

Was die Sache übersichtlicher machen kann ist die Verwendung von enums. Damit kann man den Zuständen sprechende Namen geben. Das ist vor allem sinnvoll wenn man nicht nur eine Schrittkette hat die stur in den nächsten Zustand geht, sondern einen Zustandsautomaten wo man hin-und-her wechseln kann, und/oder abhängig von einer Bedingung die Wahl zwischen zwei Folge-Zuständen hat.

goto hat in einem C/C++ Programm übrigens in den seltensten Fällen was verloren. Wenn du an den Anfang von loop() springen willst reicht ein return.

Hier habe ich mal zwei Alternativen gezeigt: https://forum.arduino.cc/index.php?topic=332907.0

Ob es besser ist sei mal dahingestellt. Die Version mit den Funktionszeigern hat den Vorteil dass jeder Zustand eine eigene Funktion hat. Dadurch steht nicht die gesamte Logik in einem massiven Code-Block

Die Version mit der Zustandstabelle wird auch oft verwenden. Da gibt es sogar Makros um deren Erstellung zu automatisieren. Hier hat man auch die Wahl ob die Funktion ständig während des Zustands aufgerufen wird (z.B. um eine Messung durchzuführen) oder nur einmal während des Zustandswechsels

uwefed: ``` if (M_Freigabe == true)

switch (Zaehler) {




Das if ist so ohne Funktion (für die Katz).

Nö, das funktioniert wie gewünscht.

Danke Euch für die Tipps!

uwefed: switch (Zaehler) {  ...  case 2:  if (Zaehler == 2 ...

Bist Du unsicher daß SWITCH funktioniert weil Du Zaehler nochmals kontrollierst?

Benutze das F() Makro bei den Serial.print("TEXT");

grüße Uwe

Das mit dem switch funktioniert bei mir.

Wie genau muss ich das "F()" Makro verwenden?

Besten Dank :)

 Serial.println(F("************************START************************"));