finite state machine (FSM) library not working

Hi,

i was trying to use the finite state machine library (FSM) for a project I am working on but the library does not seem to compile on a recent version of the Arduino IDE. I have tried 1.6.7 and updated a few minutes ago to 1.6.9 with the same problem.

I found the library here: http://playground.arduino.cc/Code/FiniteStateMachine
and followed the link to this site: http://arduino-info.wikispaces.com/HAL-LibrariesUpdates

After the download I moved the library folder to the arduino library directory.
I have looked into the .h and .cpp file but as I am not an experienced programmer, I was not able to find a solution. The compiler error was also not very helpful as you can see below:

My code:

#include <elapsedMillis.h>

#include <FiniteStateMachine.h>

/*******************************************************************************
 initialize FSM states with proper enter, update and exit functions
*******************************************************************************/
State initState = State(initEnterFunction, initUpdateFunction, initExitFunction );
State idleState = State(idleEnterFunction, idleUpdateFunction, idleExitFunction );


//initialize state machine, start in state: Idle
FSM testStateMachine = FSM(initState);


#define INIT_TIMEOUT 5000
elapsedMillis initTimer;

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
  testStateMachine.update();

}

void initEnterFunction(){
  //start the timer of this cycle
  initTimer = 0;
}
void initUpdateFunction(){
  //time is up?
  if (initTimer > INIT_TIMEOUT) {
    testStateMachine.transitionTo(idleState);
  }
}
void initExitFunction(){
}

compiler error:

sketch_jun26a:8: error: 'initEnterFunction' was not declared in this scope

 State initState = State(initEnterFunction, initUpdateFunction, initExitFunction );

                         ^

sketch_jun26a:8: error: 'initUpdateFunction' was not declared in this scope

 State initState = State(initEnterFunction, initUpdateFunction, initExitFunction );

                                            ^

sketch_jun26a:8: error: 'initExitFunction' was not declared in this scope

 State initState = State(initEnterFunction, initUpdateFunction, initExitFunction );

So the compiler does not seem to find the functions from initState but they are there. The example sketch has the same problem after I have downloaded the missing libraries and changed WProgram.h to Arduino.h.

I would be very grateful if you could help me to solve this.

Usually, it stems from the Arduino breaking the rules of C to allow the use of a function before it is declared. Late versions of the IDE have had a difficult time tricking gcc into doing this. You can fix it by inserting function prototypes into the library, prior to the function usage.

Thank you very much for your answer aarg. Would you please be so kind and show me a short example how this needs to be done?

I have already tried to move things up in my sketch but it seems to be not possible to solve this problem completely. So I think it is necessary to insert function prototypes into the library as you suggested. Can this be done in a way that it works also for other peoples state machines without changing the code in the library again or will this just work for my project?

It's strange because a good library will have function prototypes for all the functions anyway, in a .h file. I can't answer without looking at the actual library. Are you sure you didn't just make a typo error?

I think this is a case of the IDE inserting your automatically generated function prototypes (forward declarations) just after the line starting with '/*'. Your function prototypes get inserted into that block comment where they do no good.

Modifying the beginning of your sketch should get the IDE to put your function prototypes somewhere useful. It may be as simple as adding a single line comment or dummy variable declaration just above the block comment. I can't seem to reproduce the problem with 1.6.9 (maybe it was fixed?) so I can't be sure what change will work.

@aarg: I don’t think I have made a typo because the example of the library has the same problem.

@johnwasser: I have added a dummy state and now the code seems to work in the way it should. It is not really elegant, but it works :slight_smile:
I will contact the author of the library and maybe he has some time to fix this.

new code:

#include <elapsedMillis.h>

#include <FiniteStateMachine.h>

#define INIT_TIMEOUT 5000
elapsedMillis initTimer;

#define IDLE_TIMEOUT 5000
elapsedMillis idleTimer;

void dummy(){};

/*******************************************************************************
 initialize FSM states with proper enter, update and exit functions
*******************************************************************************/
State dummyState = State(dummy);
State initState = State(initEnterFunction, initUpdateFunction, initExitFunction );
State idleState = State(idleEnterFunction, idleUpdateFunction, idleExitFunction );

//initialize state machine, start in state: Idle
FSM testStateMachine = FSM(initState);

void initEnterFunction(){
  //start the timer of this cycle
  initTimer = 0;
  Serial.println("initEnter");
}

void initUpdateFunction(){
  //time is up?
  if (initTimer > INIT_TIMEOUT) {
    Serial.println("initUpdate");
    testStateMachine.transitionTo(idleState);
  }
}

void initExitFunction(){
  Serial.println("initExit");
}

void idleEnterFunction(){
  //start the timer of this cycle
  idleTimer = 0;
  Serial.println("idleEnter");
}

void idleUpdateFunction(){
  //time is up?
  if (idleTimer > IDLE_TIMEOUT) {
    Serial.println("idleUpdate");
    testStateMachine.transitionTo(initState);
  }
}

void idleExitFunction(){
    Serial.println("idleExit");
}

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

}

void loop() {
  // put your main code here, to run repeatedly:
  testStateMachine.update();

}

Thank you all very much for your fast help! :slight_smile:

ditto thanks… !!

I found this trick was necessary to compile my code in 1.6.8 using this library as well…

relevant snippet of the area of interest that DOES compile:

#include <FiniteStateMachine.h>

void dummy (){}; // this is a needed work-around for getting FSM library to compile on IDE 1.6.8

// state definitions
State s_all_off = State(all_off);

FSM m_force_machine = FSM(s_all_off);  // init a state machine and entry point (starting state)

the snippet that DOES NOT compile:

#include <FiniteStateMachine.h>

// state definitions
State s_all_off = State(all_off);


FSM m_force_machine = FSM(s_all_off);  // init a state machine and entry point (starting state)

@scottmcphee

You do not need a dummy but you need to understand the compiler. The compiler needs to know what a function looks like so it can e.g. check if you’re passing the correct type of arguments. Therefore the compiler needs to know that before you reference the function(s).

Just adding a dummy function is not the correct way. If you would use that approach in a C/C++ program on a PC, it will still fail.

The correct way is to either move those functions to the beginning of the code or to add the so-called prototypes.

For the code used in the opening post

#include <elapsedMillis.h>

#include <FiniteStateMachine.h>

// function prototypes
void initEnterFunction();
void initUpdateFunction();
void initExitFunction();

void idleEnterFunction();
void idleUpdateFunction();
void idleExitFunction();

/*******************************************************************************
  initialize FSM states with proper enter, update and exit functions
*******************************************************************************/
State initState = State(initEnterFunction, initUpdateFunction, initExitFunction );
State idleState = State(idleEnterFunction, idleUpdateFunction, idleExitFunction );

...
...

Hi,

I use this library quiet often. I have modified the example of the library to work with an interrupt driven button to do crazy stuff...

...butI keep having the same problem with newer versions of the Arduino IDE as here described. I solved the problem also with the dummy function "dummy(){}" at the beginning of the sketch, but I'm unhappy with it. Did anyone already solved the problem modifying the library itself??

cheers

You don’t need a dummy; you just need to implement the functions before they are referenced in the code or add prototypes as decribed in reply #11.

It has nothing to do with the library, it has to do with the build process used by the Arduino environment that does not include them automatically.