Camera slider auto reverse, with limit switches / kill switch

Hi there!

I'm an making a camera slider that will auto reverse, when trigging limit switches.
I am using the arduino UNO, with Arduino motor shield.

Slider is working!, but I do not know how to add this killSwitch function.
This should brake the motor, when HIGH

I am new to arduino, so my programming could probably by simplified?

const int motor = 12;                 // motor channel A on pin 12
const int brake = 9;                  // brake channel A on pin 9
const int limitBEGIN = 4;             // limit switch BEGIN on pin 4
const int limitEND = 5;               // limit switch END on pin 5
const int killSwitch = 6;             // killSwitch on pin 6

int currentSensing = A0;              // read current on motor
int limitBeginState = 0;              // variable to hold status
int limitEndState = 0;                // variable to hold status
int killSwitchState = 0;              // variable to hold status

void setup() {
  pinMode(motor, OUTPUT);     // initiates motor channel A
  pinMode(brake, OUTPUT);     // initiates brake channel A
  pinMode(limitBEGIN, INPUT); // limit switch BEGIN
  pinMode(limitEND, INPUT);   // limit switch END
  pinMode(killSwitch, INPUT); // Brake switch channel A
  Serial.begin(9600);
  Serial.println("Camera slider with limit and kill switch:\n");

}
void loop() {
  // read the state of switch:
  limitBeginState = digitalRead(limitBEGIN);
  limitEndState = digitalRead(limitEND);
  killSwitchState = digitalRead(killSwitch);

  if (killSwitchState == HIGH) {                                    // Brake out of while loop and brake the motor
    do {
      digitalWrite(brake, HIGH);
    } while (killSwitchState == HIGH);
    digitalWrite(brake, LOW);
  }

  if (limitBeginState == LOW && limitEndState == LOW) {             // limit switches LOW and LOW
    do {
      digitalWrite(motor, LOW);                                     // turn motor on clockwise:
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitEndState = digitalRead(limitEND);                        // check state of switch
    } while (limitEndState == LOW && killSwitchState == LOW);       // Do this until limitEndState changes or killSwitch is triggered
  }
  if (limitBeginState == LOW && limitEndState == HIGH) {            // limit switches LOW and HIGH
    do {
      digitalWrite(motor, LOW);                                     // turn motor on clockwise:
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitBeginState = digitalRead(limitBEGIN);                    // check state of switch
    } while (limitBeginState == LOW && killSwitchState == LOW);     // do this until limitBeginState changes or killSwitch is triggered
  }
  if (limitBeginState == HIGH && limitEndState == LOW) {            // limit switches HIGH and LOW
    do {
      digitalWrite(motor, HIGH);                                    // turn motor on counter clockwise
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitEndState = digitalRead(limitEND);
    } while (limitEndState == LOW && killSwitchState == LOW);
  }
}

All those DO WHILEs seem to be complicating stuff. I suspect none of them is necessary.

I also think the program would be easier to manage if you have a small function that controls the motor based on the values in some variables. For example (pseudo code)

void loop() {
   checkSwitches();
   moveMotor();
}

void checkSwitches() {
   // see discussion below
}

void moveMotor() {
   if (motorDirection == 'F') {
      // set for forward
   }
   else {
     // set for reverse
   }
   if (motorON == true) {
     // set for movement
   }
   else {
     // set for stop
   }
}

With that structure your code that checks the value of the switches just needs to change the value of the variables motorDirection and motorON.

...R

Thanks for the reply!

Will try to simplify the code. Regarding my DO WHILE loops: Will it jump out of while loop if killSwitchState changes from LOW to HIGH?

if (limitBeginState == LOW && limitEndState == LOW) {             // limit switches LOW and LOW
    do {
      digitalWrite(motor, LOW);                                     // turn motor on clockwise:
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitEndState = digitalRead(limitEND);                        // check state of switch
    } while (limitEndState == LOW && killSwitchState == LOW);       // Do this until limitEndState changes or killSwitch is triggered
  }

dahlei:
Thanks for the reply!

Will try to simplify the code. Regarding my DO WHILE loops: Will it jump out of while loop if killSwitchState changes from LOW to HIGH?

The code I suggested has no blocking DO WHILE so jumping out does not arise.

...R

while (limitEndState == LOW && killSwitchState == LOW)

This will either not be executed (if either conditions turn out to be false),
Or end up in there forever (if both conditions turn out to be true).

You need to:

while (limitEndState == LOW && killSwitchState == LOW) {
  limitEndState  = digitalRead(limitEND);
  killSwitchState = digitalRead(killSwitch);
}

p.s. You should also debounce your killSwitch

jbellavance:
You need to:

while (limitEndState == LOW && killSwitchState == LOW) {

limitEndState  = digitalRead(limitEND);
  killSwitchState = digitalRead(killSwitch);
}

My guess is that it can be a lot simpler than that.

...R

I understand that your camera is moving between two limit switches (back and forth?) I am not used with motors, but I can't see any code to reverse the direction of the motor.

If I am right, you have a three-state machine:

State 1: Moving from begining to end,
State 2: Moving from end to beginning,
State 3: Stopped.

endSwitch HIGH changes to state 2
beginSwitch HIGH changes to state 1
killSwitch HIGH changes to state 3
killSwitch LOW changes to state 1 or state 2

Look at this example.

Jacques

Thanks again for reply!

Regarding motor direction: It is (motor, HIGH/LOW) that determines direction. (I see I got my comments mixed up)
I can confirm that my WHILE DO loop is not function right. If I set killSwitch to HIGH and change direction on motor, it locks the brake and I have te reset the arduino.

Will work on my code, thanks for helpful comments!

I got my code to work. I put in a lot of "// check switches". Now killSwitch stops/resume the program.
Will try to make a "state machine" to simplyfy the code.

Tried to install the YAKINDU Statechart Tool, got some JAVA error before installing. I got the latest JAVA so i do not know what the issue with that is.

Is there someting embedded in Arduino software?

This is my first code, besides blinking LED's :slight_smile:

const int motor = 12;                 // motor channel A on pin 12
const int brake = 9;                  // brake channel A on pin 9
const int limitBEGIN = 4;             // limit switch BEGIN on pin 4
const int limitEND = 5;               // limit switch END on pin 5
const int killSwitch = 6;             // killSwitch on pin 6

int currentSensing = A0;              // read current on motor
int limitBeginState = 0;              // variable to hold status
int limitEndState = 0;                // variable to hold status
int killSwitchState = 0;              // variable to hold status

void setup() {
  pinMode(motor, OUTPUT);     // initiates motor channel A
  pinMode(brake, OUTPUT);     // initiates brake channel A
  pinMode(limitBEGIN, INPUT); // limit switch BEGIN
  pinMode(limitEND, INPUT);   // limit switch END
  pinMode(killSwitch, INPUT); // Brake switch channel A
  Serial.begin(9600);
  Serial.println("Camera slider with limit and kill switch:\n");

}
void loop() {
  // read the state of switch:
  limitBeginState = digitalRead(limitBEGIN);
  limitEndState = digitalRead(limitEND);
  killSwitchState = digitalRead(killSwitch);

  if (killSwitchState == HIGH) {                                    // brake out of while loop and brake the motor
    do {
      digitalWrite(brake, HIGH);
      limitBeginState = digitalRead(limitBEGIN);                    // check switches
      limitEndState = digitalRead(limitEND);                        // check switches
      killSwitchState = digitalRead(killSwitch);                    // check switches
    } while (killSwitchState == HIGH);
    limitBeginState = digitalRead(limitBEGIN);                      // check switches
    limitEndState = digitalRead(limitEND);                          // check switches
    killSwitchState = digitalRead(killSwitch);                      // check switches
    digitalWrite(brake, LOW);                                       // brake off
  }
  if (limitBeginState == LOW && limitEndState == LOW) {             // limit switches LOW and LOW
    do {
      digitalWrite(motor, LOW);                                     // turn motor on clockwise:
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitBeginState = digitalRead(limitBEGIN);                    // check switches
      limitEndState = digitalRead(limitEND);                        // check switches
      killSwitchState = digitalRead(killSwitch);                    // check switches
    } while (limitEndState == LOW && killSwitchState == LOW);       // do this until limitEndState changes or killSwitch is triggered
    limitBeginState = digitalRead(limitBEGIN);                      // check switches
    limitEndState = digitalRead(limitEND);                          // check switches
    killSwitchState = digitalRead(killSwitch);                      // check switches
  }
  if (limitBeginState == LOW && limitEndState == HIGH) {            // limit switches LOW and HIGH
    do {
      digitalWrite(motor, LOW);                                     // turn motor on clockwise:
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitBeginState = digitalRead(limitBEGIN);                    // check switches
      limitEndState = digitalRead(limitEND);                        // check switches
      killSwitchState = digitalRead(killSwitch);                    // check switches
    } while (limitBeginState == LOW && killSwitchState == LOW);     // do this until limitBeginState changes or killSwitch is triggered
    limitBeginState = digitalRead(limitBEGIN);                      // check switches
    limitEndState = digitalRead(limitEND);                          // check switches
    killSwitchState = digitalRead(killSwitch);                      // check switches
  }
  if (limitBeginState == HIGH && limitEndState == LOW) {            // limit switches HIGH and LOW
    do {
      digitalWrite(motor, HIGH);                                    // turn motor on counter clockwise
      digitalWrite(brake, LOW);                                     // brake off
      analogWrite(3, 255);                                          // full speed
      limitBeginState = digitalRead(limitBEGIN);                    // check switches
      limitEndState = digitalRead(limitEND);                        // check switches
      killSwitchState = digitalRead(killSwitch);                    // check switches
    } while (limitEndState == LOW && killSwitchState == LOW);       // do this until limitEndState changes or killSwitch is triggered
    limitBeginState = digitalRead(limitBEGIN);                      // check switches
    limitEndState = digitalRead(limitEND);                          // check switches
    killSwitchState = digitalRead(killSwitch);                      // check switches
  }
}

Thinking this is a good place to start:

Thanks again!

Be carefull with this statement:while (killSwitchState == HIGH);The semi-colon at the end says that while ends there.

Maybe you meant:

while (killSwitchState == HIGH) {
    limitBeginState = digitalRead(limitBEGIN);                      // check switches
    limitEndState = digitalRead(limitEND);                          // check switches
    killSwitchState = digitalRead(killSwitch);                      // check switches
}
digitalWrite(brake, LOW);                                           // brake off

Jacques

Thinking this is a good place to start:
http://forum.arduino.cc/index.php?topic=261445.0

Yes it is.

Aha! Thank you jbellavance that explains a lot!

In fact, you only need this:

while (killSwitchState == HIGH) {
    killSwitchState = digitalRead(killSwitch);                      // check switches
}
digitalWrite(brake, LOW);                                           // brake off

Or it's eqivalent:

while (digitalRead(killSwitch) == HIGH);
digitalWrite(brake, LOW);                                           // brake off

Jacques

Hi again!

Yes, started erasing //check switches, and the } before while, and taking away the ; so it includes the //check switches in the WHILE loop. now I am a bit confused on how the curly braces work.

Doing this cleanup ended in "expected while" in the bottom of the program.

example working code:

if (killSwitchState == HIGH) {                                    // brake out of while loop and brake the motor
    do {
      digitalWrite(brake, HIGH);
      limitBeginState = digitalRead(limitBEGIN);                    // check switches
      limitEndState = digitalRead(limitEND);                        // check switches
      killSwitchState = digitalRead(killSwitch);                    // check switches
    } while (killSwitchState == HIGH);
    limitBeginState = digitalRead(limitBEGIN);                      // check switches
    limitEndState = digitalRead(limitEND);                          // check switches
    killSwitchState = digitalRead(killSwitch);                      // check switches
    digitalWrite(brake, LOW);                                       // brake off
  }

You use curly braces to say: all those statements that are within the opening and ending curly brace are to be considered as a unit:

{
  statement1;
  statement2;
  statement3;
}

Notice that each statement is followed by a semi-colon.

Let's take a look at your code:

if (killSwitchState == HIGH) {                          //Begin of if
    do {                                                  //Begin of do-while
      digitalWrite(brake, HIGH);                            //Put on the brakes
      limitBeginState = digitalRead(limitBEGIN);            //digitalRead not used
      limitEndState = digitalRead(limitEND);                //digitalRead not used
      killSwitchState = digitalRead(killSwitch);            //Read kill switch so that while has the most recent status
    } while (killSwitchState == HIGH);                    //End of do-while

    limitBeginState = digitalRead(limitBEGIN);            //digitalRead not used
    limitEndState = digitalRead(limitEND);                //digitalRead not used
    killSwitchState = digitalRead(killSwitch);            //digitalRead not used
    digitalWrite(brake, LOW);                             //Brakes released                                                                                
}                                                       //End of if

What you would like to do may be:

killSwitchState = digitalRead(killSwitch);    //Read kill switch once (You did it in the beginning of the loop)

while (killSwitchState == HIGH) {             //While it is HIGH (if low, the two lines between { and } are skipped)
  digitalWrite(brake, HIGH);                    //Put on the breakes
  killSwitchState = digitalRead(killSwitch);    //Read kill switch again, so while can check killSwitchState
}                                             //End of while

digitalWrite(brake, LOW);                     //killSwitch is off: release the brakes

This would be equally good:

if (killSwitchState == HIGH) {                          //Begin of if
    do {                                                  //Begin of do-while
      digitalWrite(brake, HIGH);                            //Put on the brakes
      killSwitchState = digitalRead(killSwitch);            //Read kill switch so that while has the most recent status
    } while (killSwitchState == HIGH);                    //End of do-while
    digitalWrite(brake, LOW);                             //Brakes released                                                                                
}                                                       //End of if

Jacques

Using a state machine:

First start by defining in which states your motor could be in, and use enum:

enum motorState {GOING_CW, GOING_CCW, STOPPED};
motorState currentState = GOING_CW; //Notice that currentState is declared globaly. Any part of the sketch can have access to it

In the loop, first read all the events that could change the state of your machine:

limitBeginState = digitalRead(limitBEGIN);
limitEndState = digitalRead(limitEND);
killSwitchState = digitalRead(killSwitch);

Then, using a switch construct, make some room for the three states of your machine:

switch (currentState) {
  case GOING_CW: {
    //For each event that changes my state, change to that state, take note of it.
    break;
  }
  case GOING_CCW: {
    //For each event that changes my state, change to that state, take note of it.
    break;
  }
  case STOPPED: {
    //For each event that changes my state, change to that state, take note of it.
    break;
  }
}

For each state, figure out:

  • what event(s) could change the state(s) of your machine:
  • what will be the new state
  • what actions you need to take to put that machine in it's new state
  case GOING_CW: {
    if (limitBeginState == HIGH) {
      digitalWrite(motor, HIGH);
      digitalWrite(brake, LOW);
      analogWrite(3, 255);
      currentState = GOING_CCW;
    }
    if (killSwitchState == HIGH) {
      digitalWrite(brake, HIGH);
      currentState = STOPPED;
      //If you want to return to the GOING_CW state after STOPPED, add the necessary code here
    }
    break;
  }
}

Going this way allows you to add more features afterwards easily.

Jacques

jbellavance:

  • what actions you need to take to put that machine in it's new state
  case GOING_CW: {

if (limitBeginState == HIGH) {
      digitalWrite(motor, HIGH);
      digitalWrite(brake, LOW);
      analogWrite(3, 255);
      currentState = GOING_CCW;
    }
    if (killSwitchState == HIGH) {
      digitalWrite(brake, HIGH);
      currentState = STOPPED;
      //If you want to return to the GOING_CW state after STOPPED, add the necessary code here
    }
    break;
  }
}

I reckon this state machine approach is very much cleaner.

But I still have a problem with this because it looks to me like there would have to be a case GOING_CCW: { which would have duplicate code.

I think I would organize my SWITCH CASE based on which button is pressed - for example CASE KILL-PRESSED and use that to set a variable that defines how a single motor function would cause the motor to behave.

...R

Is there someting embedded in Arduino software?

Yep. An intelligence test…