Limit Switch Programming

Hello everybody!

I have been working for a couple of weeks on a project, and I'm at a point where I need some guidance.

My goal is to have a prism be movable along a track remotely.

The setup

The motor rotates a screw which pushes the prism down the track, and I wired up two limit switches and plan to place them at either end of the track so that the prism stops in the same place every time. Both limit switches work and will stop the motor when they are pressed, but I ran into a problem. When one of the limit switches is pressed and the user tells the motor to run in the opposite direction to move the cube away, the motor vibrates and doesn't run well. As soon as the limit switch is open again, the motor will run fine. (I drew a picture because that description wasn't too great)

#define switchA 13
#define switchB 11

int delaylength = 4;
byte userInput = 0;

void goForward(){
//here is where the stepper motor code goes
}

void goBack(){
//here is where the stepper motor code goes
}

void setup(){
  pinMode(12, OUTPUT); 
  pinMode(13, OUTPUT); 
  pinMode(9, OUTPUT); 
  pinMode(8, OUTPUT); 
  pinMode(switchA, INPUT_PULLUP);
  pinMode(switchB, INPUT_PULLUP);
  Serial.begin(9600); 

  while (! Serial); 
    Serial.println(" Type 1 to move the cube into position and type 2 to move the cube out of position.");
  }

void loop(){  
  userInput = Serial.read();

  //Go forward
  if (userInput == '1') { 
    Serial.println(" moving in...");
    while(digitalRead(switchA) != LOW){
      goForward();
    }
    Serial.println(" done");    
  }

  //Go back
  if (userInput == '2'){
    Serial.println(" moving out...");
    while(digitalRead(switchB) != LOW){
      goBack();
    }
    Serial.println(" done");
  }
  userInput = 0;
}

(My code was a lot worse before, but I got a lot of help from reddit :P)

I'm pretty sure I wired the limit switches correctly as well. I have a motor shield, and I put the wires into digital pins 11 and 13 and one wire in the ground on the digital side and one wire in the ground on the power side. Here's what the wiring is.

Thank you so much for any suggestions you guys have!

This usual cause of that problem is the code responding to the limit switch even though (because it is going in the other direction) it should ignore it. But I don't see why your code should behave like that. I presume the code you posted is the exact code you have been trying?

I have ZERO idea what that wiring picture is intended to convey. Just make a pencil drawing showing the connections and post a photo of the drawing.

While it is not the cause of your problem (I think) you code has one big failing - the limit switches are not read unless the user has pressed the correct button. If something gets mixed up the switches may never be detected and damage may be caused.

It would be much better to read the limit switch every time through loop() and stop the motors if necessary.

You should organize your program around a variable that records the state of the system - perhaps call it moveState - which might have possible values L (stopped at left), r (moving right), R (stopped at right) and l (lower case L - moving left).

If the state is (say) 'L' pressing the button should change it to 'r'. When it hits the right limit switch it should change to 'R' etc.

The code for the motor would just look at the variable and move the motor if it is 'r' or 'l'

...R

I have not read much of your program, but this statement would appear at first sight to be incompatible with a switch wired to pin 13.

pinMode(13, OUTPUT);

Hey all!

Earlier today I posted a question about stepper motors with limit switches and received a lot of great feedback.

My end goal is to have a stepper motor run forwards until it hits a limit switch when the number 1 is entered into the serial monitor, and to run backwards when the number 2 is entered in the same manner.

The trouble I am running into is that when a limit switch is pressed and the motor stops at that end, the motor won't run the opposite direction until the limit switch isn't pressed. I think I narrowed down what the problems could be, so I was hoping someone here could give some advice :slight_smile:

Here is all of my code (sorry if it's a bit long)

#define switchA 10
#define switchB 11

int delaylength = 4;
byte userInput = 0;

void goForward(){
   //stepper motor code
}

void goBack(){
  //stepper motor code
}

void setup(){
  pinMode(12, OUTPUT); 
  pinMode(13, OUTPUT); 
  pinMode(9, OUTPUT); 
  pinMode(8, OUTPUT); 
  pinMode(switchA, INPUT_PULLUP);
  pinMode(switchB, INPUT_PULLUP);
  Serial.begin(9600); 

  while (! Serial); 
    Serial.println(" Type 1 to move the cube into position and type 2 to move the cube out of position.");
  }

void loop(){  
  userInput = Serial.read();

  //Go forward
  if (userInput == '1') { 
    Serial.println(" moving in...");
    while(digitalRead(switchA) != LOW){
      goForward();
    }
    Serial.println(" done");    
  }

  //Go back
  if (userInput == '2'){
    Serial.println(" moving out...");
    while(digitalRead(switchB) != LOW){
      goBack();
    }
    Serial.println(" done");
  }
  userInput = 0;
}

I don't see any logic problems that would cause the motor not to run the other way if the unrelated limit switch is pressed. So I sorta think that my problem lies with the stepper motor code. Is the following a valid way to run a stepper motor? (This bit of code is what I placed in for the //stepper motor code bit)

  digitalWrite(9, LOW);  
    digitalWrite(8, HIGH); 
    digitalWrite(12, HIGH);   
    analogWrite(3, 255);   
    delay(delaylength);
    digitalWrite(9, HIGH);  
    digitalWrite(8, LOW); 
    digitalWrite(13, HIGH);   
    analogWrite(11, 255);   
    delay(delaylength);
    digitalWrite(9, LOW);  
    digitalWrite(8, HIGH); 
    digitalWrite(12, LOW);   
    analogWrite(3, 255);   
    delay(delaylength);  
    digitalWrite(9, HIGH);  
    digitalWrite(8, LOW); 
    digitalWrite(13, LOW);   
    analogWrite(11, 255);  
    delay(delaylength);

And lastly, I have the motor and the limit switches connected to a motor shield which is powered by a 9 volt battery. Is this enough voltage?

Sorry if these questions are obvious, I'm completely new to arduino :stuck_out_tongue:

Thanks!

mattdallas:
I don't see any logic problems that would cause the motor not to run the other way if the unrelated limit switch is pressed

If I simplify, your loop() looks like this.

void loop() {
   userInput = Serial.read();  
   if (userInput == '1') {/* Go fwd until hitting the A limit switch*/ }
   if (userInput == '2') {/* Go bwd until hitting the B limit switch */}
   userInput = 0;
}

Some approximative things in there

1/ you don't check if there is a character coming from the Serial line. Serial.read(); returns the first byte of incoming serial data available (or -1 if no data is available). so most of the time you end up with -1 but because you check against all possibilities then no harm done

2/ userInput = 0; // this is useless as the next thing you do at the top of the loop is assign it

3/ This might be the design intention, but once you have typed 1 or 2, there is no way back. Your code is stuck in a while loop until you hit the correct switch. Hopefully that does always happen :wink:

4/ I don't know how your Serial console is set, if it sends CR/NL after each key you will read those too. again not a pb because you do look for '1' or '2' explicitly (BTW you could use nested else statements or a switch case to avoid unnecessary testing if you have found your key). just be aware that you might receive legit characters in userInput you have not really typed if you set your console that way (so be careful if you ever implement a default behavior)

But those are "minor" things (that you should handle nevertheless) and not your problem. Actually your code works totally OK if this is really how you've designed it. (I've tried it without motors, just printing F or B and using a jumper cable to simulate hitting Switches A or B (pin 10 or 11 by connecting to GND)).

Question:
1/ if you run the code above and type 1, what do you see in the console? if you manually press the A switch while the Arduino is moving towards the switch A, does the motor keep running anyway?

2/ Once you have reached Switch A, if you move the device away from switch A but do not type any character, does the device try to go again towards switch A? and Once it is at the Switch A, if you type 2, and then move it a bit away from the Switch, what happens and what do you see in the console?

Assuming it goes fine in both directions (thus that your stepper code is correct for your stepper since it is moving) the challenge is what happens when you hit the switch

My guess would be that they are not wired appropriately and they don't send a "LOW" signal when you hit them but because your device is blocked, the stepper does not "step". As you don't get a LOW, you are stuck in your while loop and never go back to listen for the next character input. Once you manually remove it from the switch, you actually exit the infinite while loop and because the code reads the '2' you have typed, the device moves in the other direction....

--> how are your end switches wired? do you have same ground as your arduino? do they have a current limiting resistor?

Don't spilt your project over multiple Threads. Your earlier Thread

I am suggesting to the Moderator to merge them so we have all the info in one place.

...R

Hi,

What pins are the limit switch input pins and where do you declare them as INPUTS?
I can see you adding INPUT_PULLUP.

BUT

switchA and switchB are declared 10 and 11, but your picture shows 11 and 13?

To quote an Australian Politician.. Please Explain?

Thanks.. Tom... :slight_smile:

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can you post a picture of your project showing hoe you have the stepper wired and its power supply?

Thank.. You.. Tom... :slight_smile:

UPDATE:

I worked on the things everyone suggested, and the system works. I had mis-wired the limit switches and in the end that was my problem. Thank you all for your help :smiley:

in the end that was my problem.

I hate when that happens. You spend all day swearing at the software when the hardware is malfunctioning.

Good so my guess in post 4 was correct

My guess would be that they are not wired appropriately and they don't send a "LOW" signal when you hit them but because your device is blocked, the stepper does not "step". As you don't get a LOW, you are stuck in your while loop and never go back to listen for the next character input. Once you manually remove it from the switch, you actually exit the infinite while loop and because the code reads the '2' you have typed, the device moves in the other direction....

When the code looks very correct then assume it is correct and try to understand the behavior you see