Taster X Sekunden gedrückt

Ist ein Taster länger als X Sekunden gedrückt, führe den CODE aus.
Das ganze soll einfach mit delay, da sonst in der Zeit keine Funktionen ausgeführt werden.
Aber so geht es nicht :frowning:

//Funkionen
bool PosFlanke( bool input, bool &hilfsmerker)
{
  if ( input == true )                                              //wenn Input Wahr ist
  {             
     delay (10);                                                    //Warte 10ms
     if ( input == true )                                           //wenn Input immer noch Wahr ist führ den CODE aus
     {
        if ( input && !hilfsmerker )
        {                                                           //wenn Signal true und hilfsmerker false
          hilfsmerker = true;                                       //Zustand von Signal abspeichern
          return true;                                              //Funktion mit Rückgabe true verlssen
        }
      
        if (!input)
        {                                                           //wenn Signal false ist Hilfsmerker auch auf false setzten
          hilfsmerker = false;
        }
     }
  }
  return false;                                                     //Funktion mit Rückgabe false verlassen
}

Warum willst Du das nicht einfach mit millis machen?

Gruß Tommy

Das kann nicht funktionieren, wenn der Pin nicht als Input definiert wird.
Zumindest sehen wir das nicht und das ist schon ein Fehler.
Warum zeigst du uns nur ein Fragment ?

@Tommy wollte das nicht, da es nicht nötig ist. Das Programm kann ruhig stehen bleiben. Dachte es wäre etwas einfacher.

@HotSystem PIN ist ein Input. Der Code ist relative lang und ich wollte nur den Ausschnitt nehmen. Weil ich annehme das der Bereich nicht funktioniert.

Du musst aber immer noch die aktuelle Zeit mitkriegen. Daher ist es nicht gut das Programm einfach anzuhalten

  mcp1.pullUp    (Schalter_Rollo_1_runter, HIGH);                                                 //Pullup aktivieren
  mcp1.pullUp    (Schalter_Rollo_1_rauf,   HIGH);                                                 //Pullup aktivieren
 mcp1.pinMode   (Schalter_Rollo_1_runter, INPUT);                                                //als Eingang setzen
  mcp1.pinMode   (Schalter_Rollo_1_rauf,   INPUT);                                                //als Eingang setzen
void loop.....
Flanke_Schalter_Rollo_1_runter  = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_runter)),   HilfFlanke_Schalter_Rollo_1_runter);
Flanke_Schalter_Rollo_1_rauf    = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_rauf)),     HilfFlanke_Schalter_Rollo_1_rauf);
.....

Dann lasse ich die Funktion ausführen.

hd458:
@HotSystem PIN ist ein Input. Der Code ist relative lang und ich wollte nur den Ausschnitt nehmen. Weil ich annehme das der Bereich nicht funktioniert.

Damit wir eine Fehlersuche durchführen können, sollte es schon ein kompilierbarer Sketch sein, der auch definitionen und Setup/loop enthält. So ist das schlecht zu prüfen.
Du kannst den ja auf das wichtigste zusammenkürzen.

Lade mal den CODE hoch, aber bitte nicht gleich alles bemängeln.
Das ist nicht TOP, was ich da gemacht habe, aber grundsätzlich funktioniert es.

Die Funktion selber ist am Ende.

Rollos2.ino (33.5 KB)

Sorry, aber ich kann den Sketch mobil nicht lesen, muss also passen.

aber bitte nicht gleich alles bemängeln.

Wie wäre es mit einem Vorschlag?

Code auf ein Rollo reduziert.

#include <Wire.h>
#include <Adafruit_MCP23017.h>

//Adressierung MCP Module
const uint8_t         mcp1_ADDRESS = 0;                                                           //Adresse des mcp1 (Einstellen mit A0, A1, A2) / Codierung: 0, 0, 0  0
const uint8_t         mcp3_ADDRESS = 6;                                                           //Adresse des mcp3 (Einstellen mit A0, A1, A2) / Codierung: 0, 1, 1  6

//Ausgänge festlegen
const uint8_t         Relais_Rollo_1_rauf = 15;
const uint8_t         Relais_Rollo_1_runter = 14;
const uint8_t         Relais_Rollo_9_rauf = 15;
const uint8_t         Relais_Rollo_9_runter = 14;

//Eingänge festlegen
const uint8_t         Schalter_Rollo_1_rauf = 7;
const uint8_t         Schalter_Rollo_1_runter = 5;
const uint8_t         Schalter_Rollo_10_rauf = 2;
const uint8_t         Schalter_Rollo_10_runter = 0;

//Hilfsmerker
boolean               HilfFlanke_Schalter_Rollo_1_runter;
boolean               HilfFlanke_Schalter_Rollo_1_rauf;
boolean               HilfFlanke_Schalter_Rollo_10_runter;
boolean               HilfFlanke_Schalter_Rollo_10_rauf;

//Zeiit wie lange ein Relais max. angezogen hat
//Zeit festlegen in ms
//Vergleichswert für den TimerComparison(Startwert muss 0 sein)
const uint32_t        Rollo_1_TimerCounter           = 150000;
uint32_t              Rollo_1_TimerComparison        = 0;

//MCP23017 aktivieren
Adafruit_MCP23017 mcp1;
Adafruit_MCP23017 mcp3;

void setup()
{
  //Adressierung MCP Module
  mcp1.begin     (mcp1_ADDRESS);                                                                  //Adresse vom Modul 1 festlegen
  mcp3.begin     (mcp3_ADDRESS);                                                                  //Adresse vom Modul 3 festlegen

  //bei den Ausgängen den internen Pullup aktivieren
  mcp1.pullUp    (Schalter_Rollo_1_runter, HIGH);                                                 //Pullup aktivieren
  mcp1.pullUp    (Schalter_Rollo_1_rauf,   HIGH);                                                 //Pullup aktivieren
  mcp3.pullUp    (Schalter_Rollo_10_runter, HIGH);                                                //Pullup aktivieren
  mcp3.pullUp    (Schalter_Rollo_10_rauf,   HIGH);                                                //Pullup aktivieren
  
  //E/A als Ausgänge setzen
  mcp1.pinMode   (Relais_Rollo_1_runter,   OUTPUT);                                               //als Ausgang setzen
  mcp1.pinMode   (Relais_Rollo_1_rauf,     OUTPUT);                                               //als Ausgang setzen  

  //E/A als Eingänge setzen
  mcp1.pinMode   (Schalter_Rollo_1_runter, INPUT);                                                //als Eingang setzen
  mcp1.pinMode   (Schalter_Rollo_1_rauf,   INPUT);                                                //als Eingang setzen
  mcp3.pinMode   (Schalter_Rollo_10_runter, INPUT);                                               //als Eingang setzen
  mcp3.pinMode   (Schalter_Rollo_10_rauf,   INPUT);                                               //als Eingang setzen
}


void loop()
{
  //Taster auswerten
  boolean Flanke_Schalter_Rollo_1_runter  = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_runter)),   HilfFlanke_Schalter_Rollo_1_runter);
  boolean Flanke_Schalter_Rollo_1_rauf    = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_rauf)),     HilfFlanke_Schalter_Rollo_1_rauf);
  boolean Flanke_Schalter_Rollo_10_runter = PosFlanke((!mcp3.digitalRead(Schalter_Rollo_10_runter)),  HilfFlanke_Schalter_Rollo_10_runter);
  boolean Flanke_Schalter_Rollo_10_rauf   = PosFlanke((!mcp3.digitalRead(Schalter_Rollo_10_rauf)),    HilfFlanke_Schalter_Rollo_10_rauf);

  //Alle "Hilfsmerker" für "Alle_Rollo_X..." setzen
  boolean Alle_Rollo_1_runter             = Flanke_Schalter_Rollo_10_runter;
  boolean Alle_Rollo_1_rauf               = Flanke_Schalter_Rollo_10_rauf;

  //Flanke für "Flanke_Schalter_Rollo_10..." zurücksetzen
  Flanke_Schalter_Rollo_10_runter         = false;
  Flanke_Schalter_Rollo_10_rauf           = false;

  //***********************  Rollo 1 MCP1 ***************************************************************************************************************************************
  //Beide Ausgänge sind LOW und Eingang runter ist HIGH: Ausgang runter wird gestzt (Rollo startet)
  if ((Alle_Rollo_1_runter || Flanke_Schalter_Rollo_1_runter) && (mcp1.digitalRead(Relais_Rollo_1_runter) == LOW && mcp1.digitalRead(Relais_Rollo_1_rauf) == LOW))
  {
    mcp1.digitalWrite(Relais_Rollo_1_runter, HIGH);
    Flanke_Schalter_Rollo_1_runter = false;
    Alle_Rollo_1_runter = false;
    Rollo_1_TimerComparison = millis();
  }

  //Beide Ausgänge sind LOW und Eingang hoch ist HIGH: Ausgang hoch wird gestzt (Rollo startet)
  if ((Alle_Rollo_1_rauf ||Flanke_Schalter_Rollo_1_rauf) && (mcp1.digitalRead(Relais_Rollo_1_rauf) == LOW && mcp1.digitalRead(Relais_Rollo_1_runter) == LOW))
  {
    mcp1.digitalWrite(Relais_Rollo_1_rauf, HIGH);
    Flanke_Schalter_Rollo_1_rauf = false;
    Alle_Rollo_1_rauf = false;
    Rollo_1_TimerComparison = millis();
  }

  //Wenn einer der Ausgänge HIGH ist und einer der beiden Taster HIGH ist: Beide Ausgänge auf LOW setzen (Rollo stoppt)
  if ((Alle_Rollo_1_runter || Flanke_Schalter_Rollo_1_runter || Alle_Rollo_1_rauf || Flanke_Schalter_Rollo_1_rauf) && (mcp1.digitalRead(Relais_Rollo_1_runter) == HIGH || mcp1.digitalRead(Relais_Rollo_1_rauf) == HIGH))
  {
    mcp1.digitalWrite(Relais_Rollo_1_runter, LOW);
    Flanke_Schalter_Rollo_1_runter = false;
    Alle_Rollo_1_runter = false;
    mcp1.digitalWrite(Relais_Rollo_1_rauf, LOW);
    Flanke_Schalter_Rollo_1_rauf = false;
    Alle_Rollo_1_rauf = false;
    Rollo_1_TimerComparison = 0;
  }

  //interner Timer, wie lange das Rollo max. laufen darf
  if (millis() - Rollo_1_TimerComparison >= Rollo_1_TimerCounter)
  {
    Rollo_1_TimerComparison = millis();
    mcp1.digitalWrite(Relais_Rollo_1_runter, LOW);
    mcp1.digitalWrite(Relais_Rollo_1_rauf, LOW);
  } 
}

//Funkionen
bool PosFlanke( bool input, bool &hilfsmerker)
{
  if ( input == true )                                              //wenn Input Wahr ist
  {             
     delay (10);                                                    //Warte 10ms
     if ( input == true )                                           //wenn Input immer noch Wahr ist führ den CODE aus
     {
        if ( input && !hilfsmerker )
        {                                                           //wenn Signal true und hilfsmerker false
          hilfsmerker = true;                                       //Zustand von Signal abspeichern
          return true;                                              //Funktion mit Rückgabe true verlssen
        }
      
        if (!input)
        {                                                           //wenn Signal false ist Hilfsmerker auch auf false setzten
          hilfsmerker = false;
        }
     }
  }
  return false;                                                     //Funktion mit Rückgabe false verlassen
}

@combie habe ich doch gemacht?!

Wieso hast du Ausgangspins doppelt belegt ?

Hallo,
Den Taster liest Du ausserhalb der Funktion ein. Nach dem delay kann sich der Zustand doch nicht geändert haben, er wurde ja nicht mehr aktualisiert. Du willst die positive Flanke des Tasters erkennen und das gleichzeitig entprellen un das in einer Funktion. Dann nimm doch millis dazu.

const byte taster = 3;
bool hilfsmerker;
int count;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(taster, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:

 bool input = !digitalRead(taster);
  if (PosFlanke(input, hilfsmerker)) {
    count++;
    Serial.println(count);
  }

}

//Funkionen
bool PosFlanke( bool input, bool &hilfsmerker) {
  static uint32_t altzeit;

  if ( input && !hilfsmerker ) { //wenn Signal true und hilfsmerker false
    if (millis() - altzeit > 10) {
      hilfsmerker = true;                                       //Zustand von Signal abspeichern
      return true;  //Funktion mit Rückgabe true verlssen
    }
  }

  if (!input) { //wenn Signal false ist Hilfsmerker auch auf false setzten
    hilfsmerker = false;
    altzeit = millis();
  }
  return false;                                                     //Funktion mit Rückgabe false verlassen
}

Nachtrag:

habe gerade gesehen das Du die Funktion mehrfach benötigst. Dann solltest Du die Variable altzeit aus meinem Beispiel ausserhalb der Funktion speichern, Du benötigst dann mehrere variable dazu, und mit an die Funktion übergeben. Da Du Datenspeicher und Funktionalität benötigst würde sich eine Klasse anbieten.

ich darf auf mein kleines Tutorial verweisen link

Hi

Ich sehe in dem Versuch des Start-Post eigentlich 'nur' das Problem, daß dort der Pegel des Input-Pin an die Funktion übergeben wird.
Diese Variable wird sich aber NIE von Selber ändern - auch nicht nach einem 3 Stunden-delay();
Wenn Du der Funktion die Pin-Nummer übergibst und die Funktion SELBER den Pegel des Pin bei jeder der Abfragen frisch einliest, wird langsam ein Schuh draus.

Meiner Meinung ist hier der 'gesamte Code' nicht wirklich nötig - wobei man vll. DOCH zwischendurch auf eine Art NotAus klatschen können möchte und nicht erst zehn Sekunden zusehen MUSS, wie sich der Rollo gerade selber zerfleischt, weil irgend etwas im Weg lag und ich eben per delay() den Arduino blind im Kreis rennen lasse.

Mit millis() wäre Das nicht passiert (oder man hätte Es zumindest verhindern KÖNNEN)

MfG

Danke für die Antworten.

Ich habe von Sekunden geschrieben und meinte Millisekunden, wie im Beispiel von Post1 :frowning: Sorry

@Postmaster-ino ich glaube zu wissen was Du meinst, aber ich weiß nicht wie ich es um setzen kann.

@Renter
Ich habe es mal so versucht, aber das geht nicht. Weiß auch warum, aber nicht wie ich es anderes machen.

Die Zeit wird bei jedem Durchlauf wieder neu gesetzt.

//Entprellen                                                                                
static uint32_t Schalter_Rollo_1_runter_Time;
static uint32_t Schalter_Rollo_1_rauf_Time;
boolean Flanke_Schalter_Rollo_1_runter;
boolean Flanke_Schalter_Rollo_1_rauf;
void loop()
{
  //Taster auswerten
  if (!mcp1.digitalRead(Schalter_Rollo_1_runter) == true)
  {
    Schalter_Rollo_1_runter_Time = millis();
  }
  if (millis() - Schalter_Rollo_1_runter_Time > 10)
  {
    Flanke_Schalter_Rollo_1_runter  = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_runter)),   HilfFlanke_Schalter_Rollo_1_runter);
  }

  if (!mcp1.digitalRead(Schalter_Rollo_1_rauf) == true)
  {
    Schalter_Rollo_1_rauf_Time = millis();
  }
  if (millis() - Schalter_Rollo_1_rauf_Time > 10)
  {
    Flanke_Schalter_Rollo_1_rauf  = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_rauf)),   HilfFlanke_Schalter_Rollo_1_rauf);
  }

So geht es auch nicht, dachte das ich hier den PIN immer wieder neu abfrage.

  if (!mcp1.digitalRead(Schalter_Rollo_1_runter == true))
  {
    delay(10);
    if (!mcp1.digitalRead(Schalter_Rollo_1_runter == true))
    {
      Flanke_Schalter_Rollo_1_runter  = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_runter)),   HilfFlanke_Schalter_Rollo_1_runter); 
    }
  }
  
  if (!mcp1.digitalRead(Schalter_Rollo_1_rauf == true))
  {
    delay(10);
    if (!mcp1.digitalRead(Schalter_Rollo_1_rauf == true))
    {
      Flanke_Schalter_Rollo_1_rauf    = PosFlanke((!mcp1.digitalRead(Schalter_Rollo_1_rauf)),     HilfFlanke_Schalter_Rollo_1_rauf);
    }
  }
// falsch
if (!mcp1.digitalRead( if (!mcp1.digitalRead(Schalter_Rollo_1_runter == true))))
// besser
 if (!mcp1.digitalRead(Schalter_Rollo_1_runter) == true)
// oder
 if (!mcp1.digitalRead(Schalter_Rollo_1_runter)  // also bei LOW aktiv?

Schalter_Rollo_1_runter == true ist immer false, also 0 und was bringt Dir mcp1.digitalRead(0)?

Gruß Tommy

HotSystems:
Wieso hast du Ausgangspins doppelt belegt ?

Wo habe ich das ?