Arduino Forum

International => Deutsch => Topic started by: Floetzinger on Dec 03, 2018, 05:01 pm

Title: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 03, 2018, 05:01 pm
guten Abend zusammen,
gibt es bekannte Schwierigkeiten bei derSwitch Case Anwendung und Millis()?

Prbier mich grad aus, ob ich bereits bekannte und erprobte Sketchteile auch in anderen Sketchen nutzen kann.
Bin dabei, eine primitive Pendelzugsteuerung mit 3 Halte/ Wendepunkte zu entwickeln.
Prizip: Überfahren eines Hallsensores löst eine zeitlich begrenzte Aktion aus (i.e. Ausgang 2 sec. High).
Allerdings stecke ich bereits beim ausschalten nach x Sec. fest.
da gibt es doch bestimmt den ein oderen anderen Lösungsschubser.
Der  (exemplarisch) Problembereich beginnt bei Case 1 und endet beim Break.
Löse ich einen , löse ich bestimmt alle (hoffe ich).

alle anderen Dinge wie Anzeige im LCD Display funktionieren, Case Auswertung funktioniert.
Danke für's weiterhelfen.

Code: [Select]

 

//***** Angaben zum Display*****
  #include <Bounce2.h>// Taster entprellen
  #include <Wire.h>   // Verdrahtung LCD Display
  #include <LiquidCrystal_I2C.h> // Ansteuerung LCD Display
  LiquidCrystal_I2C lcd(0x27,20,4); // Datenleitungen an A4/ A5
//***** Angaben zum Entprellen***** 
  Bounce debouncer = Bounce();
//***** Konstanzen Zuordnung der Taster/ Hallsensoren*****
  const int HSQ1 = 2;
  const int HSQ2 = 3;
  const int HSQ3 = 4;
  const int Taster_Start= 5;
//***** Konstanzen Zuordnung der Ansteuerung Relais*****
  const int Relais_HSQ1 = 7;
  const int Relais_HSQ2 = 8;
  const int Relais_HSQ3 = 9;
  const int Relais_Weiche_Abz = 10;
  const int Relais_Weiche_Ger = 11;
  const int Relais_Start= 12;
  const int Relais_Fahrstrom = 13;
  const int Relais_Umpolung = 14;
//***** Variablen der Startzeiten*****
  unsigned long Startzeit1 =0;
  unsigned long Startzeit2 =0;
  unsigned long Startzeit3 =0;
  unsigned long Startzeit4 =0;
  unsigned long Wecker = 3000;
//*****Beginn Setup Bereich*****
void setup()
   // Pin Modus  Ausgang Relais
  {
   pinMode(Relais_HSQ1,OUTPUT); // Pin 7
   pinMode(Relais_HSQ2,OUTPUT); // Pin 8
   pinMode(Relais_HSQ3,OUTPUT); // Pin 9
   pinMode(Relais_Weiche_Abz,OUTPUT); // Pin 10
   pinMode(Relais_Weiche_Ger,OUTPUT); // Pin 11
   pinMode(Relais_Start,OUTPUT);      // Pin 12
   pinMode(Relais_Fahrstrom,OUTPUT);  // Pin 13
   pinMode(Relais_Umpolung,OUTPUT);   // Pin 14
   // Pin Modus Hallsensoren/ Taster
   pinMode(HSQ1,INPUT); // Pin 2
   pinMode(HSQ2,INPUT); // Pin 3
   pinMode(HSQ3,INPUT); // Pin 4
   pinMode(Taster_Start,INPUT); // Pin 5
   // Entprellen vom Taster
   debouncer.attach(Taster_Start);
   debouncer.interval(5);
   // Initalisierung LCD Display
   lcd.init();
   lcd.backlight();
    }
//***** Ende Setup Bereich*****

//*****Beginn Loop Bereich*****   
  void loop() {
  int Eingabe = 0; // Variable Switch Case Auswertung
  //***** Taster entprellen und auswerten*****
  debouncer.update();
  int value = debouncer.read();
  if ( value == LOW) {
  digitalWrite(Relais_Start,HIGH );
   }
  else {
 digitalWrite(Relais_Start, HIGH );
  Eingabe = 4;// Änderung der Variable
  }
//*****Abfrage Hallsensoren HSQ1- HSQ3*****
if (digitalRead(HSQ1)==HIGH){
 Eingabe = 1;// Änderung der Variable
}
if (digitalRead(HSQ2)==HIGH){
 Eingabe = 2;// Änderung der Variable
 }
 if (digitalRead(HSQ3)==HIGH){
 Eingabe = 3;// Änderung der Variabble
 }
//*****Beginn Switch Case*****
switch (Eingabe){
case 1://***** Abfrage HSQ1 *****
 if (digitalRead(HSQ1)==HIGH){
     digitalWrite(Relais_HSQ1,HIGH);
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0,0); // Cursorpos 0, Zeile 1   
    lcd.print(F("Hallsen. HSQ1 aktiv"));
   
  Startzeit1=millis();
  }
  else if (millis()-Startzeit1>=2000){
          digitalWrite(Relais_HSQ1,LOW);
         
  }
break;
case 2://***** Abfrage HSQ2 *****
if (digitalRead(HSQ2)==HIGH){
    digitalWrite(Relais_HSQ2,HIGH);
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0,1); // Cursorpos 1, Zeile 2 
    lcd.print(F("Hallsen. HSQ2 aktiv"));
 
   Startzeit2=millis();
  }
  else if (millis()-Startzeit2>=2000){
   digitalWrite(Relais_HSQ2,LOW);
  }
break;
case 3:////***** Abfrage HSQ3 *****
if (digitalRead(HSQ3)==HIGH){
  digitalWrite(Relais_HSQ3,HIGH);
 
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0,2); // Cursorpos 1, Zeile 2 
    lcd.print(F("Hallsen. HSQ3 aktiv"));
   
   Startzeit2=millis();
  }
  else if (millis()-Startzeit2>=2000){
   digitalWrite(Relais_HSQ2,LOW);
  }
break;
case 4:////***** Abfrage Taster  *****
if (digitalRead(Taster_Start)==HIGH){
   
    digitalWrite(Relais_Weiche_Ger,HIGH);
   
    lcd.backlight();
    lcd.clear();
    lcd.setCursor(0,3); // Cursorpos 1, Zeile 2 
    lcd.print(F("Taster aktiv"));
 
   Startzeit4=millis();
  }
  else if (millis()-Startzeit4>=5000){
  digitalWrite(Relais_Weiche_Ger,LOW);
  }
break;
default:; 
}//***** Ende Switch Case

 
}//***** Ende Loop Bereich*****

Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 03, 2018, 05:46 pm
Hallo,

du aktualisierst vor jeden Vergleich den Zeitmerker. Wie soll dann der Vergleich jemals wahr werden?
Nachdem der Vergleich gültig wurde zieht man den Zeitmerker nach auf die aktuelle Zeit damit er für den nächsten Vergleich erneut warten kann.

Code: [Select]

case 1://***** Abfrage HSQ1 *****
        if (digitalRead(HSQ1) == HIGH) {
          digitalWrite(Relais_HSQ1, HIGH);
            
          Startzeit1 = millis();
        }
        else if (millis() - Startzeit1 >= 2000) {
          digitalWrite(Relais_HSQ1, LOW);
        }
        break;


ändern in
Code: [Select]

case 1://***** Abfrage HSQ1 *****
        if (digitalRead(HSQ1) == HIGH) {
          digitalWrite(Relais_HSQ1, HIGH);
        }
        else if (millis() - Startzeit1 >= 2000) {
          Startzeit1 = millis();
          digitalWrite(Relais_HSQ1, LOW);
        }
        break;
Title: Re: Millis() in Switch Case Problem
Post by: MicroBahner on Dec 03, 2018, 06:40 pm
Nein, das ist nicht das Problem. Er startet die Zeit im if-Zweig, wenn das Relais eingeschaltet wird, und fragt die Zeit im else-Zweig ab. Das wäre schon in Ordnung.
Allerdings steht der else-Zweig auch im case 1. Und wenn der Hall-Sensor inaktiv ist, kommt er da gar nicht mehr hin - kann also das Ablaufen der Zeit gar nicht mehr erkennen. Es ist ziemlich unsinnig , denn case nur bei aktivem Hall-Sensor aufzurufen, und dann im case-Zweig nochmal nach dem Status des Hallsensors verzweigen zu wollen.
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 03, 2018, 07:00 pm
Hallo,

stimmt. Das rücksetzen muss außerhalb von switch-case erfolgen.
In case3 stimmt auch etwas mit den Variablen nicht. Alles 2 statt 3 am Ende. Das nur am Rande.
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 03, 2018, 07:04 pm
Hallo,

Wenn ich das richtig überblicke steuert jeder Sensor ein bestimmtes Relais?
Wenn Sensor aktiv Relais umschalten?
Wenn Sensor nicht mehr aktiv Relais verzögert zurückschalten?
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 03, 2018, 08:58 pm
Hallo,

in der Hoffnung das meine Annahme stimmt, hab ich das komplett umgebaut und einfach mal erlerntes konsequent angewendet.
Das mag für dich TO erstmal komplizierter aussehen, vereinfacht aber fast alles mit dem Umgang der Variablenwerte.
Vereinfacht gesagt werden ständig alle struct Arrays mittels Indexdurchlauf abgearbeitet.
Erst werden alle Sensoren eingelesen und im state Array gespeichert.
Dann wird state verglichen.
Wenn das jeweilige state wahr ist, wird das zugehörige Relais eingeschalten.
Wenn das jeweilige state unwahr ist, wird die Zeit abgewartet und das zugehörige Relais ausgeschalten.

Zur Zeit weiß ich nur nicht recht ob man den Taster mit ins struct Array nimmt und damit die Funktion read_sensor aller paar ms aufruft, was dann alle betrifft oder gänzlich separat behandlet inkl. Entprellung. Meinungen?

Ich hoffe ich habe die Logik überall richtig korrigiert, weil ich mit Input Pullups arbeite.

Code: [Select]
/*
  Doc_Arduino - german Arduino Forum
  IDE 1.8.7
  Arduino Mega2560
  03.12.2018
  https://forum.arduino.cc/index.php?topic=583029.0
*/

struct t_setup
{
  const byte pin_S;
  const byte pin_R;
  bool state;
  unsigned int delay;
  unsigned long last_ms;

  // Konstruktor
  t_setup (byte _S, byte _R, unsigned int _delay) :
    pin_S(_S),
    pin_R(_R),
    state(false),
    delay(_delay),
    last_ms(0)
  {}
};

t_setup KOMBI[] = {
  {2, 7, 2000},  // Sensorpin, Relaispin, Delay
  {3, 8, 3000},
  {4, 9, 4000},
};

unsigned long global_millis;

const byte ANZAHL = sizeof(KOMBI) / sizeof(t_setup);


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

  Serial.print("Anzahl "); Serial.println(ANZAHL);      // Debug

  // bei Bedarf Pullup aktivieren, ansonsten auskommtieren
  /*
  for (byte i = 0; i < ANZAHL; i++) {
    pinMode(KOMBI[i].pin_S, INPUT_PULLUP);
  }
  */

  // Ausgänge setzen
  for (byte i = 0; i < ANZAHL; i++) {
    digitalWrite(KOMBI[i].pin_R, LOW);
    pinMode(KOMBI[i].pin_R, OUTPUT);
  }
}


void loop()
{
  global_millis = millis();                   // für einen loop Umlauf für alle die gleiche Zeit

  read_sensor();

  Auswertung();
}

// ****** Funktionen ******
void read_sensor()
{
  for (byte i = 0; i < ANZAHL; i++) {
    KOMBI[i].state = digitalRead(KOMBI[i].pin_S);
  }
}

void Auswertung()
{
  for (byte i = 0; i < ANZAHL; i++) {         // alle Sensoren per Indexdurchlauf
    if (KOMBI[i].state) {                     // true ?
      digitalWrite(KOMBI[i].pin_R, HIGH);
      KOMBI[i].last_ms = global_millis;
    }

    if (!KOMBI[i].state) {                    // false?
      if (global_millis - KOMBI[i].last_ms > KOMBI[i].delay) {
        digitalWrite(KOMBI[i].pin_R, LOW);
      }
    }
  }
}
Title: Re: Millis() in Switch Case Problem
Post by: agmue on Dec 03, 2018, 09:21 pm
Huch, wie bin ich denn in dieses Thema gerutscht? Meinst Du eventuell combie?

Ruft die Funktion nicht danach, eine Methode zu werden? Irgendwann wäre dann auch ANZAHL überflüssig, so wie bei den Blumen (https://forum.arduino.cc/index.php?topic=578429.msg3947641#msg3947641): for (Blumen &b : blumen) b.init();

Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 03, 2018, 09:45 pm
Hallo,

upps, ich hatte den Grundstock von einem anderen Sketch übernommen, Latzefratz falls du dich erinnerst.
Ich nehms raus.  ;)

Darfste gern optimieren. Tue dir keinen Zwang an. Dann hat man die Wahl zwischen den Varianten.

Zudem der Taster noch rein muss. Den kann man auch als Sensor betrachten. Da bin ich mir immer noch nicht schlüssig wie es am Dümmsten ist.
Title: Re: Millis() in Switch Case Problem
Post by: agmue on Dec 04, 2018, 08:35 am
Tue dir keinen Zwang an.
Na gut, ich würde es etwas zusammenfassen (alles ungetestet):

Code: [Select]
void loop()
{
  global_millis = millis();                   // für einen loop Umlauf für alle die gleiche Zeit

  for (byte i = 0; i < ANZAHL; i++) {         // alle Sensoren per Indexdurchlauf
    Auswertung(i);
  }
}

// ****** Funktionen ******
void Auswertung(sensor)
{
  if (digitalRead(KOMBI[sensor].pin_S)) {                     // true ?
    digitalWrite(KOMBI[sensor].pin_R, HIGH);
    KOMBI[sensor].last_ms = global_millis;
  } else {                                                    // false?
    if (global_millis - KOMBI[sensor].last_ms > KOMBI[sensor].delay) {
      digitalWrite(KOMBI[sensor].pin_R, LOW);
    }
  }
}

Ich sehe es als Schritt zur Methode:

Code: [Select]
void Auswertung()
{
  if (digitalRead(pin_S)) {                     // true ?
    digitalWrite(pin_R, HIGH);
    last_ms = global_millis;
  } else {                                      // false?
    if (global_millis - last_ms > delay) {
      digitalWrite(pin_R, LOW);
    }
  }
}

Dann in loop aber

Code: [Select]
  for (byte i = 0; i < ANZAHL; i++) {         // alle Sensoren per Indexdurchlauf
    KOMBI[i].Auswertung;
  }

oder man überläßt das Zählen dem "System":

Code: [Select]
for (t_setup &k : KOMBI) k.Auswertung();
Bin gespannt, was der TO zum Fehlen von switch/case meint :)
Title: Re: Millis() in Switch Case Problem
Post by: Hausknecht on Dec 04, 2018, 09:10 am
Wenn ich solche Programme sehe, dann komme ich mir sooo klein vor.
Ihr habt's geschafft ich hab das Buch "Der C++ Programmierer" von Ulrich Breymann angefangen zu lesen.  :)
Title: Re: Millis() in Switch Case Problem
Post by: agmue on Dec 04, 2018, 10:53 am
Wenn ich solche Programme sehe, dann komme ich mir sooo klein vor.
Dann können wir uns zusammentun, denn ich plappere nur nach, was combie mal in OOP gezeigt hat. Aber Übung macht den Meister, auch wenn ich der wohl nie werde. Aber der Weg dahin macht Spaß.

Als fauler Mensch hat mich for ohne explizite Zählung gereizt, der Compiler übernimmt das. Damit entfällt eine mögliche Fehlerquelle.

Ich traue mich nur deshalb, Dinge hier zu veröffentlichen, weil Fehler gnadenlos angesprochen werden. Darauf kann ich mich verlassen, da bleibt am Ende kein Blödsinn übrig.
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 04, 2018, 01:34 pm
Hallo,

Hausknecht:

Keine Sorge ich stecke da auch noch mittendrin.

Das ist nur die Zusammensetzung bzw. gemeinsame Nutzung von struct und array. Das vermeidet die Ellenlangen globalen Variablenlisten wo am Ende niemand mehr durchblickt. Jedem Eingang ist ein Ausgang inkl. einer Verzögerungszeit zugewiesen. Die eigentlichen Werte werden mit t_setup KOMBI[] = { ... } initialisiert. Damit man default Werte nicht extra angegeben muss bei der Initialisierung ist im struct noch ein Konstruktor hinzugefügt wurden.

Mit struct baut man sich eigene Datentypen. Zu besseren Erkennung setze ich ein t_ davor.
Mit arrays baut man "Listen" von Werten die aufgefädelt sind.
Array Zugriff auf dessen Elemente erfolgt mit dem Index.
Zugriffe auf eine struct Element erfolgt mit dem Punkt-Operator.
Ich denke soweit ist dir das mit Buch klar.

Code: [Select]

struct t_setup
{
  byte pin;
  unsigned int delay;
};

Der neue Datentyp besteht aus einem byte Wert und einem unsigned int Wert.

Variablen mit dem neuen Datentyp erstellt man

t_setup var1;
t_setup var3;
t_setup var3;

oder 
Code: [Select]

struct t_setup
{
  byte pin;
  unsigned int delay;
} var;

Zugriff lautet nun var.pin oder var.delay

Wenn du nun 2 struct Arrays angelegt hast, Array Name KOMBI, Datentyp t_setup
Code: [Select]

t_setup KOMBI[] = {
  {2, 2000},          // Index 0   KOMBI[0].pin oder KOMBI[0].delay
  {3, 3000},          // Index 1   KOMBI[1].pin oder KOMBI[1].delay
};

erfolgt der Zugriff erst mittels Index und dann mit der struct Variablen.
Zum Schluss wird nur noch in einer for Schleife, worin für alle die Indexnummer gleich ist, darauf zugriffen.
Title: Re: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 04, 2018, 03:09 pm
uih, ne Menge zu leen und zu verstehen lernen.
Erstmal Danke.
mehr Rückmeldung nach dem Studium eurer ansätze und Hinweise/ Vorschläge.
Ich versuche das mal zu erkennen, wie,wann, wo welche Frage/ Antwort nötig ist.
Lieben Dank.
bis später dann!

wbr. Flötzinger
Title: Re: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 04, 2018, 05:26 pm
...fix mal alles zusammen in ein Dokument kopiert.
Versuch das zuverstehen.
vermutlich sieht/ liest man sich erst Freitag/ Samstag wieder...

Flötzinger
Title: Re: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 06, 2018, 04:16 pm
Hallo, just nen Moment Zeit gefunden.
Erstmal zum Verstehen würde ich das Switch Case Szenario aufdröseln und lernen wie das genau geschrieben werden muss, damit es funktioniert.

Danach die " Struct" Geschichte und abschliessend den Rest.
...denke mir, so lerne ich drei Varianten richtig schreiben und anzuwenden.

hier Quasi mein Teil 1 im Quote mit anschliessneder Frage:

Hallo,

du aktualisierst vor jeden Vergleich den Zeitmerker. Wie soll dann der Vergleich jemals wahr werden?
Nachdem der Vergleich gültig wurde zieht man den Zeitmerker nach auf die aktuelle Zeit damit er für den nächsten Vergleich erneut warten kann.

Code: [Select]

case 1://***** Abfrage HSQ1 *****
        if (digitalRead(HSQ1) == HIGH) {
          digitalWrite(Relais_HSQ1, HIGH);
           
          Startzeit1 = millis();
        }
        else if (millis() - Startzeit1 >= 2000) {
          digitalWrite(Relais_HSQ1, LOW);
        }
        break;


ändern in
Code: [Select]

case 1://***** Abfrage HSQ1 *****
        if (digitalRead(HSQ1) == HIGH) {
          digitalWrite(Relais_HSQ1, HIGH);
        }
        else if (millis() - Startzeit1 >= 2000) {
          Startzeit1 = millis();
          digitalWrite(Relais_HSQ1, LOW);
        }
        break;





Nein, das ist nicht das Problem. Er startet die Zeit im if-Zweig, wenn das Relais eingeschaltet wird, und fragt die Zeit im else-Zweig ab. Das wäre schon in Ordnung.
Allerdings steht der else-Zweig auch im case 1. Und wenn der Hall-Sensor inaktiv ist, kommt er da gar nicht mehr hin - kann also das Ablaufen der Zeit gar nicht mehr erkennen. Es ist ziemlich unsinnig , denn case nur bei aktivem Hall-Sensor aufzurufen, und dann im case-Zweig nochmal nach dem Status des Hallsensors verzweigen zu wollen.
...bedeutet für mich, den else if teil komplett hinter der "default:" Anweisung zu schreiben?
 btw: Schreibfehler im Case 3 korrigiert.
Title: Re: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 06, 2018, 04:17 pm
Hallo Doc,

Hallo,

Wenn ich das richtig überblicke steuert jeder Sensor ein bestimmtes Relais?
Wenn Sensor aktiv Relais umschalten?
Wenn Sensor nicht mehr aktiv Relais verzögert zurückschalten?

ja, richtig. Es werden dann irgendwann sicherlich pro Hallsensor 3 Aktionen/ Relais.
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 06, 2018, 04:57 pm
Hallo,

das case switch macht eigentlich keinen richtigen Sinn - laut meiner Meinung. Woher sollen die Ganzzahlen zur Abfrage kommen? Ein Bsp. ohne switch case. Wenn man das verlängert landet zwangläufig zumindestens bei Arrays. Sonst sind eine Menge Tippfehler möglich.

Ich simuliere das mit Tasten, deswegen die 2 Taster ...

Code: [Select]
#include <Bounce2.h>

const byte HSQ1 = 2;
const byte HSQ2 = 3;
Bounce debouncer1 = Bounce();
Bounce debouncer2 = Bounce();

const byte Relais_HSQ1 = 28;
const byte Relais_HSQ2 = 29;

unsigned long Startzeit1;
unsigned long Startzeit2;

unsigned long global_millis;

void setup()
{
  pinMode(HSQ1, INPUT_PULLUP);
  pinMode(HSQ2, INPUT_PULLUP);

  pinMode(Relais_HSQ1, OUTPUT);
  pinMode(Relais_HSQ2, OUTPUT);

  debouncer1.attach(HSQ1); debouncer1.interval(30);
  debouncer2.attach(HSQ2); debouncer2.interval(30);
}


void loop() {
  
  global_millis = millis();
  
  byte input = 0;

  debouncer1.update();
  debouncer2.update();

  input = debouncer1.read();
  if ( input == LOW) {
    digitalWrite(Relais_HSQ1, HIGH );
    Startzeit1 = global_millis;
  }

  input = debouncer2.read();
  if ( input == LOW) {
    digitalWrite(Relais_HSQ2, HIGH );
    Startzeit2 = global_millis;
  }

  if (global_millis - Startzeit1 >= 2000) {
    digitalWrite(Relais_HSQ1, LOW);
  }

  if (global_millis - Startzeit2 >= 2000) {
    digitalWrite(Relais_HSQ2, LOW);
  }

}
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 06, 2018, 05:32 pm
Hallo,

habs mal mit switch case gemacht. Wie schon gesagt, passt nicht zum Problem und verkompliziert die Sache. Problem ist, dass Sensorsignal liegt nicht ständig an. Für switch case muss es das jedoch damit die case gültig werden. Man muss damit switch case zur Endlosschleife machen. Indem es innerhalb die Zustände wechselt. Damit reagiert das Programm nur noch auf die Zeitvergleiche. Deswegen kann man sich das drum herum mit switch case gänzlich einsparen und nur die if Abfragen nutzen zum ausschalten.

Ich nutze switch case vorallendingen mit enum sehr gerne, hier halte ich es jedoch für nicht sinnvoll, weil es nichts einfacher macht. Auch ein speichern des Sensorsignal in der Steuervariablen macht keinen sinn, weil immer der letzte Sensor gewinnt. Kann ich drehen und wenden wie ich möchte. Das ist kein Bsp. zum nachmachen.

Code: [Select]

#include <Bounce2.h>

const byte HSQ1 = 2;
const byte HSQ2 = 3;
Bounce debouncer1 = Bounce();
Bounce debouncer2 = Bounce();

const byte Relais_HSQ1 = 28;
const byte Relais_HSQ2 = 29;

unsigned long Startzeit1;
unsigned long Startzeit2;

unsigned long global_millis;

enum class state : byte {HSQ1, HSQ2};   // Steuerzustände
state sensor = state::HSQ1;

void setup()
{
  pinMode(HSQ1, INPUT_PULLUP);
  pinMode(HSQ2, INPUT_PULLUP);

  pinMode(Relais_HSQ1, OUTPUT);
  pinMode(Relais_HSQ2, OUTPUT);

  debouncer1.attach(HSQ1); debouncer1.interval(30);
  debouncer2.attach(HSQ2); debouncer2.interval(30);
}


void loop() {

  global_millis = millis();

  byte input = 0;

  debouncer1.update();
  debouncer2.update();

  input = debouncer1.read();
  if ( input == LOW) {
    digitalWrite(Relais_HSQ1, HIGH);
    Startzeit1 = global_millis;
  }

  input = debouncer2.read();
  if ( input == LOW) {
    digitalWrite(Relais_HSQ2, HIGH);
    Startzeit2 = global_millis;
  }

  switch (sensor) {
    case state::HSQ1:
          if (global_millis - Startzeit1 >= 2000) {
            digitalWrite(Relais_HSQ1, LOW);
          }
          sensor = state::HSQ2;
          break;
    case state::HSQ2:
          if (global_millis - Startzeit2 >= 2000) {
            digitalWrite(Relais_HSQ2, LOW);
          }
          sensor = state::HSQ1;
          break;
    default: break;
  }
}
Title: Re: Millis() in Switch Case Problem
Post by: agmue on Dec 08, 2018, 11:54 am
das case switch macht eigentlich keinen richtigen Sinn - laut meiner Meinung.
Dieser Meinung schließe ich mich an.

Bei einer Verzögerung von 2 Sekunden scheint mir eine Entprellung von 30 Millisekunden nicht unbedingt notwendig, da debouncer1.read(); auch noch die aktive Zeit des Sensors mit einbezieht. Die Auswertung der Flanke fände ich da besser. Wahrscheinlich hast Du aber Dein Augenmerk nicht drauf gelegt.


@Floetzinger: Steht für Dich die Pendelzugsteuerung oder ein Switch/case-Beispiel im Vordergrund? Im letzteren Fall könntest Du mal einen Blick auf Anleitung Ein Endlicher Automat entsteht (https://forum.arduino.cc/index.php?topic=335352.0) aus meinen Anfangszeiten werfen. Das Kohlekranfunktionsmodell geht ja in die Richtung von Deinem Beispiel. Da habe ich MilliVerzoegerung als Funktion "ausgelagert". Manche case sind zeitabhängig, andere nicht, da gehört das zu case. Sind alle Schritte zeitabhängig, kann man switch/case auch als Teil der Verzögerung einbinden.
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 08, 2018, 12:42 pm
Hallo,

seine Sensorsignale muss er nicht entprellen, richtig, ich hab zum Test meine Taster verwendet, deswegen die Entprellung.  Hätte ich hier auch weglassen können, ja.   ;) 
Title: Re: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 09, 2018, 11:55 am
Hallo Agmue, Hello Doc (scnr),
einen schönen 2 Advent.
also Switch Case passt eutrer Meinung nach, nicht zum akteullen problem. Ok, verstanden.
Dann stelle ich das Verstrehen und Gestaltzen von Switch Case nach hinten und kümmere mich später ums erlernen.
Danke für den Link zum Kran...

euer neuer Ansatz, insbesondere die ersten Programmzeilen versuche ich nochmal auf Richtig verstanden mit euch zu klären.

im Bereich :
struct t_setup
{
  const byte pin_S;
  const byte pin_R;
  bool state;
  unsigned int delay;
  unsigned long last_ms;

wird im Byte pin_S eine noch zu bestimmende Anzahl von "Sensoren"(Eingang) hinterlegt.
Das Gleiche gilt für pin_R, hier als Ausgang für die Relaisansteuerung.
Klar ist mir, das bool state entweder True oder False sein kann. hier vermute ich mal, das der Pinzustand v. Sensor geprüft wird.
unsigned int enthält später die Verzögerungszeit (hierzu später noch eine Frage!)
unsigned long last_ms ist für die vergangene Zeit reserviert.


im Bereich:_
// Konstruktor
  t_setup (byte _S, byte _R, unsigned int _delay) :
    pin_S(_S),
    pin_R(_R),
    state(false),
    delay(_delay),
    last_ms(0)
  {}
finde ich für mich neu "t_setup", ist das ein eigenes Setup?
_S() füllt die Variable pin_S mit werten 8gilt ebenso für den Rest)?
Und welche Funktion haben die geschweiften Klammern?

Dann käme :
t_setup KOMBI[] = {
  {2, 7, 2000},  // Sensorpin, Relaispin, Delay
  {3, 8, 3000},
  {4, 9, 4000},

Dieser Teil hat wieder einen eigenen Namen, um weniger Schreibarbewit im laufenden Sketch zu haben, da hier eigentlich alles schon drin steht, was später passieren soll?

Sensorpin 2 schaltet Relais 7 ein, nach ablauf von Delay 2000 wird das Relais wieder abgeschaltet.

Muss jetzt leider unterbrechen, melde mich dann mit Fragen und so zu den void Setup und loop Gedöns!
Danke erstmal.
wbr. Flötzinger
Title: Re: Millis() in Switch Case Problem
Post by: combie on Dec 09, 2018, 12:07 pm
Quote
finde ich für mich neu "t_setup", ist das ein eigenes Setup?
_S() füllt die Variable pin_S mit werten 8gilt ebenso für den Rest)?
Und welche Funktion haben die geschweiften Klammern?
Das ist ein Konstruktor!
Mit Initialisierungsliste und leerem Anweisungsblock


Evtl. interessant für dich:
Topic: OOP für Anfänger - Einstieg mit nachvollziehbarer Erklärung (http://forum.arduino.cc/index.php?topic=578831.0)
Title: Re: Millis() in Switch Case Problem
Post by: Doc_Arduino on Dec 09, 2018, 01:10 pm
Hallo,

Wegen struct. Fast richtig erfasst. :)  Kann auch sein du meinst das und hast dich nur ungünstig ausgedrückt. Passiert mir auch bei neuen Dingen. Ich präzisiere nochmal etwas. Du kennst die definierten Datentypen byte, int, long usw. Da passen genau ein, zwei bzw. 4 Bytes rein. Mit struct baust du dir deinen eigenen Datentyp.
Der Datentyp heißt nun nicht byte, int oder long sondern t_setup. Kannste auch anders benennen. Aber das ist dein neuer Datentyp. Und genau der Datentyp nimmt in der angegebenen Reihenfolge, zwei Bytes, ein bool, ein unsigned int und ein unsigned long auf. Der Datentyp t_setup ist demnach 9 Byte groß.

Mit einem Datentyp alleine kann man nichts anfangen. Demzufolge muss man damit noch Variablen deklarieren bzw. initialisieren. Diese Variable heißt hier KOMBI (soll für Kombination stehen, kannste auch umbenennen) und ist ein Array. Array deshalb weil wir bzw. du mehrere benötigen und nicht jedesmal einen neuen Variablennamen erstellen möchten, was den Zugriff wieder erschweren würde. Und der reine Indexzugriff so nicht möglich wäre mit einem Durchlauf.

Also statt

Code: [Select]
byte var[] = { ... };
steht hier
t_setup KOMBI[] = { ... };



Für eine einzige Variable mit dem eigenen Datentyp würde

Code: [Select]
t_setup KOMBI;

genügen. Das wäre eine reine Deklaration
Der Zugriff darauf bzw. Initialisierung wäre dann

Code: [Select]
KOMBI.pin_S = 2;
KOMBI.state = false;



Mit dem hier

Code: [Select]
t_setup KOMBI[] = {
 {2, 7, 2000},  // Sensorpin, Relaispin, Delay
 {3, 8, 3000},
 {4, 9, 4000},



erstellen wir praktisch 3 Variablen mit dem Datentyp t_setup gebunden in einem Array. Der Zugriff erfolgt nun nicht mit 3 verschiedenen Variablennamen sondern mit einem und der Indexnummer. Was wie du gesehen hast nur Vorteile bringt. Wenn dir jetzt auffällt das pro Index nur 3 Werte von den 5 initialisiert wurden, dann ist das erstmal richtig erkannt. Die "fehlenden" werden mittels Konstruktur mit einem Defaultwert initialisiert, false und 0.
Title: Re: Millis() in Switch Case Problem
Post by: Floetzinger on Dec 19, 2018, 06:09 pm
Hallo zusammen,

leider muss ich dieses Projekt für ein paar Tage zurück stellen, es findet sich im Moment für diese gedankliche Schwerarbeit keine genügend große Lücke.
Aber ich bleibe dran, denn das will ich ja wissen, wie ich mir 2019 das Leben leichter machen kann.Also beim programmieren.

schon mal Danke fürs helfen.
Flötzinger