2

I am trying to release one technique that I use a lot in my projects as an open source library. A way to quicly generate state machines in Arduino projects.

You create a class for your state machine, and this class inherits from a StateMachine superclass. Then you wrap your state functions around State objects that are called inside the main loop, and each state informs the next state at the end. It is hard to explain but easy to show up.

#include "StateMachine.h"

class Blink : public StateMachine{
  private:
    int port;
    int waitTime;
    CREATE_STATE(Blink, low);
    CREATE_STATE(Blink, high);
    void low() {
      digitalWrite(port, LOW);
      *this << &STATE(high) + waitTime;
    }
    void high() {
      digitalWrite(port, HIGH);
      *this << &STATE(low) + waitTime;
    }
  public:
    Blink(int port, int waitTime) :
      StateMachine(&STATE(low)),
      port(port),
      waitTime(waitTime),
      INIT_STATE(Blink, low),
      INIT_STATE(Blink, high)
      {
        pinMode(port, OUTPUT);
      }
};

Blink led1(13, 1000);
Blink led2(14, 2000);
Blink led3(15, 3000);

void setup() {}

void loop() {
  led1();
  led2();
  led3();
}

The most complex parts are abstracted inside the macros CREATE_STATE(), STATE and INIT_STATE.

CREATE_STATE creates an wrapper for the state function. INIT_STATE runs the wrapper constructor. STATE references to the wrapper inside the code.

They looks like this:

#define CREATE_STATE(statemachine, state) State<statemachine> state_##state
#define INIT_STATE(statemachine, state) state_##state(this, &statemachine::state)
#define STATE(state) state_##state

The problem is that this solution is too verbose for my liking. I wish I could cut up some verbosity removing the class name from the wrapper declaration and initiation, getting the name from context. In order to do so, I would require a way to retrieve the current scope class name on compile time. Is there any way to do so?

Luiz Menezes
  • 749
  • 7
  • 16
  • @RaymondChen thanks for the heads up... but I guess the answer is in this question... https://stackoverflow.com/questions/21143835/can-i-implement-an-autonomous-self-member-type-in-c – Luiz Menezes Nov 02 '18 at 16:26
  • Great job digging that up! – Raymond Chen Nov 02 '18 at 16:37
  • I think I will leave the question here, because the correlation between those two concepts (getting the class name, and implementing a self member) is not imediatelly obvious, and it might help others with the same problem. – Luiz Menezes Nov 02 '18 at 16:54
  • @RaymondChen I got the answer from the question I linked there... can you edit to change your duplication link? – Luiz Menezes Nov 02 '18 at 22:30
  • Sadly I cannot. Hopefully the comments here will send people to a better answer. – Raymond Chen Nov 02 '18 at 23:24

1 Answers1

2

It appears your problem is chiefly due to macro's. They're handled by the preprocessor, whuich is a bit inherited from C. It's not scope-aware - period.

Instead, have a look at the various C++ state machine implementations on the 'net. They generally use templates. Templates are processed by the C++ compiler itself. This makes them far more powerful. They understand syntax, scoping, overloading, advanced math including recursive functions, etcetera.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Sorry, but this is not an answer. This is a lengthy comment. – SergeyA Nov 02 '18 at 15:16
  • 2
    @SergeyA: Be serious. I explain that it's not possible with macros, why it's not possible, and then I provide an alternative. That's as good an answer as you're going to get. – MSalters Nov 02 '18 at 15:17