Как заблокировать вход кнопки с возможностью выбора задержки?

У меня есть программа, над которой я работаю, в которой реле включается -> ждет задержки -> затем выключается после того, как происходит одно из двух: 1) достигается заданное время r ИЛИ 2) кто-то нажимает кнопку, чтобы активировать его.

Сейчас 90% моего кода работает, и я застрял на том, как «заблокировать» кнопку, чтобы она не срабатывала при срабатывании реле, на выбираемое время задержки.

Часть кода с таймером, с выбираемым временем, работает. В зависимости от того, что видит аналоговый 1, он соответствующим образом включит реле после выбранного времени.

Я попытался реализовать этот же подход для таймера блокировки, используя аналоговый 2, чтобы определить длительность задержки. Я использовал переменную, которую назвал LOK, чтобы либо прочитать кнопку, если она разблокирована (LOK = 0), либо, если она заблокирована (LOK = 1), подождать отведенное время задержки перед разблокировкой и повторным считыванием кнопки.

Я перепробовал все виды вещей, но это все еще не работает правильно. Возможно, есть лучший или более простой способ сделать это, но я сломал голову, и поиск по ключевым словам не помогает.

Код ниже - простите за случайные комментарии. Я что-то резал и перемещал, я не редактировал комментарии, поэтому некоторые из них могут быть из других фрагментов кодов из других проектов.

int DUMP = 2; // Контакт подключен к большому реле дампа
int BUTTON = 3; // Контакт подключен к кнопке ручного сброса.
int BUTTONlight = 4; // Контакт подключен к кнопочной подсветке.


int BUTstate; // Текущее показание с контакта BUTTON
int lastBUTstate = LOW; // Предыдущее чтение с контакта BUTTON

long lastDebounce = 0; // Последний раз вывод был изменен
long Delay = 50; // Время дребезга

unsigned long DUMPTIME;
unsigned long LOT;

unsigned long prevTIME;

int a=0;
int d=0;

int LOK = 0;

void setup()
{ 
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);

  pinMode (BUTTON, INPUT);
  pinMode (BUTTONlight, OUTPUT);
  pinMode (DUMP, OUTPUT);

  digitalWrite(DUMP, HIGH);
  delay(10000);
  digitalWrite(DUMP, LOW);
  digitalWrite(BUTTONlight, HIGH);
}

int readTselector(int pin)
// возвращает номер нажатой кнопки или ноль, если кнопка не нажата
// int pin — номер аналогового контакта для считывания
{
  int b,c = 1;
  c=analogRead(pin); // получить аналоговое значение
  if (c>1000)
  {
    b=0; // кнопки не были нажаты
  }   
  else
    if (c<1000 && c>600)
    {
      b=1; // кнопка 1 нажата
    }     
    else
      if (c<520 && c>400)
      {
        b=2; // кнопка 2 нажата
      }       
      else
        if (c>100 && c<400)
        {
          b=3; // кнопка 3 нажата
        }         
        else
          if (c<100)
          {
            b=4; // кнопка 4 нажата
          }           
  return b; 
  }


void loop()
{
  int DUMPTIME = DTselect();
  int LOT = LOselect();

  int reading = digitalRead(BUTTON);

  unsigned long currTIME = millis();

  if ((currTIME - prevTIME) >= DUMPTIME) // Считаем до 2 минут
   {
     LOK = 1;
     digitalWrite(BUTTONlight, LOW);
     digitalWrite(DUMP, HIGH);
     delay(10000);
     digitalWrite(DUMP, LOW);
     prevTIME = currTIME;
   }

  if (reading != lastBUTstate)
  {
    lastDebounce = millis();
  }


  if (LOK == 1)
  {
    delay(LOT);
    digitalWrite(BUTTONlight, HIGH);
    LOK = 0;

  }
  if ((millis() - lastDebounce) > Delay && LOK == 0)
  {
    BUTstate = reading;
  }

  if (BUTstate == HIGH)
  {
    digitalWrite(BUTTONlight, LOW);
    digitalWrite(DUMP, HIGH);
    delay(10000);
    digitalWrite(DUMP, LOW);
    prevTIME = currTIME;
  }
  lastBUTstate = reading;
}

int DTselect()
{
  a=readTselector(1); 
  if (a==0) // кнопки не нажаты
  {
    DUMPTIME = 210000;
  }   
  else
    if (a==1) // кто-то нажал кнопку!
    {
      DUMPTIME = 180000;
    }
    else
     if (a==2) // кто-то нажал кнопку!
     {
       DUMPTIME = 150000;
     }
     else
      if (a==3) // кто-то нажал кнопку!
      {
        DUMPTIME = 120000;
      }
     else
       if (a==4) // кто-то нажал кнопку!
       {
         DUMPTIME = 90000;
       }
  return DUMPTIME; 
 }

int LOselect()
{
  d=readTselector(2); 
  if (d==0) // кнопки не нажаты
  {
    delay(20000);
  }   
  else
    if (d==1) // кто-то нажал кнопку!
    {
      delay(15000);
    }
    else
     if (d==2) // кто-то нажал кнопку!
     {
       delay(10000);
     }
     else
      if (d==3) // кто-то нажал кнопку!
      {
        delay(5000);
      }
      else
       if (d==4) // кто-то нажал кнопку!
       {
         delay(0);
       }
 }

, 👍2

Обсуждение

что случилось с аккаунтом ОП?, @crowie


1 ответ


Лучший ответ:

1

Я взял ваш код и немного отредактировал. У вас были некоторые бесполезные переменные, и вы переопределяли DUMPTIME и LOT странным образом. Я также определил некоторые из ваших констант как #define, потому что именно так вы всегда должны это делать.

#define DUMP 2          // Контакт подключен к большому реле дампа
#define BUTTON 3        // Контакт подключен к кнопке ручного сброса.
#define BUTTONlight 4   // Контакт, подключенный к кнопочной подсветке.
#define DELAY 50        // Время дребезга

int BUTstate;           // Текущее показание с контакта BUTTON
int lastBUTstate = LOW; // Предыдущее чтение с контакта BUTTON

long lastDebounce = 0;  // Последний раз вывод был изменен

unsigned long DUMPTIME;
unsigned long LOT;
unsigned long prevTIME;

int LOK = 0;

int readTselector(int pin)
// возвращает номер нажатой кнопки или ноль, если кнопка не нажата
// int pin — номер аналогового контакта для считывания
{
    int c = analogRead(pin); // получить аналоговое значение
    if (c > 1000){
        return 0; // кнопки не были нажаты
    }   
    else if (c<1000 && c>600){
        return 1; // кнопка 1 нажата
    }
    else if (c<520 && c>400){
        return 2; // кнопка 2 нажата
    }       
    else if (c>100 && c<400){
        return 3; // кнопка 3 нажата
    }         
    else if (c<100){
        return 4; // кнопка 4 нажата
    } 
    else return 0; // на всякий случай
    }

long DTselect()
{
    switch(readTselector(1)){
        case 0: return 210000; // кнопки не нажаты
            break;
        case 1: return 180000; // кто-то нажал кнопку!
            break;
        case 2: return 150000;
            break;
        case 3: return 120000;
            break;
        case 4: return 90000;
            break;
        default: return 210000; // по умолчанию
            break;
    }
 }

int LOselect()
{
  switch( readTselector(2) ){
        case 0:  return 20000; // кнопки не нажаты
            break;
        case 1:  return 15000; // кто-то нажал кнопку!
            break;
        case 2:  return 10000;
            break;
        case 3:  return 5000;
            break;
        case 4:  return 0;
            break;
        default: return 20000; // по умолчанию
            break;
    }
 }

void setup()
{ 
    pinMode(A1, INPUT);
    pinMode(A2, INPUT);

    pinMode (BUTTON, INPUT);
    pinMode (BUTTONlight, OUTPUT);
    pinMode (DUMP, OUTPUT);

    digitalWrite(DUMP, HIGH);
    delay(10000);
    digitalWrite(DUMP, LOW);
    digitalWrite(BUTTONlight, HIGH);
}


void loop()
{
    DUMPTIME = DTselect();
    LOT = LOselect();

    int reading = digitalRead(BUTTON);

    unsigned long currTIME = millis();

    if ((currTIME - prevTIME) >= DUMPTIME){// отсчитывать до 2 минут
        LOK = 1;
        digitalWrite(BUTTONlight, LOW);
        digitalWrite(DUMP, HIGH);
        delay(10000);
        digitalWrite(DUMP, LOW);
        prevTIME = currTIME;
    }

    if (reading != lastBUTstate){
        lastDebounce = millis();
    }

    if (LOK){
        delay(LOT);
        digitalWrite(BUTTONlight, HIGH);
        LOK = 0;
    }

    if ((millis() - lastDebounce) > DELAY && !LOK){
        BUTstate = reading;
    }

    if (BUTstate == HIGH){
        digitalWrite(BUTTONlight, LOW);
        digitalWrite(DUMP, HIGH);
        delay(10000);
        digitalWrite(DUMP, LOW);
        prevTIME = currTIME;
    }
    lastBUTstate = reading;
}

Другая версия с переменной BUTflag для отслеживания нажатия и отпускания кнопки. Я не имел дела с переменной DUMPTIME, но надеюсь, это даст вам представление о том, как использовать флаги, чтобы логика не дала сбой.

#define DUMP 2          // Контакт подключен к большому реле дампа
#define BUTTON 3        // Контакт подключен к кнопке ручного сброса.
#define BUTTONlight 4   // Контакт, подключенный к кнопочной подсветке.
#define DELAY 50        // Время дребезга

int BUTstate;           // Текущее показание с контакта BUTTON
int BUTflag = 0; 
int go = 0;
long lastDebounce = 0;  // Последний раз вывод был изменен

unsigned long DUMPTIME;
unsigned long LOT;
unsigned long prevTIME;

int LOK = 0;

int readTselector(int pin)
// возвращает номер нажатой кнопки или ноль, если кнопка не нажата
// int pin — номер аналогового контакта для считывания
{
    int c = analogRead(pin); // получить аналоговое значение
    if (c > 1000){
        return 0; // кнопки не были нажаты
    }   
    else if (c<1000 && c>600){
        return 1; // кнопка 1 нажата
    }
    else if (c<520 && c>400){
        return 2; // кнопка 2 нажата
    }       
    else if (c>100 && c<400){
        return 3; // кнопка 3 нажата
    }         
    else if (c<100){
        return 4; // кнопка 4 нажата
    } 
    else return 0; // на всякий случай
    }

long DTselect()
{
    switch(readTselector(1)){
        case 0: return 210000; // кнопки не нажаты
            break;
        case 1: return 180000; // кто-то нажал кнопку!
            break;
        case 2: return 150000;
            break;
        case 3: return 120000;
            break;
        case 4: return 90000;
            break;
        default: return 210000; // по умолчанию
            break;
    }
 }

int LOselect()
{
  switch( readTselector(2) ){
        case 0:  return 20000; // кнопки не нажаты
            break;
        case 1:  return 15000; // кто-то нажал кнопку!
            break;
        case 2:  return 10000;
            break;
        case 3:  return 5000;
            break;
        case 4:  return 0;
            break;
        default: return 20000; // по умолчанию
            break;
    }
 }

void setup()
{ 
    pinMode(A1, INPUT);
    pinMode(A2, INPUT);

    pinMode (BUTTON, INPUT);
    pinMode (BUTTONlight, OUTPUT);
    pinMode (DUMP, OUTPUT);

    digitalWrite(DUMP, HIGH);
    delay(10000);
    digitalWrite(DUMP, LOW);
    digitalWrite(BUTTONlight, HIGH);
}


void loop()
{
    DUMPTIME = DTselect();
    LOT = LOselect();

    BUTstate = digitalRead(BUTTON);

    unsigned long currTIME = millis();
/*
    if ((currTIME - prevTIME) >= DUMPTIME && !LOK){
        LOK = 1;
        digitalWrite(BUTTONlight, LOW);
        digitalWrite(DUMP, HIGH);
        delay(10000);
        digitalWrite(DUMP, LOW);
        prevTIME = currTIME;
    }
    else */
    if (LOK){
        delay(LOT);
        digitalWrite(BUTTONlight, HIGH);
        LOK = 0;
    }
    else if(!LOK){
        if(!go && BUTstate && !BUTflag){
            lastDebounce = millis();
            BUTflag = 1;
        }
        else if (!go && BUTstate && BUTflag==1 && (millis() - lastDebounce) > DELAY){
            BUTflag = 2;
        }
        else if (!go && !BUTstate && BUTflag==2){
            BUTflag = 0;
            go = 1;
        }
        else if (go){
            digitalWrite(BUTTONlight, LOW);
            digitalWrite(DUMP, HIGH);
            delay(10000);
            digitalWrite(DUMP, LOW);
            prevTIME = currTIME;
            go = 0;
            LOK = 1;
        }
    }
}
,

Спасибо, но он все равно не работает правильно, когда выбран любой другой случай, кроме 0 на A2. Похоже, кнопка полностью блокируется от срабатывания вообще., @Adam Alexander

Что вы подразумеваете под A2? Я не менял никакой логики. Просто привел в порядок функции и переменные. Теперь код должен выглядеть немного компактнее., @crowie

Ах, ладно, и то, что я имел в виду под A2, было аналоговым входом 2. Теперь, что происходит, если любое другое значение, кроме 0, считывается с A2, то, похоже, процесс проходит цикл дважды после каждого нажатия кнопки. Так что с LOT, равным 5000 или 5 секундам, он проходит цикл, ждет 5 секунд, и вместо того, чтобы сбросить светодиод и ждать нового нажатия кнопки, он проходит цикл второй раз, ждет 5 секунд, затем сбрасывает светодиод. Также он иногда будет продолжать застревать в цикле и сбрасываться., @Adam Alexander

@AdamAlexander Я добавил другую версию, @crowie

Не могу достаточно отблагодарить вас! Мне нужно немного логически продумать флаг, чтобы понять концепцию, но флаги работают отлично! Мне удалось немного отредактировать логику DUMPTIME, чтобы использовать флаги, и теперь она также работает в сочетании с задержкой LOT! Респект!, @Adam Alexander

Нет проблем. Использование модели конечного автомата — это действительно путь к этому в долгосрочной перспективе. Вам следует изучить теорию конечного автомата, чтобы понять идею. Не забудьте проголосовать за меня., @crowie