Implementing Finite State Machine with an Array of Pointer to Member Functions

Hello all,

Per the title, I am trying to implement a finite state machine (actually a series of tasks, all of which are FSMs, but that will come later) in Arduino and am running into some issues.

My program is built as follows:

A main .INO file, which will serve as a mastermind file for calling a set of .CPP and .H files, which will each contain a task.

Right now I am just trying to get one FSM up and running before implementing task scheduling, etc.

Here is the code I have, broken into 3 files: Testing3.ino, t3p0.cpp and t3p0.h.

Testing3.ino:

#include "t3p0.h"



pat0 Pat0;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
}

void loop() {
  // put your main code here, to run repeatedly:
    Serial.println("loop"); //used for debugging purposes
    delay(500);
    
    Pat0.main(); //Right now, I only want to call one of my tasks, later I will build in task handling, etc.



   
    
}

t3p0.cpp:

#include "t3p0.h"
#include <Arduino.h>
#include "HardwareSerial.h"
#include "print.h"




pat0::pat0(){
    pat0fn pat0_array[] = {&pat0::p0_s0, &pat0::p0_s1, &pat0::p0_s2}; 
}

void pat0::p0_s0(){
  Serial.println("p0 state0");
  zerostate++;

}

void pat0::p0_s1(){
  Serial.println("p0 state1");
  zerostate++;

}

void pat0::p0_s2(){

  Serial.println("p0 state2");
  zerostate=0;
}


void pat0::main(){

  //This is where I want to implement my state machine.
  
  
  
}

t3p0.h:

/*
   t3p0.h

    Created on: Dec 13, 2018
        Author:
*/

#ifndef T3P0_H_
#define T3P0_H_

class pat0
{
    static int zerostate; //This is the state variable for task/pattern 0.

  public:

    pat0();          //Class constructor

    void p0_s0(); // Function for state 0 of pattern 0.

    void p0_s1(); // Function for state 1 of pattern 0.

    void p0_s2(); // Function for state 2 of pattern 0.

    void main();

};

typedef void (pat0::*pat0fn)();


extern pat0fn pat0_array[3];




#endif /* T3P0_H_ */

My goal is for my mastermind file to decide which task it needs to be running on each run through loop(), and then step into the relevant .cpp file, and have the task's state machine be implemented in a main() function there.

The issue I am having is when I attempt to use the array of pointer to member functions that I created. I have tried the following methods, all in t3p0's main() function, which right now I automatically run when I put the code on the board:
METHODS

Method1 :

(pat0_array[zerostate])();


//Method 2:

(pat0fn ->*pat0_array[zerostate])();


//Method 3:

(pat0fn .*pat0_array[zerostate])()

I attempted these based on feedback I was given in a still open thread, which I plan to update as soon as this is working properly.

Here are the errors I get when I attempt methods 1-3
ERRORS:

//Error for Method 1:

sketch\t3p0.cpp: In member function 'void pat0::main()':

t3p0.cpp:39:27: error: must use '.*' or '->*' to call pointer-to-member function in 'pat0_array[((pat0*)this)->pat0::zerostate] (...)', e.g. '(... ->* pat0_array[((pat0*)this)->pat0::zerostate]) (...)'

   (pat0_array[zerostate])();

                           ^

exit status 1
must use '.*' or '->*' to call pointer-to-member function in 'pat0_array[((pat0*)this)->pat0::zerostate] (...)', e.g. '(... ->* pat0_array[((pat0*)this)->pat0::zerostate]) (...)'




//Error for Method 2


sketch\t3p0.cpp: In member function 'void pat0::main()':

t3p0.cpp:40:10: error: expected primary-expression before '->*' token

  (pat0fn ->*pat0_array[zerostate])();

          ^

exit status 1
expected primary-expression before '->*' token



//Error for Method 3


sketch\t3p0.cpp: In member function 'void pat0::main()':

t3p0.cpp:40:10: error: expected primary-expression before '.*' token

  (pat0fn .*pat0_array[zerostate])();

          ^

exit status 1
expected primary-expression before '.*' token

I have also tried the same three methods but passing in an integer instead of zerostate, just in case. I used the integer 0. The results were the same.

Has anyone seen this before? If I don't include the 3 lines that cause errors, I can run the code. It will step through my loop() function in Testing3.ino, then when loop() calls Pat0.main(), I can individually call any of the 3 state functions in t3p0 within main. I just can't seem to use my array of pointers to member functions.

I appreciate any insight folks can give!

As @Delta_G said, you need to decide exactly what you want your class(es) to be. Will each FSM be a separate class unrelated to the others? If so, save yourself some grief and make all the members of each class static and hence a singleton.

Or, are you trying to define an FSM class that will support multiple instances? If so, that seems a bit limiting as each instance would need to have the same state functions / variables (although each one could be in a different state at any given time).

Or, are you trying to define a base FSM class and then create multiple derived classes that inherit from the base allowing them to be called in a polymorphic manner? If so, then the same question about multiple instances above now applies to the derived classes.

You cannot call any function/method main(). There can be 1 and 1 only main function and that is provided by the IDE

Mark

holmes4:
You cannot call any function/method main(). There can be 1 and 1 only main function and that is provided by the IDE

Mark

There is not a reason in the world why you cannot have a class member function named main(). Try it...

Regards,
Ray L.