4

I've redone a previous Arduino sketch I posted in which I was having trouble capturing encoder counts within critical statements, having no luck properly attaching and detaching interrupts. I've studied various ISR sketches but haven't been able to produce anything that caters to my needs.

I now have a switch case in which a DC motor with CPR encoder correctly rotates back and forth between specified boundaries if it alone is in the void loop. However, once enclosed within a critical statement (I want this action to occur only if a button is pressed), the DC motor continues to rotate only one direction.

I need assistance in where to properly attach and detach these interrupts and how to correctly pass the encoder value to the next action. Below is what I've done so far and any help would greatly be appreciated.

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

An explanation of my setup is as follows:

My button is a tactile button on breadboard (connected to pin 8 of an Arduino Uno), with 5V supply from Arduino. Pins 6 of the Arduino is connected input 1 of the L298N motor driver, pin 7 of Arduino connected to input 2 of the motor driver, and pin 9 of the Adruino connected to the enable of the motor driver. Them motor driver is being supplied by an external 12V supply which is also power the 12V DC geared motor with encoder. The encoder outputs are connected to pin 2 and 3 of the Arduino.

3
  • 1
    what is a critical statement?
    – jsotola
    Commented Sep 12, 2020 at 1:04
  • For halt shouldn’t you turn that Enable pin back off?
    – Delta_G
    Commented Sep 12, 2020 at 17:00
  • Setting in1 LOW and on2 HIGH in halt() doesn't seem to be correct
    – Sim Son
    Commented Sep 12, 2020 at 21:07

1 Answer 1

2

The way I see it, the state should go back to IdleState if the button is not pressed. Just putting the switch-case inside the if-statement will result in the motor continue rotating the way it was rotating when the button is released.

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

switch(State) {
  ...

Depending on what it is you want to do, you might want to add another state (say StoppedState), where the motors are halted, just like IdleState, but you don't get a state change if counter<2000. Then you don't have to change the counter variable.

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

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

PS please indent the if statements inside you cases.

12
  • 1
    What part of your code would make it stop and go the other way? Is that inside an if statement that only executes if the button is pressed? Then it will only happen if button isn’t pressed. Let button press choose a state. Let the switch run all the time.
    – Delta_G
    Commented Sep 12, 2020 at 17:59
  • 1
    I'm confused. Do you want to motor to do nothing, until the button is pressed? And then go back and forth no matter whether the button is pressed or not? If that's the case, go with the second solution, but leave out the State = StoppedState; in the if statement, and put that in the setup (instead of State = IdleState).
    – Gerben
    Commented Sep 13, 2020 at 13:27
  • 1
    Will you marry me Gerben???!!! That's exactly what I wanted and it worked!!! But the honeymoon is short lived I added a second button to stop, but all it does is rotate counterclockwise when pressed: if(button2State==HIGH){ State = StoppedState; } Will the switch case not work with this setup? Commented Sep 13, 2020 at 15:46
  • 1
    Sorry, I'm a confusing person by nature, but there was also a problem with my code for halt (), which I corrected and now my second button correctly stops the motor. But I've added a third button, when pressed, I want the motor to move continuously clockwise, so I added this: if(button3State==HIGH){clockwise();} but it doesn't do anything. Should I create another state or void function? <-- but that seems necessary to me. I can indeed post this as another question if you feel it best. Commented Sep 14, 2020 at 18:01
  • 1
    That did work; however, it doesn't break from button 3 action when button 1 or 2 is pressed. I also tried this: while(button3State==HIGH&&button1State==LOW&&button2State==LOW){ clockwise();} but this really doesn't change anything. We're so close!!! Commented Sep 14, 2020 at 18:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.