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.

1 Answers1

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.

Gerben
  • 11,286
  • 3
  • 20
  • 34
  • I actually want it to continuously rotate back and forth, even after the button is depressed. Later, I plan to add buttons to stop and to rotate in one designated direction. So if I want this continuous back and forth motion to continue after the button is depressed, should the first IF statement (button == LOW) be altered? I've tried removing it but that doesn't do the trick. – wickedhurricane Sep 12 '20 at 17:09
  • 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 Sep 12 '20 at 17:59
  • I suppose it would have to be the first part of the IF statement for when the button is LOW, being that "counter=2000", the condition for counterclockwise motion. I've tried changing or removing that condition without any success. Should I be focusing more on Gerben's second suggestion? It seems to have a similar behavior as the first in my attempts. – wickedhurricane Sep 12 '20 at 18:50
  • 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 Sep 13 '20 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?

    – wickedhurricane Sep 13 '20 at 15:46
  • The code you've provided looks okay, so I'm not sure what the problem is. Please post your code, as I'm still a bit confused. And you marriage proposal makes me even more confused q-;. I think it would be best to create a new question. – Gerben Sep 14 '20 at 17:41
  • 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. – wickedhurricane Sep 14 '20 at 18:01
  • Seems like you fixed our honeymoon issue. For the third problem use while(button3State==HIGH){clockwise();} instead. That way the switch statement isn't called right after it, and negate the clockwise rotation. Adding a separate state would also work, and will probably result in nicer and easier to read code. – Gerben Sep 14 '20 at 18:10
  • 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!!! – wickedhurricane Sep 14 '20 at 18:15
  • I added another state, and button 3 works, but then button 1 no longer works AFTER button 3 is pressed (button 2 works at anytime). – wickedhurricane Sep 14 '20 at 18:56
  • Nevermind, I figured it out....and by "I" I mean 99% StackExchange and 1% me. I had an issue with the counter value, it needed to be reset to 0 before button 1 could properly work. I can't thank you all enough, for now we can go our separate ways...I guess we're getting divorced :( – wickedhurricane Sep 14 '20 at 19:42
  • It was 100% that searched SE. So "You" solved it 100% yourself. I guess it wasn't meant to be ;-p – Gerben Sep 15 '20 at 13:18