Errors occurring when implementing finite state machine

Hello all,

Apologies for dumping this here but I have attempted to resolve these errors several times and I just cant seem to get it.

In my code below I have attempted to create a state machine to enforce an order of execution for 3 servos. The libraries I have used include: <Button.h>, <FiniteStateMachine.h>, <Servo.h>

#include <Button.h> //button library
#include <FiniteStateMachine.h> //FSM library
#include <Servo.h> //servo library

//initialize states

State start = State(startEnter,startUpdate,startExit); //0 state
State opened = State(openedEnter,openedUpdate,openedExit); //1st state
State pause = State(pauseEnter,pauseUpdate,pauseExit); //2nd state
State closed = State(closedEnter,closedUpdate,closedExit); //3rd state
FiniteStateMachine ABStateMachine = FiniteStateMachine(start); //initialize state machine, start in state: start

Button mpb = Button(12,PULLUP); //initialize the momentary push button (wire between pin 12 and ground)

Servo myservo1; //projector platform servo
Servo myservo2; //kinect platform servo
Servo myservo3; //scissor legs servo

unsigned long Timer1; //define timer variable for state 1 if statement
unsigned long Timer2; //define timer variable for state 3 if statement

void setup() 
{ 
  myservo1.attach(9); // attatch servo 1 to pin 9
  myservo2.attach(10); // attatch servo 2 to pin 10
  myservo3.attach(11); // attatch servo 3 to pin 11
}

/////////////////////// State Functions /////////////////////////////

// State 0
void startEnter();
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
  myservo2.writeMicroseconds(1474); // ensures servo 2 is stationary
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary
}

void startUpdate();
{
  if(mpb.isPressed()) // if the button is pressed, state 0 (start) transitions to state 1 (opened)
  {
    ABStateMachine.transitionTo(opened);
    else start getCurrentState(); // if the button is not pressed, state 0 (start) repeats
    }
  }
}

// State 1
void openedEnter();
{
  for(int speedv1 = 0; speedv1 <= 100; speedv1 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 + speedv1); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (ACW)
  myservo2.writeMicroseconds(1474 + speedv1); // servo 2
  myservo3.writeMicroseconds(1474 + speedv1); // servo 3
  delay(30); // delay between loop iterations
  }
  loop();
  {
    myservo1.writeMicroseconds(1574); // maintains servo 1 at full speed (ACW)
    myservo2.writeMicroseconds(1574); // maintains servo 2 at full speed (ACW)
    myservo3.writeMicroseconds(1574); // maintains servo 3 at full speed (ACW)
  }
  Timer1 = millis();
  if (millis() - Timer1 >= 10000) // after 10 seconds servos are ramped down in speed until stationary
    {
      for(int speedv2 = 0; speedv2 <= 100; speedv2 += 2) // loop to ramp down servo speed
      {
       myservo1.writeMicroseconds(1574 - speedv2); // speed decrease by 2 each iteration (servo 1) until servo stops
       myservo2.writeMicroseconds(1574 - speedv2); // servo 2
       myservo3.writeMicroseconds(1574 - speedv2); // servo 3
       delay(30); //delay between loop iterations
      }
    }  
}
void openedUpdate();
{
  ABStateMachine.transitionTo(pause); // state 1 (opened) transitions to state 2 (pause) when complete
}

// State 2
void pauseEnter();
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
  myservo2.writeMicroseconds(1474); // ensures servo 2 is stationary
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary 
}
void pauseUpdate();
{
  if(mpb.isPressed()) // if the button is pressed, state 2 (pause) transitions to state 3 (closed)
  {
    ABStateMachine.transitionTo(closed);
    {
    else pause getCurrentState(); // if the button is not pressed, state 2 (pause) repeats
    }
  }
}

// State 3
void closedEnter();
{
  for(int speedv3 = 0; speedv3 <= 100; speedv3 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 - speedv2); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (CW)
  myservo2.writeMicroseconds(1474 - speedv2); // servo 2
  myservo3.writeMicroseconds(1474 - speedv2); // servo 3
  delay(30); // delay between loop iterations
  }
  loop();
  {
    myservo1.writeMicroseconds(1374); // maintains servo 1 at full speed (CW)
    myservo2.writeMicroseconds(1374); // maintains servo 2 at full speed (CW)
    myservo3.writeMicroseconds(1374); // maintains servo 3 at full speed (CW)
  }
  Timer2 = millis();
  if (millis() - Timer2 >= 10000) // after 10 seconds servos are ramped down in speed until stationary
    {
      for(int speedv4 = 0; speedv4 <= 100; speedv4 += 2) // loop to ramp down speed of servos
      {
       myservo1.writeMicroseconds(1374 + speedv2); // speed decrease by 2 each iteration (servo 1) until servo stops
       myservo2.writeMicroseconds(1374 + speedv2); // servo 2
       myservo3.writeMicroseconds(1374 + speedv2); // servo 3
       delay(30); // delay between loop iterations
      }
    }  
}
void closedUpdate();
{
  ABStateMachine.transitionTo(start); // when state 3 (closed) is complete, the state machine returns to state 0 (start)
}

And the errors that are produced include:

TEST2rampbutton:8: error: 'startEnter' was not declared in this scope
TEST2rampbutton:8: error: 'startUpdate' was not declared in this scope
TEST2rampbutton:8: error: 'startExit' was not declared in this scope
TEST2rampbutton:9: error: 'openedEnter' was not declared in this scope
TEST2rampbutton:9: error: 'openedUpdate' was not declared in this scope
TEST2rampbutton:9: error: 'openedExit' was not declared in this scope
TEST2rampbutton:10: error: 'pauseEnter' was not declared in this scope
TEST2rampbutton:10: error: 'pauseUpdate' was not declared in this scope
TEST2rampbutton:10: error: 'pauseExit' was not declared in this scope
TEST2rampbutton:11: error: 'closedEnter' was not declared in this scope
TEST2rampbutton:11: error: 'closedUpdate' was not declared in this scope
TEST2rampbutton:11: error: 'closedExit' was not declared in this scope
TEST2rampbutton:34: error: expected unqualified-id before '{' token
TEST2rampbutton:41: error: expected unqualified-id before '{' token

My code has essentially produced 2 types of error. Would be much appreciated if I could be advised on where I have gone wrong.

Thanks

void openedEnter();
{
  for(int speedv1 = 0; speedv1 <= 100; speedv1 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 + speedv1); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (ACW)
  myservo2.writeMicroseconds(1474 + speedv1); // servo 2
  myservo3.writeMicroseconds(1474 + speedv1); // servo 3
  delay(30); // delay between loop iterations
  }
  loop();

I really don’t like the look of that there loop()
That could lead to recursion, that could.

void startUpdate();
{
  if(mpb.isPressed()) // if the button is pressed, state 0 (start) transitions to state 1 (opened)
  {
    ABStateMachine.transitionTo(opened);
    else start getCurrentState(); // if the button is not pressed, state 0 (start) repeats
    }

difficult to see what the “else” relates to.
Maybe try auto format.

You are using variables before you have defined them. I have no idea what type of variables that library is expecting.

Suppose that is expecting integer variables you would have int startEnter; etc before the lines that make use of those variables.

...R

[...]
void setup() 
{ 
  myservo1.attach(9); // attatch servo 1 to pin 9
[...]
  myservo3.attach(11); // attatch servo 3 to pin 11
}

void startEnter();
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
[...]
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary
}

void startUpdate();
{
  if(mpb.isPressed()) // if the button is pressed, state 0 (start) transitions to state 1 (opened)
  {
    ABStateMachine.transitionTo(opened);
    else start getCurrentState(); // if the button is not pressed, state 0 (start) repeats
    }
  }
}

[...]

You've got semicolons where you don't want them (compare the code above for 'setup' vs. the other functions) and you've also got a problem with mismatched brackets (you have an extra "}" in 'startUpdate').

That might help a bit as well.

Regards,

Brad
KF7FER

@AWOL

How would this loop produce recursion ? The else relates to the if statement for whether the button I am using has been pressed or not. If the button has not been pressed start getCurrentState(); returns the current state. I have interpreted this as if the button has not been pressed, the processes within the current state are just repeated, until the button is pressed. Is this incorrect ? I have obtained the definition for start getCurrentState(); from the FSM library page on the arduino website.

@Robin2

I understand what you mean. I have attempted define these variables as int but this prodcued another error:

TEST2rampbutton:35: error: 'void startEnter()' redeclared as different kind of symbol
TEST2rampbutton:8: error: previous declaration of 'int startEnter'

. The variables are essentially used a function titles but I do not know how to define them.

How would this loop produce recursion ?

Think about it.

@Brad

Thank you for your input. From your advice I have managed to get rid of the declaration errors, as well as the expected unqualified-id errors.

This is how my code now looks:

#include <Button.h> //button library
#include <FiniteStateMachine.h> //FSM library
#include <Servo.h> //servo library

//initialize states

State start = State(startEnter,startUpdate,NULL); //0 state
State opened = State(openedEnter,openedUpdate,NULL); //1st state
State pause = State(pauseEnter,pauseUpdate,NULL); //2nd state
State closed = State(closedEnter,closedUpdate,NULL); //3rd state
FiniteStateMachine ABStateMachine = FiniteStateMachine(start); //initialize state machine, start in state: start

Button mpb = Button(12,PULLUP); //initialize the momentary push button (wire between pin 12 and ground)

Servo myservo1; //projector platform servo
Servo myservo2; //kinect platform servo
Servo myservo3; //scissor legs servo

unsigned long Timer1; //define timer variable for state 1 if statement
unsigned long Timer2; //define timer variable for state 3 if statement

void setup() 
{ 
  myservo1.attach(9); // attatch servo 1 to pin 9
  myservo2.attach(10); // attatch servo 2 to pin 10
  myservo3.attach(11); // attatch servo 3 to pin 11
}

/////////////////////// State Functions /////////////////////////////

// State 0
void startEnter()
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
  myservo2.writeMicroseconds(1474); // ensures servo 2 is stationary
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary
}

void startUpdate()
{
  if(mpb.isPressed()) // if the button is pressed, state 0 (start) transitions to state 1 (opened)
  {
    ABStateMachine.transitionTo(opened);
    }
  }

// State 1
void openedEnter()
{
  for(int speedv1 = 0; speedv1 <= 100; speedv1 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 + speedv1); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (ACW)
  myservo2.writeMicroseconds(1474 + speedv1); // servo 2
  myservo3.writeMicroseconds(1474 + speedv1); // servo 3
  delay(30); // delay between loop iterations
  }
 void loop();
  {
    myservo1.writeMicroseconds(1574); // maintains servo 1 at full speed (ACW)
    myservo2.writeMicroseconds(1574); // maintains servo 2 at full speed (ACW)
    myservo3.writeMicroseconds(1574); // maintains servo 3 at full speed (ACW)
  }
  Timer1 = millis();
  if (millis() - Timer1 >= 10000) // after 10 seconds servos are ramped down in speed until stationary
    {
      for(int speedv2 = 0; speedv2 <= 100; speedv2 += 2) // loop to ramp down servo speed
      {
       myservo1.writeMicroseconds(1574 - speedv2); // speed decrease by 2 each iteration (servo 1) until servo stops
       myservo2.writeMicroseconds(1574 - speedv2); // servo 2
       myservo3.writeMicroseconds(1574 - speedv2); // servo 3
       delay(30); //delay between loop iterations
      }
    }  
}
void openedUpdate()
{
  ABStateMachine.transitionTo(pause); // state 1 (opened) transitions to state 2 (pause) when complete
}

// State 2
void pauseEnter()
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
  myservo2.writeMicroseconds(1474); // ensures servo 2 is stationary
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary 
}
void pauseUpdate()
{
  if(mpb.isPressed()) // if the button is pressed, state 2 (pause) transitions to state 3 (closed)
  {
    ABStateMachine.transitionTo(closed);
  }
}

// State 3
void closedEnter()
{
  for(int speedv3 = 0; speedv3 <= 100; speedv3 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 - speedv3); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (CW)
  myservo2.writeMicroseconds(1474 - speedv3); // servo 2
  myservo3.writeMicroseconds(1474 - speedv3); // servo 3
  delay(30); // delay between loop iterations
  }
  void loop();
  {
    myservo1.writeMicroseconds(1374); // maintains servo 1 at full speed (CW)
    myservo2.writeMicroseconds(1374); // maintains servo 2 at full speed (CW)
    myservo3.writeMicroseconds(1374); // maintains servo 3 at full speed (CW)
  }
  Timer2 = millis();
  if (millis() - Timer2 >= 10000) // after 10 seconds servos are ramped down in speed until stationary
    {
      for(int speedv4 = 0; speedv4 <= 100; speedv4 += 2) // loop to ramp down speed of servos
      {
       myservo1.writeMicroseconds(1374 + speedv4); // speed decrease by 2 each iteration (servo 1) until servo stops
       myservo2.writeMicroseconds(1374 + speedv4); // servo 2
       myservo3.writeMicroseconds(1374 + speedv4); // servo 3
       delay(30); // delay between loop iterations
      }
    }  
}
void closedUpdate()
{
  ABStateMachine.transitionTo(start); // when state 3 (closed) is complete, the state machine returns to state 0 (start)
}

I have managed to resolve all the errors except this:

core.a(main.cpp.o): In function `main':
C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/main.cpp:14: undefined reference to `loop'

Im not sure what this means. Do I need to define a void loop for the entire program ?

Im not sure what this means.

It means you haven't defined a function called "loop".
If you sort out your erratic indentation and bracing, you'll see why the compiler says that.

@AWOL

According to this file location:

C:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino/main.cpp:14: undefined reference to `loop'

There appears to be an error in the main.cpp file that came with the arduino software (I have not edited this file). Also the name of my sketch is TEST2rampbutton, and not main if any confusion was caused.

void openedEnter()
{
  for(int speedv1 = 0; speedv1 <= 100; speedv1 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 + speedv1); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (ACW)
  myservo2.writeMicroseconds(1474 + speedv1); // servo 2
  myservo3.writeMicroseconds(1474 + speedv1); // servo 3
  delay(30); // delay between loop iterations
  }
 void loop();
  {

There appears to be an error in the main.cpp file that came with the arduino software

On balance, it doesn’t seem all that likely, does it?

This is my code now, with no void loops, and the error still occur ?

#include <Button.h> //button library
#include <FiniteStateMachine.h> //FSM library
#include <Servo.h> //servo library

//initialize states

State start = State(startEnter,startUpdate,NULL); //0 state
State opened = State(openedEnter,openedUpdate,NULL); //1st state
State pause = State(pauseEnter,pauseUpdate,NULL); //2nd state
State closed = State(closedEnter,closedUpdate,NULL); //3rd state
FiniteStateMachine ABStateMachine = FiniteStateMachine(start); //initialize state machine, start in state: start

Button mpb = Button(12,PULLUP); //initialize the momentary push button (wire between pin 12 and ground)

Servo myservo1; //projector platform servo
Servo myservo2; //kinect platform servo
Servo myservo3; //scissor legs servo

unsigned long Timer1; //define timer variable for state 1 if statement
unsigned long Timer2; //define timer variable for state 3 if statement

void setup() 
{ 
  myservo1.attach(9); // attatch servo 1 to pin 9
  myservo2.attach(10); // attatch servo 2 to pin 10
  myservo3.attach(11); // attatch servo 3 to pin 11
}

/////////////////////// State Functions /////////////////////////////

// State 0
void startEnter()
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
  myservo2.writeMicroseconds(1474); // ensures servo 2 is stationary
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary
}

void startUpdate()
{
  if(mpb.isPressed()) // if the button is pressed, state 0 (start) transitions to state 1 (opened)
  {
    ABStateMachine.transitionTo(opened);
    }
  }

// State 1
void openedEnter()
{
  for(int speedv1 = 0; speedv1 <= 100; speedv1 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 + speedv1); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (ACW)
  myservo2.writeMicroseconds(1474 + speedv1); // servo 2
  myservo3.writeMicroseconds(1474 + speedv1); // servo 3
  delay(30); // delay between loop iterations
  }

Timer1 = millis();

while(millis() - Timer1 <= 10000)
  {
    myservo1.writeMicroseconds(1374); // maintains servo 1 at full speed (CW)
    myservo2.writeMicroseconds(1374); // maintains servo 2 at full speed (CW)
    myservo3.writeMicroseconds(1374); // maintains servo 3 at full speed (CW)
  }
  if (millis() - Timer1 >= 10000) // after 10 seconds servos are ramped down in speed until stationary
    {
      for(int speedv2 = 0; speedv2 <= 100; speedv2 += 2) // loop to ramp down servo speed
      {
       myservo1.writeMicroseconds(1574 - speedv2); // speed decrease by 2 each iteration (servo 1) until servo stops
       myservo2.writeMicroseconds(1574 - speedv2); // servo 2
       myservo3.writeMicroseconds(1574 - speedv2); // servo 3
       delay(30); //delay between loop iterations
      }
    }  
}
void openedUpdate()
{
  ABStateMachine.transitionTo(pause); // state 1 (opened) transitions to state 2 (pause) when complete
}

// State 2
void pauseEnter()
{
  myservo1.writeMicroseconds(1474); // ensures servo 1 is stationary
  myservo2.writeMicroseconds(1474); // ensures servo 2 is stationary
  myservo3.writeMicroseconds(1474); // ensures servo 3 is stationary 
}
void pauseUpdate()
{
  if(mpb.isPressed()) // if the button is pressed, state 2 (pause) transitions to state 3 (closed)
  {
    ABStateMachine.transitionTo(closed);
  }
}

// State 3
void closedEnter()
{
  for(int speedv3 = 0; speedv3 <= 100; speedv3 += 2) // loop to ramp up speed of servos
  {
  myservo1.writeMicroseconds(1474 - speedv3); // speed increase by 2 each iteration (servo 1) until servo reaches fullspeed (CW)
  myservo2.writeMicroseconds(1474 - speedv3); // servo 2
  myservo3.writeMicroseconds(1474 - speedv3); // servo 3
  delay(30); // delay between loop iterations
  }
  
  Timer2 = millis();
  
  while(millis() - Timer2 <= 10000)
  {
    myservo1.writeMicroseconds(1374); // maintains servo 1 at full speed (CW)
    myservo2.writeMicroseconds(1374); // maintains servo 2 at full speed (CW)
    myservo3.writeMicroseconds(1374); // maintains servo 3 at full speed (CW)
  }
  if (millis() - Timer2 >= 10000) // after 10 seconds servos are ramped down in speed until stationary
    {
      for(int speedv4 = 0; speedv4 <= 100; speedv4 += 2) // loop to ramp down speed of servos
      {
       myservo1.writeMicroseconds(1374 + speedv4); // speed decrease by 2 each iteration (servo 1) until servo stops
       myservo2.writeMicroseconds(1374 + speedv4); // servo 2
       myservo3.writeMicroseconds(1374 + speedv4); // servo 3
       delay(30); // delay between loop iterations
      }
    }  
}

void closedUpdate()
{
  ABStateMachine.transitionTo(start); // when state 3 (closed) is complete, the state machine returns to state 0 (start)
}

with no void loops, and the error still occur

You need to provide a function called “loop”
Where is it?
(It’s also preferable if you don’t call it recursively, but you already know that)

Sorting out the indentation will help you visualise the structure.

@AWOL

Cool, the errors are gone. Thanks for the input.