Taste für verschiedene Funktionen verwenden

Ich verwende das Beispiel:

<ezButton.h>

Gibt es eine Möglichkeit nach Langem Druck, zB. in einer Schleife, mit mehreren kurzen Drücken eine Variable von 1-5 hochzuzählen, ohne dass die ursprüngliche Funktion des Tasters für kurzen Druck ausgeführt wird ?

Alternativ müsste ich einen zweiten Taster verwenden.

Klar!
In dem du die Taster Auswertungsroutinen zur Laufzeit austauscht!

Ein Beispiel aus meiner Wühlkiste, leicht für dich angepasst:




using FuncPtr = void (*)();


void verfahrenA()
{
  // hier auswerten
}


void verfahrenB()
{
   // hier auswerten
}




FuncPtr tasterAuswertung {nullptr};


void setup() 
{

}

void loop() 
{
 if(tasterAuswertung) tasterAuswertung();
 
 // tasterAuswertung = verfahrenA;
 // tasterAuswertung = verfahrenB;
 // tasterAuswertung = nullptr; // Auswertung abschalten
}

Danke combie, für die schnelle Antwort.
Es ist erst mein zweiter Sketch und ich werde mich morgen mal einlesen, wo und wie ich das in meinen Sketch einfügen kann.

Hallo,
du könntest auch die Funktion für kurze Drücke nutzen und da mittels einer Hilfsvariablen verzweigen und entscheiden was Du tust. Die Hilfsvariable setzt Du mit dem langen Drücken ( z.B Toggeln )

Du kannst Dir auch mal die "OneButton" Lib ansehen.

Ich denke da würde ich eine Statemachine draufwerfen...

Diagramm1

Genau!
(sach ich ja auch, nur mit anderen Worten)

Hello hardl

Herzlich Willkommen im weltbesten Arduino Forum.

Nehme zwei Timer. Einen Timer zum Entprellen der Taste und der zweite Timer macht ein Zeitfenster auf in dem die Anzahl der Tastenbedienungen gezählt werden.
Das geht am Besten mit einer Datenstruktur, in der du alle relevanten Daten wie Portpinadresse und die Timer ablegst.
Ein Dienstprogramm bearbeitet diese Datenstruktur und zählt die Tastenbedienungen.

Viel Spass und Erfolg beim Programmieren in C++.

Mit der OneButton Library sollte das eigentlich nur wenige Zeilen Code sein.
die Library ist hier gut beschrieben:
http://www.mathertel.de/Arduino/OneButtonLibrary.aspx

/*
  OneButon - several functions
  https://forum.arduino.cc/t/taste-fur-verschiedene-funktionen-verwenden/1115508

  2023-04-15 by noiasca
  to be deleted: 2023-06
  code in forum
*/


#include "OneButton.h"                              //we need the OneButton library

const uint8_t buttonPin = A0;

OneButton button(buttonPin, true, true);

void doA(){
 Serial.println(F("doA"));
}

void doB() {
  static uint8_t counter = 0;
  counter++;
  if (counter > 5) counter = 0;
  Serial.println(counter);
}

void setup() {
  Serial.begin(115200);
   button.attachClick(doA);
   button.attachLongPressStart(doB);
}

void loop() {
  button.tick();
}

Danke für die Vorschläge, speziell OneButton hat mich interessiert.
Das Beispielprogramm funktioniert einwandfrei.
Ich versuchte jetzt stundenlang diese Statemaschine in ein Programm einzubinden, aber dort stimmen die Tastendrücke nicht mehr.
Jetzt habe ich festgestellt, dass das Problem an
" sensors.requestTemperatures();" in Void loop() liegt.
Wenn ich diese Zeile entferne stimmt die Tastaturabfrage, sonst nicht.

Schau Dir mal in den Beispielen an, wie man den Sensor blockierungsfrei auslesen kann. (Stichwort sensors.setWaitForConversion(false))
Sonst wartet der je nach Auflösung bis 750 ms und in der Zeit reagiert er auf keine Taste.

Gruß Tommy

Du blockierst damit den Sketch.
Schau in die Example - DallasTemperature und dort waitfor conversation und waitforconversation 2

[@Tommy56 war nen ticken schneller :wink: ]

Danke für die Hinweise, das werde ich morgen umsetzen.
Heute geht nichts mehr in meinen Kopf.

Also, die Auswertung von OnButton funktioniert dank eurer Hilfe jetzt einwandfrei.
Mein Problem ist noch, wenn ich longPress aktiviere müsste die Hauptschleife gestoppt werden und ich würde gerne über 1 - 5 kurze click() die int-Variable Hysterese hochzählen und nach 5 Sekunden verlassen.

WelcheHauptschleifewillstDu stoppen? loop() ?
Wenn ja: das tut man nicht.

Es geht um einen Sketch, der die Pumpe in Abhängigkeit der Sonneneinstrahlung steuert und gut funktioniert.
Ein LCD-Display zeigt Temperaturen und Modus der Pumpe.
Die Taste ist auch für Dauer-Ein oder -Aus zuständig.
Ich möchte die Variable, die für die Hysterese zuständig ist, über Tastendruck
zwischen 1 und 5 verändern.
Mit OneButton klappt alles, aber wenn ich über langen Tastendruck verzweige und das Display lösche wird es wieder mit Temperatur usw. überschrieben und die Taste schaltet in der Hauptschleife ein oder aus.
Deshalb suchte ich z.B. nach einer Funktion, die loop() pausieren lässt und in der ich über die gleiche Taste die Variable ändere, um dann wieder in die Hauptschleife zurückzukehren.

Zeige doch mal Deinen Code!
Was denkst Du denn, wer sich da rein versetzen kann, was Du vor Dir auf dem Monitor siehst?
Alles was notwendig ist, wurde gesagt. Hilfestellung bei der Umsetzung geht nur, wenn hier bekannt ist wie das implemetiert werden kann.

Ist sicher nicht optimal strukturiert, aber für den zweiten Versuch bin ich zumindest ganz zufrieden. Ich habe gesehen, dass es einige Beispiele für Poolsteuerung gibt, aber alle passten nicht optimal und ich wollte das selbst mal probieren und auch einigermaßen verstehen. Es geht im Wesentlichen um "click lang schwarz" Es sind noch click-Verzweigungen und Serial.print() Zeilen drin, die ich löschen muß.

#include <ArduinoOTA.h>
#include "LiquidCrystal_I2C.h"
#include <ESP8266WiFi.h>
#include <ESP8266WiFiScan.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "OneButton.h"

#define ONE_WIRE_BUS D1
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

const char* ssid = "XXX";
const char* password = "XXX";
const char* mqtt_server = "xxx.xxx.xxx.xxx";
int TempPin = 5;
int SwEin = 13;
int SwAus = 12;
int LedPin = 14;
int Hyst = 3;
int MinDiff = 1;
float solar = 0;
float pool = 0;
float diff = 0;

OneButton e_button(13, true);
OneButton a_button(12, true);

LiquidCrystal_I2C lcd(0x27, 20, 4);

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {

  Serial.begin(115200);

  sensors.begin();
  
  lcd.init();
  lcd.backlight();
  
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
}
  ArduinoOTA.setHostname("xy");
  ArduinoOTA.setPassword("0");
  ArduinoOTA.begin();
  
  client.setServer(mqtt_server, 1883); 

  e_button.attachClick(click1);
  e_button.attachDoubleClick(doubleclick1);
  e_button.attachLongPressStart(longPressStart1);
  e_button.attachLongPressStop(longPressStop1);
  e_button.attachDuringLongPress(longPress1);

  a_button.attachClick(click2);
  a_button.attachDoubleClick(doubleclick2);
  a_button.attachLongPressStart(longPressStart2);
  a_button.attachLongPressStop(longPressStop2);
  a_button.attachDuringLongPress(longPress2);

  pinMode(TempPin, OUTPUT);
  pinMode(LedPin, OUTPUT);
  pinMode(SwEin, INPUT);
  pinMode(SwAus, INPUT);
 
  Automatik();
} // setup


void loop() {

  e_button.tick();
  a_button.tick();

  ArduinoOTA.handle();

  if (!client.connected()) {
    reconnect();
}

  client.loop();

  sensors.setWaitForConversion(false);  // makes it async
  sensors.requestTemperatures();
  sensors.setWaitForConversion(true);

  solar = sensors.getTempCByIndex(0);
  pool = sensors.getTempCByIndex(1); 

  char PoolTemp[TempPin];
  char SolarTemp[TempPin];
  char DiffTemp [10];
  char minddiff [1];
  char hysterese [1];

  diff = solar-pool;

  dtostrf(pool, 4, 1, PoolTemp);
  dtostrf(solar, 4, 1, SolarTemp);
  dtostrf(diff, 4, 1, DiffTemp);
  dtostrf(Hyst, 1, 0, hysterese);
  
  lcd.setCursor(0, 0);
  lcd.print("POOL : ");
  lcd.setCursor(14, 0);
  lcd.print(PoolTemp);
  client.publish("Pool", PoolTemp);
  client.publish("Solar", SolarTemp);
  client.publish("Diff", DiffTemp);
  client.publish("Hyst", hysterese);

  lcd.print("\337C");
  lcd.setCursor(0, 1);
  lcd.print("SOLAR : ");
  lcd.setCursor(14, 1);
  lcd.print(SolarTemp);
  lcd.print("\337C");
  lcd.setCursor(0, 2);
  lcd.print("DIFFERENZ : ");

  if (diff <= -10) {
    lcd.setCursor(12, 2);
  } else if (diff <= 0) {
    lcd.setCursor(12, 2);
    lcd.print(" ");
    lcd.setCursor(14, 2);
  } else if (diff >= 10) {
    lcd.setCursor(13, 2);
    lcd.print(" ");
    lcd.setCursor(14, 2);
  } else {
    lcd.setCursor(13, 2);
    lcd.print("  ");
    lcd.setCursor(14, 2);
  }
  lcd.print(DiffTemp);
  lcd.print("\337C");
  e_button.tick();
  a_button.tick();
} // Ende loop

//Tastendruck auswerten
// click schwarz 1x
void click1() {
digitalWrite(LedPin, HIGH);
Serial.println("schwarz ein");
lcd.setCursor(0, 3);
lcd.print("DAUER :          EIN");
  client.publish("Led", "true");
  client.publish("Modus", "ein");
}

// click schwarz 2x
void doubleclick1() {
Automatik();
} 

// click schwarz lang Start
void longPressStart1() {
} 

// click schwarz lang
void longPress1() {
   Serial.println("e_button longPress start");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Einschaltdifferenz ");
  static uint8_t counter = 0;
    counter ++;
    if (counter > 5) counter = 0;
      Serial.println(counter);    
}

// click schwarz lang Stop
void longPressStop1() {
  Serial.println("e_button longPress stop");
}

// Taste rot 
void click2() {
  Serial.println("rot ein");
  digitalWrite(LedPin, LOW);
  lcd.setCursor(0, 3);
  lcd.print("PUMPE :          AUS");
  client.publish("Led", "false");
  client.publish("Modus", "aus");
}

// Taste rot 2x
void doubleclick2() {
  Automatik();
}

// Taste rot lang Start
void longPressStart2() {
  Serial.println("a_button longPress start");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Ausschaltdifferenz ");
  lcd.setCursor(0, 1);
  lcd.print("Taster rot drücken");
}

// Taste rot lang
void longPress2() {
  Serial.println("a_button longPress...");
}

// Taste rot lang Stop
void longPressStop2() {
  Serial.println("a_button longPress stop");
      lcd.setCursor(0, 1);
      lcd.print("Taster schwarz lang stop  ");
}
void Automatik() {
  
  lcd.setCursor(0, 3);
  Serial.println("Auto ");

  if (diff >= Hyst) {
    lcd.print("Automatik :      EIN");
    digitalWrite(LedPin, HIGH);
    client.publish("Led", "true");
    client.publish("Modus", "auto_ein");
  } 
  else if (diff <= MinDiff) {
    digitalWrite(LedPin, LOW);
    lcd.print("Automatik :      AUS");
    client.publish("Led", "false");
    client.publish("Modus", "auto_aus");
    if (solar <= 0) {
      lcd.setCursor(0, 3);
      lcd.print("Frostschutz :    EIN");
      digitalWrite(LedPin, HIGH);
      client.publish("frost", "true");
      client.publish("Led", "true");
    } else {
      client.publish("frost", "false");
      client.publish("Led", "false");
    }  
  }
}

void reconnect() {
  while (!client.connected()) {
    String clientId = "ESP8266_DS18b20";
    if (client.connect(clientId.c_str())) {
    } else {
      delay(6000);
    }
  }
}

Hat sich erledigt.
Ich habe einen anderen Ansatz gewählt und den einen Taster zum Schalten und den anderen zum Ändern der Variablen gewählt.
Danke.

Och schade....
Dann war mein schöner 2 Zustandsautomat in #2 ja voll für die Katz.

Hi combie,
nicht ganz, denn ich hatte deinen Zusatzautomaten auch so eingepflegt und auch wieder etwas dazu gelernt.