You could implement your washing machine as a state machine, but there's just as much potential for state proliferation as there is for if
statements if you don't do things carefully.
Working in states requires a different mindset where you think in terms of states (where you are), stimuli (what you get from the outside) and actions (what you do). In that context, let's look at some things in your model:
A running state, either on or off.
These are your two states, which I'll call WASHING
and STOPPED
. I'll add a third called READY_TO_WASH
, which is a stopped-but-ready-to-run state you'll see later.
It has a door state that should be open or closed
This isn't really a state, but two stimuli that you get from a sensor on the machine, which I'll call door_opened
and door_closed
. Assume that when power is first applied, the washer will detect what state the door is in and send one of those stiumuli.
Prevent the door from being set to 'open' while the machine is 'on'.
This would imply that in addition to the sensor that generates stimuli when the door is opened or closed, there's also a latch that you can program to physically prevent the door from opening. Let's call the actions that control it door_lock()
and door_unlock()
.
Prevent the running state from changing from 'off' to 'on' when the door is 'open'
Changing between off and on is based a stimulus that comes from the outside, perhaps when the user presses corresponding buttons on the front panel. Let's call the stimuli we get from those buttons wash_start
and wash_stop
.
For completeness, let's also say there's a motor in the machine that does the actual washing and is controllable using actions called motor_start()
and motor_stop()
.
Everything above gives us a full set of information about what the washer's states are, what the parts of the washer can be told to do and what stimuli we can get from the outside. That's enough to build a state machine, which you do by looking at each state and figuring out what to do in response to each stimulus.
The STOPPED
state (this is the "ground" state, or the state which the FSM enters when initialized):
- On entering this state: Do actions
motor_stop()
and door_unlock()
. This puts the washer into a known, sane state.
- On
door_open
: Do nothing. We don't care if the door is open when stopped.
- On
door_closed
: transition to the READY_TO_WASH
state.
- On
wash_start
: Do nothing. The door might be open. If it's closed, we won't be in this state anyway.
- On
wash_stop
: Do nothing. We're already stopped.
The READY_TO_WASH
state:
- On entering this state: Do actions
motor_stop()
and door_unlock()
. Again, this makes sure the washer is in a sane state.
- On
door_open
: Transition to the STOPPED
state. If the door's open, we're not ready to wash.
- On
door_closed
: Do nothing. We're already ready and should have been put in this state already.
- On
wash_start
: Transition to the WASHING
state.
- On
wash_stop
: Do nothing. We're already stopped.
The WASHING
state:
- On entering this state: Do actions
door_lock()
and motor_start()
.
- On
door_open
: Transition to the STOPPED
state. We shouldn't be getting any door stimuli in this state because the latch prevents it. If the latch fails and someone pulls the door open, this will provide some safety.
- On
door_closed
: Same as door_open
.
- On
wash_start
: Do nothing. We're already washing.
- On
wash_stop
: Transition to the READY_TO_WASH
state. The door will still be closed, so we're technically ready to wash some more.