Hallo zusammen, wie bereits angedeutet, habe ich mich dem Thema Button angenommen. Ich habe mich bei meiner Box gegen einen Encoder entschieden und somit 5 Taster verbaut. Um die Box manuell in Sleepmodus zu schalten, wollte ich Multitaster 4+5 verwenden. Hier gab es dann leider ein paar Probleme und so habe ich mich durch das Programm gewurschtelt.
Ich habe folgende Anpassungen in Setting.h gemacht:
- Habe ich die Varibalen erweitert, so dass man unterscheiden kann, welche Funktion bei einem kurzem Tastendruck+loslassen, bei einem langem Tastendruck+loslassen und bei einem langen Tastendruck+ohne loslassen passieren soll. Das ganze für jeden einzelnen und für jede zweier Multitaster eingabe.
2
#define BUTTON_0_SHORT CMD_NEXTTRACK
#define BUTTON_1_SHORT CMD_PREVTRACK
#define BUTTON_2_SHORT CMD_PLAYPAUSE
#define BUTTON_3_SHORT CMD_NOTHING
#define BUTTON_4_SHORT CMD_VOLUMEDOWN
#define BUTTON_5_SHORT CMD_VOLUMEUP
#define BUTTON_MULTI_01_SHORT CMD_NOTHING //CMD_TOGGLE_WIFI_STATUS (disabled now to prevent children from unwanted WiFi-disable)
#define BUTTON_MULTI_02_SHORT CMD_NOTHING
#define BUTTON_MULTI_03_SHORT CMD_NOTHING
#define BUTTON_MULTI_04_SHORT CMD_NOTHING
#define BUTTON_MULTI_05_SHORT CMD_NOTHING
#define BUTTON_MULTI_12_SHORT CMD_NOTHING
#define BUTTON_MULTI_13_SHORT CMD_NOTHING
#define BUTTON_MULTI_14_SHORT CMD_NOTHING
#define BUTTON_MULTI_15_SHORT CMD_NOTHING
#define BUTTON_MULTI_23_SHORT CMD_NOTHING
#define BUTTON_MULTI_24_SHORT CMD_NOTHING
#define BUTTON_MULTI_25_SHORT CMD_NOTHING
#define BUTTON_MULTI_34_SHORT CMD_NOTHING
#define BUTTON_MULTI_35_SHORT CMD_NOTHING
#define BUTTON_MULTI_45_SHORT CMD_NOTHING
#define BUTTON_0_LONG CMD_NOTHING
#define BUTTON_1_LONG CMD_NOTHING
#define BUTTON_2_LONG CMD_NOTHING
#define BUTTON_3_LONG CMD_NOTHING
#define BUTTON_4_LONG CMD_VOLUMEDOWN
#define BUTTON_5_LONG CMD_VOLUMEUP
#define BUTTON_0_LONG_Release CMD_NOTHING
#define BUTTON_1_LONG_Release CMD_NOTHING
#define BUTTON_2_LONG_Release CMD_NOTHING
#define BUTTON_3_LONG_Release CMD_NOTHING
#define BUTTON_4_LONG_Release CMD_NOTHING
#define BUTTON_5_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_01_LONG CMD_MEASUREBATTERY //CMD_TOGGLE_WIFI_STATUS (disabled now to prevent children from unwanted WiFi-disable)
#define BUTTON_MULTI_02_LONG CMD_NOTHING
#define BUTTON_MULTI_03_LONG CMD_NOTHING
#define BUTTON_MULTI_04_LONG CMD_NOTHING
#define BUTTON_MULTI_05_LONG CMD_NOTHING
#define BUTTON_MULTI_12_LONG CMD_NOTHING
#define BUTTON_MULTI_13_LONG CMD_NOTHING
#define BUTTON_MULTI_14_LONG CMD_NOTHING
#define BUTTON_MULTI_15_LONG CMD_NOTHING
#define BUTTON_MULTI_23_LONG CMD_NOTHING
#define BUTTON_MULTI_24_LONG CMD_NOTHING
#define BUTTON_MULTI_25_LONG CMD_NOTHING
#define BUTTON_MULTI_34_LONG CMD_NOTHING
#define BUTTON_MULTI_35_LONG CMD_NOTHING
#define BUTTON_MULTI_45_LONG CMD_NOTHING
#define BUTTON_MULTI_01_LONG_Release CMD_NOTHING //CMD_TOGGLE_WIFI_STATUS (disabled now to prevent children from unwanted WiFi-disable)
#define BUTTON_MULTI_02_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_03_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_04_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_05_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_12_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_13_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_14_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_15_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_23_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_24_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_25_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_34_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_35_LONG_Release CMD_NOTHING
#define BUTTON_MULTI_45_LONG_Release CMD_SLEEPMODE
- Habe ich die Zeitvariablen etwas umbenannt und erweitert.
buttonDebounceInterval : ist wie gebt die Zeit um die Taster zu entprellen
buttonDelayLastButtonState : ist die Zeit, in der man bei einem Multitaster+loslassen die Taster gleichzeitig loslassen muss
intervalToLongPress: ist die Zeit, ab wann es ein langer Tasterdruck ist.
intervalToLongPressRepeat: ist es ein langer Tasterdruck, wird die Funktion in dieser Zeit wiederholt ausgeführt. Dies ist praktisch, um z.B. die Lautstärke zu erhöhen.
constexpr uint8_t buttonDebounceInterval = 20; // Interval in ms to software-debounce buttons
constexpr uint16_t buttonDelayLastButtonState = 1000; // Interval in ms to software-debounce buttons
constexpr uint16_t intervalToLongPress = 2000; // Interval in ms to distinguish between short and long press of buttons
constexpr uint16_t intervalToLongPressRepeat = 100; // Interval in ms to distinguish between short and long press of buttons
Button.cpp
Hier habe ich natürlich recht viel angepasst. Im wesentlichen habe ich den Code von vorher übernommen und angepasst. Die Zeit wird sich beim Tastendruck gemerkt usw.
#include <Arduino.h>
#include "settings.h"
#include "Button.h"
#include "Cmd.h"
#include "Log.h"
#include "Port.h"
#include "System.h"
bool gButtonInitComplete = false;
// Only enable those buttons that are not disabled (99 or >115)
// 0 -> 39: GPIOs
// 100 -> 115: Port-expander
#if (NEXT_BUTTON >= 0 && NEXT_BUTTON <= MAX_GPIO)
#define BUTTON_0_ENABLE
#elif (NEXT_BUTTON >= 100 && NEXT_BUTTON <= 115)
#define EXPANDER_0_ENABLE
#endif
#if (PREVIOUS_BUTTON >= 0 && PREVIOUS_BUTTON <= MAX_GPIO)
#define BUTTON_1_ENABLE
#elif (PREVIOUS_BUTTON >= 100 && PREVIOUS_BUTTON <= 115)
#define EXPANDER_1_ENABLE
#endif
#if (PAUSEPLAY_BUTTON >= 0 && PAUSEPLAY_BUTTON <= MAX_GPIO)
#define BUTTON_2_ENABLE
#elif (PAUSEPLAY_BUTTON >= 100 && PAUSEPLAY_BUTTON <= 115)
#define EXPANDER_2_ENABLE
#endif
#if (ROTARYENCODER_BUTTON >= 0 && ROTARYENCODER_BUTTON <= MAX_GPIO)
#define BUTTON_3_ENABLE
#elif (ROTARYENCODER_BUTTON >= 100 && ROTARYENCODER_BUTTON <= 115)
#define EXPANDER_3_ENABLE
#endif
#if (BUTTON_4 >= 0 && BUTTON_4 <= MAX_GPIO)
#define BUTTON_4_ENABLE
#elif (BUTTON_4 >= 100 && BUTTON_4 <= 115)
#define EXPANDER_4_ENABLE
#endif
#if (BUTTON_5 >= 0 && BUTTON_5 <= MAX_GPIO)
#define BUTTON_5_ENABLE
#elif (BUTTON_5 >= 100 && BUTTON_5 <= 115)
#define EXPANDER_5_ENABLE
#endif
t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
bool gShutdownCurrentState;
bool AllButtonsReleased;
bool AllButtonsReleasedLast;
unsigned long gShutdownPressedTimestamp;
#ifdef PORT_EXPANDER_ENABLE
extern bool Port_AllowReadFromPortExpander;
#endif
static volatile SemaphoreHandle_t Button_TimerSemaphore;
hw_timer_t *Button_Timer = NULL;
static void IRAM_ATTR onTimer();
static void Button_DoButtonActions(void);
void Button_Init() {
#if (WAKEUP_BUTTON >= 0 && WAKEUP_BUTTON <= MAX_GPIO)
if (ESP_ERR_INVALID_ARG == esp_sleep_enable_ext0_wakeup((gpio_num_t) WAKEUP_BUTTON, 0)) {
Log_Printf(LOGLEVEL_ERROR, wrongWakeUpGpio, WAKEUP_BUTTON);
}
#endif
// Activate internal pullups for all enabled buttons connected to GPIOs
#ifdef BUTTON_0_ENABLE
if (BUTTON_0_ACTIVE_STATE) {
pinMode(NEXT_BUTTON, INPUT);
} else {
pinMode(NEXT_BUTTON, INPUT_PULLUP);
}
#endif
#ifdef BUTTON_1_ENABLE
if (BUTTON_1_ACTIVE_STATE) {
pinMode(PREVIOUS_BUTTON, INPUT);
} else {
pinMode(PREVIOUS_BUTTON, INPUT_PULLUP);
}
#endif
#ifdef BUTTON_2_ENABLE
if (BUTTON_2_ACTIVE_STATE) {
pinMode(PAUSEPLAY_BUTTON, INPUT);
} else {
pinMode(PAUSEPLAY_BUTTON, INPUT_PULLUP);
}
#endif
#ifdef BUTTON_3_ENABLE
if (BUTTON_3_ACTIVE_STATE) {
pinMode(ROTARYENCODER_BUTTON, INPUT);
} else {
pinMode(ROTARYENCODER_BUTTON, INPUT_PULLUP);
}
#endif
#ifdef BUTTON_4_ENABLE
if (BUTTON_4_ACTIVE_STATE) {
pinMode(BUTTON_4, INPUT);
} else {
pinMode(BUTTON_4, INPUT_PULLUP);
}
#endif
#ifdef BUTTON_5_ENABLE
if (BUTTON_5_ACTIVE_STATE) {
pinMode(BUTTON_5, INPUT);
} else {
pinMode(BUTTON_5, INPUT_PULLUP);
}
#endif
// Create 1000Hz-HW-Timer (currently only used for buttons)
Button_TimerSemaphore = xSemaphoreCreateBinary();
Button_Timer = timerBegin(0, 240, true); // Prescaler: CPU-clock in MHz
timerAttachInterrupt(Button_Timer, &onTimer, true);
timerAlarmWrite(Button_Timer, 10000, true); // 100 Hz
timerAlarmEnable(Button_Timer);
}
// If timer-semaphore is set, read buttons (unless controls are locked)
void Button_Cyclic() {
unsigned long currentTimestamp;
currentTimestamp = millis();
#ifdef PORT_EXPANDER_ENABLE
Port_Cyclic();
#endif
if (System_AreControlsLocked()) {
return;
}
gButtons[0].ActualStateIsPressed = false;
gButtons[1].ActualStateIsPressed = false;
gButtons[2].ActualStateIsPressed = false;
gButtons[3].ActualStateIsPressed = false;
gButtons[4].ActualStateIsPressed = false;
gButtons[5].ActualStateIsPressed = false;
// Buttons can be mixed between GPIO and port-expander.
// But at the same time only one of them can be for example NEXT_BUTTON
#if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
if(Port_Read(NEXT_BUTTON) ^ BUTTON_0_ACTIVE_STATE){
gButtons[0].ActualStateIsPressed = false;
}else{
gButtons[0].ActualStateIsPressed = true;
}
#endif
#if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
if(Port_Read(PREVIOUS_BUTTON) ^ BUTTON_1_ACTIVE_STATE){
gButtons[1].ActualStateIsPressed = false;
}else{
gButtons[1].ActualStateIsPressed = true;
}
#endif
#if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
if(Port_Read(PAUSEPLAY_BUTTON) ^ BUTTON_2_ACTIVE_STATE){
gButtons[2].ActualStateIsPressed = false;
}else{
gButtons[2].ActualStateIsPressed = true;
}
#endif
#if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
if(Port_Read(ROTARYENCODER_BUTTON) ^ BUTTON_3_ACTIVE_STATE){
gButtons[3].currentState = false;
}else{
gButtons[3].currentState = true;
}
#endif
#if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
if(Port_Read(BUTTON_4) ^ BUTTON_4_ACTIVE_STATE){
gButtons[4].ActualStateIsPressed = false;
}else{
gButtons[4].ActualStateIsPressed = true;
}
#endif
#if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
if(Port_Read(BUTTON_5) ^ BUTTON_5_ACTIVE_STATE){
gButtons[5].ActualStateIsPressed = false;
}else{
gButtons[5].ActualStateIsPressed = true;
}
#endif
AllButtonsReleased = true;
for (uint8_t i = 0; i < sizeof(gButtons) / sizeof(gButtons[0]); i++) {
if (gButtons[i].ActualStateIsPressed) {
AllButtonsReleased = false;
}
}
// Iterate over all buttons in struct-array
for (uint8_t i = 0; i < sizeof(gButtons) / sizeof(gButtons[0]); i++) {
gButtons[i].CommandPressedLong = false;
gButtons[i].CommandReleaseShort = false;
gButtons[i].CommandReleaseLong = false;
if (gButtons[i].ActualStateIsPressed != gButtons[i].ActualStateIsPressedLast ) {
if (gButtons[i].ActualStateIsPressed) { // is pressed
gButtons[i].PressedTimestamp = currentTimestamp;
gButtons[i].DelayRepeatTimestamp = currentTimestamp;
Log_Printf(LOGLEVEL_DEBUG, "tEST1. %d ", gButtons[i].PressedTimestamp);
Log_Printf(LOGLEVEL_DEBUG, "Pressed.%d",i);
} else { //is released
gButtons[i].ReleasedTimestamp = currentTimestamp;
gButtons[i].DelayRepeatTimestamp = currentTimestamp;
Log_Printf(LOGLEVEL_DEBUG, "tEST2. %d ", gButtons[i].ReleasedTimestamp);
Log_Printf(LOGLEVEL_DEBUG, "Released. %d",i);
}
}
gButtons[i].ActualStateIsPressedLast = gButtons[i].ActualStateIsPressed;
if (gButtons[i].ActualStateIsPressed) //remeber was pressed delayed
{
gButtons[i].DelayedActualStateIsPressed = true;
}else if (currentTimestamp > (gButtons[i].ReleasedTimestamp + buttonDelayLastButtonState + buttonDebounceInterval)){
gButtons[i].DelayedActualStateIsPressed = false;
}
if (gButtons[i].ActualStateIsPressed) //is pressed
{
//long Press detected
if ((currentTimestamp > (gButtons[i].PressedTimestamp + buttonDebounceInterval + intervalToLongPress))
&& (currentTimestamp > (gButtons[i].DelayRepeatTimestamp + buttonDebounceInterval + intervalToLongPressRepeat))) {
gButtons[i].CommandPressedLong = true;
gButtons[i].DelayRepeatTimestamp = currentTimestamp;
Log_Printf(LOGLEVEL_DEBUG, "CommandPressedLong. %d",i);
}
//Log_Printf(LOGLEVEL_DEBUG, "currentState. %d",i);
//Log_Printf(LOGLEVEL_DEBUG, "tEST3. %d ", (gButtons[i].PressedTimestamp + buttonDebounceInterval + intervalToLongPress));
//Log_Printf(LOGLEVEL_DEBUG, "tEST4. %d ", gButtons[i].ReleasedTimestamp);
}else if(AllButtonsReleasedLast != AllButtonsReleased && AllButtonsReleased){
//long Press detected
if (gButtons[i].ReleasedTimestamp > (gButtons[i].PressedTimestamp + buttonDebounceInterval + intervalToLongPress)) {
if(gButtons[i].DelayedActualStateIsPressed){
gButtons[i].CommandReleaseLong = true;
Log_Printf(LOGLEVEL_DEBUG, "CommandReleaseLong. %d",i);
}
}else
{
if(gButtons[i].DelayedActualStateIsPressed){
gButtons[i].CommandReleaseShort = true;
Log_Printf(LOGLEVEL_DEBUG, "CommandReleaseShort. %d",i);
}
}
}
}
for (uint8_t i = 0; i < sizeof(gButtons) / sizeof(gButtons[0]); i++) {
if(gButtons[i].CommandReleaseLong || gButtons[i].CommandReleaseShort || gButtons[i].CommandPressedLong){
Log_Println("call1", LOGLEVEL_NOTICE);
Button_DoButtonActions();
break;
}
}
AllButtonsReleasedLast = AllButtonsReleased;
gButtonInitComplete = true;
}
// Do corresponding actions for all buttons
void Button_DoButtonActions(void) {
uint8_t Cmd_Short = 0;
uint8_t Cmd_Long = 0;
Log_Println("call2", LOGLEVEL_NOTICE);
gShutdownCurrentState = false;
if(gButtons[0].ActualStateIsPressed)
{
if (gButtons[1].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_01_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[2].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_02_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[3].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_03_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[4].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_04_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[5].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_05_LONG_Release == CMD_SLEEPMODE;
}else{
gShutdownCurrentState = BUTTON_0_LONG_Release == CMD_SLEEPMODE;
}
if(gShutdownCurrentState){
gShutdownPressedTimestamp = gButtons[0].PressedTimestamp;
}
}else if(gButtons[1].ActualStateIsPressed)
{
if (gButtons[2].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_12_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[3].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_13_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[4].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_14_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[5].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_15_LONG_Release == CMD_SLEEPMODE;
}else{
gShutdownCurrentState = BUTTON_1_LONG_Release == CMD_SLEEPMODE;
}
if(gShutdownCurrentState){
gShutdownPressedTimestamp = gButtons[1].PressedTimestamp;
}
}else if(gButtons[2].ActualStateIsPressed)
{
if (gButtons[3].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_23_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[4].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_24_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[5].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_25_LONG_Release == CMD_SLEEPMODE;
}else{
gShutdownCurrentState = BUTTON_2_LONG_Release == CMD_SLEEPMODE;
}
if(gShutdownCurrentState){
gShutdownPressedTimestamp = gButtons[2].PressedTimestamp;
}
}else if(gButtons[3].ActualStateIsPressed)
{
if (gButtons[4].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_34_LONG_Release == CMD_SLEEPMODE;
}else if (gButtons[5].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_35_LONG_Release == CMD_SLEEPMODE;
}else{
gShutdownCurrentState = BUTTON_3_LONG_Release == CMD_SLEEPMODE;
}
if(gShutdownCurrentState){
gShutdownPressedTimestamp = gButtons[3].PressedTimestamp;
}
}else if(gButtons[4].ActualStateIsPressed)
{
if (gButtons[5].ActualStateIsPressed) {
gShutdownCurrentState = BUTTON_MULTI_45_LONG_Release == CMD_SLEEPMODE;
}else{
gShutdownCurrentState = BUTTON_4_LONG_Release == CMD_SLEEPMODE;
}
if(gShutdownCurrentState){
gShutdownPressedTimestamp = gButtons[4].PressedTimestamp;
}
}else if(gButtons[5].ActualStateIsPressed)
{
gShutdownCurrentState = BUTTON_4_LONG_Release == CMD_SLEEPMODE;
if(gShutdownCurrentState){
gShutdownPressedTimestamp = gButtons[5].PressedTimestamp;
}
}
//////////////////////////////////////////////////////////////////////////
//Long Push
//////////////////////////////////////////////////////////////////////////
if(gButtons[0].CommandPressedLong)
{
if (gButtons[1].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_01_LONG;
}else if (gButtons[2].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_02_LONG;
}else if (gButtons[3].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_03_LONG;
}else if (gButtons[4].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_04_LONG;
}else if (gButtons[5].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_05_LONG;
}else{
Cmd_Long = BUTTON_0_LONG;
}
}else if(gButtons[1].CommandPressedLong)
{
if (gButtons[2].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_12_LONG;
}else if (gButtons[3].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_13_LONG;
}else if (gButtons[4].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_14_LONG;
}else if (gButtons[5].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_15_LONG;
}else{
Cmd_Long = BUTTON_1_LONG;
}
}else if(gButtons[2].CommandPressedLong)
{
if (gButtons[3].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_23_LONG;
}else if (gButtons[4].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_24_LONG;
}else if (gButtons[5].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_25_LONG;
}else{
Cmd_Long = BUTTON_2_LONG;
}
}else if(gButtons[3].CommandPressedLong)
{
if (gButtons[4].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_34_LONG;
}else if (gButtons[5].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_35_LONG;
}else{
Cmd_Long = BUTTON_3_LONG;
}
}else if(gButtons[4].CommandPressedLong)
{
if (gButtons[5].ActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_45_LONG;
}else{
Cmd_Long = BUTTON_4_LONG;
}
}else if(gButtons[5].CommandPressedLong)
{
Cmd_Long = BUTTON_5_LONG;
}
//////////////////////////////////////////////////////////////////////////
//Short Command
//////////////////////////////////////////////////////////////////////////
if(gButtons[0].CommandReleaseShort)
{
if (gButtons[1].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_01_SHORT;
}else if (gButtons[2].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_02_SHORT;
}else if (gButtons[3].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_03_SHORT;
}else if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_04_SHORT;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_05_SHORT;
}else{
Cmd_Short = BUTTON_0_SHORT;
}
}else if(gButtons[1].CommandReleaseShort)
{
if (gButtons[2].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_12_SHORT;
}else if (gButtons[3].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_13_SHORT;
}else if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_14_SHORT;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_15_SHORT;
}else{
Cmd_Short = BUTTON_1_SHORT;
}
}else if(gButtons[2].CommandReleaseShort)
{
if (gButtons[3].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_23_SHORT;
}else if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_24_SHORT;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_25_SHORT;
}else{
Cmd_Short = BUTTON_2_SHORT;
}
}else if(gButtons[3].CommandReleaseShort)
{
if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_34_SHORT;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_35_SHORT;
}else{
Cmd_Short = BUTTON_3_SHORT;
}
}else if(gButtons[4].CommandReleaseShort)
{
if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Short = BUTTON_MULTI_45_SHORT;
}else{
Cmd_Short = BUTTON_4_SHORT;
}
}else if(gButtons[5].CommandReleaseShort)
{
Cmd_Short = BUTTON_5_SHORT;
}
//////////////////////////////////////////////////////////////////////////
//Long release Command
//////////////////////////////////////////////////////////////////////////
if(gButtons[0].CommandReleaseLong)
{
if (gButtons[1].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_01_LONG_Release;
}else if (gButtons[2].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_02_LONG_Release;
}else if (gButtons[3].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_03_LONG_Release;
}else if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_04_LONG_Release;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_05_LONG_Release;
}else{
Cmd_Long = BUTTON_0_LONG_Release;
}
}else if(gButtons[1].CommandReleaseLong)
{
if (gButtons[2].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_12_LONG_Release;
}else if (gButtons[3].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_13_LONG_Release;
}else if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_14_LONG_Release;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_15_LONG_Release;
}else{
Cmd_Long = BUTTON_1_LONG_Release;
}
}else if(gButtons[2].CommandReleaseLong)
{
if (gButtons[3].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_23_LONG_Release;
}else if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_24_LONG_Release;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_25_LONG_Release;
}else{
Cmd_Long = BUTTON_2_LONG_Release;
}
}else if(gButtons[3].CommandReleaseLong)
{
if (gButtons[4].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_34_LONG_Release;
}else if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_35_LONG_Release;
}else{
Cmd_Long = BUTTON_3_LONG_Release;
}
}else if(gButtons[4].CommandReleaseLong)
{
if (gButtons[5].DelayedActualStateIsPressed) {
Cmd_Long = BUTTON_MULTI_45_LONG_Release;
}else{
Cmd_Long = BUTTON_4_LONG_Release;
}
}else if(gButtons[5].CommandReleaseLong)
{
Cmd_Long = BUTTON_5_LONG_Release;
}
if(Cmd_Long>0)
{
Cmd_Action(Cmd_Long);
}
if(Cmd_Short>0)
{
Cmd_Action(Cmd_Short);
}
}
void IRAM_ATTR onTimer() {
xSemaphoreGiveFromISR(Button_TimerSemaphore, NULL);
}
Button.h
Hier habe ich teils Variablen umbenannt und weitere hinzugefügt:
Ich habe es einfach mal Kommentiert, hoffe man versteht die Variablen.
gShutdownCurrentState: Wird für die Animation benötigt Roter Kreis wird gefüllt
AllButtonsReleased: Ist dazu gekommen, da ich immer Drücken+loslassen immer auf alle Taster prüfe.
#pragma once
typedef struct {
bool CommandPressedLong : 1; //Befehl für langes Drücken+halten ausführen
bool CommandReleaseShort : 1; //Befehl für kurzes Drücken+loslassen ausführen
bool CommandReleaseLong : 1; //Befehl für langes Drücken+loslassen ausführen
bool ActualStateIsPressed :1; //aktuell wird der Taster gedrückt
bool DelayedActualStateIsPressed :1; //aktuell wird der Taster gedrückt oder wurde bereits losgelassen aber liegt noch in der Delay Zeit
bool ActualStateIsPressedLast: 1; //wurde im letzten Zyklus gedrückt
unsigned long PressedTimestamp; //Zeitstempel als der Taster gedrückt wurde
unsigned long ReleasedTimestamp; //Zeitstempel als der Taster losgelassen wurde
unsigned long DelayRepeatTimestamp; //Zeitstempel um die Funktion zu wiederholen
} t_button;
extern bool AllButtonsReleased; //Alle Taster wurden losgelassen
extern bool AllButtonsReleasedLast; //Im letzten Zyklus wurden alle Taster losgelassen
extern bool gShutdownCurrentState; //SleepModus wird vorraussichtlich aktiviert
extern unsigned long gShutdownPressedTimestamp; //Sleepmodus wird vorraussichtlich aktiviert Zeitstempel
extern bool gButtonInitComplete;
void Button_Init(void);
void Button_Cyclic(void);
LED.CPP
Hier habe ich im wesentlichen die Animation für den SleepModus angepasst.
Hier habe ich die Varibale gShutdownCurrentState hinzugefügt
// check indications and set led-mode
// this mode will then be animated if the priority and the current animation state fit
if (!LED_INDICATOR_IS_SET(LedIndicatorType::BootComplete)) {
nextAnimation = LedAnimationType::Boot;
} else if (gShutdownCurrentState) {
nextAnimation = LedAnimationType::Shutdown;
} else if (LED_INDICATOR_IS_SET(LedIndicatorType::Error)) {
LED_INDICATOR_CLEAR(LedIndicatorType::Error);
Und diese Funktion etwas umgebaut
AnimationReturnType Animation_Shutdown(const bool startNewAnimation, CRGBSet &leds) {
// return values
bool animationActive = true;
int32_t animationDelay = 0;
// static vars
static bool singleLedStatus = false;
static uint32_t animationIndex = 0;
if (startNewAnimation) {
animationIndex = 0;
}
if constexpr (NUM_INDICATOR_LEDS == 1) {
leds = CRGB::Black;
if (millis() - gShutdownPressedTimestamp <= intervalToLongPress) {
leds[0] = CRGB::Red;
animationDelay = 5;
} else {
if (singleLedStatus) {
leds[0] = CRGB::Red;
}
singleLedStatus = !singleLedStatus;
animationDelay = 50;
}
animationActive = false;
} else {
if (animationIndex == 0) {
leds = CRGB::Black;
}
if (animationIndex < leds.size()) {
leds[Led_Address(animationIndex)] = CRGB::Red;
animationDelay = intervalToLongPress / leds.size();
animationIndex++;
}else { // Wait a little
animationDelay = 20 * 100;
animationActive = false;
}
}
return AnimationReturnType(animationActive, animationDelay, true);
}
Ich denke ich habe noch weitere Anpassungen gemacht, aber dies sind die Wesentlichen.
Außerdem denke ich auch, dass ich bestimmt noch ein paar Denkfehler drin habe, habe mit dieser Programmierumgebung sozusagen 0 Erfahrung.
Da ich das ganze nicht wirklich debuggen konnte, habe ich das ganze immer mal wieder in der Console ausgegeben. Diese Codezeilen kann man natürlich ignorieren.
Soweit erstmal:-)
Bei Interesse, kann ich natürlich auch den ganzen Code bereitstellen.
Grüße
Felix