Befehl erst ausführen wenn Pin Status über eine bestimmte Mindestzeit hinweg unverändert ist

Hallo,

ich habe mal wieder eine typische Anfängerfrage: ich möchte einen digitalen Output Pin erst dann auf High setzen, wenn mehrere digitale Input Pins für eine bestimmte Dauer auf Low sind, also z.B.

Pin 4 und Pin 5 sind beide für mindestens 500ms auf Low -> setze Pin 10 auf High

Wie sieht der Code prinzipiell aus, um die Zeitdauer zu messen in der Pin 4 und Pin 5 auf Low stehen, und erst danach den Pin 10 auf High zu setzen?

Danke euch wieder sehr für Anregungen/Tips die mich hier weiterbringen :slight_smile:

millis(), if, und ein bisschen Grundrechenarten anwenden.

Arduino Doku lesen.
C++ Grundlagen lernen

// Forensketch
// https://forum.arduino.cc/

#include <Streaming.h>     // https://github.com/janelia-arduino/Streaming
constexpr byte inputPinNums {2};
constexpr byte inputPin[inputPinNums] {4, 5};
constexpr byte outputPin {6};
bool isActive;
uint32_t startTime;
constexpr uint32_t waitTime {2000};


void setup()
{
  Serial.begin(115200);
  Serial.println(F("\r\nStart...\r\n"));
  for (byte b = 0; b < inputPinNums; b++)
  {
    pinMode(inputPin[b], INPUT_PULLUP);
  }
  pinMode(outputPin, OUTPUT);
  digitalWrite(outputPin, LOW);
}

void  loop()
{
  checkPin();
  setPin();
}

void checkPin()
{
  if (!isActive)                                           // Noch nicht aktiv
  {
    isActive = true;                                       // belege Merker vor
    for (byte b = 0; b < inputPinNums; b++)                // Frage alle Pins ab
    {
      if (digitalRead(b))                                  // Der PIN ist HIGH
      { isActive = false; }                                // lösche den Merker
      else
      { startTime = millis(); }                            // oder merke die Abfragezeit
    }
  }
  else                                                     // Activ:
  {
    for (byte b = 0; b < inputPinNums; b++)                // Frage alle Pins ab
    {
      if (digitalRead(b))                                  // Einer ist aus
      { isActive = false; }                                // lösche den Merker
    }
  }
}

void setPin()
{
  if (isActive && millis() - startTime > waitTime)         // Wenn  aktiv udn zeit abgelaufen
  { digitalWrite(outputPin, HIGH); }
  else
  { digitalWrite (outputPin, LOW);}
}

Moin hervshahn

Zeig mal was du bereits programmiert hast.

Wofür braucht man das Programm.

Danke @my_xy_projekt my_xy_projekt für die superschnelle Reaktion, ich denke das hilft mir schon weiter !

das müsste funktionieren:

/*

   https://forum.arduino.cc/t/befehl-erst-ausfuhren-wenn-pin-status-uber-eine-bestimmte-mindestzeit-hinweg-unverandert-ist/1238604
   https://wokwi.com/projects/393062541441394689

   2024-03-22 by noiasca
   to be deleted 2024-06
*/

constexpr uint8_t inputPin[] {4, 5};
constexpr uint8_t outputPin {13};

enum Status {IDLE, WARTEN, AKTIV} status;
uint32_t previousMillis = 0;

void setup() {
  Serial.begin(115200);
  for (auto &i : inputPin) pinMode(i, INPUT_PULLUP);
  pinMode(outputPin, OUTPUT);
}

void test() {
  uint8_t bitmap = 0b11111111;  // wird später zu einem "wie sind die Pins"
  uint8_t mask = 0b11111111;    // wird später zu einem "wie sollen die Pins sein"
  for (int i = 0; i < sizeof(inputPin); i++) {
    mask ^= 1 << i;  // bit löschen
    if (digitalRead(inputPin[i]) == LOW ) bitmap ^= 1 << i;
  }

  //Serial.print(mask, BIN); Serial.print(' '); Serial.println(bitmap, BIN);

  switch (status) {
    case IDLE :
      if (mask == bitmap) {
        previousMillis = millis();
        status = WARTEN;
        Serial.println(status);
      }
      break;
    case WARTEN :
      if (mask != bitmap) {
        digitalWrite(outputPin, LOW);
        status = IDLE;
        Serial.println(status);
      }
      if (millis() - previousMillis > 1000) {
        digitalWrite(outputPin, HIGH);
        status = AKTIV;
        Serial.println(status);
      }
      break;
    case AKTIV :
      if (mask != bitmap) {
        digitalWrite(outputPin, LOW);
        status = IDLE;
        Serial.println(status);
      }
      break;
  }
}

void loop() {
  test();
}

von der Idee her ist es eine finite state machine mit den Status
IDLE - Pin Bedingung ist nicht erfüllt
WARTEN - die Pin Bedingung ist erfüllt, aber noch nicht genug Zeit ist um
AKTIV Pin Bedingung ist erfüllt, und genug Zeit ist um

1 Like

Hi @paulpaulson,

ich experimentiere grade erst etwas, hab noch nichts programmiert. Letztendlich ist es ein Programm zur Auslösung von Aktionen durch Abfrage von unterschiedlichen Schalterstellungen mittels des Zustandes zweier Pins:

Pin 4 auf High, oder Pin5 auf High, oder beide Pins auf Low

Da der Schalter immer von "Pin 4 High" über "beide Pins auf Low" zu "Pin 5 High" schaltet, und wieder zurück, will ich die Aktion für den Zustand "beide Pins auf Low" erst dann auslösen wenn dieser Zustand eine gewisse Zeit lang besteht, um abzufangen dass beim Übergang von "Pin 4 High" über "beide Pins auf Low" zu "Pin 5 High" diese ungewollt ausgelöst wird.

@noiasca Danke Dir !!!

Ich rate mal, du hast einen Umschalter (mit Mittelstellung?) mit dem du HIGH entweder auf den einen oder den anderen Pin gibst.
Hast du überhaupt zwei Pulldown Widerstände an die Pins 4 und 5 angeschlossen?
Sonst sind die offenen Pins nicht LOW, sondern UNDEFINIERT.

Nicht umsonst gibt es einige Beispiele, wie man Schalter oder Taster einliest.

Hallo hervshahn

Ich habe einen Sketch, zum Studium der Möglichkeiten, für dich:

//https://forum.arduino.cc/t/befehl-erst-ausfuhren-wenn-pin-status-uber-eine-bestimmte-mindestzeit-hinweg-unverandert-ist/1238604
//https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
#define ProjectName "Befehl erst ausführen wenn Pin Status über eine bestimmte Mindestzeit hinweg unverändert ist"
#define NotesOnRelease "Arduino MEGA tested"
// make names
enum TimerEvent {NotExpired, Expired};
enum TimerControl {Halt, Run};
enum ButtonStates {Released, Pressed};
enum Names {One, Two};
// make variables
uint32_t currentMillis = millis();
constexpr uint8_t ButtonPins[] {4,5};
constexpr uint8_t LedPin {10};
constexpr uint32_t FiveSecondsMillis {5000};
// make structures
struct TIMER
{
  uint32_t interval;
  uint8_t control;
  uint32_t now;
  uint8_t expired(uint32_t currentMillis)
  {
    uint8_t timerEvent = currentMillis - now >= interval and control;
    if (timerEvent == Expired) now = currentMillis;
    return timerEvent;
  }
};
struct BUTTON
{
  uint8_t pin;
  uint8_t stateOld;
  uint32_t timePressed;
  TIMER debounce;
  void make()
  {
    pinMode(pin, INPUT_PULLUP);
    stateOld = digitalRead(pin) ? LOW : HIGH;
    debounce.interval = 20;
    debounce.control = Run;
    debounce.now = millis();
  }
  uint8_t run()
  {
    if (debounce.expired(currentMillis) == Expired)
    {
      uint8_t stateNew = digitalRead(pin) ? LOW : HIGH;
      if (stateOld != stateNew)
      {
        stateOld = stateNew;
        stateNew == Pressed ? timePressed = currentMillis : timePressed = 0;
      }
    }
    return (currentMillis - timePressed > FiveSecondsMillis and timePressed != 0);
  }
} buttons[]
{
  {ButtonPins[One], LOW,  0, 20, Run, 0},
  {ButtonPins[Two], LOW,  0, 20, Run, 0},
};
// make support
void heartBeat(const uint8_t LedPin, uint32_t currentMillis)
{
  static bool setUp = false;
  if (setUp == false) pinMode (LedPin, OUTPUT), setUp = true;
  digitalWrite(LedPin, (currentMillis / 500) % 2);
}
// make application
void setup()
{
  Serial.begin(115200);
  Serial.print("Source: "), Serial.println(__FILE__);
  Serial.print(ProjectName), Serial.print(" - "), Serial.println(NotesOnRelease);
  for (auto &button : buttons) button.make();
  pinMode (LedPin, OUTPUT);
  Serial.println(" =-> and off we go\n");
}
void loop()
{
  currentMillis = millis();
  heartBeat(LED_BUILTIN, currentMillis);
  static uint8_t offOn[2] {LOW, LOW};
  uint8_t element = 0;
  for (auto &button : buttons)
  {
    offOn[element++] = button.run();
  }
  digitalWrite (LedPin, offOn[One] and offOn[Two]);
}

Sorry, hatte in der Beschreibung einen Fehler - Pin 4 und Pin 5 werden durch den Schalter auf LOW gezogen, in Mittelstellung sind beide Pins auf HIGH.

Vielen vielen Dank auch allen für die Beispiele, ich arbeite mich jetzt mal dadurch

Hat sich ja scheinbar noch nicht viel getan beim „half moon“ Schalter für die Orgel.

1 Like

Nicht wirklich, da ich die letzten Wochen massiv beruflich eingespannt war, bin ich erst heute dazu gekommen, mich mal wieder etwas darum zu kümmern. Eine Testschaltung steht, funktioniert auch fast so wie sie soll aber diese zeitliche Verzögerung beim auslösen einer Aktion für den beschriebenen speziellen Status Muss ich noch einbauen, leider fehlt mir da das Know-how, was die Programmierung angeht. Das ganze wird aber auch noch eine ziemliche Zeit dauern, bis es wirklich fertig ist, da ich auch absehbar nur sporadisch mal Zeit dafür haben werde. Aber nichts, desto trotz will ich das Ganze nutzen, um zu lernen, Also seht es mir nach, wenn ich auch noch länger ab und zu mal solche Fragen dazu stellen werde solange das Projekt noch nicht abgeschlossen ist. Ich bin ja froh, dass es dieses Forum und hier so viele hilfsbereite Benutzer gibt, das ist echt super!

Und sorry für die Fehler in meiner Antwort, das kommt dabei raus, wenn man im Auto sitzt und dem Smartphone den Text diktiert

Hab es heute endlich fertiggestellt, s. den Sketch in dem ursprünglichen Thread zu dem gesamten Thema :sweat_smile:

https://forum.arduino.cc/t/anfangerfrage-schalterstellung-abfragen-und-tasterfunktion-auslosen/1233547/75?u=hervshahn

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.