0

I'm writing practice finite state machine code and can't wrap my head around the order of my "Switch" and "if" statements (which should come first).

Currently, I have it written as such:

task main()
{
    // State variable default.
    SystemStateType SystemState = State1;

    While(1)
    {
        //Taken in from external sensors in real time
        int reading;

        if (reading == 0)
        {
            SystemState = State1;
        }
        else
        {
            SystemState = State2;
        }

        switch (SystemState)
        {
            case State1:
                //actions
                break;

            case State2:
                //other actions 
                break;
        }
    }
}

The code is intended to take sensor data in real time and respond accordingly. I realize that this is not actual functioning code, but I'm hoping that since the question is theoretical that my current code shown will suffice. Please let me know if I am missing anything.

Thank you!

LPs
  • 16,045
  • 8
  • 30
  • 61
Ben
  • 59
  • 8
  • 3
    I didn't understand what exactly your problem is. – Marievi Jan 17 '17 at 07:09
  • What do you think the *order* is? – DeiDei Jan 17 '17 at 07:10
  • @DeiDei I believe that I should implement the "if" statements first, since the cases are dependent on their results. Then, once a case "breaks" the switch, I can go back to the start of the loop and reread all sensors, look at the if statements, and then run the corresponding case. Is that a correct assumption? – Ben Jan 17 '17 at 07:13
  • Well, yes, that seems like a logical way to proceed. – DeiDei Jan 17 '17 at 07:14
  • At least you forgot to leave to task "time to breath".. – LPs Jan 17 '17 at 07:15
  • @Marievi I am unsure if, in my while loop, my program should be running the "if" statements, that are dependent on the realtime readings, before the switch, or after. – Ben Jan 17 '17 at 07:15
  • @LPs does that mean that I am not allowing the program to re-read all of the incoming sensor values? Forgive me, I am extremely new to RobotC – Ben Jan 17 '17 at 07:17
  • I don't know how your system is working. In code shown the `reading` variable is local to task so nothing can be "received on that variable. The question is totally unclear. – LPs Jan 17 '17 at 07:18
  • @LPs There is an external function with code in it that reads the sensor value, transferring it into the "reading" variable. – Ben Jan 17 '17 at 07:20
  • There is no question here. Please ask one. – Lundin Jan 17 '17 at 07:56

2 Answers2

1

can't wrap my head around the order of my "Switch" and "if" statements (which should come first).

Your switch statement examines the value of the SystemState variable, which is set through your if statement. So the correct order is to have your if statement, so that SystemStatevariable takes the desired value, and then examine the value of SystemState in your switch statement.

Suppose that you had if and switch statements the opposite way, like this :

task main()
{
    // State variable default.
    SystemStateType SystemState = State1;

    While(1)
    {
        //Taken in from external sensors in real time
        int reading;

        switch (SystemState)
        {
            case State1:
                //actions
                break;

            case State2:
                //other actions 
                break;
        }

        if (reading == 0)
        {
            SystemState = State1;
        }
        else
        {
            SystemState = State2;
        }

    }
}

Then, in the switch statement your SystemState variable would always be State1.

Of course, keep in mind that in the way you have written your code right now, reading cannot receive any input. You need to give reading a way to get a value.

Marievi
  • 4,951
  • 1
  • 16
  • 33
  • Thank you for the straightforward explanation! That makes sense, my apologies for the poor style used in my example. – Ben Jan 17 '17 at 07:24
  • @marievi Warning: "your SystemState variable would always be State1". I don't think this is true, because the `if` gets executed always, and the state can be changed there. – linuxfan says Reinstate Monica Jan 17 '17 at 07:59
  • @ben I think that a finite state machine could, in some states, ignore some inputs; your code does not do that - there is no need to have both an IF and a SWITCH. A real state machine is mainly a big SWITCH; in each of its CASE all the conditions that COULD change state are verified and, eventually, the state is changed; in the next loop a (perhaps different) CASE is chosen, and so on. – linuxfan says Reinstate Monica Jan 17 '17 at 08:04
  • @linuxfan this is for the case that the OP reverses the order of `if` and `switch`, as shown in the code I posted. – Marievi Jan 17 '17 at 08:06
  • @marievi The OP code, and your, never assign a value to `reading` - I assume that both fragments are conceptual skeletons (apart from the fact that `reading` could be changed by some other thread/interrupt routine. I really think that your answer is totally wrong - in a cycle like this, the order of IF and SWITCH make really little little difference. – linuxfan says Reinstate Monica Jan 17 '17 at 08:12
  • @linuxfan as I pointed out in the last sentence of my answer, the code needs modification so that `reading` takes` a value, and the OP says that it takes a value from an external function. So assuming that it does take a value (and the OP does not show the way just for simplifying reasons), the order of `if` and `switch` make a big difference. – Marievi Jan 17 '17 at 08:18
0

The order of IF and SWITCH statements is not important in the OP example. In a finite state machine, for every different STATE, the machine carries out a certain set of operations. The transition from one state to another is conceptually separated, but often is performed by the same code: this way, in some state a set of inputs can be checked (and other ignored), and in another state a different set of inputs can be checked. Among the checked inputs, one of them can trigger a state change.

Suppose you have a motor, a start button, a stop button, and a knob to set the speed of the motor. When you press START, the motor turns with the speed set by the knob. When you press STOP, the motor stops (until START is pressed again). This machine has two states: STOPPED and RUNNING. Motor, Knob, Start and Stop all are I/Os that another thread care to read or set. The pseudocode would be like this.

STATE = STOPPED;
while (1) {
  switch (STATE) {

    case STOPPED:
      Motor = 0;   // the motor does not turn
      if (Start) STATE = RUNNING;
      break;

    case RUNNING:
      Motor = Knob;   // rotate with the speed given by Knob
      if (Stop) STATE = STOPPED;
      break;

  } // end switch
} // end of forever cycle

Now, imagine that the motor has to do ramp-up and ramp-down. Two states can be added, ACCEL and DECEL. In the state STOPPED, the code checks if Start is pressed; if it is, the new state becomes ACCEL. In the ACCEL state, the value of Motor is increased until it reaches the value of Knob. It goes similarly for the DECEL state, I omit it for brevity.

Please note that, during ACCEL state, the buttons are NOT checked. It could be perfectly legal to say that the ACCEL phase must not be interrupted. If the phase must support interruption, then the phase ACCEL has to check the Stop button. This is the beauty of a state machine: you can break a complex thing down in different stages and concentrate on them separately.

The idea of putting an IF outside the switch can play a role too, and in fact, emergency/safety stop buttons should be treated this way: no matter the state of the machine, a Stop command should stop the machine. For simplicity this can be done outside the normal flux of the state machine: when the Emergency button is pressed stop every movement, turn off everything, and force the state STOPPED (or, even better, a state EMERGENCY which requires more user attention).

If the whole while (1) { cycle is executed at maximum speed, there is no difference in putting the IF before the SWITCH or after. If, instead, the whole logic of the machine runs inside a routine that gets called cyclically, say, every millisecond, then the if can be executed 1 millisecond earlier if it is put before the switch. But this has little importance anyway, because the whole machine suffers of a latency of 1 millisecond.