FiniteStateMachine

From Flowcode Help
Jump to navigationJump to search

Introduction

Finite state machines are used all over the place in Flowcode components to keep track of things.

They are a means to allow a fixed number of deterministic states which can vastly simplify a program and is a great tool to add to your coding kit.

Flowcode now offers a State Diagram method of coding but the techniques shown here are still valid and can be used in either coding paradigm.


Techniques

A good technique when learning state machines is to try and break the task up into jobs and then try to implement those jobs in a orderly way.


E.g. making a cup of tea.


State 0 - Buy Ingredients - OK = State 1

State 1 - Fill Kettle With Water - OK = State 2 or Not Enough Water = State 1

State 2 - Boil Kettle - OK = State 3 or Not boiled yet = State 2

State 3 - Place teabag in cup - OK = State 4 or No Teabags = State 0

State 4 - Place milk in cup - OK = State 5 or No Milk = State 0

State 5 - Place boiling water in cup - OK = State 6 or Not filled yet = State 5 or Not Enough Water = State 1

State 6 - Stir the water - OK = State 7 or Not Stirred Enough State 6

State 7 - Cup of tea ready


As you can see making a cup of tea actually has a lot of stages and could be made much more complex, e.g. adding sugar, time to let the tea brew, removing the tea bag, milk before or after water, amount of milk....


It is also possible to design in error handling at this stage, let's consider the kettle is broken and therefore the water will never boil. We could potentially get stuck forever at stage 2 waiting for the kettle to boil. This can be handled by adding a timeout which resets back to State 0 or a special error state if the stage is taking longer than usual. The error state could display a user message to let you know what the specific problem is. Consider each minor task and try to determine what problems could arise and what you might do to try and catch or work around them.

FSM Example 1 - Simple comms parsing

Here is a very basic example.

We want to control a robot via a serial data connection. We control it by sending packets of 2 bytes.

The first byte is the value 'L' to signify the Left motor speed, the next byte is the motor speed 0-255.

The first byte is the value 'R' to signify the Right motor speed, the next byte is the motor speed 0-255.

The firmware for the robot could look something like this.


FC6 Icon.png State Machine Example1


we always start at state 0, and we keep receiving bytes until the characters 'L' or 'R' are received. Once we receive one of the characters we know the next byte will be the corresponding motor speed so we can jump to the right state to collect and assign the value.

This would allow some fault tolerance. e.g. if the robot received a speed byte first then it would do nothing until the 'L' or 'R' bytes are received.

You could even control the Left motor without touching the Right motor by sending the 2 bytes packet starting with 'L' over and over again.


FSM Example 2 - Adding direction control

You could then expand the state machine if you wanted to by using a 3-byte packet and including the motor direction.

The first byte is the value 'L' to signify the Left motor speed, the next byte is the motor speed 0-255, the next byte is the direction 0-1.

The first byte is the value 'R' to signify the Right motor speed, the next byte is the motor speed 0-255, the next byte is the direction 0-1.


FC6 Icon.png State Machine Example2


FSM Example 3 - Multi Mode Torch

Of course state machine don't just apply to comms, you could do a similar thing with a switch and a LED to make a multi-mode torch.

Start State 0 - Torch Off

Press 1 the torch turns on - State 1.

Press 2 the torch automatically flashes - State 2.

Press 3 the torch turns off - State 0.


FC6 Icon.png State Machine Example3


FSM Example 4 - Multiple State Machines

Here is a project created to drive a pick and place component feeder bank.

The PC tells us when we need to move to the next component using a motor so we need to use a state machine to listen to and decode the incoming comms to detect when one of our feeder channels gets called up for action. When a valid feeder channel is detected we use a second state machine to start the motor moving and then after a delay to allow the motor to move we bring the motor back to the original start position. The second state machine has 8 tracking variables which allows us to control all 8 servo channels using the state machine. Using the state machines means that we are not having to use blocking code such as delays when moving the motors which means that multiple feeder channels can be in various stages of motion at once.


FC6 Icon.png ServoFeeder


FSM Example 5 - SCADA Slave Firmware

The firmware for the SCADA Slave targets is driven using a simple state machine approach.

Mode 0

Monitor incoming comms data for a valid command code, once a valid code is found we assign a count of parameters and returns.

If there are any parameters then move to Mode 1, else action the command and if there are any returns then move to Mode 2. If no returns then stay on Mode 0.


Mode 1

Store incoming bytes until we have collected all the incoming parameters for the command.

Action the command and if there are any returns then move to Mode 2. If no returns then return to Mode 0.


Mode 2

Send out all the outgoing return bytes and once complete return to Mode 0.


ZIP Icon.png Arduino Uno SCADA Firmware