jonblack / arduino-fsm

Arduino library for implementing a finite state machine.
MIT License
200 stars 97 forks source link

Multiple triggers #2

Closed alxhoff closed 8 years ago

alxhoff commented 8 years ago

To explain my problem a little more in detail. I wasn't able to get loops to run within each state to properly refresh the values being recorded and displayed from each sensor. As a solution I decided to implement a second trigger, that I called refresh_toggle, which would be regularly called such that a state would exit and enter back to itself thus refreshing the outputted data. The original trigger is used toggle between each sensor via push button that triggers display_button, causing the state to go to its next respective state. Within my setup I followed the example code and defined all my transitions. The transitions for the push button are defined first and the refresh transitions defined below them. My problem is that the refresh_toggle trigger triggers the display_button transitions, which are defined first. It's as if the trigger specified within the transition is irrelevant and the first found transition, matching the current state, is triggered.

#define display_button 1
#define refresh_toggle 1

//State machine states
State state_time_display(display_time_enter,display_time_exit);
State state_temperature_display(display_temperature_enter, display_temperature_exit);
State state_pressure_display(display_pressure_enter,display_pressure_exit);
State state_moisture_display(display_moisture_enter,display_moisture_exit);
State state_light_display(display_light_enter,display_light_exit);

Fsm fsm(&state_time_display);
  fsm.add_transition(&state_time_display,&state_temperature_display,
                    display_button,&trans_time_temperature);
  fsm.add_transition(&state_temperature_display,&state_pressure_display,
                    display_button,&trans_temperature_pressure);
  fsm.add_transition(&state_pressure_display,&state_moisture_display,
                    display_button,&trans_pressure_moisture);
  fsm.add_transition(&state_moisture_display,&state_light_display,
                    display_button,&trans_moisture_light);
  fsm.add_transition(&state_light_display,&state_time_display,
                    display_button,&trans_light_time);

  //state refresh transitions
  fsm.add_transition(&state_time_display,&state_time_display,
                    refresh_toggle,NULL);
  fsm.add_transition(&state_temperature_display,&state_temperature_display,
                    refresh_toggle,&trans_temperature_refresh);
  fsm.add_transition(&state_pressure_display,&state_pressure_display,
                    refresh_toggle,&trans_pressure_refresh);
  fsm.add_transition(&state_moisture_display,&state_moisture_display,
                    refresh_toggle,&trans_moisture_refresh);
  fsm.add_transition(&state_light_display,&state_light_display,
                    refresh_toggle,&trans_light_refresh);

}

void loop() {

  buttonState = digitalRead(buttonPin);
  if(buttonState == HIGH){
    fsm.trigger(display_button);
    delay(10);
    fsm.trigger(refresh_toggle);
  }

This causes the first two transitions to occur given the machine starts in the state_time_display state.

jonblack commented 8 years ago

Just a quick sanity check. You have the following defines for the event id's:

#define display_button 1
#define refresh_toggle 1

Is that a typo? They should be unique:

#define display_button 1
#define refresh_toggle 2
alxhoff commented 8 years ago

I do believe that was my problem. I couldn't suss from the documentation how all that was meant to be implemented. After quickly changing the event ID it looks to be working as intended. Thanks a heap!

jonblack commented 8 years ago

A transition is dependent on the current state and the input. When you add a transition such as fsm.add_transition(&state1, &state2, 1, NULL); you are saying that, to end up in state2, you must be in state1 and require the symbol 1. If you're in state1 and the symbol 2 appears, no transition will occur. Symbols are provided using the fsm.trigger() function.