switch and if statement order (Robot C)

747 views Asked by At

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!

2

There are 2 answers

6
Marievi On BEST ANSWER

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.

0
linuxfan says Reinstate Monica On

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.