Корпус кнопки и переключателя

Я разрабатываю проект для своего колледжа.

ПЛАН ПРОЕКТА: Есть 3 датчика (температура, акселерометр и влажность), которые будут непрерывно считывать соответствующие параметры. в промежутке, если я нажимаю кнопку «PushButton1» в течение 2 секунд, Arduino должен войти в режим программирования.

Режим программирования имеет 6 случаев переключения. Каждое дело выбирается одно за другим, даже когда кнопка «PushButton1» нажимается на короткое время.

Также, если я снова нажму кнопку «PushButton1» на 2 секунды в режиме программирования, Arduino должен выйти из режима программирования.

ПРОБЛЕМА: В моем текущем скетче мне нужно нажать кнопку «PushButton1» в течение 2 секунд в режиме программирования в течение 2 секунд, чтобы изменить регистр. Также я не понимаю, как выйти из цикла Switch Case.

Скетч прилагается к этой теме.

const int btn = 2;     
const int ledPin =  13;     
int selector = 0;
boolean  volatile wait = false;
const unsigned long event=2000;
unsigned long a=0;
unsigned long b=0;
unsigned long c=0;
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(btn, INPUT);
attachInterrupt(digitalPinToInterrupt(btn),decoder,CHANGE);
}

void loop()
{
  while(wait) {  }
  if (digitalRead(btn) == LOW) {
    a = millis();
  }
  else
  {
    b = millis();
    c=b-a;
    Serial.println(c);
        if (c>=event)
            {
              doSwitchStatement();
              selector++;
              if (selector >6)
                  {
                  selector = 0;
                  delay(500);
                  }
            }
  }
  wait = true;
  interrupts();

}

void decoder()
{
  noInterrupts();
  wait = false;
}

void doSwitchStatement()
{
  switch(selector)
  {
  case 0:
    Serial.println("Case 0");
    break;

  case 1:
    Serial.println("Case 1");
    break;

  case 2:
   Serial.println("Case 2");
    break;

  case 3:
   Serial.println("Case 3");
     break;

  case 4:
   Serial.println("Case 4");
    break;

  case 5:
  Serial.println("Case 5");
    break; 

  case 6:
  Serial.println("Case 6");
    break;

  }
}

, 👍0

Обсуждение

Использование блокирующего оператора while в вашем цикле и прерывания - это уродливый способ выполнить то, что вы пытаетесь сделать. Ваша реализация заморозит приложение в этом цикле while(wait) за исключением случаев, когда состояние кнопки изменяется, что означает, что вы не можете ничего делать, кроме как реагировать на изменения состояния кнопки., @Duncan C

Где ваш код для чтения и отображения значений датчика?, @Duncan C


1 ответ


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

0

Я бы сделал это как простое состояние без блокировки while определить два логических значения

bool buttonPress = false;
bool inMenu = false;

и добавьте его в петлю.
Чтобы различать разные длины нажатия, вам нужно определить их. Нет ничего лучше «автоматического» распознавания короткого нажатия. Также используйте переменные, которые «говорят», облегчая чтение кода другими.

const unsigned long buttonPressLong = 2000;  // 2 секунды
const unsigned long buttonPressShort = 250;  // 0,25 секунды выполнимо
const unsigned long buttonPressDebounce = 50;  
// устранение дребезга при слишком коротком нажатии. Спасибо, Эдгар Боне.
unsigned long buttonPressStart = 0;

Приведенная ниже программа делает то, что вам нужно (проверено в моей тестовой лаборатории uno).
Как уже прокомментировал Эдгар Боне, вам также следует отменить дребезг кнопки (поищите в WiKi), чтобы исключить нежелательные эффекты. Время, которое я использую, является практичным для моего оборудования, поэтому вы можете поиграть, глядя на монитор последовательного порта.

const int btn = 2;
const int ledPin =  13;
int selector = 0;
const unsigned long buttonPressLong = 2000;  // 2 секунды
const unsigned long buttonPressShort = 250;  // 0,25 секунды выполнимо
const unsigned long buttonPressDebounce = 50;  // устранение дребезга при слишком коротком нажатии. Спасибо, Эдгар Боне.
unsigned long buttonPressStart = 0;

bool buttonPress = false;
bool inMenu = false;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(btn, INPUT);
  }

void loop() {
  if (digitalRead(btn) == LOW && !buttonPress ) {
    buttonPressStart = millis();
    buttonPress = true;
  }
  // Подпрограмма запускается только в том случае, если имело место предыдущее нажатие, в противном случае она игнорируется
  else if (digitalRead(btn) == HIGH && buttonPress) {
    if (millis() - buttonPressStart > buttonPressLong && millis() - buttonPressStart > buttonPressDebounce && inMenu) {
      Serial.print("Long press: ");
      Serial.println(millis() - buttonPressStart);
      buttonPress = false;
      inMenu = false;
    }
    if (millis() - buttonPressStart < buttonPressShort && millis() - buttonPressStart > buttonPressDebounce && !inMenu) {
      Serial.print("First short press ");
      inMenu = true;
    }
    if (millis() - buttonPressStart < buttonPressShort && millis() - buttonPressStart > buttonPressDebounce && inMenu) {
      Serial.print("Short press: ");
      Serial.println(millis() - buttonPressStart);
      doSwitchStatement();
      selector++;
      if (selector > 6) {
        selector = 0;
        delay(500);
      }
      buttonPress = false;
    }
  }
  // Здесь вы можете делать другие вещи, так как это не блокирует
}
doSwitchStatement(){...}// Остается таким же, как у вас

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

,

Большое спасибо за такую большую помощь. Я снова помещаю всю свою тему проекта., @swa8788

Пожалуйста, отметьте как принятое и спасибо за отзыв, @Codebreaker007