Как изменить значение переменной при нажатии переключателя

Я новичок в arduino, и я хочу создать проект, в котором у меня есть двигатель, вращающийся по часовой стрелке, затем при нажатии кнопки он вращается против часовой стрелки, а при повторном нажатии он возвращается к часовой стрелке и т.д... К сожалению, у меня возникли проблемы с тем, чтобы заставить это работать. То, как я стремился заставить это работать, заключалось в том, чтобы иметь переменную, и всякий раз, когда нажимается кнопка, значение этой переменной изменяется от ВЫСОКОГО к НИЗКОМУ, к ВЫСОКОМУ и так далее, и на основе этой переменной двигатель вращается в любом направлении. До сих пор у меня есть этот код:

const int buttonPin = 8;     // номер контакта кнопки

// переменные изменятся:
int buttonState = 0;         //переменная для изменения статуса

void setup() {

 Serial.begin(9600);
 pinMode(buttonPin, INPUT);
}

void loop() {
 // считывание состояния значения кнопки:
 buttonState = digitalRead(buttonPin);
 Serial.print("Digital value: ");
 Serial.println(buttonState);
 delay(150);
}

, 👍0

Обсуждение

итак, в чем заключается ваш вопрос? ... пока у вас все хорошо получается, @jsotola

используйте библиотеку Bounce2 для чтения кнопки, @Juraj


3 ответа


0

Сначала я бы создал тип перечисления и переменную направления двигателя (вместо состояния кнопки):

enum EMotorDirection
{
    CLOCK_WISE,
    COUNTER_CLOCK_WISE
}

EMotorDirection _motorDirection = CLOCK_WISE;

Затем прочитайте название кнопки и, когда оно изменится (создайте переменную _previousButtonState), отрегулируйте направление двигателя.

int _previousButtonState = LOW;

В функции цикла:

int buttonState = digitalRead(buttonPin);
// Отменить состояние кнопки;
if (buttonState != _previousButtonState)
{
   if (_motorDirection == CLOCK_WISE)
   {
       _motorDirection = COUNTER_CLOCK_WISE;
   }
   else
   {
       _motorDirection = CLOCK_WISE;
   }
   SwitchMotorDirection();

   _previousButtonState = buttonState;
}

И создайте функцию SwitchMotorDirection

void SwitchMotorDirection()
{
   if (_motorDirection == CLOCK_WISE)
   {
       // Управление двигателем по часовой стрелке
   }
   else
   {
       // Управление счетчиком двигателя по часовой стрелке
   }
}

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

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

// Типы

enum EMotorDirection
{
    CLOCK_WISE,
    COUNTER_CLOCK_WISE
};

// Константы
const int _buttonPin = 8;     // номер контакта кнопки

// Глобальные переменные
int             _previousButtonState = LOW;
EMotorDirection _motorDirection      = CLOCK_WISE;

// Прототипы функций
void SwitchMotorDirection();

// Функции

void setup() 
{
  Serial.begin(9600);
  pinMode(_buttonPin, INPUT);  
}

void loop() 
{
  int buttonState = digitalRead(_buttonPin);
  // Отменить состояние кнопки;
  if (buttonState != _previousButtonState)
  {
     if (_motorDirection == CLOCK_WISE)
     {
         _motorDirection = COUNTER_CLOCK_WISE;
     }
     else
     {
         _motorDirection = CLOCK_WISE;
     }
     SwitchMotorDirection();
  
     _previousButtonState = buttonState;
  }    
}

void SwitchMotorDirection()
{
   if (_motorDirection == CLOCK_WISE)
   {
       // Управление двигателем по часовой стрелке
   }
   else
   {
       // Управление счетчиком двигателя по часовой стрелке
   }
}
,

Я очень новичок, и я понятия не имею, как это скомпилировать, не могли бы вы мне сказать?, @bstplyr2401

Я добавил код, который компилируется., @Michel Keijzers


2

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

Внесите это изменение следующим.

Когда вы проверите это, вы можете обнаружить, что состояние кнопки меняется несколько раз, когда вы нажимаете ее один раз. Механические переключатели могут включаться/выключаться... несколько раз при каждом переключении. (Это называется подпрыгиванием, хотя это не "подпрыгивание", а два контакта, соприкасающиеся друг с другом. Результат тот же самый.) Есть несколько способов справиться с этим, но самый простой - подождать 20-30 миллисекунд после того, как вы впервые увидите изменение; прочитайте его еще раз, и если оно все еще находится в новом состоянии, примите это, в противном случае проигнорируйте его. Эта временная задержка является приблизительной; возможно, вам потребуется настроить ее для конкретной кнопки.

Как только вы решите, что кнопка действительно нажата, измените направление вращения двигателя.

,

Спасибо, это хорошее объяснение, @bstplyr2401


1

Я бы рекомендовал вам сначала "отменить" ввод кнопки. Вместо того чтобы заново изобретать колесо, вы могли бы использовать существующую библиотеку: Bounce2.

Используя условный ввод, вы можете просто манипулировать счетчиком для определения состояния.

// Подсоедините один конец кнопочного выключателя N.O. к
// GND, а другой конец - к контакту 2 Arduino.
#include <Bounce2.h>
byte buttonState = 0;
const byte modeButtonPin = 2;
const unsigned long debouncerInterval = 50;  // Время в мс.

Bounce modeButton = Bounce();

void setup(){
  Serial.begin(9600);
  pinMode(modeButtonPin, INPUT_PULLUP);
  modeButton.attach(modeButtonPin);
  modeButton.interval(debouncerInterval);
}

void loop(){
  if(modeButton.update()){
    if(modeButton.read() == 0){
      buttonState++;
      if(buttonState > 1){buttonState = 0;}
      Serial.println(buttonState);
    }
  }
}
,