3

I'm new both to this forum and to Arduino. My robot is comprised of Arduino Uno with Arduino Motor Shield, 12V DC gear motor, and two limit switches. The robot supposed to move endlessly on rails between the two walls back-and-forth. I have it all wired up and am able to switch the directions of the motor's rotation by pushing the limit switches. However, I also want to have a pause between switching of directions:

... Robot moving forward ...

If front limit switch is pushed
Stop motor
Pause 2 seconds
Run motor CCW

... Robot moving backwards ...

If rear limit switch is pushed
Stop motor
Pause 2 seconds
Run motor CW

... Robot moving forward ...

Simple delay(2000) doesn't work as the limit switch remains pushed against the wall. I've been trying out millis() approach but the fact that limit switch remains pushed (HIGH) I can never produce a difference in time needed to trigger an action. I learned about State Machine but not sure if and how this could help my case?

Can anyone please help me in implementing a two second pause between the switching of the motor's direction?

Below is the code that momentarily switches the motor's direction when robot reaches the wall and limit switch is pushed.

int switchFront_State = 0;
int switchRear_State = 0;

const int ledYellow = 6;
const int ledGreen = 5;

const int switchFront = 4;
const int switchRear = 2;

const int motorDirection = 12;
const int motorBreak = 9;
const int motorPWM = 3;

void setup() {
  Serial.begin (9600);

  pinMode(switchFront, INPUT_PULLUP); // Front switch
  pinMode(switchRear, INPUT_PULLUP); // Rear switch

  pinMode(ledYellow, OUTPUT);
  pinMode(ledGreen, OUTPUT);

  // Setup Channel A
  pinMode(motorDirection, OUTPUT); // Motor direction pin
  pinMode(motorBreak, OUTPUT); // Motor break pin
  pinMode(motorPWM, OUTPUT); // Motor PWM pin
}

void runMotorBackward(){ // Motor moving backward
  digitalWrite(motorDirection, LOW);
  digitalWrite(motorBreak, LOW);
  digitalWrite(motorPWM, 128);
}

void motorStop(){ // Stop motor
  digitalWrite(motorBreak, HIGH);
  digitalWrite(motorPWM, 0);
}

void runMotorForward(){ // Motor moving forward
  digitalWrite(motorDirection, HIGH);
  digitalWrite(motorBreak, LOW);
  digitalWrite(motorPWM, 128);
}

void loop(){
  switchFront_State = digitalRead (switchFront);
  switchRear_State = digitalRead (switchRear);

  if (switchFront_State == HIGH){ // If front switch is pressed
    digitalWrite(ledYellow, HIGH); // Yellow LED
    motorStop();
    runMotorBackward();
    } else {
    digitalWrite(ledYellow, LOW);
  }

  if (switchRear_State == HIGH){ // If rear switch is pressed
    digitalWrite(ledGreen, HIGH); // Green LED
    motorStop();
    runMotorForward();
  } else {
    digitalWrite(ledGreen, LOW);
  }
}
  • Have you considered using a full state machine rather than just sensing the states of the switches? – Ignacio Vazquez-Abrams Nov 11 '16 at 11:34
  • I don't get why delay(2000) does work? – Gerben Nov 11 '16 at 14:35
  • Gerben, delay(2000) works but it requires limit switch to be in LOW position in order for motor to run again. Originally, I tried placing delay(2000) between motorStop() and runMotorForward() / runMotorBackward() which worked but not in the useful way for me. In other words, the delay would be fired if the limit switch is pushed (HIGH) but the motor wouldn't start running again till the limit switch is released again (LOW). – Dragan Miletic Nov 11 '16 at 22:40
  • Ignacio Vazquez-Abrams, I'm not sure what do you mean by "full state machine?" As I suggested, I'm new to Arduino and programming in general. – Dragan Miletic Nov 11 '16 at 22:41
2

I think the problem is because there is no delay time after your motor switch its direction, so the robot is stay on position where the switch is pressed. I don't know if this gonna work, but perhaps you can add delay after the direction changed.
But based on your code, I can't find a condition to run if no switch is pressed. For alternative, you can try this

int direction_state = 1; //state where robot moves forward

void loop(){

  /*notes that here I assume while robot moving forward,
   *the rear switch is impossible to pressed, so does while
   *robot moving backward, the front switch is impossible to
   *pressed.
   */

  while ((digitalRead (switchRear)==LOW) && (digitalRead (switchFront)==LOW))
  //no switch pressed, loop will break if any switch pressed
    {
      if (direction_state == 1) runMotorForward(); else
                                runMotorBackward();
    }

  //indicator which switch is pressed and start of 2s motor stops
  if (direction_state==1) digitalWrite(ledYellow,HIGH); 
  else digitalWrite(ledGreen,HIGH);

  motorStop(); //stop the motor
  delay(2000);

  //indicator 2s motor stops finished
  if (direction_state==1) digitalWrite(ledYellow,LOW); //indicator front switch is pressed
  else digitalWrite(ledGreen,LOW);

  direction_state = -direction_state //toggle the state
  if (direction_state == 1) runMotorForward(); else
                            runMotorBackward();

  delay(2000);

}    

Feel free to ask if it's not works

  • Well, your suggestion above is exactly what doesn't work, adding i.e. delay(2000); after runMotorForward() / runMotorBackward() is not firing at all. Originally, I tried placing delay(2000) between motorStop() and runMotorForward() / runMotorBackward() which worked but not in the useful way for me. In other words, the delay would be fired if the limit switch is pushed (HIGH) but the motor wouldn't start running again till the limit switch is released again (LOW). As I described above, this is not an option as robot will get stuck first time it reaches a wall. The 2nd code doesn't have pause? – Dragan Miletic Nov 11 '16 at 22:39
  • dpw, if you look at my code you'll realize that pressing on either limit switch (by hand) will set the robot in motion. I power the robot, it's not moving, then i press say the front limit switch and robot immediately starts to move backwards, hits the rear wall, changes the direction, runs towards the front wall, hits the front wall, changes the direction... endlessly, or as long as it is powered. All I want is that the robot pauses for two seconds when it hits the wall instead of just "bouncing" off of it. – Dragan Miletic Nov 11 '16 at 22:50
  • 1
    Hi Dragan, I've edited the answers. Perhaps you can try it – dhimaspw Nov 13 '16 at 3:01
  • 1
    Hi dpw, thank you sooooo very much for the corrected code. I uploaded it and it works EXACTLY the way I want!!! BTW, would it be possible to make switchRear to only switch motor to run forward and similarly that switchFront only switches motor to run backward. As of now, the directions could be confused if a "wrong" switch is pressed by accident. – Dragan Miletic Nov 14 '16 at 11:16
  • Sure it can, you can modify the "while" condition. Happy I can help, and good luck to your project – dhimaspw Nov 14 '16 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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