Остановка/запуск двигателя постоянного тока с концевыми выключателями и кнопкой включения/выключения
У меня есть Arduino UNO с 3 подключенными переключателями (2 концевых выключателя, 1 переключатель активации). Я пытаюсь заставить переключатель активации повернуть двигатель вперед после нажатия, затем дождаться нажатия любого из конечных выключателей и остановить двигатель. Следующий шаг состоит в том, чтобы дождаться повторного нажатия на переключатель активации и повернуть двигатель в противоположном направлении, дождаться нажатия на концевой переключатель и остановить двигатель.
Но проблема, с которой я сталкиваюсь прямо сейчас, заключается в том, что я нажимаю переключатель активации платы arduino и перезагружаю плату моста H. Индикатор включается и выключается, и код перезапускается. И ничего не происходит. Я знаю, что все переключатели и двигатель работают, потому что я протестировал их, упростив код только с помощью функций.
(править) Вот изображение схемы:
Может ли кто-нибудь, пожалуйста, просмотреть мой код ниже, чтобы убедиться, что моя логика верна.
const byte frontButtonPin = 2;
const byte backButtonPin = 4;
const byte onOffButtonPin = 11;
const int motorPin = 8;
const int motorPin2 = 7;
boolean frontButtonState = 0;
boolean backButtonState = 0;
boolean onOffButtonState = 0;
/**
setup inputs for switches and outs for motor pins
serial begin to read the switches to test for errors
*/
void setup() {
// initialize the pin as an inputs:
pinMode(motorPin, OUTPUT);
pinMode(motorPin2, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(frontButtonPin, INPUT);
pinMode(backButtonPin, INPUT);
pinMode(onOffButtonPin, INPUT);
Serial.begin(9600);
}
/**
this function turns motor foward
*/
void drawMovesForward() {
// turn motor foward:
digitalWrite(motorPin, LOW);
digitalWrite(motorPin2, HIGH);
}
/**
this function turns motor backwards
*/
void drawMovesBackward() {
// turn motor in other direction:
digitalWrite(motorPin, HIGH);
digitalWrite(motorPin2, LOW);
}
/**
Stop the motor form moving
*/
void stopDrawFromMoving() {
digitalWrite(motorPin, LOW);
digitalWrite(motorPin2, LOW);
}
/**
*/
void loop() {
frontButtonState = digitalRead(frontButtonPin);
backButtonState = digitalRead(backButtonPin);
onOffButtonState = digitalRead(onOffButtonPin);
if (onOffButtonState == HIGH) {
if ( frontButtonState == LOW ) {
drawMovesForward();
}
else if (backButtonState == LOW ) {
drawMovesBackward();
}
}
else {
if ( frontButtonState == HIGH ) {
stopDrawFromMoving();
}
else if (backButtonState == HIGH ) {
stopDrawFromMoving();
}
}
}
@Leeham, 👍6
Обсуждение4 ответа
Лучший ответ:
Я знаю, что это было открыто много лет назад, но я просто хотел добавить некоторые пояснения. Когда я начал этот проект и создал этот вопрос, я плохо разбирался в разработке программного обеспечения и не понимал код, который я писал в то время. Теперь, 3 года спустя, я несколько раз пересматривал этот проект.
Логика для такого проекта довольно проста, но если вы новичок в программировании и пытаетесь проникнуть в область STEM с помощью школьных проектов Arduino и тому подобного, вот как теперь выглядит мой код для этого же проекта: https://github.com/LeehamElectronics/Automated-Cabinet
Я постарался прокомментировать это как можно лучше, чтобы помочь другим студентам понять это. Проект представляет собой просто деревянный шкаф с электрической автоматической вытяжкой внутри, который можно открывать и закрывать по желанию.
Если вы столкнулись с аналогичной проблемой в своем собственном проекте, я бы посоветовал вам посмотреть бесплатный видеокурс YouTube по программированию на C++ или даже видеокурс по программированию на Arduino. Даже нескольких часов на это будет достаточно, чтобы начать. Это единственное, что я хотел бы, чтобы кто-нибудь сказал мне делать, когда я начинал 3 года назад, я тратил часы и часы на отладку кода, который я не понимал, потому что я просто прыгнул прямо в Arduino, плохо разбираясь в кодировании.
Я надеюсь, что этот комментарий поможет кому-то еще в подобной ситуации, как у меня 3 года назад.
Ура
Проверьте, есть ли у ваших переключателей подтягивающие резисторы
Было бы полезно, если бы ваш вопрос включал схему. Есть ли у вас подтягивающие резисторы в соответствии с вашими активационными и концевыми выключателями? Если нет, вы можете обнаружить, что входные данные "плавающие", то есть они будут случайным образом возвращать либо ВЫСОКИЕ, либо НИЗКИЕ значения. Это, возможно, приведет к тому, что двигатель будет двигаться вперед и назад, но поскольку цикл, возможно, происходит сотни раз в секунду, вы можете не видеть ничего движущегося. Вам нужны повышающие или понижающие резисторы в схеме, чтобы Arduino мог видеть определенный НИЗКИЙ или ВЫСОКИЙ уровень. Видишь https://www.arduino.cc/en/Tutorial/Button для урока с резистором или даже лучше используйте https://www.arduino.cc/en/Tutorial/InputPullupSerial и используйте существующие бортовые импульсные резисторы на Arduino, как предложил Юрай ниже.
Потенциальная Логическая Ошибка
В этой части кода может быть логическая ошибка:
if (onOffButtonState == HIGH) {
if ( frontButtonState == LOW ) {
drawMovesForward();
}
else if (backButtonState == LOW ) {
drawMovesBackward();
}
}
else {
if ( frontButtonState == HIGH ) {
stopDrawFromMoving();
}
else if (backButtonState == HIGH ) {
stopDrawFromMoving();
}
}
Цикл №1: Допустим, состояние кнопки включения ВЕЛИКО (кто - то нажал переключатель в положение ВКЛ.). Ящик закрыт, поэтому передний концевой выключатель нажат, поэтому состояние передней кнопки ВЫСОКОЕ. Таким образом, программа выполнит stopDrawFromMovingи ничего не сделает. В настоящее время вы говорите, что ничего не происходит, так что это может быть вашей проблемой.
Что вам, вероятно, понадобится сделать, так это использовать флаги и циклы while. Например:
В начале цикла() объявите это
drawerMovingOutFlag = 1;
Затем измените цикл, чтобы он содержал:
if (onOffButtonState == HIGH) {
if ( frontButtonState == HIGH ) {
while(drawerMovingOutFlag == 1)
drawMovesForward();
if ( backButtonState == HIGH ) {
drawerMovingOutFlag = 0;
stopDrawFromMoving()
}
}
}
else ...
Я позволю тебе сделать все остальное!
только не этот учебник по кнопкам, пожалуйста. используйте учебник input_pullup https://www.arduino.cc/en/Tutorial/InputPullupSerial, @Juraj
Эй, спасибо за быстрый ответ. Да, у меня резисторы снижаются до GND на всех 3 переключателях. И я использовал последовательные мониторы, чтобы проверить все переключатели, и они работают и считываются правильно., @Leeham
Сейчас я работаю над схемой (:, @Leeham
Схема загружена (: Спасибо за вашу помощь, @Leeham
На самом деле у меня все время был правильный код, но мне просто пришлось добавить задержки при считывании конечных переключателей и обнаружении переключателей активации. Вот одна из оригинальных программ, которые я написал, которую я выбросил, думая, что она не работает, но как только были добавлены задержки, она отлично работает.
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 4; // the number of the pushbutton pin
const int buttonPin3 = 11; // the number of the pushbutton pin
const int buttonPin2 = 2; // the number of the pushbutton pin
const int motorPin = 8; // the number of the LED pin
const int motorPin2 = 7; // the number of the LED pin
// variables will change:
boolean buttonState = 0; // variable for reading the pushbutton status
boolean buttonState2 = 0; // variable for reading the pushbutton status
boolean buttonState3 = 0; // variable for reading the pushbutton status
int drawPosition = 2; // Tells progam what position the draw is in
/**
* setup inputs for switches and outs for motor pins
* serial begin to read the switches to test for errors
*/
void setup() {
// initialize the pin as an inputs:
pinMode(motorPin, OUTPUT);
pinMode(motorPin2, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
Serial.begin(9600);
}
/**
* this function turns motor foward
*/
void drawForward() {
// turn motor foward:
digitalWrite(motorPin, LOW);
digitalWrite(motorPin2, HIGH);
}
/**
* this function turns motor backwards
*/
void drawBackward() {
// turn motor in other direction:
digitalWrite(motorPin, HIGH);
digitalWrite(motorPin2, LOW);
}
/**
* Stop the motor form moving
*/
void stopDrawFromMoving() {
digitalWrite(motorPin, LOW);
digitalWrite(motorPin2, LOW);
}
/**
*
*/
void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH) {
drawPosition = 2;
Serial.println(F("Front button state is high draw is open"));
stopDrawFromMoving();
}else if (buttonState2 == HIGH) {
drawPosition = 1;
stopDrawFromMoving();
}
if (buttonState3 == HIGH) {
if( drawPosition == 1 ){
drawBackward();
delay(100);
drawPosition = 2;
delay(100);
}else if (drawPosition == 2 ) {
delay(100);
drawForward();
delay(100);
drawPosition = 1;
}
}
}
Пожалуйста, "Отметьте это как ответ", потому что это реальный ответ на вашу проблему., @MechtEngineer
Это отличный проект. Отличная работа.
Некоторые предложения по улучшению. Вы можете использовать байт класса перечисления
вместо строки
для указания положения ящика и направления перемещения ящика:
/* Allows the program to keep track of the last known position of the drawer */
enum class DrawerPositions : byte
{
Closed,
Open
} drawerPosition = DrawerPositions::Closed;
/* Keep track of what direction the drawer is moving, can one of the following: Null | Closing | Opening */
enum class DrawerMovingDirections : byte
{
Null,
Closing,
Opening
} drawerMovingDirection = DrawerMovingDirections::Null;
...
if (drawerPosition == DrawerPositions::Closed)
...
else if (drawerPosition == DrawerPositions::Open)
...
if (drawerMovingDirection == DrawerMovingDirections::Opening)
...
Также было бы неплохо добавить отключение для всех входов коммутатора. В Интернете есть много алгоритмов дебоунсинга, но вот очень простой дебоунсер, который я разместил на GitHub, который можно было бы реализовать примерно так:
#include "Debouncer.h"
...
void loop()
{
static Debouncer limitSwitch0(limitSwitchPin0);
static Debouncer limitSwitch1(limitSwitchPin1);
static Debouncer manualToggleButton(manualToggleButtonPin);
limitSwitch0.Update();
limitSwitch1.Update();
manualToggleButton.Update();
if (drawerIsMoving == true)
{
if (drawerMovingDirection == DrawerMovingDirections::Opening)
{
if (limitSwitch0.Output() == LOW) // Get the debounced output of the switch.
{
drawerPosition = DrawerPositions::Open;
...
if(manualToggleButton.Rise()) // For rising edge trigger.
//if(manualToggleButton.Fall()) // For falling edge trigger.
{
...
}
...
}
Вот демо-версия дебюта, которую я поставил на Wokwi.
Спасибо за ваш совет. Я предполагаю, что часть моей лени от Python проникла в мою работу на c++, делая глупые вещи, такие как использование ссылочных типов для хранения, эффективно 1 и 0. Я определенно должен использовать примитивный тип, такой как байт, как вы упомянули, я, скорее всего, скоро внесу эти изменения. Что касается дебоша, у меня на самом деле не было необходимости часто его использовать, но я знаю, что должен, я добавлю это в список дел. Спасибо!!, @Leeham
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как устранить шум от вентилятора 12 В с ШИМ-управлением на низкой скорости
- Вопрос о различных способах подключения платы драйвера двигателя L298N к Arduino и двигателям и их питания.
- Обратное вращение шагового двигателя
- Неиспользуемые контакты в Arduino L293D motor shield?
- Arduino uno + cnc Shield v3 + драйвер шагового двигателя A4988 + AccelStepper?
- Как заставить сервопривод вращаться на угол больше 180°
- Почему Adafruit motor shield не крутит моторы?
Добро пожаловать в StackExchange. Я рад сказать, что вы отлично начали, отформатировав свой код и подробно описав свою проблему в описании. Твоя логика мне нравится. Чтобы начать устранение неполадок, я бы поместил инструкции println() в каждую из функций и попытался выяснить, где висит программа. Когда вы говорите "Светодиоды включаются и выключаются", какие светодиоды вы имеете в виду? Здесь схема может помочь нам в устранении неполадок, но вы упомянули, что детали работают сами по себе., @MechtEngineer
Предположительно, в настоящее время вы проводите тестирование с отсоединенными деталями (не установленными в ящике?). Это значительно облегчает определение того, что происходит не так., @MechtEngineer
Спасибо, у меня был профессиональный программист, который помог мне запрограммировать Arduino, но он никогда раньше не использовал материалы Arduino, поэтому он рекомендовал использовать этот веб-сайт для поиска советов других людей. Светодиоды-это светодиоды на плате arduino. они снова включаются и выключаются, и платы arduino сбрасываются (они выключаются и снова выключаются) при нажатии на задний концевой выключатель, и я одновременно нажимаю на переключатель включения/выключения., @Leeham
Можете ли вы отредактировать свой вопрос, чтобы указать, использует ли схема "переключатель" или кнопочный переключатель активации? Я предполагаю, что это переключатель "тумблер", так как в противном случае ваш код будет работать только при удержании нажатой кнопки., @MechtEngineer
Да, там просто мгновенные кнопки, нажмите кнопку и отпустите. Кроме того, я действительно исправил код, и теперь он работает нормально. Должен ли я обновить исходное сообщение, чтобы сказать "проблема решена", а затем вставить код и как я его исправил? или мне сделать это где-нибудь в другом месте?, @Leeham
Это блестящая новость! Если вы решили ответ, пожалуйста, опубликуйте новый ответ ниже с вашим решением (как вы его решили и ваш последний код), чтобы помочь кому-либо еще в той же проблеме. Ваш ответ затем поднимется на вершину, чтобы люди могли увидеть, каким было решение. Затем "отметьте свой ответ" (выберите значок галочки/галочки) и озвучьте любые другие вопросы или ответы, которые вы найдете полезными на сайте (у вас может еще не быть привилегий, но скоро вы их получите). Отличная работа!, @MechtEngineer
В настоящее время я работаю над проектом "тупой официант". кажется, все идет гладко, когда я сделал симуляцию на макете и с помощью кнопок. Как только я заменил некоторые кнопки (переключатель для каждого этажа) на концевые выключатели, все пошло не так. а потом я прочитал этот пост, и это спасло меня. все, что мне нужно, - это просто "задержка(100)" внутри цикла . спасибо, Чувак., @andi yunus
Каков правильный код для этого проекта, который работает правильно? Я хотел бы попробовать это, спасибо., @Chris Brand
@andiyunus Это может исправить проблему на данный момент, но это не правильный способ сделать это, и вы можете столкнуться с проблемами в будущем. Реальный способ исправить это-использовать деблокирование в вашем коде (google that), а также подтягивающие (или опускающие) резисторы на ваших концевых выключателях., @Leeham
@ChrisBrand Я продолжал добавлять к этому проекту на протяжении многих лет, так что он стал немного сложнее. Вы можете просмотреть исходный код здесь, в [репо](https://github.com/LeehamElectronics/Automated-Cabinet):, @Leeham