Совместная работа кнопок управления

Доброго времени суток!
Максимально новичок в работе с ардуино и программным кодом, но пытаюсь разобраться, поставлена цель: механический контактор замыкающие некие контакты необходимо перевести на управление одной не фиксируемой кнопкой, а так же активация устройства при получении сигнала с кан шины(пока что в скетче опробовано только с помощью кнопки, далее начну разбираться с кан шиной). Строиться схема будет на ардуино нано и сборке из 6ти реле. На данный момент собрана схема и скетч только в виртуальном виде на сайте WOKWI, так же пошел немного не по правильному пути и использовал AI генератор кода для создания кода по необходимым мне условиям. Управление кнопками почти что отрабатывает как нужно, но есть одно НО - при включении Реле №5 второй кнопкой и последующей его работе в течении заданного времени не возможно использовать первую кнопку. Прошу не закидывать помидорами, а дать дельный совет либо ткнуть носом в нужном направлении.


#define BUTTON1_PIN 2   
#define BUTTON2_PIN 10
#define RELAY1_PIN 3
#define RELAY2_PIN 4
#define RELAY3_PIN 5
#define RELAY4_PIN 5
#define RELAY5_PIN 7
#define RELAY6_PIN 9

Bounce button1 = Bounce();
Bounce button2 = Bounce();

uint8_t button1PressCount = 0;
unsigned long button1_press_time = 0;

void setup() {
    pinMode(BUTTON1_PIN, INPUT_PULLUP);
    pinMode(BUTTON2_PIN, INPUT_PULLUP);
    pinMode(RELAY1_PIN, OUTPUT);
    pinMode(RELAY2_PIN, OUTPUT);
    pinMode(RELAY3_PIN, OUTPUT);
    pinMode(RELAY4_PIN, OUTPUT);
    pinMode(RELAY5_PIN, OUTPUT);
    pinMode(RELAY6_PIN, OUTPUT);

    button1.attach(BUTTON1_PIN);
    button1.interval(5);
    button2.attach(BUTTON2_PIN);
    button2.interval(5);
}

void loop() {
    button1.update();
    button2.update();

    if(button1.rose()) {
        unsigned long duration = millis() - button1_press_time;
        if(duration >= 4000)
            digitalWrite(RELAY5_PIN, LOW);
        else if(duration >= 2000)
            digitalWrite(RELAY5_PIN, HIGH);
        else {
            button1PressCount++;
      switch (button1PressCount) {
        case 1: digitalWrite(RELAY1_PIN, HIGH); break;
        case 2: digitalWrite(RELAY1_PIN, LOW); digitalWrite(RELAY2_PIN, HIGH); break;
        case 3: digitalWrite(RELAY3_PIN, HIGH); break;
        case 4: digitalWrite(RELAY1_PIN, LOW); digitalWrite(RELAY2_PIN, LOW); digitalWrite(RELAY3_PIN, LOW); digitalWrite(RELAY4_PIN, LOW); button1PressCount = 0; break;
        }
    }
       } else if(button1.fell()) {
        button1_press_time = millis();
    }

    if(button2.rose()){
        digitalWrite(RELAY6_PIN, HIGH);
        delay(10000);
        digitalWrite(RELAY6_PIN, LOW);
    }
}

Ссылка на макет WOKWI https://wokwi.com/projects/393420622597798913

Под кнопки я бы воспользовался готовой библиотекой, хотя бы от Гайвера, вроде никто не плевался на неё, ну или огрызком от Квона, с шестью кнопками не пробовал но не вижу почему не должно работать, из функционала там доступны короткое и длинное нажатие

1 лайк

Подскажите пожалуйста где эти библиотеки взять и как ими воспользоваться. У меня по сути использоваться будет только одна кнопка (если перейти по ссылке на макет это “красная кнопка”), вторая кнопка пока что временная вместо нее должен встать интерфейс кан шины.

Главный вопрос, как поведет себя кан интерфейс, так же как и при запуске “зеленой” кнопкой или же будет все нормально

если квон не обидится, ниже код:

#define PIN_ENC_BUTTON 5

bool isWorkStarted = false;
unsigned long mill;  // переменная под millis()


/*** Обработчик кнопки энкодера ***/
//------Cl_Btn----------------------
enum { sbNONE = 0,
       sbClick,
       sbLong
     }; /*состояние не изменилось/клик/долгое нажатие*/
class Cl_Btn {
  protected:
    const byte pin;
    byte state;
    bool bounce = 0;
    bool btn = 1, oldBtn;
    unsigned long past;
    const uint32_t time = 500;
    bool flag = 0;
    uint32_t past_flag = 0;
  public:
    Cl_Btn(byte p)
      : pin(p) {}
    /*инициализация-вставить в setup()*/
    void init() {
      pinMode(pin, INPUT_PULLUP);
    }
    /*работа-вставить в loop()*/
    void run() {
      state = sbNONE;
      bool newBtn = digitalRead(pin);
      if (!bounce && newBtn != btn) {
        bounce = 1;
        past = mill;
      }
      if (bounce && mill - past >= 10) {
        bounce = 0;
        oldBtn = btn;
        btn = newBtn;
        if (!btn && oldBtn) {
          flag = 1;
          past_flag = mill;
        }
        if (!oldBtn && btn && flag && mill - past_flag < time) {
          flag = 0;
          state = sbClick;
        }
      }
      if (flag && mill - past_flag >= time) {
        flag = 0;
        state = sbLong;
      }
    }
    byte read() {
      return state;
    }
};
Cl_Btn Btn1(PIN_ENC_BUTTON);  //Экземпляр обработчика для кнопки энкодера


void setup() {
  Btn1.init();
}

void loop() {
  Btn1.run();
  if (Btn1.read() == sbLong) {
    isWorkStarted = !isWorkStarted;
  }
}
1 лайк

Это наверно вот эта часть кода?

Конечно вы не сможете пользоваться кнопкой, если у вас “заданное время” отрабатывается в виде delay()

если будете задавать время так же, с помощью делея - точно так все будет зависать, как сейчас

При использовании кнопок операторов delay() в коде быть не должно.

1 лайк

Да, время отработки реле задано функцией дэлай, есть ли какой аналог для решения этой проблемы?

Библиотеки от Гайвера (да простит меня всевышний)

1 лайк

есть - переписывать весь код как неблокирующий с использованием миллис Но концепция кода должна быть совершенно иной.

1 лайк

Спасибо!

Слабо верится…
Я вот скомпилировать захотел, и?

error: ‘Bounce’ does not name a type; did you mean ‘tone’?

Компилировали где?, на сайте wokwi отрабатывает, физически проверить не могу, ардуинка в пути.

Ну где-где? У себя открыл Arduino IDE, скопировал туда код из #1 и вот…

я так понимаю библиотека bounce2.h нужна, или у вас она стоит? не ругайтесь, я полный 0 пока что в этом)

Что-то в #1 ни о каких библиотеках речи не идет…

Да и хрен с ним. Тебе всё равно нужно всё с нуля переписывать…


установил библиотеку Bounce2, в начале скетча она указана, как понимаю по скриншоту с ардуино иде ему выгрузить скетч некуда вот и ругается.

Да, понимаю что придется с нуля, но я только начинаю во все это вникать, думаю ошибки были у всех.

Твою задачу (без CAN) нужно разбить на три части.

  1. Чтение состояние кнопок (это любая библиотека может сделать, например я пользуюсь kakmyc_btn.h)
  2. Из прочитанных состояний кнопок сформировать “задания на выполнение”
  3. Выполнить задания (выставить на пинах управления реле соответствующие сигналы)

Потом будет проще добавить CAN: Ловишь свой сигнал в CAN (или как там правильно у него, я с ним никогда не рабтал), так же формируешь “задания на выполнение” и 3 часть отработает сама.

Потом уже можно всякого выпендрежа добавить - блокировать/не блокировать управление кнопками если активен CAN и тп…

Ну я бы так делал, если бы мне подобное нужно было бы сделать…

1 лайк

Перепроверил, и верно заметили самая первая строчка в посте №1 не содержит строку #include <Bounce2.h>, Приношу извинения.!! ПС. не пойму как отредактировать первое сообщение.

В промте для АИ пишешь “создай неблокирующий код”. Если на аглицком промты пишешь то, “create non blocking code with Arduino IDE for board Ardiuno Nano…” и так далее.


чует мое сердце, что скоро на форуме будут вопросы: “помогите написать промт для ЧатГПТ, шоп он он родил скетч, который…”. Пипец деградация!

1 лайк