Hilfe! Multifunktionstaster-Abfrage von jurs verstehen

Hallo zusammen,

habe hier im Forum eine MultifunktionsTaster-Abfrage con jurs entdeckt und habe dabei noch ein paar Verständniss Probleme. Um diese wissenslücken zu schließen würde ich euch gerne einige fragen zu stellen, wenn ich darf ;-))

// Tastenerkennung SHORTCLICK, DOUBLECLICK, LONGCLICK

#define INPUTMODE INPUT_PULLUP  // INPUT oder INPUT_PULLUP
#define PRELLZEIT 5             // Prellzeit in Millisekunden
#define SHORTCLICKTIME 250      // Längste Zeit für einen SHORTCLICK
#define DOUBLECLICKTIME 400     // Längste Zeit für den zweiten Klick beim DOUBLECLICK
#define LONGCLICKTIME 600       // Mindestzeit für einen LONGGLICK

byte buttonPins[]={2,3,A3}; // Arduino Pins (mehrere als Array möglich)

#define NUMBUTTONS sizeof(buttonPins)

byte buttonState[NUMBUTTONS];  // Aktueller Status des Buttons HIGH/LOW

enum {NONE, FIRSTDOWN, FIRSTUP, SHORTCLICK, DOUBLECLICK, LONGCLICK}; 

byte buttonResult[NUMBUTTONS]; // Aktueller Klickstatus der Buttons 

NONE/SHORTCLICK/LONGCLICK


void setup() {
  Serial.begin(9600);
  Serial.println("Button test");
  for (int i=0;i<NUMBUTTONS;i++) pinMode(buttonPins[i],INPUTMODE);
}


boolean eingabe()
// Rückgabewert false ==> Prellzeit läuft, Taster wurden nicht abgefragt
// Rückgabewert true ==> Taster wurden abgefragt und Status gesetzt
{
  static unsigned long lastRunTime;
  static unsigned long buttonDownTime[NUMBUTTONS];
  unsigned long now=millis();
  if (now-lastRunTime<PRELLZEIT) return false; // Prellzeit läuft noch
  lastRunTime=now;
  for (int i=0;i<NUMBUTTONS;i++)
  {
    byte curState=digitalRead(buttonPins[i]); 
    if (INPUTMODE==INPUT_PULLUP) curState=!curState; // Vertauschte Logik bei INPPUT_PULLUP
    if (buttonResult[i]>=SHORTCLICK) buttonResult[i]=NONE; // Letztes buttonResult löschen
    if (curState!=buttonState[i]) // Flankenwechsel am Button festgestellt
    {
      if (curState)   // Taster wird gedrückt, Zeit merken
      {
        if (buttonResult[i]==FIRSTUP && now-buttonDownTime[i]<DOUBLECLICKTIME)
          buttonResult[i]=DOUBLECLICK;
        else
        {  
          buttonDownTime[i]=now; 
          buttonResult[i]=FIRSTDOWN;
        } 
      }
      else  // Taster wird losgelassen
      {
        if (buttonResult[i]==FIRSTDOWN) buttonResult[i]=FIRSTUP;
        if (now-buttonDownTime[i]>=LONGCLICKTIME) buttonResult[i]=LONGCLICK;
      }
    }
    else // kein Flankenwechsel, Up/Down Status ist unverändert
    {
      if (buttonResult[i]==FIRSTUP && now-buttonDownTime[i]>DOUBLECLICKTIME) 
        buttonResult[i]=SHORTCLICK;
    }
    buttonState[i]=curState;
  } // for
  return true;
}


void verarbeitung()
{
  // dummy function 
}


void ausgabe()
// Klickstatus von geklickten Buttons mit Zeitstempel ausgeben
{
  for (int i=0;i<NUMBUTTONS;i++)
  {
    if (buttonResult[i]>=SHORTCLICK) // Ein Button wurde geklickt
    {
      Serial.print(millis()/1000.0,3); // Zeitstempel mit Millisekundenauflösung
      Serial.print("\tPin-");Serial.print(buttonPins[i]);
      if (buttonResult[i]==SHORTCLICK) Serial.println(" CLICK");
      else if(buttonResult[i]==DOUBLECLICK) Serial.println(" DOUBLE CLICK");
      else if(buttonResult[i]==LONGCLICK) Serial.println(" LONG CLICK");
    }
  }
}

void benchmark() {
  static unsigned long counterStartTime;
  static unsigned long counter;
  counter++;
  if (counter>=1000000L)
  {
    Serial.print("Average Time per loop(): ");
    Serial.print((micros()-counterStartTime)/1000000.0);
    Serial.println(" microseconds");
    counter=0;
    counterStartTime=micros();
  }
}


void loop() {
  if (eingabe())
  {
    verarbeitung();
    ausgabe();
  }
  benchmark();
}

In der boolean eingabe werden ja drei lolale Vorzeichenlose long-Variablen erstellt:

static unsigned long lastRunTime;
static unsigned long buttonDownTime[NUMBUTTONS];

Gehe ich richtig in der Annahme das diese beim erstellen den wert 0 haben

unsigned long now=millis();

Startet das Programm hier mit dem Zählen der Zeit?
Bzw. wie funktioniert dann diese Funktion?

if (now-lastRunTime<PRELLZEIT) return false; // Prellzeit läuft noch
lastRunTime=now;

Gruß Joe

Mein Tipp:
Leg den Code weg, wenn er zu kompliziert ist.
Es ist ein Zeichen dafür, dass du erst andere, einfachere Dinge lernen solltest.

Programmierern lernen ist wie eine Treppe.
Vielleicht 2 Stufen auf einmal, das mag gehen, aber keine 3, 4, oder gar 5 Stufen, mit einem Schritt.

unsigned long now=millis();

Startet das Programm hier mit dem Zählen der Zeit?
Bzw. wie funktioniert dann diese Funktion?

if (now-lastRunTime<PRELLZEIT) return false; // Prellzeit läuft noch
lastRunTime=now;

Du hast BlinkWihtoutDelay nicht gelesen, oder nicht verstanden.
Also nochmal lesen.

Danke für deine deine Hilfe und Geduld mit mir :confused:

und nein hatte ich in der Tat nicht gemacht, was ich aber nachgeholt habe ;-))

Jetzt denke ich auch das ich es verstehe, heißt solange nichts gedrückt wird ist now immer eine milli höher als lastRunTime und sobald ein Taster gedrückt wird, unabhängig von der Logik im Programm wird am ende return true; ausgegeben was dazu führt das für diesen Taster die Prellzeit ab läuft und anschließend die Logik!?

Oder?

Joe-muc:
... solange nichts gedrückt wird ist now immer eine milli höher als lastRunTime ...

Nö, der Taster wird nur alle paar Millisekunden abgefragt als Entprellung. Das Prinzip habe ich mir für meinen Sketch im anderen Thema abgeschaut, aber anders implementiert..

Joe-muc:
Gehe ich richtig in der Annahme das diese beim erstellen den wert 0 haben

Globale und statische Variablen werden automatisch mit 0 initialisiert. Nur nicht-statische lokale Variablen müssen per Hand initialisiert werden

Serenifly:
Globale und statische Variablen werden automatisch mit 0 initialisiert. Nur nicht-statische lokale Variablen müssen per Hand initialisiert werden

Genau deshalb initialisiere ich Variablen, egal, wo sie stehen. Mir zu merken, welche Sachen wo automatisch initialisiert werden, ist mir einfach zu blöd.

Gruß

Gregor

gregorss:
Mir zu merken, welche Sachen wo automatisch initialisiert werden, ist mir einfach zu blöd.

Das soll aber das Gehirn trainieren, heißt es. :wink:

HotSystems:
Das soll aber das Gehirn trainieren, heißt es. :wink:

Wenn es um „heißt es“ geht, geht es im Großen und Ganzen um beliebiges Zeug. Für's Hirntraining gibt es besseres :wink:

Gruß

Gregor

Es gibt halt Leute, deren Hirn kann sich das merken und andere Leute. :wink:

Gruß Tommy