Прерывания в Critical Statements

Я переделал предыдущий скетч Arduino, который я опубликовал, в котором у меня были проблемы с захватом количества кодировщиков в критических заявлениях, не удавалось правильно прикреплять и отсоединять прерывания. Я изучил различные скетчи ISR, но не смог создать ничего, что отвечало бы моим потребностям.

Теперь у меня есть корпус переключателя, в котором двигатель постоянного тока с кодером CPR правильно вращается взад и вперед между указанными границами, если он один находится в пустом контуре. Однако, будучи заключенным в критическое утверждение (я хочу, чтобы это действие происходило только при нажатии кнопки), двигатель постоянного тока продолжает вращаться только в одном направлении.

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

#define enA 9
#define in1 6
#define in2 7

const int button1Pin = 8;

int button1State = 0;     

volatile long temp, counter = 0;

long local_counter=counter;

enum {IdleState, ForwardState, BackwardState} State;

void setup() {
  
  Serial.begin(9600);
  
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);

  Serial.begin (9600);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  
  attachInterrupt(0, ai0, RISING);
  attachInterrupt(1, ai1, RISING);

  pinMode(button1Pin, INPUT);

  State = IdleState;
}

void loop() {

  button1State = digitalRead(button1Pin);

   if( counter != temp ){
   Serial.print("counter = ");
   Serial.print (counter);
   Serial.print("     local counter = ");
   Serial.println(local_counter);
   temp = counter;
   }

   //if (button1State == HIGH) {

          switch (State) {
            
              case IdleState:
                halt ();
        
              if (counter<2000)
                State = ForwardState;
              break;
        
              case ForwardState:
                clockwise();
                         
              if (counter>=2000)
                State = BackwardState;
              break;
        
              case BackwardState:
                counterclockwise();

              if (counter <=0)
                State = ForwardState;
              break;   
           
          } // end switch
   //  }

}

void ai0() {
  if(digitalRead(3)==LOW) {
  counter++;
  }else{
  counter--;
  }
  }
   
void ai1() {
  if(digitalRead(2)==LOW) {
  counter--; 
  }else{
  counter++;
  }
  }

void clockwise (){
    analogWrite(enA, 255);
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
  }

void counterclockwise () {
    analogWrite(enA, 255);
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
  }

void halt () {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
}

Объяснение моей настройки выглядит следующим образом:

Моя кнопка-это тактильная кнопка на макете (подключена к контакту 8 Arduino Uno) с питанием 5 В от Arduino. Контакты 6 Arduino подключены к входу 1 драйвера двигателя L298N, вывод 7 Arduino подключен к входу 2 драйвера двигателя, а вывод 9 Adruino подключен к разъему включения драйвера двигателя. Их драйвер двигателя питается от внешнего источника питания 12 В, который также питает мотор-редуктор постоянного тока 12 В с энкодером. Выходы кодера подключены к контактам 2 и 3 Arduino.

, 👍4

Обсуждение

что такое критическое утверждение?, @jsotola

Для остановки не следует ли вам отключить этот контакт включения?, @Delta_G

Установка НИЗКОГО значения in1 и ВЫСОКОГО значения on2 в "halt ()" кажется неправильной, @Sim Son


1 ответ


2

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

if (button1State == LOW ) {
  State = IdleState;
  counter=2000;
}
else if(button1State==HIGH && State==IdleState ) {
  counter = 0;
}

switch(State) {
  ...

В зависимости от того, что вы хотите сделать, вы можете добавить другое состояние (скажем,StoppedState), в котором двигатели остановлены, как в режиме ожидания, но вы не получите изменения состояния, если счетчик<2000. Тогда вам не нужно менять переменную счетчика.

if (button1State == LOW ) {
  State = StoppedState;
}
else if(button1State==HIGH && State==StoppedState ) {
  State = IdleState;
}

switch(State) {
  case StoppedState:
    halt ();
    break;
  case IdleState:
    ...

PS пожалуйста, сделайте отступы в утверждениях if внутри вашего делаs.

,

На самом деле я хочу, чтобы он непрерывно вращался вперед и назад, даже после нажатия кнопки. Позже я планирую добавить кнопки для остановки и поворота в одном указанном направлении. Итак, если я хочу, чтобы это непрерывное движение вперед и назад продолжалось после нажатия кнопки, следует ли изменить первое утверждение IF (кнопка == НИЗКИЙ)? Я пытался удалить его, но это не помогает., @wickedhurricane

Какая часть вашего кода заставит его остановиться и пойти другим путем? Это внутри оператора if, который выполняется только при нажатии кнопки? Тогда это произойдет только в том случае, если кнопка не нажата. Позвольте кнопке нажать выбрать состояние. Пусть переключатель работает все время., @Delta_G

Я полагаю, что это должна быть первая часть инструкции IF для того, когда кнопка находится на низком уровне, поскольку "счетчик=2000" - условие для движения против часовой стрелки. Я пытался изменить или удалить это условие без какого-либо успеха. Должен ли я больше сосредоточиться на втором предложении Гербена? Похоже, он ведет себя так же, как и первый в моих попытках., @wickedhurricane

Я в замешательстве. Вы хотите, чтобы двигатель ничего не делал, пока не будет нажата кнопка? А затем переходить туда и обратно, независимо от того, нажата кнопка или нет? Если это так, перейдите ко второму решению, но опустите "State = StoppedState;" в операторе if и поместите это в настройку (вместо State = IdleState)., @Gerben

Ты выйдешь за меня замуж, Гербен???!!! Это именно то, чего я хотел, и это сработало!!! Но медовый месяц длится недолго, я добавил вторую кнопку, чтобы остановиться, но все, что она делает, это поворачивается против часовой стрелки при нажатии: если(button2State==ВЫСОКИЙ){ Состояние = остановленное состояние; } Будет ли корпус коммутатора не работать с этой настройкой?, @wickedhurricane

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

Извините, я по натуре человек сбивающий с толку, но была также проблема с моим кодом для остановки (), который я исправил, и теперь моя вторая кнопка правильно останавливает двигатель. Но я добавил третью кнопку, при нажатии я хочу, чтобы двигатель непрерывно двигался по часовой стрелке, поэтому я добавил следующее: если(button3State==ВЫСОКИЙ){по часовой стрелке ();}, но это ничего не делает. Должен ли я создать другое состояние или функцию void? <-- но мне это кажется необходимым. Я действительно могу опубликовать это как еще один вопрос, если вы чувствуете, что это лучше всего., @wickedhurricane

Похоже, ты решил нашу проблему с медовым месяцем. Для третьей задачи используйте вместо этого " while(button3State==HIGH){по часовой стрелке ();}". Таким образом, оператор switch не вызывается сразу после него и отрицает вращение по часовой стрелке. Добавление отдельного состояния также будет работать и, вероятно, приведет к более приятному и легкому для чтения коду., @Gerben

Это сработало; однако оно не прерывается действием кнопки 3 при нажатии кнопки 1 или 2. Я также попробовал это: в то время как(button3State==ВЫСОКИЙ&&button1State==НИЗКИЙ&&button2State==НИЗКИЙ){ по часовой стрелке();} но это действительно ничего не меняет. Мы так близки!!!, @wickedhurricane

Я добавил другое состояние, и кнопка 3 работает, но затем кнопка 1 больше не работает ПОСЛЕ нажатия кнопки 3 (кнопка 2 работает в любое время)., @wickedhurricane

Неважно, я понял это....и под "я" я имею в виду 99% StackExchange и 1% меня. У меня возникла проблема со значением счетчика, его нужно было сбросить до 0, прежде чем кнопка 1 сможет нормально работать. Я не могу отблагодарить вас всех как следует, потому что теперь мы можем разойтись в разные стороны...Я думаю, мы разводимся :(, @wickedhurricane

Это было на 100% то, что искал SE. Так что "Ты" решил это на 100% самостоятельно. Я думаю, этому не суждено было случиться ;-p, @Gerben