wenn taste X sekunden gedrückt dann für X sekunden ausgang HIGH

Hallo,

ich bin Neuling und brauche für mein Projekt Hilfe!

Ich habe 5 Tasten (später Sensoren) und 5 LED´s (später Magnetventile).

LED 1 bis 4 soll wenn der jeweilige Taster (1-4) gedrückt wird (Zeitunabhängig) für 1sekunde geschalten werden.
LED 5 soll für ebenfalls 1sekunde geschalten werden aber erst wenn Taster5 eine gewisse zeit gedrückt wurde.

ich hoffe das mir das jemand helfen kann.

danke im Voraus

LED 1 bis 4 soll wenn der jeweilige Taster (1-4) gedrückt wird (Zeitunabhängig) für 1sekunde geschalten werden.
LED 5 soll für ebenfalls 1sekunde geschalten werden aber erst wenn Taster5 eine gewisse zeit gedrückt wurde.

a) du musst dir auch überlegen was passieren soll, wenn der Taster nach einer Sekunde noch immer gedrückt ist.
b) hier schreibt dir niemand einen Sketch, sondern hier wird dir nur geholfen deinen Sketch zu schreiben.
Also solltest du deinen bisherhigen Versuch hier posten und eine konkrete Frage stellen.
c) vermeide die Verwendung von delay(), arbeite nach dem Muster "BlinkWithoutDelay"
d) mach die wichtigsten IDE Beispiele durch (01 Basics und 02 Digital)
e) anschließend rate ich dir das durchzulesen: Arduino: LED oder Relais per Tastendruck einschalten und mit Zeitablauf abschalten - es behandelt ein ähnliches Thema wie deine LED 1 bis LED 4. Macht aber nur Sinn, wenn du d) gemacht hast

danke erstmal für die schnelle antwort!

zu a) der taster (später reedsensor) ist immer länger als 1sek gedrückt/aktiv. die LED’s sollen immer nur die “1sek” geschalten sein. wie kann man so etwas lösen?

zu b) er funktioniert nur teils. pin9-12 haben das problem dass sie so lange taster 1-4 gedrückt wird aktiv sind. taster5 sollte erst 2sek gedrückt sein bevor pin13 (ledweis) für 1sek aktiv ist.

#include <Bounce2.h>

int ledweis = 13;
int ledblau = 12;
int ledgruen = 11;
int ledrot = 10;
int ledgelb = 9;
int taster1 = 2;
int taster2 = 3;
int taster3 = 4;
int taster4 = 5;

const unsigned long gemesseneZeit = 2000;

unsigned long lastMillis1;
unsigned long lastMillis2;
unsigned long lastMillis3;
unsigned long lastMillis4;

Bounce taster5;

void setup() {

Serial.begin(9600);
pinMode(ledweis, OUTPUT);
pinMode(ledblau, OUTPUT);
pinMode(ledgruen, OUTPUT);
pinMode(ledrot, OUTPUT);
pinMode(ledgelb, OUTPUT);
pinMode(taster1, INPUT_PULLUP);
pinMode(taster2, INPUT_PULLUP);
pinMode(taster3, INPUT_PULLUP);
pinMode(taster4, INPUT_PULLUP);
taster5.attach(6, INPUT_PULLUP);

unsigned long lastMillis1;
unsigned long lastMillis2;
unsigned long lastMillis3;
unsigned long lastMillis4;
}

void loop() {

if (!digitalRead(taster1)) {
lastMillis1 = millis();
}
if (millis() - lastMillis1 <= 100) {
digitalWrite(ledgelb, HIGH);
}
else {
digitalWrite(ledgelb, LOW);
}
if (!digitalRead(taster2)) {
lastMillis2 = millis();
}
if (millis() - lastMillis2 <= 100) {
digitalWrite(ledrot, HIGH);
}
else {
digitalWrite(ledrot, LOW);
}
if (!digitalRead(taster3)) {
lastMillis3 = millis();
}
if (millis() - lastMillis3 <= 100) {
digitalWrite(ledgruen, HIGH);
}
else {
digitalWrite(ledgruen, LOW);
}
if (!digitalRead(taster4)) {
lastMillis4 = millis();
}
if (millis() - lastMillis4 <= 100) {
digitalWrite(ledblau, HIGH);
}
else {

digitalWrite(ledblau, LOW);
}

//…taster5……

static unsigned long tastenZeitpunkt;
if (taster5.update()) {
if (taster5.fell()) {
tastenZeitpunkt = millis();
}
}
if (tastenZeitpunkt && (millis() - tastenZeitpunkt >= gemesseneZeit)) {
digitalWrite(ledweis, !digitalRead(ledweis));
tastenZeitpunkt = 0;
}
else {

digitalWrite(ledweis, LOW);
}
}

:frowning:

der taster ist immer länger als 1sek gedrückt.

Wenn der Taster länger als 49,x Tage gedrückt wird, blitzen die LEDs eben genau alle 49,x Tage für 100ms auf.

ich möchte im späteren den sketch nutzen um anhand von 4 reedkontakten eine bestimmte stellung von 4 pneumatikzylindern auszulesen (diese stellung halten die 4 zylinder im besten und häufigsten fall für ca. 10sek. im schlimmsten fall mehrer minuten) und anhand dieser signale sollen dann 4Relais für "X" sekunden geschalten werden.

Im schlechtesten fall steht ein zylinder (1,2,3 oder 4) für mehrer minuten auf dieser stelle. dann sollte das jeweilige relais dennoch nur die "X" sekunden geschalten werden.

im gerade beschrieben schlechtesten fall kommen keine weiteren signale der anderen 3 reedkontakte hinzu, erst wieder wenn kein signal der 4 reedkontakte aktiv ist.

jetzt zur frage:
ist es überhaupt möglich einen "output" für "X" sekunden zu schalten trotz das der dazugehörige "input" länger HIGH ist als die zeit die der "output" auf HIGH gesetzt wird? wenn ja, wie realisiere ich das?

viele dank schon mal

:wink:

wenn ja, wie realisiere ich das?

Endliche Automaten bauen.

im ernst? es ist also nicht programmierbar?

Endliche Automaten sind in der Regel Programme.
Und als solches auch programmierbar.

Endliche Automaten bauen.

Natürlich ist es programmierbar.
Wenn es fertig ist, nennen viele Leute hier (insbesondere combie :stuck_out_tongue: ) das einen "Endlichen Automaten"

Du musst aus dem Zustand des Tasters einen Zustandswechsel ermitteln.

Dazu brauchst du :

 static bool alterZustand1; // den Zustand beim vorigen Mal
  bool zustand1 = digitalRead(taster1);  // den aktuellen Zustand
  if (zustand1 && alterZustand1 == LOW) {
     // kommende Flanke:
     // LED an, Zeitmerker1 setzen (TODO)
  }
  alterZustand1 = zustand1; // merken für's nächste Mal 
  if (millis() - Zeitmerker1 > 1 sec) {
     // LED wieder aus (TODO)
  }

Hi

Man kann zur Not auch danach Google befragen, Was Combie Da gemeint haben könnte :wink:

Mich erschüttert viel mehr die Möglichkeit, daß von diese Pipi-Aufgabe als unprogrammierbar ausgegangen wurde.
So ziemlich Alles, was Du Dir so denken kannst, lässt Sich mit einem µC erschlagen - wenn’s klemmt, am Platz, der erforderlichen Hardware, der Geschwindigkeit oder so Kram.
Sonst liegen die Grenzen nur bei Dir als Programmierer - Du musst Dein Problem halt ‘nur’ in Code gießen.

MALE Dir auf, WAS WANN passieren soll.
AUCH, was passiert, wenn besagtes Signal KÜRZER als diese Sekunde anliegt oder LÄNGER als x Minuten.
‘Passiert nie’ ist der Anfang eines Versagens, Welches Du hättest vorher sehen können MÜSSEN.

Und wenn so unzulässige Signale kommen, kannst Du außerdem noch drauf reagieren - rotes Blinkelämpchen, Error-Meldung auf dem LCD, Hilfe-SMS ans Handy … (… benötigt Zusatz-Hardware …)

MfG

So ziemlich Alles, was Du Dir so denken kannst, lässt Sich mit einem µC erschlagen - wenn's klemmt, am Platz, der erforderlichen Hardware, der Geschwindigkeit oder so Kram.

Wenn das zu lösende Problem endlich ist, und deterministisch, ja, dann wirds einem besonders einfach gemacht.

Ansonsten gibts noch die Methode der Projektion.

A:
Betrachte die Lösung aus Sicht der Daten, wie sie durchs System fließen.
Definiere die Kanäle und baue die Transformatoren.
Male Datenflussdiagramme.

B:
Betrachte die Lösung als einen endlichen Automaten.
Also benenne die Zustände und baue die Zustandsübergänge.
Male Zustandsdiagramme.

C:
Betrachte die Lösung aus Sicht der einzelnen Komponenten, der Objekte.
Schreibe Klassen und lass deren Instanzen miteinander kommunizieren.
Male UML Diagramme.

D:
Betrachte die Lösung aus Sicht des Kontrollablaufs, wann wird was getan.
Verwende if, Case For usw. Baue Funktionen
Male Programmablaufpläne

Alle diese Sichtweisen haben ihre Eigenheiten, welche sich auch vortrefflich verquicken lassen.

Hi

Allen ist aber gemein: MALE (so mit Stift und Papier hat sich durchaus bewährt).
Mache ich selber auch zu selten - oft benutze ich eine .txt ... klappt damit aber nur bedingt :wink: ... man ist aber halt faul und das .txt-File ist ohne größere Anstrengungen erstellt ...

MfG

(deleted)

Und teile das Problem erstmal auf: Du willst zwei unterschiedliche Verhalten, und das eine in vierfacher Ausfertigung.
Ein Sketch für nur eins von beiden, in code tags dargestellt, verleitet mehr Leute, kurz draufzuschauen und dir zu zeigen, warum dich das Verhalten verwirrt. Wenn du denn genau sagst, was dich daran verwirrt.

Wie du am Ende alles in einen Sketch zusammenkriegst, ist dann eventuell eine weitere Aufgabe. Aber viele kleine Probleme sind besser als ein großes.

Peter-CAD-HST:
dafür nehme ich immer die Kühlschranktür. Nur mit der Ablage der Aufzeichnungen ist das immer so schwierig :slight_smile:

:grin:

arcaine:
im ernst?

Endlicher Automat = Schrittkette = finite state machine = eine endliche Zahl Zustände verarbeiten

Eine Realisierung geht beispielsweise mit switch/case.

Die Aufgabe ruft auch nach einer Struktur oder Klasse, weil dann zusammengehörige Daten zusammenstehen. (Wo habe ich das nur schon mal gelesen ;D ). Nach einer Anregung von combie als Diskussionsgrundlage:

#define LEDSCHALTZEIT 1000

class Taster
{
    const byte tasterPin, ledPin;
    const uint32_t tastMinzeit, ledAn;
    uint32_t tastMillis, ledMillis;
    bool tastNeu, tastAlt;
    byte schritt;
  public:
    Taster(const byte tasterPin, const byte ledPin, const uint32_t tastMinzeit):
      tasterPin(tasterPin), ledPin(ledPin), tastMinzeit(tastMinzeit), ledAn(LEDSCHALTZEIT), tastMillis(), ledMillis(0), tastNeu(0), tastAlt(), schritt(0) {}

    void init() //Initialisierung
    {
      digitalWrite(ledPin, HIGH);
      pinMode (ledPin, OUTPUT);
      pinMode (tasterPin, INPUT_PULLUP);
      tastAlt = digitalRead(tasterPin);
    }

    enum {WARTEN, MINZEIT, LEDZEIT};

    void run()
    {
      uint32_t jetzt = millis();
      tastAlt = tastNeu;
      tastNeu = digitalRead(tasterPin);
      switch (schritt)
      {
        case WARTEN:
          if (tastAlt && !tastNeu)
          {
            tastMillis = jetzt;
            schritt = MINZEIT;
          }
          break;
        case MINZEIT:
          if ((jetzt - tastMillis >= tastMinzeit))
          {
            if (!tastNeu)
            {
              digitalWrite(ledPin, LOW);
              ledMillis = jetzt;
              schritt = LEDZEIT;
            } else {
              schritt = WARTEN;
            }
          }
          break;
        case LEDZEIT:
          if (jetzt - ledMillis >= ledAn)
          {
            digitalWrite(ledPin, HIGH);
            schritt = WARTEN;
          }
          break;
      }
    }
};

Taster taster []
{ //tasterPin, ledPin, tastMinzeit
  {         2,      9,         30}, // gelb
  {         3,     10,         30}, // rot
  {         4,     11,         30}, // gruen
  {         5,     12,         30}, // blau
  {         6,     13,       2000}  // weiß
};

void setup()
{
  for (Taster &t : taster) t.init();
}

void loop()
{
  for (Taster &t : taster) t.run();
}

agmue:
:grin:
Endlicher Automat = Schrittkette = finite state machine = eine endliche Zahl Zustände verarbeiten

Eine Realisierung geht beispielsweise mit switch/case.

Die Aufgabe ruft auch nach einer Struktur oder Klasse, weil dann zusammengehörige Daten zusammenstehen. (Wo habe ich das nur schon mal gelesen ;D ). Nach einer Anregung von combie als Diskussionsgrundlage:

#define LEDSCHALTZEIT 1000

class Taster
{
    const byte tasterPin, ledPin;
    const uint32_t tastMinzeit, ledAn;
    uint32_t tastMillis, ledMillis;
    bool tastNeu, tastAlt;
    byte schritt;
  public:
    Taster(const byte tasterPin, const byte ledPin, const uint32_t tastMinzeit):
      tasterPin(tasterPin), ledPin(ledPin), tastMinzeit(tastMinzeit), ledAn(LEDSCHALTZEIT), tastMillis(), ledMillis(0), tastNeu(0), tastAlt(), schritt(0) {}

void init() //Initialisierung
    {
      digitalWrite(ledPin, HIGH);
      pinMode (ledPin, OUTPUT);
      pinMode (tasterPin, INPUT_PULLUP);
      tastAlt = digitalRead(tasterPin);
    }

enum {WARTEN, MINZEIT, LEDZEIT};

void run()
    {
      uint32_t jetzt = millis();
      tastAlt = tastNeu;
      tastNeu = digitalRead(tasterPin);
      switch (schritt)
      {
        case WARTEN:
          if (tastAlt && !tastNeu)
          {
            tastMillis = jetzt;
            schritt = MINZEIT;
          }
          break;
        case MINZEIT:
          if ((jetzt - tastMillis >= tastMinzeit))
          {
            if (!tastNeu)
            {
              digitalWrite(ledPin, LOW);
              ledMillis = jetzt;
              schritt = LEDZEIT;
            } else {
              schritt = WARTEN;
            }
          }
          break;
        case LEDZEIT:
          if (jetzt - ledMillis >= ledAn)
          {
            digitalWrite(ledPin, HIGH);
            schritt = WARTEN;
          }
          break;
      }
    }
};

Taster taster
{ //tasterPin, ledPin, tastMinzeit
  {        2,      9,        30}, // gelb
  {        3,    10,        30}, // rot
  {        4,    11,        30}, // gruen
  {        5,    12,        30}, // blau
  {        6,    13,      2000}  // weiß
};

void setup()
{
  for (Taster &t : taster) t.init();
}

void loop()
{
  for (Taster &t : taster) t.run();
}

Fantastisch! Danke!!!

agmue:
Die Aufgabe ruft auch nach einer Struktur oder Klasse, weil dann zusammengehörige Daten zusammenstehen. (Wo habe ich das nur schon mal gelesen ;D ). Nach einer Anregung von combie als Diskussionsgrundlage:

Ich habe mir das mal aufmerksam angesehen.

Es gibt dort 2 Dinge, welche aus meiner Sicht verbesserungswürdig sind.

Einmal das magische Define "#define LEDSCHALTZEIT 1000".
Das verbessere ich mal nicht großartig, denn das tuning ist eher trivial. Einfach ein weiterer Konstruktor Parameter.

Der zweite Punkt betrifft den "schritt". Das Tuning ist nicht ganz so trivial.
Erstmal sollte es begrenzt werden, auf die tatsächlich möglichen Schritte.
Denn bisher könnte man auf die Idee kommen mit schritt++ einfach einen weiter zu gehen, was wegen des fehlenden default: Zweigs zu einem Problem werden könnte.
Ebenso wird eine Initialisierung/Zuweisung, z.B. so: schritt = PI; nicht unterbunden
Ansonsten finde ich die Idee, die Schritte auf byte zu begrenzen zu wollen voll OK.
Die magische Null bei der Initialisierung darf auch unterbunden werden.

Die Verbesserung findet sich im folgenden.
a. schritt und alles damit zusammenhängende, auf 8 Bit begrenzt
b. schritt ist jetzt vollkommen Typesicher
c. das #define entsorgt, aber die Funktionalität nicht verändert
d. ein paar Nullen bei der Konstruktorinitialisierungsliste hinzugefügt(Kosmetik(?!))

constexpr uint32_t LEDSCHALTZEIT = 1000;

class Taster
{
  private:
    enum class Schritt:byte {WARTEN, MINZEIT, LEDZEIT};
    const byte tasterPin, ledPin;
    const uint32_t tastMinzeit, ledAn;
    uint32_t tastMillis, ledMillis;
    bool tastNeu, tastAlt;
    Schritt schritt;
  public:
    Taster(const byte tasterPin, const byte ledPin, const uint32_t tastMinzeit):
      tasterPin(tasterPin), ledPin(ledPin), tastMinzeit(tastMinzeit), ledAn(LEDSCHALTZEIT), tastMillis(0), ledMillis(0), tastNeu(0), tastAlt(0), schritt(Schritt::WARTEN) {}

    void init() //Initialisierung
    {
      digitalWrite(ledPin, HIGH);
      pinMode (ledPin, OUTPUT);
      pinMode (tasterPin, INPUT_PULLUP);
      tastAlt = digitalRead(tasterPin);
    }


    void run()
    {
      uint32_t jetzt = millis();
      tastAlt = tastNeu;
      tastNeu = digitalRead(tasterPin);
      switch (schritt)
      {         case Schritt::WARTEN:
          if (tastAlt && !tastNeu)
          {
            tastMillis = jetzt;
            schritt = Schritt::MINZEIT;
          }
          break;
        case Schritt::MINZEIT:
          if ((jetzt - tastMillis >= tastMinzeit))
          {
            if (!tastNeu)
            {
              digitalWrite(ledPin, LOW);
              ledMillis = jetzt;
              schritt = Schritt::LEDZEIT;
            } else {
              schritt = Schritt::WARTEN;
            }
          }
          break;
        case Schritt::LEDZEIT:
          if (jetzt - ledMillis >= ledAn)
          {
            digitalWrite(ledPin, HIGH);
            schritt = Schritt::WARTEN;
          }
          break;
      }
    }
};

Taster taster []
{ //tasterPin, ledPin, tastMinzeit
  {         2,      9,         30}, // gelb
  {         3,     10,         30}, // rot
  {         4,     11,         30}, // gruen
  {         5,     12,         30}, // blau
  {         6,     13,       2000}  // weiß
};

void setup()
{
  for (Taster &t : taster) t.init();
}

void loop()
{
  for (Taster &t : taster) t.run();
}

Wie man sieht, keine Welt bewegenden Änderungen .....
Im Grunde alles beim alten.

combie:
Ich habe mir das mal aufmerksam angesehen.

Es gibt dort 2 Dinge, welche aus meiner Sicht verbesserungswürdig sind.

Einmal das magische Define "#define LEDSCHALTZEIT 1000".
Das verbessere ich mal nicht großartig, denn das tuning ist eher trivial. Einfach ein weiterer Konstruktor Parameter.

Der zweite Punkt betrifft den "schritt". Das Tuning ist nicht ganz so trivial.
Erstmal sollte es begrenzt werden, auf die tatsächlich möglichen Schritte.
Denn bisher könnte man auf die Idee kommen mit schritt++ einfach einen weiter zu gehen, was wegen des fehlenden default: Zweigs zu einem Problem werden könnte.
Ebenso wird eine Initialisierung/Zuweisung, z.B. so: schritt = PI; nicht unterbunden
Ansonsten finde ich die Idee, die Schritte auf byte zu begrenzen zu wollen voll OK.
Die magische Null bei der Initialisierung darf auch unterbunden werden.

Die Verbesserung findet sich im folgenden.
a. schritt und alles damit zusammenhängende, auf 8 Bit begrenzt
b. schritt ist jetzt vollkommen Typesicher
c. das #define entsorgt, aber die Funktionalität nicht verändert
d. ein paar Nullen bei der Konstruktorinitialisierungsliste hinzugefügt(Kosmetik(?!))

constexpr uint32_t LEDSCHALTZEIT = 1000;

class Taster
{
 private:
   enum class Schritt:byte {WARTEN, MINZEIT, LEDZEIT};
   const byte tasterPin, ledPin;
   const uint32_t tastMinzeit, ledAn;
   uint32_t tastMillis, ledMillis;
   bool tastNeu, tastAlt;
   Schritt schritt;
 public:
   Taster(const byte tasterPin, const byte ledPin, const uint32_t tastMinzeit):
     tasterPin(tasterPin), ledPin(ledPin), tastMinzeit(tastMinzeit), ledAn(LEDSCHALTZEIT), tastMillis(0), ledMillis(0), tastNeu(0), tastAlt(0), schritt(Schritt::WARTEN) {}

void init() //Initialisierung
   {
     digitalWrite(ledPin, HIGH);
     pinMode (ledPin, OUTPUT);
     pinMode (tasterPin, INPUT_PULLUP);
     tastAlt = digitalRead(tasterPin);
   }

void run()
   {
     uint32_t jetzt = millis();
     tastAlt = tastNeu;
     tastNeu = digitalRead(tasterPin);
     switch (schritt)
     {         case Schritt::WARTEN:
         if (tastAlt && !tastNeu)
         {
           tastMillis = jetzt;
           schritt = Schritt::MINZEIT;
         }
         break;
       case Schritt::MINZEIT:
         if ((jetzt - tastMillis >= tastMinzeit))
         {
           if (!tastNeu)
           {
             digitalWrite(ledPin, LOW);
             ledMillis = jetzt;
             schritt = Schritt::LEDZEIT;
           } else {
             schritt = Schritt::WARTEN;
           }
         }
         break;
       case Schritt::LEDZEIT:
         if (jetzt - ledMillis >= ledAn)
         {
           digitalWrite(ledPin, HIGH);
           schritt = Schritt::WARTEN;
         }
         break;
     }
   }
};

Taster taster
{ //tasterPin, ledPin, tastMinzeit
 {         2,      9,         30}, // gelb
 {         3,     10,         30}, // rot
 {         4,     11,         30}, // gruen
 {         5,     12,         30}, // blau
 {         6,     13,       2000}  // weiß
};

void setup()
{
 for (Taster &t : taster) t.init();
}

void loop()
{
 for (Taster &t : taster) t.run();
}




Wie man sieht, keine Welt bewegenden Änderungen .....
Im Grunde alles beim alten.

hallo liebe gemeinde, :smiley:

am Wochenende hatte ich nun endlich wieder mal zeit für mein Projekt. ;D ich habe es soweit fertig gestellt. 8)
Nur ist mir beim testen aufgefallen das beim Start des UNOs immer erstmal alle LEDs auf High sind und sie erst auf low geschalten werden wenn ich die tasten der jeweiligen led für die TastMinzeit betätige.
so als müsste man erst alles initialisieren. :astonished:
leider erschließt sich mir aus dem Sketch nicht warum dies so ist!? :slightly_frowning_face:
Hat jemand Tipps?

vielen dank im voraus :wink:

(deleted)

combie:
Ich habe mir das mal aufmerksam angesehen.
...
Im Grunde alles beim alten.

Danke!

Kürzlich suchte ich nach "enum class", jetzt habe ich es wiedergefunden. Dann will ich mal hoffen, beim nächsten Mal werde ich erneut fündig, ich wollte es eigentlich in meinen Standard übernehmen.