Go Down

Topic: Millis() in Switch Case Problem (Read 578 times) previous topic - next topic

Floetzinger

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.

Doc_Arduino

#16
Dec 06, 2018, 04:57 pm Last Edit: Dec 06, 2018, 05:02 pm by Doc_Arduino
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);
  }

}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

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;
  }
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

agmue

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 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.

Doc_Arduino

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.   ;) 
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Floetzinger

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

combie

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
Schreie nach Besserem, bis du es auch erhältst.
Das noch Bessere verabschiedet sich rechtzeitig vor deinem Lärm.

Quelle: Martin Gerhard Reisenberg

Doc_Arduino

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.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up