SM PossibiltiesPlus

From ArduinoInfo
Jump to: navigation, search




Many newbies and even semi-experienced Arduino coders have difficulty grasping the concept of managing overlapping activities with different time requirements.

I think it is key to create a framework that many can start from to write non-trivial Arduino sketches that are easy-to-use, easy-to-understand, and Lightweight.

The State Machine approach is a good way to ensure a correct program and it also provides for easily managing overlapping activities with different time requirements. </span>

What is needed is a SM "Framework" that Newbies can get, that starts them off with things like:

  • The SM Library, possibly including some additional services</span>
  • A Book or Website that addresses both formal and practical information</span>
  • A Running example that includes some more advanced capabilities</span>
  • Easy to expand examples of things like counting, waiting and synchronization for multiple functions.
  • A command/status console that can be displayed on the Serial Monitor</span>
    • Shows running machines and possibly current states</span>
    • Possibly start and stop individual machines</span>
    • Supports optional Debug messages</span>
    • Possibly supports timing traces</span>
  • (relatively) easy-to-understand working examples (or library functions?) that handle the usual "problem" situations:</span>
    • Human I/O on Serial Monitor or Processing,</span>
    • communications to other machines,</span>
    • 'concurrent' motor drive movements while looking at sensors etc.</span>

Graphical Editor for SCXML


The first file is the executable visual editor. Downlaod that, and then the example, OPen the example in the editor.
[/file/view/fsm-editor.jar/476550744/fsm-editor.jar fsm-editor.jar]
[/file/view/fsm-editor.jar/476550744/fsm-editor.jar fsm-editor.jar]
  • [/file/detail/fsm-editor.jar Details]
  • [/file/view/fsm-editor.jar/476550744/fsm-editor.jar Download]
  • 4 MB

Simple example:
[/file/view/sctry1.scxml/476558836/sctry1.scxml sctry1.scxml]
[/file/view/sctry1.scxml/476558836/sctry1.scxml sctry1.scxml]
  • [/file/detail/sctry1.scxml Details]
  • [/file/view/sctry1.scxml/476558836/sctry1.scxml Download]
  • 1 KB


(Code fragment. Now calls functions that have delays. What is a good way to handle the idea of "Subroutine calls" in a State Machine environment, where "Return to calling procedure" is not the same as in single-threaded code??)

/**************************( STATE MACHINE FUNCTIONS )******************************/ State RoboStartState() { Serial.println("+++ RoboStartState"); digitalWrite(PIN13_LED,LOW); // LED Means Target Too Close ForwardFast(); // Start moving forward if (RoboGo.Timeout(25)) RoboGo.Set(RoboForwardSlow) ; }// END State RoboStartState State RoboForwardSlow() { ForwardSlow(); // Start moving forward if (RoboGo.Timeout(600)) RoboGo.Set(RoboStopLookState) ; } State RoboStopLookState() { Serial.println("+++ RoboStopLookState"); for (int i = 0; i < TARGET_ARRAY_SIZE; i++) TargetArray[i] = false; Stop(); // Start moving forward LookAround(); // Ping Ultrasonic in different directions, Set TargetArray if (TargetArray[TARGET_CENTER ] == true) RoboGo.Set(RoboTargetCenter); else if (TargetArray[TARGET_LEFT ] == true) RoboGo.Set(RoboTargetLeft); else if (TargetArray[TARGET_RIGHT ] == true) RoboGo.Set(RoboTargetRight); else RoboGo.Set(RoboStartState); }// END State RoboStartState State RoboTargetLeft() { Serial.println("***** RoboTargetLeft"); Stop(); BackwardSlow(500); SpinRight(500); delay(500); RoboGo.Set(RoboStartState); }// END State RoboTargetLeft ---------------------- State RoboTargetCenter() { Serial.println("***** RoboTargetCenter"); Stop(); BackwardSlow(500); SpinLeft(1100); delay(500); RoboGo.Set(RoboStartState); } // END State RoboTargetCenter ----------------- State RoboTargetRight() { Serial.println("***** RoboTargetRight"); Stop(); delay(500); BackwardSlow(500); SpinLeft(500); delay(500); RoboGo.Set(RoboStartState); }// END State RoboTargetRight ----------------- //*********( THE END )***********


@niltont61, my point is not about the value of a State Machine as a good way to ensure a correct program (which of course it does) but rather about the facility it also provides for easily managing overlapping activities with different time requirements - something newbies seem to have difficulty grasping.

And rules for state diagrams do not need to be theoretic/academic or hard to grasp. Its not harder to make a state diagram than playing a board game with one game figur

ROBIN: I can't help feeling that a deep discussion of the theory of State Machines and State Machine diagrams will just drive newbies away.

TERRY: BUT that does NOT mean that we can not.find ways to enable Newbies to learn how to use State Machines and think that way. I plan to put a series of examples on the ArduinoInfo.Info WIKI showing that. I'm following Nick's and Nilton's ideas.


Some easy to understand examples of state machines (simple ones) might be all that some people are looking for. Then, there can be a section on more advanced state machines, and how to determine the states, the transitions, the actions that trigger (or not) transitions, and the actions that occur as a state change happens, with code snippets to illustrate what the state/event/transition/trigger/action looks like in Arduino-ese would be good.

As i wrote on another thread: Its obviously time for a book on the subject, or a dedicated webpage or both. And i have been planning so for a time. The problem i see is my current publisher is specialized in Swedish schoolbooks and is reluctant to publish an English book outside the Swedish school curriculum

Also, doing a state diagram forces you to think through the problem itself without actually thinking about code. I consider this very powerful tool for problem solving.

Jack Christianson:

(quote)Would it be so hard for newbees doing a state diagram before coding and getting the gratification of having their code work with little or no debugging??

No it wouldn't be hard! In fact it's essential! As you have said, once the state diagram or table is completed, the code just about writes itself. And it's quick to do. I wouldn't even consider not doing a state diagram for anything more complex than blinking an LED.


It is actually quite hard to write training material that doesn't slide off into being either:

  • So simple it doesn't teach anything except trivial cases (and therefore isn't much practical use).
  • So complex that students are overwhelmed and don't learn anything from it.
Very true, Nick. I think that good and clear and incremental examples tied to text and graphics that explain the concepts are probably the best solution to this.

(nick) To be honest with you guys, I kind-of like my diagram:
So do I. Formal state diagrams are fine but a table will be more familiar to most people and therefore more likely to be used.</span>


May I repeat my plea to mention, for the benefit of the many authors whose questions imply that they don't know, that the State Machine concept is ideal for managing overlapping activities that require different timing.

I am just wondering if something that does multiple things (eg. blinks LEDs at different rates) is really multiple state machines running simultaneously?


I think the subject may be something like, "How can sketch writers who do not have much background in timing in the Arduino environment be enabled to manage overlapping activities that require different timing".

We do not have a Real Time Operating system or a clocked hardware state machine, we have a small right-on-the-metal machine. The lightweight SM library approach that supports multiple quasi-concurrent State Machines does provide a way of managing the overlapping activities that plague and discourage many Arduino enthusiasts. I am trying to figure out good examples of doing that.

In the simple case where you only need to manage one instance of each type of activity, the simplest approach IMO is to write a handler function that deals with that thing. Where it needs some persistent data, make that local static as far as possible so that it is self contained. For example:

void blinkLed()
static const int LED_PIN = 13;
static const unsigned long BLINK_INTERVAL = 500; // duration of each blink phase
static unsigned long lastBlinkTime = 0;

if(millis() - lastBlinkTime >= BLINK_INTERVAL)
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
lastBlinkTime += BLINK_INTERVAL

If you need to make it configurable, or deal with with multiple instances, that's possible with minor changes to the implementation. This example is not a finite state machine, but it is easy to use a similar approach to implement functions to maintain a finite state machine, and doing so makes it easy to maintain multiple independent machines with minimal coupling between them.