Help please. Two end switches, one input

Hi,

I am trying to implement end switches. I haven't got enough inputs, so I used two switches on each end of the axis connected to just one input. I am using two buttons to move the motor around the axis, the motor is moved while the button is pushed, so it is momentary. I would like the motor to stop on the end and also to not move when i press the button and it is in the end position of that direction. I hope I was able to explain reasonably.

I have tried this code:

if (digitalRead(SW1) == LOW)
      {
       if (digitalRead(END_IN) == HIGH || (digitalRead(END_IN) == LOW && PrevDir == 0)) {
        digitalWrite(DIR_PIN, HIGH);
        PrevDir = 1;
        digitalWrite(MS_SWITCH, HIGH);
        digitalWrite(EN_PIN, LOW);
        MotorOn = 1;
        lcd.setCursor(15, 1);
        lcd.print("<");
       }
      }

      if (digitalRead(SW2) == LOW)
      {
       if (digitalRead(END_IN) == HIGH || (digitalRead(END_IN) == LOW && PrevDir == 1)) {
        digitalWrite(DIR_PIN, LOW);
        PrevDir = 0;
        digitalWrite(MS_SWITCH, HIGH);
        digitalWrite(EN_PIN, LOW);
        MotorOn = 1;
        lcd.setCursor(15, 1);
        lcd.print(">");
       }
      }

This works just partially, the motor wont stop at the end while holding the button, it will crash to the end switch but when I release the button and press it again it wont start to move again, which is correct, but I also need it to stop when it reaches the end switch while the button is still held.

Any help would be supercool,

thanks,

Lu.

can you post the entire code, have no idea which pins do what nor how they are configure (INPUT or INPUT_PULLUP)?

The code is very very long, it is a controller for record cutting lathe. For this part, there are three inputs set as INPUT_PULLUP, so there is LOW when buttons are pressed or end switch reached.

The outputs are DIR_PIN for setting direction, MS_SWITCH for microstepping settings and EN_PIN for enabling the motor so it starts to move

What do you think this is doing? Your second digitalRead() is

(digitalRead(END_PIN == LOW)
and since END_PIN is not equal to 0, that comparison is 0 so this is
(digitalRead(0)

which is reading pin 0. Probably not what you want.

As for having both end switches tied to one input, you will not be able to tell which end you have reached.

Sorry, there is mistake in the code with brackets, it should be:

if (digitalRead(END_IN) == HIGH || (digitalRead(END_IN) == LOW && PrevDir == 0))

I have fixed the code in the first post

I know the end it reached, because I know the direction it went...

Many have tried this. Work through the logic, it will work. Add in little details like mechanical switch bounce, and all heck breaks loose. MUCH better, and simpler, to use two inputs.

Good luck. If this is, for example, an Uno, have you used up all the analog pins as well? Because they can also be digital inputs. Or, you can use an analog input with two different voltage levels for the end positions, though that means you'll be doing analog reads to check limits, which is slower.

It also breaks down if a limit switch is tripped at power up.

1 Like

I know the cons of this solution, the undefined position doring powering up can be a problem, but I have to work with what I have, it is already wired up, lot of cables, I cannot change it now. I will be happy if it will work just with those buttons

what are END_IN and END_PIN?

don't understand what this is attempting to do

when there are separate pins at each endpoint, travel is stopped when traveling in one direction and one end-pt is reached. And when the direction is changed, that condition doesn't prevent leaving that position

when the same pin is used for each end-pt, the end-pt switches need to temporarily be ignored when direction is reversed and re-enabled once the switch opens so that the travel will stop when the opposite end is reached

Famous last words!

Maybe my logic is wrong, but when the "go left" button is pressed down, the motor should go left until the limit switch is activated so END_IN pin is LOW, the motor should stop even if the button is still pressed, also, when the last direction was left and the limit switch is activated, the motor won't move when I press the "go left" button again, but it can move in the other direction if I press the "go right" button. That's what I am trying to do...

which is it "it can move" or "I am trying to do"?

Do you mean that it can't, because the limit switch is still activated? This is that it has to be ignored somehow? Is there any solution?

just trying to understand what you are saying.

i believe there is a solution

maybe you didn't read this and that's why you asked

I described what I want it to do, but the mentioned code wont stop the movement when the motor reaches the limit switch, but when I release the button and press the same button again it wont move, so it is somehow half working, now I need to figure out how to stop it when the button is pressed and the motor reaches the limit switch. Sorry, I am not sure if i can explain it any better.

I think most of us understand it, maybe better than you do.

The key as @gcjr points out is figuring out how to get off the limit switch.

To do that, you should be looking not at the state of the limit switch input pin, but transitions that appear there.

When the limit input goes form HIGH to LOW, that is to say when either switch becomes closed, you have reached the limit.

Switch directions and only allow going the other way.

You don't need to care about whether the limit is open or closed, only that it went from open to closed.

This is called state change detection, and in combination with contact or switch debouncing, is all and what you need to accomplish.

The detection will see the other transition, and then it is ready to see the transition you are interested in at the other end.

You will need to have a loop that comes around often enough checking for the transition you are interested in so the motor can drive too far past either limit switch.

You'll need to keep track of which direction means you'll not be banging against the end of the rail.

a7

If the left and right limit switches are on the same pin, and it's parked at the left end, how does the going-right motion know it hasn't reached the right limit switch?

I think you might be able to solve this with edge-detecting the changes on the limit switch pin, plus a state machine for handling the IDLE, GOING_LEFT, STOPPED_LEFT, GOING_RIGHT, STOPPED_RIGHT logic. If you are STOPPED_LEFT with the limit switch triggered, you can transition to GOING_RIGHT or IDLE but not GOING_LEFT until the limit switch un-triggers & vice versa.

1 Like

Yes. Oddly that will be at once more complicated and simpler.

It comes down to knowing whether you are moving or not, in which direction and if stopped if it is because you banged into a limit switch.

But rolls all that up into one variable, the "state" in the so-called finite state machine.

google

 arduino finite state machine

and dare to have your life changed. It will be hard until it is easy, then you'll wonder how you ever did without.

a7

All of you probably understand better than me, that's why I asked you for help. Thank you. I will try to figure it out.

look this over
and again

const byte PinStart = A3;
const byte PinLimit = A2;
const byte PinDir   = 13;
const byte PinRun   = 12;

bool       armed;
bool       cw;
bool       running;

enum { Off = HIGH, On = LOW };

// -----------------------------------------------------------------------------
void run ()
{
    Serial.println ("run");
    digitalWrite (PinRun, On);
    running = true;
}

void stop ()
{
    Serial.println ("stop");
    digitalWrite (PinRun, Off);
    running = false;
    armed   = false;
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    if (! running)  {
        if (LOW == digitalRead (PinStart))
            run ();
    }
    else {
        if (! armed && HIGH == digitalRead (PinLimit)) {
            armed = true;
        }
        else if (armed && LOW == digitalRead (PinLimit))  {
            stop ();
            cw = ! cw;
            digitalWrite (PinDir, cw);
        }
    }
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);
    pinMode (PinStart, INPUT_PULLUP);
    pinMode (PinLimit, INPUT_PULLUP);

    pinMode (PinDir,   OUTPUT);
    pinMode (PinRun,   OUTPUT);
    digitalWrite (PinDir, cw);

    stop ();

    if (LOW == digitalRead (PinLimit))
        Serial.println (" position unknown");
    while (LOW == digitalRead (PinLimit))
        ;
    armed = true;
}
2 Likes