Introduction: Arduino Finite State Machine and Multitasks

Picture of Arduino Finite State Machine and Multitasks

A finite state machine is diagram used to organise tasks to control several insdustrial systems (production, heater, pump, conveyors...).

All these sytems include states (associated with an "action", ie: start, run, stop) some of them are "wanted" or said "stable" others are "unwanted" or unstable. The finite state machine method or diagram organizes only stable states. When a trigger or a transition is true (ie: sensor ON, button pushed), the previous state is turned off and the following state is turned on.

For details:

Other diagrams have almost the same running: Moore machine, Mealy machine, SFC diagram (GRAFCET in french).

In this instructable I will talk about to implement a state machine in an arduino uno using SM library. This library allows you to run "concurent states" or parallel tasks (real time machines): you can control many different machine or independant system with only a microcontroller. It 's very powerfull and doesn't need too many lines of code.

In my previous instructables I use a simple way to run a finite state machine on my arduino light dimmer (without any special library) but I think it's impossible to run concurent state and it's very difficult to use emergency stop (essential and usefull in indstrial systems for security).

The editor I used, draws diagrams with SYSML or UML 2 rules and makes finites states machines like a Moore/Mealy mix.

I implemented 3 "real" examples of state machine to explore most of the capabilities of the library SM.h.

PS: This method is suitable, common and well known for people working in automation, many computer developper don't like it. See this article:

Step 1: The First State Machine: 1 Master and 3 Concurent Slaves

Picture of The First State Machine: 1 Master and 3 Concurent Slaves

The control interface:

I use an arduino uno with a small interface (2 buttons (ATU1, ATU2) for trigger switch on and 3 LEDS (11, 12, 13) for output action) and a LCDKeypad.

The machines:

The microcontroller can control a Master machine which can launch 3 differents slave machines:

-the FB machine blink a led at 1Hz. If ATU1 is pushed, it disables the FB machine, if ATU1 is pulled, it restarts the FB machine

-the SB machine blink a led at a faster frequence with no synchronization or interaction with the FB machine. If LEFT is pressed (on the rising edge), it disables the SB machine, if SELECT is pressed (on the rising edge), it restarts the SB machine.

-the PUMP machine which is run stop of an output or a relay to start a pump. If UP is pressed (on the rising edge), the output is HIGH, if ATU2 is pressed (on the rising edge) the output is switched OFF.

This called an encapsulation : when you disable an encapsulation state, every encapsulated states are disable at the same time.

When you launch parallel states ,in automation, you do a Divergence of Simultaneous Sequences or machines.

The schematic:

Because of the LCDkeypad shield, a lot of pins are used: pins 4, 5, 6, 7, 8, 9, 10. The keypad push buttons are analog on pin A0.

So it remains a few amount of pins to control a system. This the reason why I have added an I2C I/O expansion circuit used in the next steps. You will ignore it at this step: just keep on your mind ATU1, ATU2, Keypad Buttons, and the pin 11, 12, 13 digital outputs.

The program:

A lot of comments are inside.

The messages displayed:

The first line displays which machine is launched.

The second line displays if actions are running (coin moving from state to state).

Step 2: The Second Machine: 1 Master (with Emergency Stop) and 3 Slave With a Synchronization State

Picture of The Second Machine: 1 Master (with Emergency Stop)  and 3 Slave With a Synchronization State

The machines:

You have to push the DOWN button to start the Master machine and another time (the same button) to stop it and so on.

When the 3 machines are launched and running, if at one moment, the 3 leds are on (a state called "synchro" is scanning this all the time), the Master machine is disable. Push the DOWN button to restart it.

The state synchro is called a Convergence of Simultaneous Sequences or machines.

It 's an emergency stop on the master, very used in industrial machine to protect the devices and the human bodies.

Step 3: The Third Machine: 1 Master (with Emergency Stop) and 3 Slaves Synchronized and I2C I/O Expansions

Picture of The Third Machine: 1 Master (with Emergency Stop) and 3 Slaves Synchronized and I2C I/O Expansions

I use 2 kind of I2C IC:

- 2 x PCF8591P: to give 2 x 4 analog inputs and 2 x1 analog outputs

-2 x PCF8574P: to give 1 x 8 digital inputs and 1 x 8 digital outputs.

The I2C adresses are claculated with the table supplied.

According to the schematic, I found the following adresses:

- 73 dec for the first analog output (IC PCF8591P)

- 74 dec for the second analog output (IC PCF8591P)

- 59 dec for the digital inputs (IC PCF8574P)

- 60 dec for the digital outputs (IC PCF8574P)

Now the 3 independant machines are actioning 3 different byte registers FBx, SBx and PUMPx on which I put an XOR mask to give a unique register "x" which updates the IC outputs on the adress 60.

See the source code, there are many comments on it.

WARNING!! When you power up the PCF8574 all the digital outputs go HIGH quickly and then LOW: it can injured your system. Be carefull!! To fix this you do use a complement of the bytes to send and an inverting buffer behind the PCF8574. I will correct it asap.

Step 4: To Conclude...

It 's a very powerfull library and don't forget to reset the output when you disable a machine.

If you don't want to use I2C expansion you can adapt it on my famous (I think so!) arduino atmega644/1284 clone.

Thanx to several interesting running amazing and shared tutorial on the net.

Step 5: I2C Power Up Bug Fixed!!

Picture of I2C Power Up Bug Fixed!!

I used an IC like CD4049 or 74HCT540 to complement byte of the 8 outputs of the PCF8574P because when power up this circuit all the outputs went HIGH. It 's dangerous and could destroy your system with unwanted initial tasks.

So now you have to send on the I2C bus a complement of the x value, written like this in C: x= ~ ((FBx ^ SBx) ^ PUMPx)).

I give you the new schematic and the last source version.


GerryGit (author)2016-07-03

Thanks again. I have answered my own questions. I found the SM.h library in your Arduino Flowmeter with a state machine Instructable. It compiles best in IDE 1.0.1.

manu4371 (author)GerryGit2016-07-03

Hello GerryGit!!

Thanks for your support!

Indeed, it's been very difficult to find SM.h lib for few month because of a conflict with the author Nilton61 and some people who decided to put the code on a repository without any author's agreement. What a pity for such a valuable and so usefull library. I hope I will not have troubles with the code put on my instructables...but you can find it on the net... somewhere.

So I used the IDE 1.6.0 with SM lib v1.2 and it runs very well. There are perhaps sometimes bugs with Delay() vs state.Timeout but easy to correct them. Recently I worked on a fireworks control unit and a very complicated state machine (1 master and 2x3 slave multitasking machines): no problem, not so much line code, and a very easy to read program.

Good instructables!!

RenéB2 (author)2016-06-20

Hey! I just wrote an Instructable about this topic as well. Check it out if you want to know how you can implement a statemachine without writing any state-related code - the tool I used generates it for you. It also allows multitasking, because you can have multiple state machines running at once. The only task left to the developer is writing the functions that talk to the outside world, like lighting up a LED, or raising events to the state machine when a button is pressed. Take a look!

manu4371 (author)RenéB22016-07-03

Hi RenéB2

Thanks for your interest in State Machine programing and application. I tried the Eclipse plugin you gave me and it runs very well. For me it's a good way to draw state machines with (pseudo) multitasking and to run it. I don't try to put the code in an arduino but I think it will be easy. It's been a long time I'm looking for such a freeware. Another one I 'did not have time to test: Quantum Leap, but I don't think it allows you to run multitasks.

Thanks and good instructable!!!!

GerryGit (author)2016-07-03

Thanks for this work. Looks really interesting. Unfortunately it looks as if the <SM.h> library has been pulled off the Arduino site. There is one on Codebender but I suspect it is not the correct one. Do you have any indication of where the <SM.h> library lives? Alternatively a downloadable on the project page might help. Also I see there are issues with <SM.h> and Arduino IDE. Which version did you use for this project? Thanks.

zavorra (author)2015-02-26


this is a very valuable instructable, indeed. Thanks for pointing out the SMlib, which I was completely missing.

manu4371 (author)zavorra2015-02-26

Thanks for your support. This lib is really reliable and fitted to automation. I'm using it these days on a new project: a power factor compensator. Soon on instructables...

mgosztyła (author)2014-12-17

thats shows power of arduino

peppypickle (author)2014-12-17

awesome Instructable, thanks for sharing!

About This Instructable




More by manu4371:Arduino 1.8.x Clone With Atmega 8535/32/644p/1284p: the MightycoreArduino PLC 32 I/O+State Machine+SCADA or HMIArduino-tomation part 1
Add instructable to: