Modified existing project from this link: Problem : Trigger limit switch to stop DC motor

I modified this code to control two relays which are wired to motor poles for Forward or Reverse movements until they physically reach a limit switch on either side.

  • Serial input of 'A' turns on one relay. If Limitswitch1 is pressed, this relay switches off.
  • It detects the current state of the system and awaits the Serial input of 'B' which then turns on the second relay. If Limitswitch2 is pressed, this relay switches off.

The issues are:

  1. Please help with code - I require option where the two relays switch off on the serial input of letter 'S' and to add the corresponding state machine. Essentially to add a Stop function.

  2. The limit switches work intermittently, sometimes they respond flawlessly, sometimes not at all. I have bought three different brands of switches to test but all have the same behaviour. I have pulled switches up and down with resistors in vain. I have performed button count test using code from this forum and confirm that the switch also behaves erratically. Can changes to code improve switch feedback?

Suggestions will be greatly appreciated.

const byte RELAY1 = 2;
const byte RELAY2 = 3;

const byte LimitSwitch1 = A1;
const byte LimitSwitch2 = A2;

const byte State_Idle = 0;
const byte State_Forward = 1;
const byte State_Reverse = 2;
byte currentState;

void setup(){
pinMode(RELAY1,OUTPUT);
pinMode(RELAY2,OUTPUT);

pinMode(LimitSwitch1, INPUT);
pinMode(LimitSwitch2, INPUT);

Serial.begin(9600);
currentState = 0xFF; // Force a change to enter the idle state
 }

void loop(){
// Check if we need to change state
byte nextState = currentState;
switch (currentState)
{
case State_Idle:
    { // If we received a valid command, start the operation
        if(Serial.available() > 0)
        {
            switch (Serial.read())
            {
            case 'A':
                nextState = State_Forward;
                break;
            case 'B':
                nextState = State_Reverse;
                break;
            default:
                break;
            }
        }
    }
    break;
case State_Forward:
    if(digitalRead(LimitSwitch2))
        nextState = State_Idle;
    break;
case State_Reverse:
    if(digitalRead(LimitSwitch1))
        nextState = State_Idle;
    break;
default:
    nextState = State_Idle;
    break;
}

// If there was a change, switch state and trigger enter condition
if (nextState != currentState)
{
    currentState = nextState; // Move in the new state
    switch (currentState)
    { // Entering the new state
    case State_Idle:
        // Switch both Relays OFF
        digitalWrite(RELAY1, HIGH);
        digitalWrite(RELAY2, HIGH);
        break;
    case State_Forward:
        // Move Forward
        digitalWrite(RELAY1, LOW);
        digitalWrite(RELAY2, HIGH);
        break;
    case State_Reverse:
        // Move Reverse
        digitalWrite(RELAY1, HIGH);
        digitalWrite(RELAY2, LOW);
        break;
    }
}
}
  • It is not completely clear, what your problem is. I think you should try to debounce the switches. You can google this, there are many tutorials and even full libraries for this. – chrisl Jul 5 at 19:02
  • I would like to add a function to switch off the relays after letter 'S' is typed on serial monitor. also Case_Stop to detect the state after being stopped. – S B Jul 5 at 19:19

Here I am again for another exciting episode of "Fun with StateMachines".. ;)

Ok, basically you modified the code well, but you thought of the modification in the wrong way.

First of all describe what you want to do in simple words. Let's say you want that

When I'm moving in one direction and I receive the letter 'S', I immediately stop without waiting for the endstop

Consequently, you know that

  1. you will have to add something when you are moving in one direction
  2. this "something" will top you, which is what the endstop does

So, to implement this, you can do something like this:

switch (currentState)
{
case State_Idle:
    { // If we received a valid command, start the operation
        if(Serial.available() > 0)
        {
            switch (Serial.read())
            {
            case 'A':
                nextState = State_Forward;
                break;
            case 'B':
                nextState = State_Reverse;
                break;
            default:
                break;
            }
        }
    }
    break;
case State_Forward:
    if(digitalRead(LimitSwitch2))
        nextState = State_Idle;
    else  if((Serial.available() > 0) && (Serial.read() == 'S'))
        nextState = State_Idle;
    break;
case State_Reverse:
    if(digitalRead(LimitSwitch1))
        nextState = State_Idle;
    else  if((Serial.available() > 0) && (Serial.read() == 'S'))
        nextState = State_Idle;
    break;
default:
    nextState = State_Idle;
    break;
}

Now, your second problem is a bit harder to understand. When I read it, I immediately thought what chrisl already pointed out, which is switch bounces. But when I was halfway into completing this part of the answer I found out that.. no, the bounces are not what can give problems here, unless you are constantly writing 'A' or 'B' on the serial. So for the second part of the question please post your schematic and/or photos of the setup, so we can see if there is something not normal

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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