2 кнопки, 1 сервопривод, поворот только при нажатии

У меня проблема с кодом. Мне нужно повернуть сервопривод по часовой стрелке или против часовой стрелки, используя 2 микропереключателя.

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

Как мне сделать так, чтобы он вращался только при нажатии кнопок и выключался, когда они не нажаты?

#include <Servo.h>

Servo myservo; // создаем сервообъект для управления сервоприводом

// КОНСТАНТЫ

// PIN-коды
const int crServo = 12; // устанавливает контакт 12 как сервопривод
const int buttonPinCW = 2; // устанавливает контакт 2 как кнопку; по часовой стрелке => по часовой стрелке => ФОКУС ДАЛЕКО
const int buttonPinCC = 3; // устанавливает контакт 3 как кнопку; СС => против часовой стрелки => ФОКУСИРОВАТЬ БЛИЖЕ

// СВОЙСТВА СЕРВО
const int crSpeedDefault = 0; // неподвижное положение, двигатель не должен вращаться
const int crSpeedCW = 110; // вращаем двигатель на полной скорости по часовой стрелке
const int crSpeedCC = 70; // поворачиваем двигатель на полную скорость против часовой стрелки

// УСТАНОВИТЬ СОСТОЯНИЯ КНОПКИ
int buttonStateCW = 0; //устанавливает кнопку 1 как выключенную
int buttonStateCC = 0; // отключаем кнопку 2

void setup()
{
  myservo.attach(crServo); // прикрепляем сервопривод к контакту 12 к объекту сервопривода
  pinMode (crServo, OUTPUT);
  pinMode (buttonPinCW, INPUT); // устанавливает кнопку в качестве ввода
  pinMode (buttonPinCC, INPUT); // устанавливает кнопку в качестве ввода
  myservo.write(crSpeedDefault); // сервопривод по умолчанию crSpeedDefault
}

void loop()
{
  crServo = digitalRead(crSpeedDefault);
  buttonStateCW = digitalRead(buttonPinCW);
  buttonStateCC = digitalRead(buttonPinCC);
  // вращение по часовой стрелке
  if (buttonStateCW == HIGH) {
    myservo.write(crSpeedCW);
    // вращение против часовой стрелки
  } 
  if (buttonStateCC == HIGH) {
    myservo.write(crSpeedCC);
  }
}

, 👍0

Обсуждение

У вас есть внешний выпадающий список на кнопках?, @Maximilian Gerhardt

Привет, Максимилиан. Да, у меня есть колесо, которое вручную вращается пользователем. Идея в том, что когда руль поворачивается на 180 градусов, нажимается микропереключатель. Это поворачивает сервопривод в одном направлении, противоположное — поворачивает сервопривод в противоположном направлении., @Richard

Я имел в виду подтягивающий резистор. Логика вашей прошивки заключается в том, что если на контакте кнопки написано «HIGH», он нажат. Таким образом, у вас должна быть кнопка, подключенная через выпадающее меню к GND, а другая сторона к + 5 В, верно? Также: почему там есть строка crServo = digitalRead(crSpeedDefault);? При const int crServo = 12 переменная не может быть изменена. Нет смысла перезаписывать вывод сервопривода в 0 или 1, используя результат digitalRead, который считывается с вывода 0, который является последовательным TX Arduino., @Maximilian Gerhardt


2 ответа


2

Если вам нужна логика "если ни одна из двух кнопок не нажата, сервопривод немедленно остановится", то вы должны выразить это в своем цикле как if выражение, в котором вы проверяете, читаются ли обе кнопки LOW:

void loop()
{
  buttonStateCW = digitalRead(buttonPinCW);
  buttonStateCC = digitalRead(buttonPinCC);
  // вращение по часовой стрелке
  if (buttonStateCW == HIGH) {
    myservo.write(crSpeedCW);
    // вращение против часовой стрелки
  } 
  if (buttonStateCC == HIGH) {
    myservo.write(crSpeedCC);
  }

  // Обе кнопки не нажаты?
  if(buttonStateCC == LOW && buttonStateCW == LOW) {
    // Остановить сервопривод.
    myservo.write(0);
  }
}

Это предполагает, что ваши кнопки снабжены подтягивающими резисторами к GND с одной стороны и +5 В с другой стороны, как подробно описано в Учебное пособие по Arduino. Вкратце это означает, что ненажатая кнопка читается как 0, а нажатая читается как 1 (HIGH). Это необычно, потому что мы обычно используем внутренние подтягивающие резисторы через параметр INPUT_PULLUP pinMode с переключаемой логикой (1 = не нажат, 0 = нажато).

Я также удалил строку crServo = digitalRead(crSpeedDefault);, потому что, на мой взгляд, это не имеет смысла, как я подробно описал в своем комментарии.

,

спасибо, Максимилиан, я думаю, что это должно быть в проводке моего переключателя, редактирование кода, которое вы прислали, заставляет их непрерывно вращаться в любом направлении при нажатии кнопки. Я думаю, мне нужно посмотреть, как я подключаю их к Uno, так как здесь что-то не так., @Richard

Пожалуйста, отредактируйте свой вопрос, чтобы показать свою схему., @Maximilian Gerhardt

извините за задержку, хорошо, кнопки идут к GND и к входным контактам 2 и 3 (есть 2 кнопки с 1 по 2 и с 1 по 3), @Richard

затем сервопривод отрывается от 12 и также подключается к GND и +5v, @Richard

@Richard Когда вы редактируете свой вопрос, вы заметите кнопку инструмента «Схема», с помощью которой вы можете точно представить свою схему., @Maximilian Gerhardt

@Richard, в моем ответе в операторе if была ошибка копирования-вставки, которая могла привести к сбою. Повторите попытку., @Maximilian Gerhardt


1

Это решение похоже на решение @Maximilian Gerhardt. Так что его комментарии о подтягивающих/понижающих резисторах применимы.

Я предполагаю, что вы хотите вращать только CW или CC и не колебаться между ними.

Тогда вы должны выполнить 4 условия кнопки:
Ни один из них не нажат, только CW, только CC, оба нажаты.

Нам нужно беспокоиться только об условиях "только нажатие" и состоянии по умолчанию при кодировании.

Вот мое решение:

void loop()
{
  buttonStateCW = digitalRead(buttonPinCW);
  buttonStateCC = digitalRead(buttonPinCC);

  // нажата только кнопка CW
  if (buttonStateCW == HIGH && buttonStateCC == LOW) {
    myservo.write(crSpeedCW); // вращение по часовой стрелке
  }
  // Только нажата кнопка CC
  else if (buttonStateCW == LOW && buttonStateCC == HIGH) {
    myservo.write(crSpeedCC); // вращение против часовой стрелки
  }
  // Условие по умолчанию
  else {
    myservo.write(crSpeedDefault);
  }
}
,