Need Finite State Machine Help and/or Guidance

Not open for further replies.


I'm attempting to learn about state machines (fsm) and encountering some difficulties. I'm not the brightest bulb in the pack so I know someone here can direct me!

Here is what I want to do:

Using the Emic2 speech board alongside a teensy 3.6 and/or 3.2 (audio shield optional and I also have a prop shield)...I have 10 different modes & 10 corresponding buttons. I want each button to be a mode. I think the emic code is 'blocking' (recently learned about I said, I'm a noob!) so my efforts have all ended in failure. In fact, I failed at only using two buttons (two states).

I often find myself frustrated when I see LEDs for every example. Maybe my brain just doesn't get it.

I know the forum rules say you should post your code but I've tried a handful of different state machine / task scheduling libraries...I'm not sure which code variation to post. The best (or easiest) library I found so far has been:

I just don't know how to get the autoRepeat function to work and I'm super frustrated with myself. I know it's probably real life stuff getting in the way of my learning (husband just had a heart valve replacement, flying on the 6th and lost my ID)....but I was hoping to figure all this out before April 6th.

In summary, I would have 10 buttons that are associated with 10 different functions -- all functions utilize the emic2 board but in different ways. So, let's say I press button1 and I want it to auto repeat the function associated with it until I push another button...let's say, button2 which will stop the function associated with button1 and start the function associated with button2 (which is also AutoRepeated).

Anyone have any pointers? Some links for me to study?

I have looked at the libraries but because I'm fresh off the boat...I'm struggling (super sleep deprived too). Yet I don't want to cheat...I want to learn! I would love any resources, links, insight anyone has.

Here is what I have equipment wise: Two Teensy 3.6 (also have a 3.2 with Audio shield and a bunch of emic2 boards)....I also have an extra audio shield and prop shield. I have other things in mind but until I figure out how to do a finite state machine with buttons (I have 10), I can't entertain further. First things first, right?

Speaking of which...Paul, if you should see this post -- another big thanks for putting the ST7789_t3 library out there. I got it up and running! :)

Are you picking the correct tools? I don't see your program description as needing a state machine. You simply want to dispatch to one of 10 functions. I don't see your program as needing a task scheduling library. You want to run only one task at a time. On the other hand perhaps you want to learn how to use this library for some future project or like the OOP type of programming involved.

Here is an example of a state machine.
Notice how pushing the state variable through its possible values replaces a bunch of hard to understand logic.

Break the big problem down into smaller pieces and solve each of those:
   Get the board to talk.   Will you need to stay in this function or can you return to loop().
   Get the board to repeat when it runs out of something to say.
   Get the board to stop when a switch is pressed.
      Will all the tasks call the switch routine?  
      Or Use a pin change interrupt?  Perhaps all 10 could just go to one interrupt function.
      Is there a hardware reset pin on the DECtalk board.  That would stop it quickly. 
      Is there a stop function in the library.
   Now expand to more than one task.   A simple variable could hold a task number.
   How to dispatch to the correct task function?
      If else If else.    Switch case.   Function pointer.   The task library.
Hello Katie,

Implementing a finite state machine is fairly straight forward.
First you need a variable that represents your state. In your case just take an int and set it a value from 1..10, corresponding to your ten modes.
Whenever you have a transition, i.e. you change the the state, you set the state variable to the new value. In your case whenever a button is pressed. Since you said the emic is blocking, you should use interrupts to detect when a button is pressed, and then update your state variable inside the ISR.
The only thing left to do is to call the function corresponding to the state. In your case I'd just put a stack of while(state == X) -loops in the loop() function, where X goes from 1 to 10, and inside the while-loops there are the emic functions you want to execute. This way one function will be repeated until the state changes.

Unfortunately I don't know any resources for you to look into, but I hope this will help you to get a basic understanding of how to implement finite state machines.

Thank you, rcarr & Flophi for the replies. This morning I did a better google search and learned some more. My error was not putting a while(state == X)! When I post in the future, I will think about the items that rcarr suggested, then sleep on it...because many times I'm able to figure it out on my own. This time, I think I was simply frustrated. I definitely have a ton to learn. To make emic stop speaking immediately, I use the following code that I found on an emic forum & it works nicely. Thanks again for the replies!

void PrintEmicNoWait(String emiccmd) {                            //  Function to prep string to send to EMIC right now.
  for (int chardex = 0; chardex != emiccmd.length(); chardex++) { //  Sends as individually chars one after another(EMIC requirement for 'X' Stop command to work)
  emicSerial.print('\n');  //Rdy!

void PrintEmic(String emiccmd) {            //  Function to prep string to send to EMIC when it's ready
  while ( != ':');         //  Ready for talks?
  emicSerial.print(emiccmd);                //  Send to EMIC
  emicSerial.print('\n');                   //  Ready!

void stopEmicNow() {
  if ( != ':') {
    PrintEmicNoWait("X"); //If your talking, shutup already (& send ready signal: all PrintEmic functions return \n).
    PrintEmic("R");  // Reset stuff
  emic.begin(RX_PIN, TX_PIN);
Not open for further replies.