Управление кнопкой с контролем повторного нажатия

Сильно не пинайте, давно не развлекался и уже всё забыл. Управляю люком авто в двух направлениях. сам люк двигается. Но встал в тупик на элементарном.
вырезал основное:

#define BUTTON1F 2
#define BUTTON1R 4
#define BUTTON_LONG_PRESS_TIME 800 //время длинного нажатия кнопки
#define STABILB 20 // время стабилизации дребезга контактов кнопок


bool isRun1 = false; // статус - мотор в движении
uint32_t testTime; // эмуляция мотора

//физическое состояние кнопки
enum ButtonResult {
	buttonNotPress,     //если кнопка не нажата
	button_shortPress,  //код короткого нажатия
	button_longPress    //код длинного нажатия
};

struct ButtonConfiguration {
	//состояние кнопки
	enum ButtonResult curent;
  //отпускание кнопки
  bool depressed;
  //блокировка состояния
  bool lock;
	//номер входа, к которому подключена кнопка
	uint8_t pin;
	//для измерения длительности нажатия
	uint32_t pressingTime;
};
//--------------------------------------------------
//для хранения параметров кнопки
struct ButtonConfiguration button1F = {
  .curent = buttonNotPress,
  .depressed = false,
  .lock = false,
  .pin = BUTTON1F,
  .pressingTime = 0
};
struct ButtonConfiguration button1R = {
  .curent = buttonNotPress,
  .depressed = false,
  .lock = false,
  .pin = BUTTON1R,
  .pressingTime = 0
};

void setup() {
	// входы кнопок
	pinMode(BUTTON1F, INPUT_PULLUP);
	pinMode(BUTTON1R, INPUT_PULLUP);
	//отладка
	Serial.begin(9600);
}

void ButtonCheck(struct ButtonConfiguration &button) {
	bool btnState = !digitalRead(button.pin); // читаем состояние пина и переворачиваем
	//если кнопка нажата
	if (btnState && button.curent == buttonNotPress && millis() - button.pressingTime > STABILB)
	{
		button.curent = button_shortPress;
		button.pressingTime = millis();
	}
	//если кнопка не нажата
	if (!btnState && button.curent != buttonNotPress && millis() - button.pressingTime > STABILB)
	{
		button.curent = buttonNotPress;
		button.pressingTime = millis();
	}
	// если нажата долго
	if (btnState && button.curent == button_shortPress && millis() - button.pressingTime > BUTTON_LONG_PRESS_TIME)
	{
		button.curent = button_longPress;
		//button->pressingTime = millis();
	}

  if(isRun1)
  {
    if ((button.depressed == false) && (button.curent == buttonNotPress))
    {
      Serial.print("test\tRun=");
      Serial.print(isRun1);
      Serial.print("\tbuttoncurent=");
      Serial.print(button.curent);
      Serial.print("\t1R=");
      Serial.print(button1R.curent);
      Serial.print("\t1F=");
      Serial.print(button1F.curent);
      Serial.print("\tdepressed=");
      Serial.print(button.depressed);
      Serial.print("\tb=");
      Serial.println(!digitalRead(button.pin));

      button.depressed = true;
    }
  }
}

void loop() {


	// читаем состояние кнопок
	ButtonCheck(button1F);
	ButtonCheck(button1R);

  if (button1F.curent == button_shortPress) 
  {
    if(!isRun1) Serial.println("run_front");
    isRun1 = true;
    testTime = millis();
  }
	else if (button1R.curent == button_shortPress) 
  {
    if(!isRun1) Serial.println("run_rear");
    isRun1 = true;
    testTime = millis();
  }

  if (isRun1 && millis() - testTime > 5000)
	{
    Serial.println("run_stop");
		isRun1 = false;
    button1R.depressed = false;
    button1F.depressed = false;		
	}
}

выхлоп от сюда

18:20:22.195 -> run_rear

18:20:22.195 -> test Run=1 buttoncurent=0 1R=1 1F=0 depressed=0 b=0

18:20:23.093 -> test Run=1 buttoncurent=0 1R=0 1F=0 depressed=0 b=0

18:20:28.113 -> run_stop

18:20:32.154 -> run_front

18:20:32.154 -> test Run=1 buttoncurent=0 1R=0 1F=1 depressed=0 b=0

18:20:32.828 -> test Run=1 buttoncurent=0 1R=0 1F=0 depressed=0 b=0

18:20:37.842 -> run_stop

видно, что кнопки отрабатывают верно. Нужен статус отпущенной кнопки во время движения. в связи чем пытаюсь реализовать со строки 75. И не понимаю что происходит:

  1. почему попадаю туда два раза( при нажатии и отпускании)?
    2)почему всегда возврат 0 в строке 82?

Первый раз Вы попадаете туда при нажатии в контексте “другой” (не нажатой) кнопки, а второй раз при отпускании в контексте “своей” кнопки. Я добавил кнопкам имена и поставил вывод имён, сами посмотрите (я заменил Ваши табуляции пробелами, на моём мониторе с табуляциями напряг).

Потому что при нажатии Вы печатаете это добро в контексте “другой” не нажатой кнопки, а при отпускании - в контексте своей, но уже отпущенной, т.е. когда там уже восстановилось в “нот пресс”.

Код с именами кнопок
#define BUTTON1F 2
#define BUTTON1R 4
#define BUTTON_LONG_PRESS_TIME 800 //время длинного нажатия кнопки
#define STABILB 20 // время стабилизации дребезга контактов кнопок


bool isRun1 = false; // статус - мотор в движении
uint32_t testTime; // эмуляция мотора

//физическое состояние кнопки
enum ButtonResult {
	buttonNotPress,     //если кнопка не нажата
	button_shortPress,  //код короткого нажатия
	button_longPress    //код длинного нажатия
};

struct ButtonConfiguration {
	const char * name;
	//состояние кнопки
	enum ButtonResult curent;
  //отпускание кнопки
  bool depressed;
  //блокировка состояния
  bool lock;
	//номер входа, к которому подключена кнопка
	uint8_t pin;
	//для измерения длительности нажатия
	uint32_t pressingTime;
};
//--------------------------------------------------
//для хранения параметров кнопки
struct ButtonConfiguration button1F = {
	.name = "BTN_F",
  .curent = buttonNotPress,
  .depressed = false,
  .lock = false,
  .pin = BUTTON1F,
  .pressingTime = 0
};
struct ButtonConfiguration button1R = {
	.name = "BTN_R",
  .curent = buttonNotPress,
  .depressed = false,
  .lock = false,
  .pin = BUTTON1R,
  .pressingTime = 0
};

void setup() {
	// входы кнопок
	pinMode(BUTTON1F, INPUT_PULLUP);
	pinMode(BUTTON1R, INPUT_PULLUP);
	//отладка
	Serial.begin(9600);
}

void ButtonCheck(struct ButtonConfiguration &button) {
	bool btnState = !digitalRead(button.pin); // читаем состояние пина и переворачиваем
	//если кнопка нажата
	if (btnState && button.curent == buttonNotPress && millis() - button.pressingTime > STABILB)
	{
		button.curent = button_shortPress;
		button.pressingTime = millis();
	}
	//если кнопка не нажата
	if (!btnState && button.curent != buttonNotPress && millis() - button.pressingTime > STABILB)
	{
		button.curent = buttonNotPress;
		button.pressingTime = millis();
	}
	// если нажата долго
	if (btnState && button.curent == button_shortPress && millis() - button.pressingTime > BUTTON_LONG_PRESS_TIME)
	{
		button.curent = button_longPress;
		//button->pressingTime = millis();
	}

  if(isRun1)
  {
    if ((button.depressed == false) && (button.curent == buttonNotPress))
    {
		Serial.print(button.name);
		Serial.print(": ");
      Serial.print("test Run=");
      Serial.print(isRun1);
      Serial.print(" buttoncurent=");
      Serial.print(button.curent);
      Serial.print(" 1R=");
      Serial.print(button1R.curent);
      Serial.print(" 1F=");
      Serial.print(button1F.curent);
      Serial.print(" depressed=");
      Serial.print(button.depressed);
      Serial.print(" b=");
      Serial.println(!digitalRead(button.pin));

      button.depressed = true;
    }
  }
}

void loop() {


	// читаем состояние кнопок
	ButtonCheck(button1F);
	ButtonCheck(button1R);

  if (button1F.curent == button_shortPress) 
  {
    if(!isRun1) Serial.println("run_front");
    isRun1 = true;
    testTime = millis();
  }
	else if (button1R.curent == button_shortPress) 
  {
    if(!isRun1) Serial.println("run_rear");
    isRun1 = true;
    testTime = millis();
  }

  if (isRun1 && millis() - testTime > 5000)
	{
    Serial.println("run_stop");
		isRun1 = false;
    button1R.depressed = false;
    button1F.depressed = false;		
	}
}

Спасибо большое, осознал.

Идеально работающие кнопки я делал в таймерном прерывании, причем дребезг убирался только при замыкании, тк у разомкнутой дребезга быть не может. Первое замыкание - сработка; ждем отпускания с таймером. Тогда кнопки быстрые.

А какая разница? Замыкание размыкание подпружиненного контакта с механической точки зрения процессы похожие. И дребезг похож.

Когда кнопка отпущена всегда 1. Когда нажата контакт может пропадать. В этом разница.

При размыкании копки дребезг такой же, а может ещё и хуже чем при замыкании в плане возникновения обратной эдс, если коммутируется индуктивная нагрузка. Следуя вашей логике в замкнутом состоянии всегда 0, что совершенно не связано с дребезгом.

Моя логика проверена годами, « Первое замыкание - сработка; ждем отпускания с таймером.» я же написал.

То есть: мы НЕ ждем надежного замыкания, сразу выдаем чо ЕстьНажатие.

А вот потом ждем размыкания: Если замкнуто - сброс таймера отжатия, ждем дальше.