Chronic
Chronic

Reputation: 19

State machine coding - im stuck

I am trying to create a state machine but am a little lost. Please go easy on me, i've only been coding 4 months.

Im using a pic16f18325 and coding in mplab

So i think im pretty much there, i know what i want it to do, i have written diagrams etc and think i have set it up correctly. My question is how to i switch between the states? How do i change an event?

If for example i was in the maincode and i wanted to trigger the ENTER event by press of a button. Would i just write:

if (button == 0){ // (button has been defined already)
event = ENTER;
}
void ENTER (void){
// do some stuff
}

mplab is not liking the word "event" im getting a fair few errors that i dont understand:

main.c:33:6: error: redefinition of 'ENTER' as different kind of symbol
void ENTER (void);
     ^
main.c:26:5: note: previous definition is here
int ENTER; // for entering programming from maincode
    ^
main.c:34:6: error: redefinition of 'EXIT' as different kind of symbol
void EXIT (void);
     ^
main.c:27:5: note: previous definition is here
int EXIT; // for exiting programming and returning to maincode
    ^
main.c:35:6: error: redefinition of 'Reset' as different kind of symbol
void Reset (void);
     ^
main.c:28:5: note: previous definition is here
int Reset; // to reset the speed and return to main code
    ^
main.c:36:6: error: redefinition of 'INCREASE' as different kind of symbol
void INCREASE (void);
     ^
main.c:29:5: note: previous definition is here
int INCREASE; // to increase the speed while in programming
    ^
main.c:37:6: error: redefinition of 'DECREASE' as different kind of symbol
void DECREASE (void);
     ^
main.c:30:5: note: previous definition is here
int DECREASE; // to decrease the speed while in programming
    ^
main.c:110:36: error: function definition is not allowed here
void step_state(enum events event) { // not sure what to write here, will work it out
                                   ^
main.c:145:18: error: function definition is not allowed here
void ENTER (void){
                 ^
main.c:148:17: error: function definition is not allowed here
void EXIT (void){
                ^
main.c:151:18: error: function definition is not allowed here
void Reset (void){
                 ^
main.c:154:21: error: function definition is not allowed here
void INCREASE (void){
                    ^
main.c:157:21: error: function definition is not allowed here
void DECREASE (void){
                    ^
11 errors generated.

Heres my state machine coding:

#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/device_config.h"

int ENTER; // for entering programming from maincode
int EXIT; // for exiting programming and returning to maincode
int Reset; // to reset the speed and return to main code
int INCREASE; // to increase the speed while in programming
int DECREASE; // to decrease the speed while in programming

int events;
void ENTER (void);
void EXIT (void);
void Reset (void);
void INCREASE (void);
void DECREASE (void);


void main(void) {

enum states { // this state machine will have 2 states

    MAINCODE, // main code where it will sit most of the time
    PROGRAMMING, // and then programming which is used to change the speed
} state;

enum events { // we will have 5 events
    ENTER, // for entering programming from maincode
    EXIT, // for exiting programming and returning to maincode
    RESET, // to reset the speed and return to main code
    INCREASE, // to increase the speed while in programming
    DECREASE, // to decrease the speed while in programming
};
void step_state(enum events event) { // not sure what to write here??? what is step_state? why enum events event?
 switch(state) { // the switch is done by a change of state
 case MAINCODE: // while in maincode
  switch(event) { // and the enter event is initiated
  case ENTER: // enter programming
   state = PROGRAMMING; // to do this we change the state
   break; // break to jump into that state

  default: // if something messes up, the default instruction
   state = MAINCODE; // is to go back into the maincode
   break;
  }
  break;

 case PROGRAMMING: // while in programming state
  switch(event) { // and an event is triggered
  case EXIT: // which happens to be exit
   state = MAINCODE; // enter maincode
   break;
  case RESET:
   // add code to revert default speed value
   state = MAINCODE; // then enter maincode
   break;
  case INCREASE:
   // add code for increasing speed
   break;
  case DECREASE:
   // add code for decreasing speed
   break;

  default:
   state = MAINCODE;
   break;
  }
  break;
 }

}

if (button == 0){
event = ENTER;
}
void ENTER (void){
    state = PROGRAMMING;
}
if (button == 0){
event = EXIT;
}
void EXIT (void){
    state = MAINCODE;
}
if (button == 0 && but1 == 0){
event = Reset;
}
void Reset (void){
    value = default;
    state = MAINCODE;
}
if (but1 == 0){
event = INCREASE;
}
void INCREASE (void){
    // add code to increase speed
}
if (but2 == 0){
event = DECREASE;
}
void DECREASE (void){
    // add code to decrease speed
}
    while (1)

    {

    }
    }

Upvotes: 0

Views: 247

Answers (3)

atabulog-DSM
atabulog-DSM

Reputation: 61

I am not seeing an error regarding your "events" variable, and I am not aware of it being a keyword. As for the other errors, you have a few namespace issues going on. When a enum is defined, it tells the compiler to use the specified key words in place for a number to help make your source code more maintainable. The enum implicitly sets the type of these keywords to "int" making the following lines unnecessary and causes a name collision.

int ENTER; // for entering programming from maincode
int EXIT; // for exiting programming and returning to maincode
int Reset; // to reset the speed and return to main code
int INCREASE; // to increase the speed while in programming
int DECREASE; // to decrease the speed while in programming

Even with these lines removed, the compiler is getting confused because your state functions are sharing the same name as your states in your "events" enumeration. If instead you rename your state functions INCREASE_func(), DECREASE_func(), etc. it will resolve the issue. here is a good source of implemented state machine code in C.

Upvotes: 1

Clifford
Clifford

Reputation: 93466

So i think im pretty much there, [...] My question is how to i switch between the states? How do i change an event?

Surely your question is why am I getting all these errors?! You are clearly a lot further from "pretty much there" than you think. Get valid code that compiles (i.e. learn to write valid C code) first - then ask about how to make the state machine work if it does not. Otherwise all these other errors are just a distraction - you are not even close to "pretty much there" is it does not compile so you can run, test and debug it. In fact so much so I am going to ignore your question and address the code validity. When you get the build working, ask a new question if necessary about how to make it work - or better use your debugger and figure it out for yourself.

The error messages seem pretty clear:

main.c:33:6: error: redefinition of 'ENTER' as different kind of symbol
void ENTER (void);
     ^
main.c:26:5: note: previous definition is here
int ENTER; // for entering programming from maincode

Line 33 has a definition for a function called ENTER, but ENTER is previously defined as an int variable at line 26. It is telling you not to use the same name twice (at least not in the same scope).

In fact the symbol ENTER (for example - the same error for other symbols) is defined three times for different things:

An integer variable:

int ENTER; // for entering programming from maincode

A function:

void ENTER (void);

An enum constant:

enum events { // we will have 5 events
    ENTER, // for entering programming from maincode

It is generally a bad idea to us the same symbol name for multiple purposes and in most cases it is ambiguous so the compiler cannot determine which to use.

In this case you should use lower or CamelCase for the function names - conventionally upper case is used for constants. Somewhat inconsistently you already have a Reset() function - you used a different naming convention elsewhere. Caution however because exit() is the name of a function in the standard library.

The variable int ENTER; and the other similarly declared variables do not appear to be used and can probably be deleted - that then removes the ambiguity with the enum constants.

Apart from that, the code posted is not the code that generated the errors posted - it has numerous other issues and the line number references in the diagnostics do not align with the code posted. Specifically:

  • You have referenced to the following undeclared variables button, event, but1, but2 and value (a particularly poor name for a variable BTW - they are all "values").
  • The statement event = Reset; is invalid, event is undefined, but context suggests that it should be an enum events object, in which case perhaps RESET was intended?
  • The statement value = default ; is invalid because default is a reserved keyword for a switch case label. It is not clear what you might have intended here, because value is undefined and this is the only place you have referenced it.

Upvotes: 3

Maurice Schmidt
Maurice Schmidt

Reputation: 127

You're trying to redefine an already used symbol, like ENTER.. You can't name your variables the same as the methods, because the compiler is getting confused and it also doesn't make much sense for anyone

You could also use a enum type to create your state machine

enum EventType {
     EVENT_NONE,
     EVENT_EXAMPLE
};

struct State {
     enum EventType last_event;  
};

int main(void) {
   struct State state = { .last_event = EVENT_NONE }

   // do what you want to do....
   {
       if (state.last_event == EVENT_EXAMPLE) {
            // do what you want 
       }
   }
}

Upvotes: 0

Related Questions