Linear Actuator Code

Hello,
I'm new to arduino. I have a question about using a push button to start and then stop a single linear actuator that will move between two limit switches (that are just inputs like buttons to basically to tell the linear actuator to move in the opposite direction until it reaches the other limit switch and again changes direction, ad infinitum). I'm not sure exactly how to do this. I found a few suggestions on the web and have tried to implement them. The code I'm pasting below "seems" to allow me to push the start/stop button (SSpin), but then I have to push by hand a limit switch to start the actuator moving between the two limit switches. I can then push the stop/start button (SSpin) again to stop the actuator. I was trying to make a condition the first time through the ActuatorUp() function (also tried in the other "if" or "else if" cases that are now commented out in the code) that when both ActUp == High and ActDwn == HIGH (no movement) that the actuator would then be switched on in the up direction then continue to loop since this should only be true the first time through the loop (otherwise the actuator is constantly moving). Also tried this using the ActUpState and ActDwnState but didn't see any difference. Any thoughts on how to fix this or where I'm going wrong?

Thanks,
Stephen

ActSwitch3.ino (3.16 KB)

const int buttonPin1 = 2;    // the number of the actuator up? limit switch pin
const int buttonPin2 = 6;    // the number of the actuator down? limit switch pin
const int ActUp = 11;
const int ActDwn = 8;
const int SSPin = 3;          // Start/Stop Pin


int buttonState1;             // the current reading from the input pin
int lastButtonState1 = LOW;   // the previous reading from the input pin
int buttonState2;             // the current reading from the input pin
int lastButtonState2 = LOW;
int ActUpState = HIGH;
int ActDwnState = HIGH;

int test = 0;
boolean currentState = LOW;//stroage for current button state
boolean lastState = LOW;//storage for last button state

long lastDebounceTime1 = 0;  // the last time the output pin was toggled
long debounceDelay1 = 10;    // the debounce time; increase if the output flickers
long lastDebounceTime2 = 0;  // the last time the output pin was toggled
long debounceDelay2 = 10;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(ActUp, OUTPUT);
  pinMode(ActDwn, OUTPUT);
  pinMode(SSPin, INPUT);

  digitalWrite(ActUp, ActUpState);
  digitalWrite(ActDwn, ActDwnState);
}

void loop() {
  currentState = digitalRead(SSPin);
  if (currentState == HIGH && lastState == LOW) {
    delay(1);
    if (test == 0) {
      test = 1;
      Serial.print(test);
    }
    else {
      test = 0;
      Serial.print(test);
    }
    if (test == 0) {
    }
  }
  lastState = currentState;
  if (test == 0) {
    digitalWrite(ActUp, HIGH);  // stops actuators ie pauses loop
    digitalWrite(ActDwn, HIGH);
  }
  if (test == 1) { //(ActUpState == HIGH && ActDwnState == HIGH) ) {
    ActuatorUp();
    ActuatorDown();
  }
}

void ActuatorUp() {
  int reading1 = digitalRead(buttonPin1);
  if (reading1 != lastButtonState1) {// || (ActUpState == HIGH && ActDwnState == HIGH) ) {
    lastDebounceTime1 = millis();
  }

  if ((millis() - lastDebounceTime1) > debounceDelay1) {
    if (reading1 != buttonState1) {
      buttonState1 = reading1;
//      Serial.print("begin");
//      Serial.print(buttonState1);
      if (buttonState1 == HIGH) {// || (ActUpState == HIGH && ActDwnState == HIGH)) {    
        digitalWrite(ActUp, HIGH);
        digitalWrite(ActDwn, LOW);
        digitalWrite(ActUpState, HIGH);
        digitalWrite(ActDwnState, LOW);
      } 
//    } else if (ActUpState == HIGH && ActDwnState == HIGH) {
//        digitalWrite(ActUp, HIGH);
//        digitalWrite(ActDwn, LOW);
//        digitalWrite(ActUpState, HIGH);
//        digitalWrite(ActDwnState, LOW);        
      }
  }
  lastButtonState1 = reading1;
}

void ActuatorDown() {
  int reading2 = digitalRead(buttonPin2);
  if (reading2 != lastButtonState2) {
    lastDebounceTime2 = millis();
  }
  if ((millis() - lastDebounceTime2) > debounceDelay2) {
    if (reading2 != buttonState2) {
      buttonState2 = reading2;
      if (buttonState2 == HIGH) {
        digitalWrite(ActDwn, HIGH);
        digitalWrite(ActUp, LOW);
        digitalWrite(ActUpState, LOW);
        digitalWrite(ActDwnState, HIGH);
      } else {
      }
    }
  }
  lastButtonState2 = reading2;
}
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(SSPin, INPUT);

You are not using the internal pullup resistors. So, how ARE the switches wired? Why aren't you using simpler wiring and the internal pullup resistors?

 currentState = digitalRead(SSPin);
  if (currentState == HIGH && lastState == LOW) {

I find it a lot easier to follow code what there is a pattern to the variable names.

  currSSState = digitalRead(SSPin);
   if(currSSState != lastSSState)
   if (test == 0) {
    }

If test is 0, do nothing. Otherwise, do nothing. So, why bother testing?

What is test supposed to imply? Wouldn't running be a better name? Why is test an int, when it only holds 0 or 1? Better would be a boolean holding true or false.

       digitalWrite(ActUpState, HIGH);
        digitalWrite(ActDwnState, LOW);

This is where I quit trying to understand the code. Using State in the name of a variable that holds a pin number does not make sense.

Hi Paul,
Thanks for the quick response. I've tried to clean up the code a bit and make it more clear.

PaulS:

  pinMode(buttonPin1, INPUT);

pinMode(buttonPin2, INPUT);
  pinMode(SSPin, INPUT);



You are not using the internal pullup resistors. So, how ARE the switches wired? Why aren't you using simpler wiring and the internal pullup resistors?

I am using 10k Ohm resistors on the bread board and all switches and buttons function properly as inputs

 currentState = digitalRead(SSPin);

if (currentState == HIGH && lastState == LOW) {



I find it a lot easier to follow code what there is a pattern to the variable names.

Tried to make this more consistent

  currSSState = digitalRead(SSPin);

if(currSSState != lastSSState)






if (test == 0) {
    }



If test is 0, do nothing. Otherwise, do nothing. So, why bother testing?

You are correct this didn't do anything. I took it out.

What is test supposed to imply? Wouldn't running be a better name? Why is test an int, when it only holds 0 or 1? Better would be a boolean holding true or false.

Whatever the name it is only testing and holding the state if the SSbutton has been pressed. It keeps track properly of the on/off state. I think the place I'm having problems is in the functions at the bottom. That was why I tried using the "ActUpState" to track and start the actuator moving the first time through the loop. Your last comment concerned my use of this "ActUpState"...

       digitalWrite(ActUpState, HIGH);

digitalWrite(ActDwnState, LOW);



This is where I quit trying to understand the code. Using State in the name of a variable that holds a pin number does not make sense.

...and I took it out.

So basically the first time I go through the "ActuatorUp() function" I would like to use the "OR" condition so the code to knows that both "ActUp" and "ActDwn" are set to "HIGH", i.e., actuator not moving, and then continue forward through the if statement and start them moving down. Next time through the "ActuatorUp()" function, "ActUp" will be "LOW" since it's moving up, then the limit switch will tell it to reverse. Thanks again for any advise on this.

-Stephen

Here is my latest iteration after your comments:

const int limit1 = 2;    // the number of the actuator up? limit switch pin
const int limit2 = 6;    // the number of the actuator down? limit switch pin
const int ActUp = 11;    // the number of the pin controlling actuator up movement
const int ActDwn = 8;    // the number of the pin controlling actuator down movement
const int SSbutton = 3;          // Start/Stop (SS) button Pin


int limit1State;             // the current reading from the input pin
int lastlimit1State = LOW;   // the previous reading from the input pin
int limit2State;             // the current reading from the input pin
int lastlimit2State = LOW;

int testSS = 0;                  // used for determining if SS button is pressed
boolean currentSSState = LOW;   //strorage for current SS button state
boolean lastSSState = LOW;    //storage for last button state

long lastDebounceTime1 = 0;  // the last time the output pin was toggled
long debounceDelay1 = 10;    // the debounce time; increase if the output flickers
long lastDebounceTime2 = 0;  // the last time the output pin was toggled
long debounceDelay2 = 10;

void setup() {
  Serial.begin(9600);
  pinMode(limit1, INPUT);  //using 10k Ohm resistors on my bread board
  pinMode(limit2, INPUT);
  pinMode(ActUp, OUTPUT);
  pinMode(ActDwn, OUTPUT);
  pinMode(SSbutton, INPUT);
}

void loop() {
  currentSSState = digitalRead(SSbutton);
  if (currentSSState == HIGH && lastSSState == LOW) {
    delay(1);
    if (testSS == 0) {
      testSS = 1;
      Serial.print(testSS);
    }
    else {
      testSS = 0;
      Serial.print(testSS);
    }
  }
  lastSSState = currentSSState;
  if (testSS == 0) {
    digitalWrite(ActUp, HIGH);  // these 2 lines stop all movement when SSbutton is pressed
    digitalWrite(ActDwn, HIGH);
  }
  if (testSS == 1) {
    ActuatorUp();   // functions defined below to move determine when limit switch is pressed then change direction
    ActuatorDown();
  }
}

/////// Actuator Going Up then Change Direction and Go Down  Once Limit Swith is pressed //////////////////

void ActuatorUp() {
  int reading1 = digitalRead(limit1);
//  Serial.print(ActUp);
  if (reading1 != lastlimit1State) {
    lastDebounceTime1 = millis();
  }

  if ((millis() - lastDebounceTime1) > debounceDelay1) {
    if (reading1 != limit1State) {
      limit1State = reading1;
      if (limit1State == HIGH || ActUp == HIGH  && ActDwn == HIGH ) {   //trying to use OR statement here 
        digitalWrite(ActUp, HIGH);
        digitalWrite(ActDwn, LOW);
      }         
      }
  }
  lastlimit1State = reading1;
}

/////// Actuator is Going Down then Change Direction and Go Up Once Limit Swith is pressed //////////////////

void ActuatorDown() {
  int reading2 = digitalRead(limit2);
  if (reading2 != lastlimit2State) {
    lastDebounceTime2 = millis();
  }
  if ((millis() - lastDebounceTime2) > debounceDelay2) {
    if (reading2 != limit2State) {
      limit2State = reading2;
      if (limit2State == HIGH) {
        digitalWrite(ActDwn, HIGH);
        digitalWrite(ActUp, LOW);
      } else {
      }
    }
  }
  lastlimit2State = reading2;
}

So basically the first time I go through the "ActuatorUp() function" I would like to use the "OR" condition so the code to knows that both "ActUp" and "ActDwn" are set to "HIGH", i.e., actuator not moving, and then continue forward through the if statement and start them moving down.

I'm sorry. This doesn't make sense.

If ActUp is assigned a value based on reading a limit switch state, you should NOT be trying to alter that in code.

It's hard to see if that is the case, since button1Pin doesn't tell us anything about the purpose of the switch attached to that pin.

If you really have changed your code to use more meaningful names (everywhere), you need to post the changed code. If not, you really need to.

So,

loop() {
  if the actuator is moving left and we are hitting the left limit switch, move right.

  if the actuator is moving right and we are hitting the right limit switch, move left.

  if the debounced user input button has changed from high to low
      and we are not hitting either limit switches {
    if we are moving right, move left
    else, move right 
  }
}

Oh! That's not what you want - you want the button to work as a start/stop button! Well, then, the code is:

if we are not moving, then
  if the start stop button has gone from high to low
    start moving in the direction we last stopped in
  else
    // stay stopped
  end if
else
  if the start stop button has gone from high to low
    stop
  else if we are moving right and have hit the right limit switch
    move left
  else if we are moving left and have hit the left limit switch
    move right
  else 
    // keep moving
  end if
end if

Sorry for the delayed response. Thank you all for the help on this. I have to set this project aside for a bit but once I get it up and running properly I'll repost final code.