Класс кнопки, одновременное нажатие

Здравствуйте.
Не могу в классе сформулировать обращение к другому объекту класса,
в данном случае сделать проверку на нажатие другой кнопки. Чтобы отследить одновременное нажатие. Для примера накидал код:

#define BTN_PIN1 2
#define BTN_PIN2 3
#define BOUNCE 30

class Button {
  private:
   uint8_t _pin;
   bool cl;
   uint16_t pressTime;
   bool btnFlag = false;
   bool push = false;
  public:
  void set(uint8_t pin) {   //в setup()
   _pin = pin;
   pinMode(_pin,INPUT_PULLUP);}
  void read(){                      //в loop()
      cl = false;
    if(digitalRead(_pin)){
      btnFlag = true;
      }
    if(btnFlag){
      pressTime = millis();
      push = true;
      btnFlag = false;
      }
    if(push && millis()-pressTime>=BOUNCE) {
      push = false;
      cl = true;
      click();
      }
    }
  bool click(){return(cl);}
};
  Button Btn1;
  Button Btn2;
void setup() {
  Serial.begin(115200);
  Btn1.set(BTN_PIN1);
  Btn2.set(BTN_PIN2);}
void loop() {
  Btn1.read();
  Btn2.read();
  if(Btn1.click()){Serial.print(1);}
  if(Btn2.click()){Serial.print(2);}
}

Если пытаться сформулировать что-то вроде

void set(uint8_t pin, uint8_t pin2) {
   _pin = pin;
   _pin2 = pin2;
   pinMode(_pin,INPUT_PULLUP);
   pinMode(_pin2,INPUT_PULLUP);}
   if(digitalRead(_pin)&&digitalRead(_pin2)){

теряется смысл класса.

Если в основном цикле

  if(Btn1.click()&&Btn2.click()){

Не попасть в микросекунды проверки, да еще эти оба обрабатываются…
Как мне получить значение переменной из другого объекта этого же класса?

Создай метод типа “doublePressInit()” и передай через него ссылку на другой объект.

1 лайк

Вот это и хочу узнать, как. Указатель или ссылку надо, и на соседний объект, чтоб действующий не задевать…

Так что именно надо? Как записать указатель или ссылку?

Button  * otherObect; // указатель
Button  & otherObect; // ссылка

Только ссылку надо сразу инициализировать. Если Вы не в теме, проще обойтись указателем. Обращаться потом к методам через →

otherObject->set(......

Или другое надо?

1 лайк

Создайте класс-менеджер клавиатуры.

Методы обработки из классов кнопок вынесите в класс-менеджер.

В классе-менеджере разместите массив отслеживаемых кнопок.

В логике класса-менеджера реализуется обработка взаимной логики нескольких кнопок (одновременное нажатие, взаимная блокировка…) Классы кнопок обрабатывают только изолированные друг от друга алгоритмы (например, антидребезг, удержание, двойное нажатие…)

Функционал программы общается с кнопками через менеджер клавиатуры, сами кнопки наружу в код не торчат, сами ничем не управляют.

2 лайка

Здесь как я понимаю, требуется указать имя объекта. А если его пока нет? Например, если этот код в качестве библиотеки?

В таком случае вы нарушите принцип ООП, организуете горизонтальные связи. В такой реализации красивых архитектурных советов вам не дадут, любое решение будет корявое (хоть и рабочее) и не особо отличаться по стройности от любых предложенных лично вами ранее.

Лично я идеологически против обращений из кнопки в кнопку. Технически можно. А представьте у вас не 2, а 104 кнопки? Когда придумываете решение, прикиньте, как оно будет масштабироваться на случай увеличения количества элементов. Если легко, значит решение правильное. Если в задаче масштабирование не требуется, значит любое (работающее) решение правильное - не усложняй.

1 лайк

Может быть, можно обратиться ко всем остальным, массив создать? А то я пробовал внутри обращаться(ставить отдельный флаг внутри метода)- он и самого себя тоже считает, насколько я понял.

Зачем? Если бы у Вас было имя, то нахрена бы Вам нужен был указатель или ссылка?

Ну, как-то так:

class Kaka {
private:
	Kaka * pOther = nullptr;

public:

	void setOtherObject(Kaka * other) {
		pOther = other;
	}

	void check(void) {
		//...
	}

	void chto_to_delaem(void) {
		if (pOther) pOther->check();
	}
};


void setup() {
	Kaka A, B;
	A.setOtherObject(& B);
	B.setOtherObject(& A);

	A.chto_to_delaem(); // вызовется метод check объекта B
	B.chto_to_delaem(); // вызовется метод check объекта А
}
void loop(void) {}
2 лайка

Или более универсально

Каka A, B, C, D;
Manager Mng;
void setup() {
    Mng.Add(A);
    Mng.Add(B);
    Mng.Add(C);
    Mng.Add(D);
    Mng.Start(); //вызов этого метода обозначает что добавление закончено, можно знакомить объекты друг с другом и начинать работу
}
2 лайка

Буду пробовать!

а какое будет максимальное количество кнопок ?

Ну, за это я Вам уже плюсик выше поставил, но, боюсь, для ТС это непросто. Там же надо либо это Manager делать другом Kaka, либо ещё как эти вопросы решать. Мне кажется, для ТС это пока излишнее плождение сущностей.

1 лайк
1 лайк

Не нужно пытаться нажимать две кнопки одновременно и, соответственно, ловить такой момент. Одна кнопка в любом случае нажимается чуть раньше. Задача - отловить событие нажатия первой кнопки и проверить текущее состояние второй в этот момент. Если вторая нажата - имеем одновременное нажатие двух кнопок. Если же порядок нажатия кнопок (вторая-первая или первая-вторая) не имеет значения, то проверка делается для обеих кнопок, см. пример выше

1 лайк

Вот это “чуть” очень относительно. В большинстве случае, при задании 50 мс подтверждения нажатия, вполне.

Когда ты нажимаешь Ctrl+Enter на клаве, ты же не тапаешь на обе эти кнопки одновременно? Правильный алгоритм - нажал Ctrl и, не отпуская его, нажимаешь Enter. Обратная последовательность в некоторых случаях (с некоторыми комбинациями) тоже работоспособна, но правильная последовательность такая.

Так зачем на МК пытаться делать по особенному? ))

1 лайк

Про одновременность. Объединяя логику одновременного нажатия и антидребезга получается следующее: полное считывание подтвержденного статуса всех кнопок допускается после истечения таймаутов дребезга всех кнопок. Поэтому, если кнопки нажимались с задержкой друг относительно друга не более таймаута дребезга, то всегда будет зафиксировано одновременное нажатие.

Таймаут нужно подбирать так, чтобы было удобно пользоваться.

Возможно, клавиатура настраиваемая. К примеру, для кнопок допускающих одновременное нажатие в текущем контексте, таймауты увеличиваются. А для индивидуальных кнопок (например меняющих значение +/- параметра) важна быстрая реакция и парная работа не требуется - им таймауты меньше.

2 лайка

Зачем изобретать велосипед? См. мое сообщение выше :wink:

Потому что в МК не клава, а кнопки.) Бывает совсем мало кнопок. Например, 2-е на всё про всё.)
Но я сторонник прежде всего удобства. И “интуитивно понятности”)