2

I have a DC motor that will need to use two limit switches to detect end of travel in two directions.

I've read that coding a state machine to do this task is the best method, however I have no idea where to even begin.

Below you'll find a fritzing sketch of my experimental configuration for the code once implemented, and a flow chart.

Valid XHTML Valid XHTML

closed as too broad by per1234, user31481, gre_gor, jose can u c, MatsK Feb 1 '18 at 18:02

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Do you have any code? – user31481 Feb 1 '18 at 14:37
2

You have created a flow chart. When discussing state machines it is better to use a state diagram.

enter image description here

In this state diagram of a turnstile (from the state machine wikipedia page linked to above) it is observed that the nodes (bubbles) contain the state of the turnstile and on the edges (arrows) is written the condition required to travel in the direction of the arrow to a new state.

For the question asked here, at least 2 nodes are needed to state the direction of the motor. The edges likely will state which arrow is to be used to travel to a new state based on which switch is open or closed. Later, consider adding a new state to stop the motor once an end switch is closed. (Hint: Likely, you will need 2 stop nodes. One for each end-stop switch. The reason being you will need to know which direction the motor is to turn when restarted.)

For certain cases, adding a momentary contact switch is complex due to the need to mitigate the contact bounce. This is true when the meaning of activating the switch changes. The end-stop switch meaning does not change so there is no need to mitigate the contact bounce or "debounce" the end-stop switches. However, it is assumed the "Cycle Switch" can start the motor spinning in different directions depending on the history of the motor movement. Therefor the "Cycle Switch" can benefit from a 4 node state machine where there is clearly nodes which output switch-closed and switch-open. But to get to either of these 2 nodes there needs to be 2 other nodes where the switch "debouncing" is handled.

enter image description here

When handling multiple state machines in one program it is important not to block the flow. All state machines need to be continuously checked for state chances (testing the edge conditions for traveling from the current node to a new node).

When writing for an Arduino (in C / C++), the code pattern most often used is a "case" statement (switch / case) where a variable is assigned numbers associated with different nodes. In such a code pattern, each "case" is a node which contains the edge test(s) and can assign a new value to the variable to switch to a new node ("case") if any of the edge tests are true.

Simplifying the design: If you do not plan on stopping the motor then you do not need to "debounce" the "Cycle Switch".

Here is why: The meaning of the "Cycle Switch" changes from push-to-start to push-to-stop should you want to stop the motor between the 2 stop-switches. If all you need is to start the motor after either of the stop-switches are closed, then the number of times the "Cycle Switch" bounces is irrelevant as long as the bounces do not continue for longer then it takes for the motor to reach the opposite stop-switch.

1

Each state in the state machine should be a state in which the arduino will be for a time. Anywhere you would use a delay() or a blocking function or a busy loop will be a state.

You can also use multiple orthogonal statemachines and mix them. For example 1 to control whether the motor needs to be driven at all and one to control which direction it is driven in. That way the motor control part will look like:

if(motorDriven) {
    if(motorDirection = TOP) {
        driveMotorCW();
    } else {
        driveMotorCCW();
    }
} else {
    stopMotor();
}

Then the control of the state machine is straightforward. If limit switch is pressed change motorDirection to the opposite (and maybe stop the motor).

For timing you should keep a timestamp of the start of the interval and then test if millis() - timestamp > interval. For intervals less than a month this will work decently enough (barring drift). For intervals greater than that you should invest in a external clock.

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