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 Answer 1
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 case
s.
-
1What 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– Delta_G09/12/2020 17:59:32Commented Sep 12, 2020 at 17:59
-
1I'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 ofState = IdleState
).Gerben– Gerben09/13/2020 13:27:06Commented Sep 13, 2020 at 13:27 -
1Will 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– wickedhurricane09/13/2020 15:46:55Commented Sep 13, 2020 at 15:46
-
1Sorry, 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– wickedhurricane09/14/2020 18:01:23Commented Sep 14, 2020 at 18:01
-
1That 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– wickedhurricane09/14/2020 18:15:48Commented Sep 14, 2020 at 18:15
halt()
doesn't seem to be correct