Остановка/запуск двигателя постоянного тока с концевыми выключателями и кнопкой включения/выключения

У меня есть Arduino UNO с 3 подключенными переключателями (2 концевых выключателя, 1 переключатель активации). Я пытаюсь заставить переключатель активации повернуть двигатель вперед после нажатия, затем дождаться нажатия любого из конечных выключателей и остановить двигатель. Следующий шаг состоит в том, чтобы дождаться повторного нажатия на переключатель активации и повернуть двигатель в противоположном направлении, дождаться нажатия на концевой переключатель и остановить двигатель.

Но проблема, с которой я сталкиваюсь прямо сейчас, заключается в том, что я нажимаю переключатель активации платы arduino и перезагружаю плату моста H. Индикатор включается и выключается, и код перезапускается. И ничего не происходит. Я знаю, что все переключатели и двигатель работают, потому что я протестировал их, упростив код только с помощью функций.

(править) Вот изображение схемы: Schematic View

Может ли кто-нибудь, пожалуйста, просмотреть мой код ниже, чтобы убедиться, что моя логика верна.

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();
    }
  }
}

, 👍6

Обсуждение

Добро пожаловать в 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


4 ответа


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

4

Я знаю, что это было открыто много лет назад, но я просто хотел добавить некоторые пояснения. Когда я начал этот проект и создал этот вопрос, я плохо разбирался в разработке программного обеспечения и не понимал код, который я писал в то время. Теперь, 3 года спустя, я несколько раз пересматривал этот проект.

Логика для такого проекта довольно проста, но если вы новичок в программировании и пытаетесь проникнуть в область STEM с помощью школьных проектов Arduino и тому подобного, вот как теперь выглядит мой код для этого же проекта: https://github.com/LeehamElectronics/Automated-Cabinet

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

Если вы столкнулись с аналогичной проблемой в своем собственном проекте, я бы посоветовал вам посмотреть бесплатный видеокурс YouTube по программированию на C++ или даже видеокурс по программированию на Arduino. Даже нескольких часов на это будет достаточно, чтобы начать. Это единственное, что я хотел бы, чтобы кто-нибудь сказал мне делать, когда я начинал 3 года назад, я тратил часы и часы на отладку кода, который я не понимал, потому что я просто прыгнул прямо в Arduino, плохо разбираясь в кодировании.

Я надеюсь, что этот комментарий поможет кому-то еще в подобной ситуации, как у меня 3 года назад.

Ура

,

5

Проверьте, есть ли у ваших переключателей подтягивающие резисторы

Было бы полезно, если бы ваш вопрос включал схему. Есть ли у вас подтягивающие резисторы в соответствии с вашими активационными и концевыми выключателями? Если нет, вы можете обнаружить, что входные данные "плавающие", то есть они будут случайным образом возвращать либо ВЫСОКИЕ, либо НИЗКИЕ значения. Это, возможно, приведет к тому, что двигатель будет двигаться вперед и назад, но поскольку цикл, возможно, происходит сотни раз в секунду, вы можете не видеть ничего движущегося. Вам нужны повышающие или понижающие резисторы в схеме, чтобы 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


3

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

// 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


3

Это отличный проект. Отличная работа.

Некоторые предложения по улучшению. Вы можете использовать байт класса перечисления вместо строки для указания положения ящика и направления перемещения ящика:

/* 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