Помощь с управлением одной кнопкой двумя выходами

Добрый день.
Реализую схему hands free для своего авто (Chevrolet). Стоит сигналка Старлайн Е90. Нет возможности прилепить нормальтный “хендс фри”. Куплена ручка от Опель Инсигнии с кнопкой, она будет подкюбчена к ардуино.
Авторизация идет через модуль HC-08 и iphone. Модуль в slave Режиме, и “засыпает” через 5сек, (АТ+MODE=2), в таком состоянии он не виден для других устройств и просыпается от подачи высокого уровня (3.3v) на вход RX От сенсорной кнопки TP223. При условии что мой тел находится рядом и на нем запущено приложение, происходит авторизация после касания сенсора и на выходе State появляется постоянный 3.3в который подается на питание ардуино нано. Та уже в свою очередь обрабатывает сигнал от кнопки ручки. Нажади один раз, на выходе ардуино 3.3 идет на вход оптопары PC817 и она на выходе импульсом должна замыкать контакт кнопки от брелка старлайн, который тоже одновременно запитывается от выхода модуля блютуз 3.3в. Соответственно при длительном нажатии на кнопку замыкается вторая кнопка брелка.
Сделал скетч на основе кусков из уроков. В данный момент у меня выход активируется не импульсом а уровнем и после того как отпустишь кнопку, а хотелось чтобы импульс был при нажатии уже сразу.

// управление двумя реле одной кнопкой
byte redPin = 7, // красное реле на ножке 7
     greenPin = 8, // зеленое реле на ножке 7

     keyPin = 3, // кнопка на ножке 3
     onOffRed = 0, // текущее состояние красного реле
     onOffGreen = 0; // текущее состояние зеленого реле
int cycle = 0; // количество успешных циклов проверки
void setup() { // все команды в этом блоке выполняются только 1 раз
  pinMode(redPin, OUTPUT); // красное
  pinMode(greenPin, OUTPUT); // зелёное
  pinMode(keyPin, INPUT); // куда подключена кнопка
  digitalWrite(keyPin, HIGH); // эта функция подключает, встроенный в микроконтроллер резистор, между плюсом питания контактом
}

void loop() { // все команды в этом блоке выполняются друг за другом циклически бесконечное число раз
  if (!digitalRead(keyPin)) // если кнопка была нажата, …
  {
    while (!digitalRead(keyPin)) // …то ждем, когда будет отжата
    {
      delay(1);
      cycle++; // 1 раз в миллисекунду переменная увеличивается на единицу
    }

    if (10 < cycle) // если успешных циклов меньше 10, считать это дребезгом и нажатие игнорировать
    {
      if (2000 < cycle) // если нажатие больше двух секунд, …
      {
        if (onOffRed) // … то изменить состояние красного реле
        {
          onOffRed = 0;
          digitalWrite(redPin, LOW);
        }
        else
        {
          onOffRed = 1;
          digitalWrite(redPin, HIGH);
        }
      }
      else if (onOffGreen) // иначе, изменить состояние зеленого реле
      {
        onOffGreen = 0;
        digitalWrite(greenPin, LOW);
      }
      else
      {
        onOffGreen = 1;
        digitalWrite(greenPin, HIGH);
      }
    }
  }
  cycle = 0; // обнулить счётчик для новой проверки
}

Код вставьте по правилам, иначе обсуждать невозможно

Вроде теперь по правилам.

Например:

if (digitalRead(keyPin)) {
 digitalWrite(...,  LOW);
 delay();
 digitalWrite(...,  HIGH);
}

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

Для этого.

Спасибо, добавил: одну задачку решил…

Как то можно изменить код чтобы импульс шел через 3 сек с момента удержания кнопки, но не отпуская ее, а как отпустили на выходе состояние не менялось

// управление двумя реле одной кнопкой
byte redPin = 7, // красное реле на ножке 7
     greenPin = 8, // зеленое реле на ножке 7
     keyPin = 3, // кнопка на ножке 3
     onOffRed = 0, // текущее состояние красного реле
     onOffGreen = 0; // текущее состояние зеленого реле
int cycle = 0; // количество успешных циклов проверки
void setup() { // все команды в этом блоке выполняются только 1 раз
  pinMode(redPin, OUTPUT); // красное
  pinMode(greenPin, OUTPUT); // зелёное
  pinMode(keyPin, INPUT); // куда подключена кнопка
  pinMode(keyPin, INPUT_PULLUP); // эта функция подключает, встроенный в микроконтроллер резистор, между плюсом питания контактом
}

void loop() { // все команды в этом блоке выполняются друг за другом циклически бесконечное число раз
  if (!digitalRead(keyPin)) // если кнопка была нажата, …
  {
    while (!digitalRead(keyPin)) // …то ждем, когда будет отжата
    {
      delay(1);
      cycle++; // 1 раз в миллисекунду переменная увеличивается на единицу
    }
    if (10 < cycle) // если успешных циклов меньше 10, считать это дребезгом и нажатие игнорировать
    {
      if (2000 < cycle) // если нажатие больше двух секунд, …
      {
          digitalWrite(redPin, HIGH);
          delay(500);
          digitalWrite(redPin,  LOW);
      }
      else 
        digitalWrite(greenPin, HIGH);
        delay(500);
        digitalWrite(greenPin,  LOW);
    }
  }
  cycle = 0; // обнулить счётчик для новой проверки
}

А что произойдёт если отпустить кнопку раньше 3 сек?

ничего желательно.
нажал - отпустил - импульс, нажал - держишь - 3сек - импульс - отпустил

Как-то - можно.

т.е. импульс идёт в двух случаях. При отпускании раньше 3 секунд или через 3 секунды, но тогда импульса нет, если отпустишь после окончания импульса, секунд через 20?

Представьте постановку авто на охрану с помощью кнопки на ручке: нажали-отпустили=замки открылись, нажали и держим кнопку, проходит 3 сек замки закрылись-отпускаем кнопку, хоть полчаса будем держать, импульс прошел через 3 сек с момента первого нажатия и одновременного удержания, дальше импульс после отпускания не нужен повторный

Ну в некоторых сигнализациях отличие от кратковременного нажатия на кнопку и удержания в том, чтобы охрана встала без звукового сопровождения (или снялась). А у вас то в чем разница?

Дело не в разнице, а надо реализовать функционал, а именно импульс во время длительного удержания кнопки. А по поводу постановки без звука, так просто даем двойной импульс

Если не получается победить кнопку самостоятельно, может быть стоит взять готовую библиотеку?

#include <shButton.h> // https://github.com/VAleSh-Soft/shButton

// управление двумя реле одной кнопкой
byte redPin = 7,    // красное реле на ножке 7
    greenPin = 8,   // зеленое реле на ножке 7
    keyPin = 3,     // кнопка на ножке 3
    onOffRed = 0,   // текущее состояние красного реле
    onOffGreen = 0; // текущее состояние зеленого реле

shButton btn(keyPin);

void pulse()
{
  digitalWrite(redPin, HIGH);
  delay(500);
  digitalWrite(redPin, LOW);
}

void setup() // все команды в этом блоке выполняются только 1 раз
{
  pinMode(redPin, OUTPUT);   // красное
  pinMode(greenPin, OUTPUT); // зелёное
  // настройка кнопки
  btn.setVirtualClickOn();            // включаем виртуальный клик
  btn.setLongClickMode(LCM_ONLYONCE); // включаем однократную подачу импульса при удержании
  btn.setTimeoutOfLongClick(3000);    // устанавливаем время удержания 3 секунды
}

void loop() // все команды в этом блоке выполняются друг за другом циклически бесконечное число раз
{
  switch (btn.getButtonState())
  {
  case BTN_ONECLICK: // импульс по короткому клику или по удержанию кнопки в течение 3 секунд
  case BTN_LONGCLICK:
    pulse();
    break;
  };
}
1 лайк

Спасибо, одна поправка: надо чтобы короткое нажатие был импульс на одном выходе а при длительном на другом, в вашем коде все на один выход сделано

Сделайте по разному, какие проблемы?

  switch (btn.getButtonState())
  {
  case BTN_ONECLICK: /
    // реакция на короткий клик
    break;
   case BTN_LONGCLICK:
    // реакция на длинный клик
    break;
 };
1 лайк

Не совсем понял, надо чтобы нажатие на Redpin шло, а удержание на Greenpin

Да, 258, и побыстрее! И не забудь чашку кофе. Двойные сливки и без сахара!

5 лайков