Home > On-Demand Archives > Talks >

Visualize Your State Machines

Adam Fraser-Kruck - Watch Now - EOC 2025 - Duration: 52:20

Visualize Your State Machines
Adam Fraser-Kruck

Let's dive into state machines by building an embedded security system!

Important Info

You should probably view my presentation as two parts:

  1. First half = introduction
  2. Second half = advanced

The first half provides a nice intro to visualizing state machines and using StateSmith with PlantUML. If all you want is some introductory info, it's OK to stop here :)

The second half starts to get more advanced and provides exclusive content to Embedded Online Conference attendees. It goes above and beyond what is already available in free StateSmith tutorials. I would highly recommend downloading the example project and following along (pausing when needed).

Presentation Description

State machines are an incredibly helpful pattern for embedded systems, but hand-coded state machines can be difficult to understand and maintain, especially as designs become more complex with additional states and transitions.

To make our lives easier, we are going to use StateSmith to visually model our state machines in PlantUML.

StateSmith is a cross-platform, free/open source tool for generating state machines in multiple programming languages (C, C++, C#, Java, Python, JavaScript, TypeScript). The generated code is human-readable, has zero dependencies, and is suitable for use with tiny bare-metal microcontrollers, video games, apps, web, computers, and more. It avoids dynamic memory allocations for those focused on safety or performance. Each state machine instance only requires a single byte of RAM.

We'll start by creating a simple button state machine that performs debouncing and long press detection. Then we will connect those button state machines to our Control and Display state machines.

Every step of the way, we will simulate our design using Wokwi (an online electronics simulator) so that you can easily follow along without any physical hardware.

Helpful Links

I'm happy to answer questions here, on GitHub or Discord.

Got any interesting state machine stories to share? I'm always interested :)

M↓ MARKDOWN HELP
italicssurround text with
*asterisks*
boldsurround text with
**two asterisks**
hyperlink
[hyperlink](https://example.com)
or just a bare URL
code
surround text with
`backticks`
strikethroughsurround text with
~~two tilde characters~~
quote
prefix with
>

Gb-coder
Score: 0 | 2 weeks ago | 1 reply

Adam, 1st - great presentation - and a lot of info for my more senior mind to assimilate!
2nd - Does the PlantUML satisfy as documentation or is there a place for something like Doxygen? I realize I'm lazy when writing good in code documentation let along requirements tracking into a project, just wondering if this tool can provide some help.
3rd - For non-trivial systems - can StateSmith encompass Test Driven Development philosophy and generate test cases as you go?

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | 1 reply

Thanks! I like the direction of your questions :)

Regarding doxygen

I haven't advertised this much yet, but StateSmith has the ability to generate a markdown file that details the behavior of each state (including inherited transitions). This is also really helpful for git diffs if you choose to use a draw.io SVG/XML format. Details here.

Would that help?

Regarding generating test cases

I love this idea! Especially for "non-trivial systems" where test coverage matters. I'm not entirely sure how to accomplish it though. Which test framework? gtest (c++)? cpputest (c++)? cmocka (c)?
I have some ideas in this issue.

Feedback and suggestions welcome!

Gb-coder
Score: 0 | 2 weeks ago | 1 reply

Doxygen - after a quick online search I see I'm not the first to wonder about Doxygen and plantUML. I suspect the underlying question is - are Doxygen and plantUML redundant description languages? Perhaps an issue to resolve under a company's coding and requirements traceability practices. Developing an actionable UML at least keeps some of the documentation in an automated format.
a StackOverflow hyperlink

Regarding test cases: James Grenning backs Test Driven Design (TDD). I'm not well enough versed in this to make recommendations but the goal is not to create more work than necessary for the developer to validate code - and do that as close to code development as possible and automate those tests.
cpptest hyperlink

I'm looking into both of your links - thanks!

Otzen
Score: 0 | 7 days ago | no reply

Regarding generating testcases and TDD.
As I understand TDD, this would be contradictory to TDD.
TDD is not just that you write the testcases at the same as you code. The key philosophy is that you write test before your code. Not all the tests but the tests that will test the next price of code that you write, in this sequence:

  1. Write a test.
  2. See the test fail.
  3. Write the code to pass the test.
  4. See the test pass
  5. go to 1.

So to my point, if anything should be auto/generated in TDD, it would be the code, based on the test you wrote.

Regards Otzen :-)

Nikos-veevue
Score: 0 | 2 weeks ago | no reply

Great talk! Thanks a lot! I am definitely gonna give it a try. I've always wanted to have such a tool, first of all for automated visualisation of my state machines but also for automated code generation. There's a lot to explore!

jseidmann
Score: 1 | 2 weeks ago | 1 reply

As someone who uses another commercial state machine tool on a project started ~7 years ago, I would have LOVED if this was available back then. Kudos to you!

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Thanks! It was about 8 years ago that I decided to write what would become StateSmith. I honestly didn't see another option other than quitting the new job I had just started. The project I was given was intense (but also super interesting). I explored hand coding (even creating a HSM helper lib), but the design was far too large (300+ states). I explored commercial tools, but they all fell short. They were either too rigid, painful to use, unstable/crashing, used dynamic memory, or output buggy code. So... in a weekend of desperation, I gave up sleeping and created a StateSmith proof of concept generating basic C99 fsm code from a simple diagram. More gory details here if you are interested.

StateSmith isn't perfect yet by any means, but it's already very useful and steadily improving :)

Thomas.Schaertel
Score: 1 | 2 weeks ago | 2 replies

Adam, that presentation was fantastic! I like the integration of state machine description, UML generation, visualisation and simulation very much. In fact, I use a lot of different tools for that now. I'll definitely give StateSmith a try. Mainly my application is in robotics where I use ROS with lots of hand-written code. Seems, that I can improve my workflow! So the EOC helped me to discover real treasures. Thank a lot for your presentation and your work!
Thomas

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

I forgot to mention a few things in my earlier reply.

  1. robots are awesome! Johnny 5!
  2. for robotics and video games (surprisingly similar) I like to mix hand coded "sequence" state machines with high level code generated state machines.

The idea is to utilize the main strength of each approach (hand coding + code generation). I find motion sequences to often be fairly linear like "do a, then b, then c, then d..." with a bit of stopping logic. These sequences are often more efficiently defined in code/data rather than a diagram. They are also generally linear/trivial so a diagram doesn't help too much.

However, the top level state machine that switches between motion sequences or high level behaviors is a great place for FSM diagrams and code generation. So I use StateSmith to design these top level states and the transitions between them, and then I have those high level states run the hand coded motion sequences.

I have a Work In Progress tutorial that illustrates this with draw.io and game "AI". That tutorial covers a lot of interesting ground, but for this conversation, this picture provides the important concept. The enemy CHARGE attack high level state runs a hand coded state machine behavior that slowly rotates the enemy blog horizontal and then launches at the player. Importantly, it also has an exit trigger. This prevents the blob enemy being stuck in a charging pose if a top level transition occurred.

I took an existing platformer web game and gave the super dumb enemy blobs increasingly interesting "AI" behaviors. Enemy3 has 15 high level behaviors like hunt the player, dodge grenades, call for help, sleep, dance, ...

The tutorial uses draw.io, but the same idea would work with PlantUML. For solo projects that may get large/deeply nested, I often prefer draw.io.
https://github.com/adamfk/game-fsm-examples

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Thanks for your kind words Thomas :)

Florian
Score: 0 | 2 weeks ago | 1 reply

Hi, great presentation. You mentioned you got feedback from using this in a safety critical system. As I work in automotive, my immediate thought was: If I use this, I need to do tool qualification OR review the ENTIRE generated code after every generation. How would you suggest handling this? I guess the tool has no ASIL qualification.

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | 1 reply

Hi Florian,

Great question! I'm not sure how the team from France was handling this issue. They didn't offer and I didn't pry. They were using the Diab compiler and OpenECU. That said, StateSmith has no certifications of any kind at this point.

I've never worked with safety critical systems, but I have worked a lot in off highway automotive (tractors and stuff). Our general approach was extensive testing. Test every single transition (including inherited transitions) and every behavior. I've been thinking about having StateSmith generate a gtest fixture class that makes this easier and guarantees state behavior coverage.

For me, I personally prefer extensive testing. I've seen people use safety certified tools in clearly unsafe and error prone ways. Sometimes management will say things like "they are using Matlab Simulink and certified code generation that cost a lot of money, it must be good". But then the user Simulink code does an out of bounds array access and has very few tests because of the perception that Matlab/Simulink will magically make everything safe.

It's the combination of user design/code and the tool code that matters. A safety certified hammer doesn't make for safe carpenters if they choose to dangle off of ladders to reach the nail.

Maybe take a look at some generated code to see what it is like?

I'd love to better understand what would help safety critical users. Happy to discuss more on StateSmith github, StateSmith discord, or EOC discord.

Florian
Score: 0 | 2 weeks ago | no reply

Hi Adam, thanks for your reply.

I kind of understand your argument regarding Simulink, however, if someone uses this argument in production, he did not understand the tooling. Yes, the tool is qualified, BUT there are assumptions of use. One of them being having to run a static analysis tool on the generated code. This would then of course find the array out of bounds access.

So, basically it boils down to the statement in the first message. For a code generating tool, you either have to qualify the tool (i.e. proof that the generated code will not produce errors), or manually review the entire generated code after every generation (i.e. for every productive generation that will land in production, no review required for development purposes obviously).
In the real world, this will probably just be a diff review of the changes, which should come kind of naturally with your version control system (like github pull request review), but will introduce extra files to review. In contrast, a generated state machine using Simulink will not require you to review the generated code, however you have to run static analysis.

I was just curious if the team you heard of using StateSmith were sharing details on how their process was dealing with this generated code.

datamstr
Score: 1 | 2 weeks ago | 1 reply

Excellent presentation!

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Thanks datamstr :)

Yolande
Score: 1 | 2 weeks ago | 1 reply

Great presentation Adam! I like how you dove straight in.

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Thanks Yolande :)

Miro
Score: 0 | 2 weeks ago | 1 reply

Thank you for your presentation about state machines and the StateSmith code generator. Having evangelized state machines for a very long time, I'm really glad to see the interest and appreciation for (hierarchical) state machines.

The StateSmith tool, in conjunction with PlantUML, seems to transform text (.plantuml file) into another text (.h, *.c/cpp files). By performing this transformation in a traditional way, StateSmith needs to manage many sections (e.g., HFileIncludes, CFileIncludes, IncludeGuardLabel, etc.), each with its own rules that the user must know.

But how about turning this upside down and inverting the dependencies? You could allow the user to provide their own "file templates", in which they would type whatever they want to go into each .h and .c/cpp file (and this will be literally copied to the generated code). The users will then explicitly request code generation (by some easy-to-parse tags) in specific places in the files. To see how all this works, please take a look at the QM modeling and code generation tool.

And finally, state machines are only the tip of the iceberg. To use them effectively, you still need to integrate them into the execution environment. In your presentation, you showed only the integration based on synchronous dispatching events to state machines. This can get messy very quickly and can lead to a violation of run-to-completion event processing. For example, let's say that you have three state machines A, B, and C. The "superloop" calls dispatch(&A), which internally calls dispatch(&B), which internally calls dispatch(&A) back(!)

Do you have any plans to extend StateSmith with event queues and asynchronous event posting?

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Hi Miro, thanks for watching and sharing ideas :)

For C99, StateSmith can do something similar to the template approach you suggested using .inc files. I've opened a new issue for the idea though. Thanks! I'm currently working on a few ideas to make StateSmith easier to use like supporting an external toml file for config.

Regarding "superloops"

I agree that developers need to consider how to connect state machines together to avoid recursion (A->B->A->B->...). With a bit of experience and simple architecture, I've found it pretty easy to avoid this problem. There are also static analysis tools for detecting recursion (like clang-tidy no-recursion).

In my presentation, I show a mix of different ways of connecting state machines. The Button and Control state machines don't actually call another state machine directly - they just set simple flag variables for the UI state machine (here's an example). This is a super easy and low cost (RAM/CPU/FLASH) method of alleviating the recursion concern.

There are a ton of benefits to using super loops for either simple or advanced critical situations.

I like that StateSmith doesn't restrict the user on how they want to wire their state machines together. Bare metal + super loop + flags? Sure. FreeRTOS + threads + queues? Sure... John Taylor's EOC 2024 data model approach would work as well.

Regarding "plans to extend StateSmith with event queues"

I don't see myself restricting StateSmith in the future to always require event queues, but an additional option could be added to make this easier for users that want it. I definitely see value in the restricted approach taken by most other tools as it makes things simpler for users, but I love that StateSmith has zero dependencies. This allows StateSmith to run almost anywhere (even on tiny 8 bit MCUs).

There is a cost to this freedom though. Learning very flexible tools like StateSmith is less straightforward.

zilvinas.nakutis
Score: 0 | 2 weeks ago | 1 reply

There is an alternative tool itemisCREATE for designing with state machines. What are the essential pros&cons of the tool chain you have demonstrated compared to itemisCREATE?

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Probably the biggest advantage is that StateSmith is fully free and open source while itemisCREATE (formerly known as yakindu) can cost up to $19000 CAD (plus a yearly $6000 CAD) for a single floating license. That's a lot. A number of StateSmith users have told me cost was the primary factor that drove them away from itemisCREATE/yakindu.

It's been quite a while since I used yakindu so some of the below info may be dated.

itemisCREATE pros:

  • supports orthogonal regions / parallel states
    • StateSmith predecessor had this, but I haven't yet added it back since rewrite
  • has nicer timing syntax like after 5s
    • StateSmith predecessor had this, but I haven't yet added it back since rewrite
  • nice syntax highlighting
  • more validations

itemisCREATE cons:

  • Very expensive tool (and no longer open source)
  • Requires special git workflow. You need to use the tool for merges. Not great for teams and pull requests.
  • Heavy weight Eclipse based UI. This can be really painful and slow at times.
  • Cumbersome editor. Slow workflow. Lots of mouse clicking.
  • Buggy editor sometimes crashes a lot. This has probably improved in recent years.
  • Generated code used significantly more RAM (checked a long time ago)
  • Lacks power features available in StateSmith (like state machine graph transformations)

Overall, I think itemisCREATE/yakindu is a solid choice for teams that need its feature set and don't mind its cons.

It's nice to have options :)

Otzen
Score: 1 | 2 weeks ago | 1 reply

Nice presentation, I definitely need to find some time to go explore that.
One small criticism of the presentation, I kept loosing track of what files where generated, and which where handwritten. Maybe if I watch it again I will find a clue in the naming or similar.

Adam.Fraser-KruckSpeaker
Score: 0 | 2 weeks ago | no reply

Hi Otzen,
Great feedback. I agree. I added a new top level comment to my presentation that helps explain how to get the most out of the presentation.

The first half provides a nice intro to visualizing state machines and using StateSmith + PlantUML.

The second half I would view as optional. It starts to get more advanced and provides exclusive content to Embedded Online Conference attendees. It goes above and beyond what is already available in free in StateSmith tutorials.

If you want to get the most out of the second half of the video which gets more advanced, I would highly recommend downloading the example project and following along (pausing when needed).

Otzen
Score: 0 | 2 weeks ago | 1 reply

You mention drawio and plantUml. But I am not sure i got it.
Can you draw the states in drawio, and then generate the fsm from that?

Adam.Fraser-KruckSpeaker
Score: 1 | 2 weeks ago | no reply

Hi Otzen, great question.

You can draw state machine diagrams in PlantUML or draw.io and feed those diagrams to StateSmith to generate working code. I was originally planning to show how to use StateSmith with both, but then decided against it as I already have a free video series & tutorial on using draw.io with StateSmith.

I wanted to provide value to EOC attendees beyond what's already freely available so I decided to focus on just PlantUML and cover more advanced topics in the second half of my presentation. I hope that makes sense.

Adam.Fraser-KruckSpeaker
Score: 3 | 2 weeks ago | no reply

Hi everyone, important info below.

You should probably view my presentation in two parts:
1) first half == introductory
2) second half == advanced

The first half provides a nice intro to visualizing state machines and using StateSmith + PlantUML. If all you want is some introductory info, it's OK to stop here :)

The second half starts to get more advanced and provides exclusive content to Embedded Online Conference attendees. It goes above and beyond what is already available in free StateSmith tutorials.

If you want to get the most out of the second half of the video which gets more advanced, I would highly recommend downloading the example project and following along (pausing when needed).

Here's some other helpful links:

I'm happy to answer questions here, on GitHub or discord.

Got any interesting state machine stories to share? I'm always interested :)

OUR SPONSORS & PARTNERS