Skip to content

Commit

Permalink
v2.2.0 (#11)
Browse files Browse the repository at this point in the history
* Add `on_state()` handler to states
* New `run_machine()` method to invoke machine execution (includes a
`check_timed_transitions()` call)
* New `timed_switchoff.ino` example sketch to ilustrate new `on_state()`
and `run_machine()` funcionality
* Corrections:
- `make_transition()` correctly initialices timed transitions start
milliseconds (`make_transition()` is now a fsm method)
- Initial state `on_enter()` handler is now correctly executed on fsm
first run
- Removed `Serial.println(now);` trace in _Fsm.cpp_
- Correct initialization of `m_num_timed_transitions`
  • Loading branch information
Thelmos authored and jonblack committed Oct 25, 2017
1 parent 27a6d8b commit 68dd63f
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 38 deletions.
72 changes: 51 additions & 21 deletions Fsm.cpp
Expand Up @@ -16,8 +16,9 @@
#include "Fsm.h"


State::State(void (*on_enter)(), void (*on_exit)())
State::State(void (*on_enter)(), void (*on_state)(), void (*on_exit)())
: on_enter(on_enter),
on_state(on_state),
on_exit(on_exit)
{
}
Expand All @@ -26,7 +27,9 @@ State::State(void (*on_enter)(), void (*on_exit)())
Fsm::Fsm(State* initial_state)
: m_current_state(initial_state),
m_transitions(NULL),
m_num_transitions(0)
m_num_transitions(0),
m_num_timed_transitions(0),
m_initialized(false)
{
}

Expand Down Expand Up @@ -90,20 +93,22 @@ Fsm::Transition Fsm::create_transition(State* state_from, State* state_to,

void Fsm::trigger(int event)
{
// Find the transition with the current state and given event.
for (int i = 0; i < m_num_transitions; ++i)
if (m_initialized)
{
if (m_transitions[i].state_from == m_current_state &&
m_transitions[i].event == event)
// Find the transition with the current state and given event.
for (int i = 0; i < m_num_transitions; ++i)
{
m_current_state = m_transitions[i].make_transition();
return;
if (m_transitions[i].state_from == m_current_state &&
m_transitions[i].event == event)
{
Fsm::make_transition(&(m_transitions[i]));
return;
}
}
}
}


void Fsm::check_timer()
void Fsm::check_timed_transitions()
{
for (int i = 0; i < m_num_timed_transitions; ++i)
{
Expand All @@ -114,31 +119,56 @@ void Fsm::check_timer()
{
transition->start = millis();
}
else
{
else{
unsigned long now = millis();
if (now - transition->start >= transition->interval)
{
m_current_state = transition->transition.make_transition();
Fsm::make_transition(&(transition->transition));
transition->start = 0;
}
}
}
}
}

void Fsm::run_machine()
{
// first run must exec first state "on_enter"
if (!m_initialized)
{
m_initialized = true;
if (m_current_state->on_enter != NULL)
m_current_state->on_enter();
}

if (m_current_state->on_state != NULL)
m_current_state->on_state();

Fsm::check_timed_transitions();
}

State* Fsm::Transition::make_transition()
void Fsm::make_transition(Transition* transition)
{

// Execute the handlers in the correct order.
if (state_from->on_exit != NULL)
state_from->on_exit();
if (transition->state_from->on_exit != NULL)
transition->state_from->on_exit();

if (transition->on_transition != NULL)
transition->on_transition();

if (on_transition != NULL)
on_transition();
if (transition->state_to->on_enter != NULL)
transition->state_to->on_enter();

m_current_state = transition->state_to;

if (state_to->on_enter != NULL)
state_to->on_enter();
//Initialice all timed transitions from m_current_state
unsigned long now = millis();
for (int i = 0; i < m_num_timed_transitions; ++i)
{
TimedTransition* ttransition = &m_timed_transitions[i];
if (ttransition->transition.state_from == m_current_state)
ttransition->start = now;
}

return state_to;
}
12 changes: 8 additions & 4 deletions Fsm.h
Expand Up @@ -26,9 +26,9 @@

struct State
{
State(void (*on_enter)(), void (*on_exit)());

State(void (*on_enter)(), void (*on_state)(), void (*on_exit)());
void (*on_enter)();
void (*on_state)();
void (*on_exit)();
};

Expand All @@ -45,8 +45,10 @@ class Fsm
void add_timed_transition(State* state_from, State* state_to,
unsigned long interval, void (*on_transition)());

void check_timed_transitions();

void trigger(int event);
void check_timer();
void run_machine();

private:
struct Transition
Expand All @@ -56,7 +58,6 @@ class Fsm
int event;
void (*on_transition)();

State* make_transition();
};
struct TimedTransition
{
Expand All @@ -68,13 +69,16 @@ class Fsm
static Transition create_transition(State* state_from, State* state_to,
int event, void (*on_transition)());

void make_transition(Transition* transition);

private:
State* m_current_state;
Transition* m_transitions;
int m_num_transitions;

TimedTransition* m_timed_transitions;
int m_num_timed_transitions;
bool m_initialized;
};


Expand Down
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -22,6 +22,18 @@ feature branch.

# Changelog

**2.2.0 - 12/03/2016**

* Add `on_state()` handler to states
* New `run_machine()` method to invoke machine execution (includes a `check_timed_transitions()` call)
* New `timed_switchoff.ino` example sketch to ilustrate new `on_state()` and `run_machine()` funcionality
* Corrections:
- `make_transition()` correctly initialices timed transitions start milliseconds (`make_transition()` is now a fsm method)
- Initial state `on_enter()` handler is now correctly executed on fsm first run
- Removed `Serial.println(now);` trace in _Fsm.cpp_
- Correct initialization of `m_num_timed_transitions`


**2.1.0 - 21/11/2015**

* Add timed transitions
Expand Down
7 changes: 4 additions & 3 deletions examples/light_switch/light_switch.ino
@@ -1,10 +1,10 @@
#include <Fsm.h>
#include "Fsm.h"

// State machine variables
#define FLIP_LIGHT_SWITCH 1

State state_light_on(on_light_on_enter, &on_light_on_exit);
State state_light_off(on_light_off_enter, &on_light_off_exit);
State state_light_on(on_light_on_enter, NULL, &on_light_on_exit);
State state_light_off(on_light_off_enter, NULL, &on_light_off_exit);
Fsm fsm(&state_light_off);

// Transition callback functions
Expand Down Expand Up @@ -53,6 +53,7 @@ void setup()

void loop()
{
// No "fsm.run_machine()" call needed as no "on_state" funcions or timmed transitions exists
delay(2000);
fsm.trigger(FLIP_LIGHT_SWITCH);
delay(2000);
Expand Down
18 changes: 9 additions & 9 deletions examples/multitasking/multitasking.ino
Expand Up @@ -2,7 +2,7 @@
// multitasking on an arduino. Two LED's are turned on and off at irregular
// intervals; the finite state machines take care of the transitions.

#include <Fsm.h>
#include "Fsm.h"

#define LED1_PIN 10
#define LED2_PIN 11
Expand All @@ -27,11 +27,11 @@ void on_led2_off_enter() {
digitalWrite(LED2_PIN, LOW);
}

State state_led1_on(&on_led1_on_enter, NULL);
State state_led1_off(&on_led1_off_enter, NULL);
State state_led1_on(&on_led1_on_enter, NULL, NULL);
State state_led1_off(&on_led1_off_enter, NULL, NULL);

State state_led2_on(&on_led2_on_enter, NULL);
State state_led2_off(&on_led2_off_enter, NULL);
State state_led2_on(&on_led2_on_enter, NULL, NULL);
State state_led2_off(&on_led2_off_enter, NULL, NULL);

Fsm fsm_led1(&state_led1_off);
Fsm fsm_led2(&state_led2_off);
Expand All @@ -50,8 +50,8 @@ void setup() {


void loop() {
fsm_led1.check_timer();
fsm_led2.check_timer();

delay(100);
fsm_led1.run_machine();
fsm_led2.run_machine();
delay(200);
}

0 comments on commit 68dd63f

Please sign in to comment.