Digital Read und delay?

Hallo zusammen,
ich nutze einen Uno als Steuerzentrale. Digital out an Relais, Digital in als Statusabfrage für ist-Zustände.
Jetzt hab ich das Problem, dass mein in Signal nicht sofort von 0 auf 5V steigt bzw sinkt, sonder ca 500ms einen undefinierten Zustand hat. Das habe ich mit einem delay(500) hinbekommen. allerdings bekommt der Uno direkt nach dem Auslesen der Inputs Steuerbefehle zum Schalten von Relays, die genau in der delayzeit kommen und demnach nicht ausgewertet werden.
Gibt es eine andere Möglichkeit, die Inputs nur in definierten Zuständen auszulesen, als mit dem Delay zu warten?

Hier ein Teil des codes:

void loop() {
  input = digitalRead(input1);
  if (input==HIGH)
  {
  if (input!=input1alt)
  {
    Serial.print('Y');
    Serial.write( '\r' );
    delay(500);
    input1alt=input;
  }}
  if (input==LOW)
  {
    if (input!=input1alt)
    {
      Serial.print('X');
      Serial.write( '\r' );
      delay(500);
      input1alt=input;
    }
  }

  while (Serial.available() > 0) 
  {
    serialin = Serial.read();
    if (serialin == 'q' || serialin =='Q')
    { 
      digitalWrite(relay,LOW);
      }
    else if (serialin == 'a' || serialin =='A')
    { 
      digitalWrite(relay,HIGH);
      }
    Serial.println(serialin);
    if (serialin == 'w' || serialin =='W'){ 
      digitalWrite(relay1,LOW);
      }

vielen Dank für Hilfe!
Gruß Florian

Dark_Dragon:
Gibt es eine andere Möglichkeit, die Inputs nur in definierten Zuständen auszulesen, als mit dem Delay zu warten?

Ja, das kannst du mit der Funktion "millis()" lösen.

Sieh dir den Beitrag "BlinkWithoutDelay" an. An dem Beispiel kannst du entnehmen, wie dein Delay ersetzt werden kann.

Dark_Dragon:
Jetzt hab ich das Problem, dass mein in Signal nicht sofort von 0 auf 5V steigt bzw sinkt, sonder ca 500ms einen undefinierten Zustand hat. Das habe ich mit einem delay(500) hinbekommen.

Merkwürdige Herangehensweise für undefinierte Zustände. Du zeigst ja auch nicht den gesamten Sketch, sprich auch die setup-Routine mit den pinMode-Definitionen usw.. Verwendest du interne/externe Pullup- oder Pulldown-Widerstände?

Hallo,
du könntest z.B. diese delay´s() rauswerfen.
Hängen könnte das ganze hier:“while (Serial.available() > 0)”
Wenn Du mit “serial” arbeitest, dann kommt es zu Verzögerungen. Wie groß
diese sind, kann ich Dir nicht sagen.
Gruß und Spaß
Andreas

Wie schon in #1 erwähnt, kannst Du das mit millis() lösen. Damit erreichst Du eine quasi parallele Verarbeitung von digitalem Eingang und Zeichenauswertung:

void loop() {
  aktMillis = millis();
  input1alt = input;
  input = digitalRead(input1);
  if (input != input1alt) {
    pauseMillis = aktMillis;
    einmal = true;
    pauseIntervall = PAUSE;
  }
  if ((aktMillis - pauseMillis >= pauseIntervall) && einmal) {
    if (input) {
      Serial.print('Y');
    } else {
      Serial.print('X');
    }
    Serial.println();
    pauseIntervall = 0;
    einmal = false;
  }

  if (Serial.available())
  {
    serialin = Serial.read();
    if (serialin == 'q' || serialin == 'Q')
    {
      digitalWrite(relay, LOW);
    }
    else if (serialin == 'a' || serialin == 'A')
    {
      digitalWrite(relay, HIGH);
    }
    Serial.println(serialin);
    if (serialin == 'w' || serialin == 'W') {
      digitalWrite(relay, LOW);
    }
  }
}

Da Du nur ein Zeichen auswertest, reicht if (Serial.available())

Du könntest auch die Bibliothek bounce2 mit 500 ms als Entprellzeit verwenden. Habe ich nicht getestet, sollte aber funktionieren, da void interval(uint16_t interval_millis);.

An den Folgen herumwerkeln ist der falsche Ansatz.
Da mußt Du den grund des Verhaltens finden und diesen beseitigen.

Jetzt hab ich das Problem, dass mein in Signal nicht sofort von 0 auf 5V steigt bzw sinkt, sonder ca 500ms einen undefinierten Zustand hat.

Es ist sehr komisch, daß ein Wechsel (H-L oder L-H) so lange braucht. Bitte Schaltplan, schaltungsbeschreibung, Teilebeschreibung.

Außerdem haben die Pins KEinen Undefinierten Zustand. bei einem L-H wechsel ist das Signal LOW solange es kleiner als 3V ist und HIGH solange es größer als 1,5V ist. Also ist da kein undefinierter Zustand. Ein Wechsel der 0,5S braucht ist technisch plausibler.

Grüße Uwe

Hallo,
erstmal vielen Dank für die Infos.
Mit den Millis hab ich das Problem schon mal etwas behoben. Allerdings noch nicht ganz sauber.
An dem Eingang hängt ein Optokoppler (an 230v) der steuert einfach über Pullup/down die 5V Spannung vom Arduino, die dann am digitalen Input hängt.

Kurze Schaltungsbeschreibung: 230V Eingang über einen C und einen R an den Optokoppler, parallel in Gegenrichtung eine Diode gegen die negativen Halbwellen. (Quasi Strombegrenzerschaltung)
An der anderen Seite des Kopplers hängt ein Pullup R an 5V+ und Optokoppler out. und ein C gegen Masse. (vielleicht sollte ich zu dem parallel noch einen R setzen, um den Entladevorgang zu beschleunigen... probiere ich nachher noch mal aus)

Hier der derzeitige komplette Code:

char serialin;
char serialout;
int input1alt;
int input;

#define relay 8
#define relay1 9
#define relay2 10
#define relay3 11
#define input1 3

unsigned long interval=500;
unsigned long previousMillis = 0;

void setup() {

 
  Serial.begin(9600);

  pinMode(relay, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(input1, INPUT);

  digitalWrite(relay,HIGH);
  digitalWrite(relay1,HIGH);
  digitalWrite(relay2,HIGH);
  digitalWrite(relay3,HIGH);


 
  }

void loop() {
  input = digitalRead(input1);
  if (input==HIGH)
  {
  if (input!=input1alt)
  {

   if (millis() - previousMillis > interval) {
   previousMillis = millis();
    
    Serial.print("Y");
   Serial.write('\r' );

    input1alt=input;
  }}
  }
  if (input==LOW)
  {
    if (input!=input1alt)
    {
   if (millis() - previousMillis > interval) {
   previousMillis = millis();

     Serial.print("X");
     Serial.write( '\r');

      input1alt=input;
    }}
  }

  while (Serial.available() > 0) 
  {
    serialin = Serial.read();
    if (serialin == 'q' || serialin =='Q')
    { 
      digitalWrite(relay,LOW);
      }
    else if (serialin == 'a' || serialin =='A')
    { 
      digitalWrite(relay,HIGH);
      }
    Serial.println(serialin);
    if (serialin == 'w' || serialin =='W'){ 
      digitalWrite(relay1,LOW);
      }
 
    else if (serialin == 's' || serialin =='S'){ 
      digitalWrite(relay1,HIGH);
      }
      Serial.println(serialin);
 
   
    if (serialin == 'e' || serialin =='E'){ 
      digitalWrite(relay2,LOW);
      }
 
    else if (serialin == 'd' || serialin =='D'){ 
      digitalWrite(relay2,HIGH);
      }
      Serial.println(serialin);
 
    if (serialin == 'r' || serialin =='R'){ 
      digitalWrite(relay3,LOW);
      }
   
    else if (serialin == 'f' || serialin =='F'){ 
      digitalWrite(relay3,HIGH);
      }
      Serial.println(serialin);
  }  }

Ich werde mir nachher noch mal die letzten Beiträge zu Gemüte führen und noch etwas basteln.
Erstmal vielen Dank für eure Hilfe!

Mit while (Serial.available() > 0) blockierst Du loop() mit einer Schleife. Aber loop() ist eine Schleife, daher wäre if (Serial.available()) flotter für die Abfrage der digitalen Eingänge.

Du könntest auch über

switch(serialin){
  case 'Q':
  case 'q':
    digitalWrite(relay,LOW);
    break;
...
}

nachdenken. Ändert nichts an der Funktion, strafft nur das Programm.

Oder noch kürzer:

switch(tolower(serialin)){
  case 'q':
    digitalWrite(relay,LOW);
    break;
...
}