Hallo zusammen, ich bin wieder dabei einen Tonuino zu basteln. Es wird wieder einer nach dem klassischen Layout mit diversen Zusätzen wie z.B. der Pololulu Switch zum Ein- und Ausschalten. Hierbei benutze ich den Play Button zum Einschalten. Die Software ist eine angepasste Version von @Thomas-Lehnert. Hier versuche ich eine Funktion zum Ausschalten des Tonuinos per längerem Tastendruck auf den Play Knopf zu realisieren. Folgenden Code habe ich für den Play-Knopf:
// ******************* Pause Taste ****************************************************
if (pauseButton.wasReleased()) // wenn Pausetaste gedrückt wurde
{
if (activeModifier != NULL) // wenn Modifikation aktiv
if (activeModifier->handlePause() == true) // wenn akt.Modifikation pause Taste sperrt
return; // Abbrechen
if (ignorePauseButton == false) // Wenn Taste gelesen
if (isPlaying()) // wenn Wiedergabe
{
mp3.pause(); // Pause der Wiedergabe
setstandbyTimer();
}
else if (knownCard) // wenn keine Wiedergabe läuft und karte bekannt
{
mp3.start(); // Wiedergabe starten
disablestandbyTimer();
}
ignorePauseButton = false; // Pausetaste auswerten
}
else if (pauseButton.pressedFor(LONG_PRESS)
&& ignorePauseButton == false) // Langer Druck Pausetaste für Ansage des aktuellen Tracks
{
if (activeModifier != NULL) // wenn Modifikationskarte aktiv
if (activeModifier->handlePause() == true) // wenn Pausetaste gesperrt - Abbruch
return;
if (isPlaying()) // wenn Wiedergabe läuft
{
uint8_t advertTrack = queue[currentQueueIndex]; // Auslesen der Tracknummer für Ansage Tracknr
// Spezialmodus Von-Bis für Album und Party gibt die Dateinummer relativ zur Startposition wieder
if (myFolder->mode == 8 || myFolder->mode == 9) // Spezialmodus Album oder Spezialmodus Party
{
advertTrack = advertTrack - myFolder->special + 1; // Ansage auf relative Track Nr
}
//************ Rücksetzen - Hörbuch auf Anfang ****************************
// Im Hörbuchmodus wird durch langen Druck Pause Taste der Fortschritt auf Anfang gesetzt
#ifdef HB_Reset
if (myFolder->mode == 5) // Hörbuchmodus
{
currentQueueIndex = 1; // aktueller Track auf 1 setzen
advertTrack = currentQueueIndex; // Ansage auf aktueller Track
mp3.playAdvertisement(advertTrack); // Tracknummer ansagen
#ifndef AiO
EEPROM.update(myFolder->folder, currentQueueIndex); // Track 1 im EEProm speichern
#endif
#ifdef AiO
EEPROM_update(myFolder->folder, currentQueueIndex); // Track 1 im EEProm speichern
#endif
#ifdef DEBUG
Serial.println(F("Hörbuch Modus -> Anfang"));
#endif
mp3.playFolderTrack(myFolder->folder, currentQueueIndex); // aktuellen Track spielen
}
#endif
//************** Ende, Rücksetzen - Hörbuch auf Anfang ***********************
else // alle anderen Abspielmodi
{
mp3.playAdvertisement(advertTrack); // Tracknummer ansagen
}
}
else // wenn keine Wiedergabe läuft
{
playShortCut(0); // Shortcut Pausetaste spielen
}
ignorePauseButton = true; // PauseTaste übergehen
}
#ifdef PUSH_ON_OFF
else if (pauseButton.pressedFor(LONGER_PRESS) &&
ignorePauseButton == true) {
ignorePauseButton = false; // Pausetaste auswerten
ShutDown();
}
#endif
// *********** Ende Pausetaste *************************************************
Das was ich hinzugefügt habe kommt nach #ifdef PUSH_ON_OFF. Eigentlich funktioniert es soweit fast immer. Manchmal kommt der Tonuino allerdings in einen Zustand wo keine Knöpfe mehr funktionieren, so dass nur ein Reset Abhilfe schafft. Hat einer vielleicht eine Idee wie ich das besser umsetzen kann? Es sollten folgende Sachen funktionieren:
Kurzer Druck: Wiedergabe Pausieren (wie gehabt)
Langer Druck (etwa 1 Sekunde): Ansage der aktuellen Tracknummer
Längerer Druck (etwa 3 Sekunden): Der Tonuino soll ausgeschaltet werden, dabei soll die Trackansage nicht ausgeführt werden
Man muss sich hier was einfallen lassen, wie der Tonuino den Longpress und den longerpress unterscheiden soll. Man muss also ausschließen, dass ein longerpress vorher schon als Longpress interpretiert wird und die entsprechende Aktion verhindern. Eventuell könnte man hier die millis() Funktion verwenden und den Zeitpunkt des Loslassen der Taste auswerten. Allerdings verzögert das natürlich die Ausführung der Aktion bei Longpress, weil man erst abwarten müsste, ob die Taste länger gedrückt bleibt, als bei Longpress vorgesehen. Zuzüglich einer Toleranzzeit, weil man die exakte longpresszeit nie exakt treffen wird.
Meiner Meinung nach, ist da eine Tastenkombination immer besser und zuverlässiger zu realisieren.
Wie könnte man die Auswertung, ob ein Long oder Longer Press realisieren, solange der Knopf gedrückt ist? Und die Ausführung der Aktion erst bei loslassen des Knopfes ausgeführt wird. Also wird zum Beispiel der Knopf Long gedrückt gehalten, dann die entsprechende Aktion ausführen. Wird allerdings der Knopf Longer gehalten, sollte die Long Aktion ignoriert werden und dann bei Loslassen des Knopfes die Longer Aktion ausgeführt werden. Ich weiß nicht genau wie man sowas programmiertechnisch umsetzen kann.
Zurzeit wird bei Longerpress die Trackansage ausgeführt und anschließend wird der Tonuino ausgemacht. Wäre ja ok, wenn es nicht manchmal zu Komplikationen (Absturz des Tonuino) führt.
Bin etwas überfragt mit der Programmierung, würde es sehr gerne so umsetzen wollen…
Also ich hab für unseren tonuino mit @Thomas-Lehnert Always Queue auch eine Taste zum ein und ausschalten definiert allerdings die vor Taste da ich den Rotary encoder verwende und ich das mit dem Teil nicht hinbekomme.
Das Ausschalten läuft auch über longer_press
Allerdings wird dadurch manchmal erst long_press und dann erst longer_press ausgeführt
Ich bin aktuell etwas überfordert mit der Umsetzung des Vorschlags. Das klingt aber logisch, was du da meinst. Hast du evtl einen Tipp wie ich die Abfragen einbauen kann?
Hallo @marco-117, ich habe deinen Vorschlag mal versucht in den Code zu implementieren. Hier die aktuelle Version:
// ******************* Pause Taste ****************************************************
if (pauseButton.pressedFor(SHORT_PRESS)) // wenn Pausetaste gedrückt wurde
{
if (!pauseButton.isPressed())
{
if (activeModifier != NULL) // wenn Modifikation aktiv
if (activeModifier->handlePause() == true) // wenn akt.Modifikation pause Taste sperrt
return; // Abbrechen
if (ignorePauseButton == false) // Wenn Taste gelesen
if (isPlaying()) // wenn Wiedergabe
{
mp3.pause(); // Pause der Wiedergabe
setstandbyTimer();
}
else if (knownCard) // wenn keine Wiedergabe läuft und karte bekannt
{
mp3.start(); // Wiedergabe starten
disablestandbyTimer();
}
ignorePauseButton = false; // Pausetaste auswerten
}
}
if (pauseButton.pressedFor(LONG_PRESS)) // Langer Druck Pausetaste für Ansage des aktuellen Tracks
{
if (!pauseButton.isPressed())
{
if (activeModifier != NULL) // wenn Modifikationskarte aktiv
if (activeModifier->handlePause() == true) // wenn Pausetaste gesperrt - Abbruch
return;
if (isPlaying()) // wenn Wiedergabe läuft
{
uint8_t advertTrack = queue[currentQueueIndex]; // Auslesen der Tracknummer für Ansage Tracknr
// Spezialmodus Von-Bis für Album und Party gibt die Dateinummer relativ zur Startposition wieder
if (myFolder->mode == 8 || myFolder->mode == 9) // Spezialmodus Album oder Spezialmodus Party
{
advertTrack = advertTrack - myFolder->special + 1; // Ansage auf relative Track Nr
}
//************ Rücksetzen - Hörbuch auf Anfang ****************************
// Im Hörbuchmodus wird durch langen Druck Pause Taste der Fortschritt auf Anfang gesetzt
#ifdef HB_Reset
if (myFolder->mode == 5) // Hörbuchmodus
{
currentQueueIndex = 1; // aktueller Track auf 1 setzen
advertTrack = currentQueueIndex; // Ansage auf aktueller Track
mp3.playAdvertisement(advertTrack); // Tracknummer ansagen
#ifndef AiO
EEPROM.update(myFolder->folder, currentQueueIndex); // Track 1 im EEProm speichern
#endif
#ifdef AiO
EEPROM_update(myFolder->folder, currentQueueIndex); // Track 1 im EEProm speichern
#endif
#ifdef DEBUG
Serial.println(F("Hörbuch Modus -> Anfang"));
#endif
mp3.playFolderTrack(myFolder->folder, currentQueueIndex); // aktuellen Track spielen
}
#endif
//************** Ende, Rücksetzen - Hörbuch auf Anfang ***********************
else // alle anderen Abspielmodi
{
mp3.playAdvertisement(advertTrack); // Tracknummer ansagen
}
}
else // wenn keine Wiedergabe läuft
{
playShortCut(0); // Shortcut Pausetaste spielen
}
ignorePauseButton = true; // PauseTaste übergehen
}
}
#ifdef PUSH_ON_OFF
if (pauseButton.pressedFor(LONGER_PRESS))
{
ShutDown();
}
#endif
// *********** Ende Pausetaste *************************************************
Irgendwie funktioniert es noch nicht so richtig. Das Ausschalten läuft. Die anderen beiden Abfragen (SHORT bzw. LONG Press) funktionieren irgendwie noch nicht, keine Reaktion. Was müsste im Code noch angepasst werden?
Hallo zusammen, ich habe etwas recherchiert und eine Möglichkeit gefunden mehr als zwei Funktionen über einen Taster sauber auszuführen. Das ganze arbeitet, wie @Thomas-Lehnert auch vorgeschlagen hat, mit der millis Funktion. Fragt mich allerdings nicht genau wie es funktioniert. Folgendes wird ausgeführt:
Kurzer Tastendruck: Pause/Play
Doppeldruck: Ansage des aktuellen Tracks
Langer Druck (zwischen 3 und 8 Sekunden): Ausschalten des Tonuino (ohne Ansage des Tracks)
Bei dem Langen Druck musste die maximale Zeit begrenzt werden (daher 8 Sekunden), da beim Verlassen des Adminmenüs der Tonuino sonst ausgemacht wurde.
Das ist der Code:
// Deklaration von Variablen:
#define LONGER_PRESS 3000 // längerer Druck >= 3 sekunden
// ---------------Zur Erkennung von Mehrfachfunktionen bei Druck auf Play-/Pausetaste-------------------
int lastButtonState = HIGH; // the previous reading from the input pin
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 25; // the debounce time; increase if the output flickers
bool buttonState = HIGH; // saving state of the switch
byte tapCounter; // for saving no. of times the switch is pressed
int timediff; // for saving the time in between each press and release of the switch
bool flag1, flag2; // just two variables
long double presstime, releasetime; // for saving millis at press and millis at release
// in der void loop () eintragen:
// ************** Vorbereitung zur Auswertung der Multifunktionen der Play-/Pausetaste ****************
int reading = digitalRead(ButtonPause);
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
}
}
//when button is pressed
if (buttonState == 0 && flag2 == 0)
{
presstime = millis(); //time from millis fn will save to presstime variable
flag1 = 0;
flag2 = 1;
tapCounter++; //tap counter will increase by 1
//delay(10); //for avoiding debouncing of the button
}
//when button is released
if (buttonState == 1 && flag1 == 0)
{
releasetime = millis(); //time from millis fn will be saved to releasetime var
flag1 = 1;
flag2 = 0;
timediff = releasetime - presstime; //here we find the time gap between press and release and stored to timediff var
//Serial.println(timediff);
//delay(10);
}
// *********** Ende der Vorbereitung zur Auswertung der Multifunktionen der Play-/Pausetaste *************
// ******************* Pause Taste ****************************************************
if ((millis() - presstime) > 300 && buttonState == 1) //wait for some time and if button is in release position
{
if (tapCounter == 1) //if tap counter is 1
{
if (timediff >= LONGER_PRESS && timediff < 8000) //if time diff is larger than LONGER_PRESS = 3s and lower than 8s then its a hold
{
//----fn to call when the button is hold----
#ifdef PUSH_ON_OFF
ShutDown(); // Tonuino Ausschalten
#endif
}
else if (timediff < 300) //if timediff is less than 300 then its a single tap
{
//----fn to call when the button is single taped----
if (activeModifier != NULL) // wenn Modifikation aktiv
if (activeModifier->handlePause() == true) // wenn akt.Modifikation pause Taste sperrt
return; // Abbrechen
if (isPlaying()) // wenn Wiedergabe
{
mp3.pause(); // Pause der Wiedergabe
setstandbyTimer();
}
else if (knownCard) // wenn keine Wiedergabe läuft und karte bekannt
{
mp3.start(); // Wiedergabe starten
disablestandbyTimer();
}
}
}
else if (tapCounter == 2 ) //if tapcounter is 2
{
//----fn to call when doubletap----
if (activeModifier != NULL) // wenn Modifikationskarte aktiv
if (activeModifier->handlePause() == true) // wenn Pausetaste gesperrt - Abbruch
return;
if (isPlaying()) // wenn Wiedergabe läuft
{
uint8_t advertTrack = queue[currentQueueIndex]; // Auslesen der Tracknummer für Ansage Tracknr
// Spezialmodus Von-Bis für Album und Party gibt die Dateinummer relativ zur Startposition wieder
if (myFolder->mode == 8 || myFolder->mode == 9) // Spezialmodus Album oder Spezialmodus Party
{
advertTrack = advertTrack - myFolder->special + 1; // Ansage auf relative Track Nr
}
//************ Rücksetzen - Hörbuch auf Anfang ****************************
// Im Hörbuchmodus wird durch langen Druck Pause Taste der Fortschritt auf Anfang gesetzt
#ifdef HB_Reset
if (myFolder->mode == 5) // Hörbuchmodus
{
currentQueueIndex = 1; // aktueller Track auf 1 setzen
advertTrack = currentQueueIndex; // Ansage auf aktueller Track
mp3.playAdvertisement(advertTrack); // Tracknummer ansagen
#ifndef AiO
EEPROM.update(myFolder->folder, currentQueueIndex); // Track 1 im EEProm speichern
#endif
#ifdef AiO
EEPROM_update(myFolder->folder, currentQueueIndex); // Track 1 im EEProm speichern
#endif
#ifdef DEBUG
Serial.println(F("Hörbuch Modus -> Anfang"));
#endif
mp3.playFolderTrack(myFolder->folder, currentQueueIndex); // aktuellen Track spielen
}
#endif
//************** Ende, Rücksetzen - Hörbuch auf Anfang ***********************
else // alle anderen Abspielmodi
{
mp3.playAdvertisement(advertTrack); // Tracknummer ansagen
}
}
else // wenn keine Wiedergabe läuft
{
playShortCut(0); // Shortcut Pausetaste spielen
}
}
tapCounter = 0;
}
lastButtonState = reading;
// *********** Ende Pausetaste *************************************************
Es funktioniert bisher recht gut. Man hätte sogar noch weitere Funktionen ausführen können. Zum Beispiel lässt sich ein Short Press und danach ein Hold als eine Tastenkombination oder ein Tripple-Druck realisieren.