claude hasler
claude hasler

Reputation: 21

State Machine design handling data input

Im working on a real time machine control system, which performs a series of tasks, and should react to a large number of inputs. I've decided to implement this system using a state machine.

Ive used simple switch/case based state machines in the past and would like to transition to a more maintainable solution. At the moment I'm a little confused as to how to handle input and transitions.

For example I have an AnalogInput class which provides me with measurement values which i should monitor. Say I have a state WaitForThreshold, which should read a AnalogInput and then transition if the threshold is reached.

Do I a) a pass a reference of the AnalogInput class to the WaitForThreshold class and allow it to monitor the input itself, signaling to the StateMachine class that it wishes to transition.

b) create dedicated events, LaserMeasurementAtThreshold and a state transition map: StateMachine.addTransition(State A, Event e, State B)

c)create more generic events AnalogInputChanged and implement event handlers for each of the events, which again signal to the StateMachine that a transition is desired

option a is essentially the larger version of a simple switch/case state machine, which could get messy with time, but offers great flexibility and b/c seems more structured and clean but seems like i may have to jump through alot of hoops to implement relatively simple tasks because the number of events can be very large.

Can someone offer some insight on the design of state machines where a large number of inputs sources and types must be monitored, and events are largely state-specific(Most event pertain only to a single state)?

Are there possibly other alternatives to state machine design to control a system where a sequence of steps must be implemented (non linear, looping and branchig must be possible)

Language: C++

Thanks

Upvotes: 2

Views: 405

Answers (1)

Thomas Matthews
Thomas Matthews

Reputation: 57739

I believe this would be clearer to implement as a table of transitions:

typedef (void)((*Pointer_To_Transition_Function)());
struct Table_Entry
{
  Input_Type input_value;
  Pointer_To_Transisiton_Function p_trans_function;
};

static const Table_Entry Transition_Table[] = 
{
  {4, Read_Sensor},
};
static const size_t transition_quantity =  
    sizeof(Transition_Table) / sizeof(Transition_Table[0]);

//...
for (size_t index = 0; index < transition_quantity; ++index)
{
  if (input_value = Transition_Table[index].input_value)
  {
    Pointer_To_Transition_Function p_function = Transition_Table[index].p_trans_function;
    // Call the function:
    p_function();
    break;
  }
}

You could use std::map, but the std::map has to be initialized during run-time. The table (array) is static and constant, thus it can be placed into a read-only memory segment (convenient for embedded systems); and doesn't use dynamic memory allocation.

Edit 1: ASCII drawing of the table

+-------------+--------------------------------+  
| Input value | Pointer to transition function |  
+-------------+--------------------------------+  
|     4       |   Read sensor                  |
+-------------+--------------------------------+  
|     2       |   Start motor                  |
+-------------+--------------------------------+  

Upvotes: 0

Related Questions