Нажатие и удержание кнопки с разной работой светодиодов

NikFrolBl

✩✩✩✩✩✩✩
17 Июн 2021
2
0
Всем привет. Нужна помощь с организацией кода без delay на millis()
Задача кода при однократном нажатии на кнопку светодиод горит определённое время (3 сек) и секунда перерыв. И так повторяется n раз. (Как автозапуск на автомобиле)
А при удержании горит светодиод, пока держится кнопка.
Code:

C++:
#include <OneButton.h>//Библиотека кнопки
#include <wiring.c>//Библиотека скрытых переменных
OneButton btn_on_board(12, true);// кнопка на лодке
/*==================Переменный внутренней памяти Arduino==================*/
#define Engine_button 7//Кнопка имитирующая запущенный двигатель
#define Startap_status_light 2//лампочка показывающая нажатие на кнопку/работу стартера
#define Engine_status_light 3//лампочка статуса двигателя
#define Mode_Launch 10//спооб запуска (ШИМ/потенцинометр)
#define PWM 5//Приемник шим сигнала
#define Speaker 4//спикер
#define start_contre 4//Количество попыток запуска двигателя при автозапуске
#define t_increase 200//Время увеличения
#define t_delay 700//Стартовое время автозапуска
#define _pause 3000//Перерывы между автозапусками

#define start_eng_pwm 1600//Верхний порог дребезга ШИМА
#define stop_eng_pwm 1400//Нижний порог дребезга ШИМА
/*==================Переменные==================*/
bool EngineState;//false-запущен, true - не запущен
bool Mode_Switch;//Переклчение с ШИМ на Потенциометр
bool Status_Switch;// Статус Mode_Switch

bool flag = false;//Считывания нажатия или удержания
unsigned long timing; // Переменная для хранения точки отсчета
unsigned long timing1; // Переменная для хранения точки отсчета
int pauses = 3000;// Пауза
const int tdelay1=700;// Стартовое время при автозапуске
int tdelay = 700;// Переменная стартовое время при автозапуске
int i=0;// Переменная для хранения точки отсчета
/*==================КОД==================*/
void setup() {
Serial.begin(9600);
pinMode(Engine_button, INPUT_PULLUP);
pinMode(Startap_status_light, OUTPUT);
pinMode(Engine_status_light, OUTPUT);
pinMode(Speaker, OUTPUT);
pinMode(Mode_Launch, OUTPUT);
btn_on_board.attachClick(ButtonClick);
btn_on_board.attachLongPressStart(buttonLongPress);
btn_on_board.attachLongPressStop(buttonRelease);
}

void loop() {
  digitalWrite(Engine_status_light,0);
Mode_Switch = digitalRead(Mode_Launch);
  if (Mode_Switch ==1) {
    Status_Switch=1;//Потенциометр
  }
  else if (Mode_Switch!=1) {
    Status_Switch=0;//ШИМ
  }

  if(Status_Switch==1) {
    btn_on_board.tick();
    EngineState = digitalRead(Engine_button);
    if (EngineState==false){
     EngineWorking();
      }
    }
    else if (Status_Switch==0) {
      Serial.println("SHIM");
       if (EngineState==false){
     EngineWorking();
    }
  }
}
void ButtonClick () {
  static unsigned long u=millis();
  if(!flag){
    flag = true;
    EngineState = digitalRead(Engine_button);
    
    if (u-timing> tdelay) {
    digitalWrite(Startap_status_light,0);
    Serial.println("ss");
    Serial.println(tdelay);
    Serial.println(timing);
    timing=millis();
    static unsigned long p=millis();
    if (p-timing1> pauses+tdelay) {
      digitalWrite(Startap_status_light,1);
      //EngineState = digitalRead(Engine_button);
    Serial.println("sssssssssssssss");
    timing1=millis();
    tdelay+=200;
    }
  }
  if (tdelay==1500){
    timer0_millis=0;
    timing=millis();
    timing1=millis();
    tdelay=tdelay1;
   }
}
  flag=false;
}
void buttonLongPress () {
  digitalWrite(Startap_status_light,1);
}
void buttonRelease () {
  digitalWrite(Startap_status_light,0);
 }
void EngineWorking () {
  EngineState = digitalRead(Engine_button);
  if (EngineState !=true) {
    digitalWrite(Startap_status_light,0);
    digitalWrite(Engine_status_light,1);
    Serial.println("Engine_Working");
  }
  else loop();
}
 
Изменено:

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
- При нажатии кнопки идёт прерывание, запускается таймер.
Выходим из прерывания и крутим основную программу.

- Прерывание по отпусканию кнопки.
Таймер останавливается. Поднимаем флаг.
Выходим из прерывания.
Основной цикл видит, что кнопка отпущена.
Считывает счётчик таймера.
Если счётчик превысил какую то величину "I" но не превысил величину "N", производится цикл запуска.

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

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
1) При нажатии непонятно однократное это нажатие или долгое. В любом случае делаем вот что: запоминаем время, включаем светодиод. Далее крутим луп.
2) При отпускании проверяем время, если время больше , чем однократное нажатие , то выключаем светодиод. Крутим луп.
3) В лупе проверяем, если светодиод горит, кнопка отпущена, и с момента нажатия прошло более 3 секунд - выключаем светодиод.

Все