Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible problem on timed_transitions #22

Open
njbuch opened this issue Jan 22, 2018 · 3 comments
Open

Possible problem on timed_transitions #22

njbuch opened this issue Jan 22, 2018 · 3 comments

Comments

@njbuch
Copy link

njbuch commented Jan 22, 2018

Consider these transitions:

fsm.add_timed_transition(&state_waitfortriggerack, &state_waitfortriggerack, 3000, NULL);
fsm.add_transition(&state_waitfortriggerack, &state_rpinotworking, TIMEOUT, NULL);

and then I am doing a:

fsm.trigger(TIMEOUT);

I was expecting the loop of the 3000ms to stop, but it keeps calling the entry function of state_waitfortriggerack. The fsm.trigger(TIMEOUT) is actually changing the state and doing its thing, but the timed transition keeps repeating.

@njbuch
Copy link
Author

njbuch commented Apr 29, 2018

Ping, anyone has managed to use timed transactions to same state?

@LennartHennigs
Copy link
Collaborator

Hi, this is what I used and it seemed to work:

/* ----------------------------------------------------- */
#include "Fsm.h"
#include "Button2.h";
/* ----------------------------------------------------- */
#define TIMEOUT 1000
/* ----------------------------------------------------- */
void waitfortriggerack() {
  Serial.println("waitfortriggerack");
}

void rpinotworking() {
  Serial.println("rpinotworking");
}
/* ----------------------------------------------------- */
State state_waitfortriggerack("wait", &waitfortriggerack);
State state_rpinotworking("rpinotworking", &rpinotworking);

Fsm fsm(&state_waitfortriggerack);
Button2 btn = Button2(D0);
/* ----------------------------------------------------- */
void btn_released(Button2& btn) {
  Serial.println("CLICK");
  fsm.trigger(TIMEOUT);
}
/* ----------------------------------------------------- */
void setup() {
  Serial.begin(9600);
  delay(50);

  fsm.add_timed_transition(&state_waitfortriggerack, &state_waitfortriggerack, 3000, NULL);
  fsm.add_transition(&state_waitfortriggerack, &state_rpinotworking, TIMEOUT, NULL);
  
  btn.setReleasedHandler(btn_released);
}
/* ----------------------------------------------------- */
void loop() {
  btn.loop();
  fsm.run_machine();
}
/* ----------------------------------------------------- */

This is the output - I pressed the button after a little while:

waitfortriggerack
waitfortriggerack
waitfortriggerack
waitfortriggerack
waitfortriggerack
CLICK
rpinotworking

After the button press, the machine keeps the RPI state.

@dotorg
Copy link

dotorg commented Apr 15, 2019

In case anyone runs into this, there's a limitation that isn't super obvious in the FSM code as it is implemented. The state isn't recorded as being changed until after the on_enter is called on the new state. As a result, if you use trigger to send an event from the start of the new state, it won't find a transition from that new state to the next state.

i.e., if you have three states "one", "two" and "three", and you have a timed transition from two back to itself, it'll get called forever if you try to do a trigger(three) in the start method for two.

I fixed it in a local copy of the library by moving the m_current_state = transition->state_to; line in make_transition above the transition->state_to->on_enter() call.

Its a behavioral change, but because there's no real documentation for the library its unclear if the prior behavior is as-intended or not.

LennartHennigs added a commit to LennartHennigs/arduino-fsm that referenced this issue Apr 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants