Калькулятор Arduino RichShield — мне нужно сделать так, чтобы, когда я удерживаю кнопку нажатой, эффекта не было

#c #c #arduino

Вопрос:

Итак, я создаю калькулятор Arduino RichShield, и он работает следующим образом:

  1. Я выбираю значение первого числа
  2. Я нажимаю кнопку, и она переходит во второе состояние — выбор оператора( — * /)
  3. Я снова нажимаю кнопку и могу выбрать значение второго числа
  4. Я снова нажимаю кнопку, и появляется результат
  5. Когда я нажимаю его снова, он сбрасывается, и я могу выполнить другое уравнение

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

     #include "Display.h"
//declaring the button and LEDs
const int PIN_BUTTON = 9;
int buttonState = 0;
const int PIN_LEDR = 4;
const int PIN_LEDG = 5;
const int PIN_LEDB = 6;
const int PIN_LEDY = 7;

//declaring potentiometer variables
const int PIN_POTMETER = 14;
int MAX_NUM = 20;
int MIN_NUM = -20;
int potValue = 0;
int potValueForCalculations = 0;

//setting up inputs/outputs for button, LEDs, potentiometer
void setup() {
  pinMode(PIN_LEDR, OUTPUT);
  pinMode(PIN_LEDG, OUTPUT);
  pinMode(PIN_LEDB, OUTPUT);
  pinMode(PIN_LEDY, OUTPUT);
  pinMode(PIN_POTMETER, INPUT);
  pinMode(PIN_BUTTON, INPUT_PULLUP);
  Display.show("----");
  delay(3000);
}

//declaring variables for mathematical operations/button counter
int buttonCounter = 0;
float inputValue1;
float inputValue2;
float resu<
char mathOperator;

void loop() {
  buttonState = digitalRead(PIN_BUTTON);
  //state 1- choosing the first value
  if (buttonCounter == 0) {
    
    //mapping and showing potValueForCalculations on the display
    potValue = analogRead(PIN_POTMETER);
    potValueForCalculations = map(potValue, 0, 1023, MIN_NUM, MAX_NUM);
    Display.show(potValueForCalculations);
    delay(100);

    //if we press the button we go into state 2
    if (buttonState == LOW) {
      inputValue1 = potValueForCalculations;
      buttonCounter = 1;
      delay(1000);
    }
  }
  //state 2- choosing the sign for the mathematical operation
  else if (buttonCounter == 1) {
    potValue = analogRead(PIN_POTMETER);
    if (potValue <= 256) {
      Display.show("a");
      mathOperator = 'a';
    }
    else if (potValue > 256 amp;amp; potValue <= 512) {
      Display.show("s");
      mathOperator = 's';
    }
    else if (potValue > 512 amp;amp; potValue <= 768) {
      Display.show("t");
      mathOperator = 't';
    }
    else {
      Display.show("d");
      mathOperator = 'd';
    }
    //if we press button we go into state 3
    if (buttonState == LOW) {
      buttonCounter = 2;
      delay(500);
    }
  }
  //state 3- choosing the second value
  else if (buttonCounter == 2) {
    potValue = analogRead(PIN_POTMETER);
    potValueForCalculations = map(potValue, 0, 1023, MIN_NUM, MAX_NUM);
    Display.show(potValueForCalculations);
    delay(100);

    //if we press button we go into state 4
    if (buttonState == LOW) {
      inputValue2 = potValueForCalculations;
      buttonCounter = 3;
      delay(500);
    }
  }
  
  //state 4- showing the result
  else if (buttonCounter == 3) {

    digitalWrite(PIN_LEDG, HIGH);
    digitalWrite(PIN_LEDR, LOW);

    if (mathOperator == 'a') {
      result = inputValue1   inputValue2;
      Display.show(result);
    }
    else if (mathOperator == 's') {
      result = inputValue1 - inputValue2;
      Display.show(result);
    }
    else if (mathOperator == 't') {
      result = inputValue1 * inputValue2;
      Display.show(result);
    }
    else if (mathOperator == 'd') {
      //if we try to divide by 0 the red LED turns on and the display shows "Err"
      if (inputValue2 == 0) {
        digitalWrite(PIN_LEDR, HIGH);
        digitalWrite(PIN_LEDG, LOW);
        Display.show("Err");
      }
      else {
        result = inputValue1 / inputValue2;
        Display.show(result);
      }
    }
    //if we press the button again the counter enters the reset threshold- the calculator restarts
    if (buttonState == LOW) {
        buttonCounter = 4;
        delay(500);
      }
  }
  else if (buttonCounter >= 4) {
    digitalWrite(PIN_LEDR, LOW);
    digitalWrite(PIN_LEDG, LOW);
    digitalWrite(PIN_LEDB, LOW);
    digitalWrite(PIN_LEDY, LOW);
    Display.show("");
    buttonCounter = 0;
    delay(500);
  }
}
 

Комментарии:

1. Сохраните предыдущее состояние и сравните текущее с предыдущим. Если предыдущее значение низкое, а текущее высокое, кнопка отпущена -> выполните действие (или, если вы предпочитаете, при нажатии, т. е. предыдущий максимум и текущий минимум).

2. Добро пожаловать в SO. Это не веб-сайт «программирование как услуга», вы должны рассказать нам, что вы пробовали и почему, по вашему мнению, это не сработало… тогда у вас гораздо больше шансов получить помощь.

Ответ №1:

Вместо того , чтобы проверять buttonState , есть LOW ли, вы должны проверить, не buttonState изменилось ли LOW .

Это может выглядеть примерно так:

 int prevButtonState = 0;
int newButtonState = 0;

void loop() {
  newButtonState = digitalRead(PIN_BUTTON);
  if( newButtonState == LOW amp;amp; prevButtonState != LOW) {
  // ...
  }
  prevButtonState = newButtonState;
}
 

N. B. В зависимости от используемого оборудования иногда также необходимо учитывать, что кнопка немного «подпрыгивает» при отпускании. Вы можете сделать это, проверив, что кнопка остается низкой в течение некоторого времени, прежде чем считать ее «нажатой».

Комментарии:

1. Я попытался реализовать это, отредактировав каждое «if (buttonState = LOW)» и добавив «prevButtonState = newButtonState;» после фигурных скобок «if (buttonState = LOW)», и я получаю ошибку «ожидаемый неквалифицированный идентификатор перед «else»» что я могу делать неправильно? Спасибо.

2. @daniil Звучит так, как будто вы допустили некоторые ошибки при обновлении своего кода. Убедитесь, что вы определили новые переменные, что у вас есть все фигурные скобки. Также обычно с newButtonState и prevButtonState , у вас вообще не должно buttonState быть больше.

3. Добавление конденсатора к кнопке также помогает