Design Pattern: State Machine

This is an example of a state machine approach to writing code for the Race to the Wall. The State Machine is an example of a design pattern, a solution structure that can be used to solve practical problems in lots of different (and perhaps unrelated) applications. It’s particularly useful for microcontroller programming.

Description

To implement a desired behaviour in your robot using a state machine approach, begin by breaking down the robot’s behaviour into simple states. In each robot state, the actuators (i.e. motors) must always be doing one specific thing. Knowing which pre-defined state the robot is in should tell you exactly what every motor is doing at that point in time. For every state, the exact conditions under which the robot can change to each of the possible next states are also defined precisely (usually as some combination of sensor input readings).

Before writing your state machine C code, it’s a good idea to draw up a table with an exact definition of every state.

State Description Motors Change state?
1 Wait for button to be pressed Motors stopped When button pressed, go to state 2
2 Wait for button to be released Motors stopped When button released, go to state 3
3 Drive forward to wall Motors forward When button pressed, go to state 4
4 Reverse back to white line Motors reverse When colour_voltage < threshold, go to state 5
5 Brake by driving motors forward for 100ms Motors forwards After 100ms, go to state 1

It’s also a good idea to draw out a map of all possible state transitions, showing clearly for each state which states can follow it. In this example, the state transition map is very simple since each state leads into just one other state:

Example code

int main()
{
	int state = 1; // robot state variable
	int button;
	int colour, white_threshold=500;

	// Configure PIC pins
	setup();

	while(1)
	{
		// Read all sensors
		button = PORTDbits.RD4;
		colour = read_analog_channel(0);

		// Do actions for current state
		if (state == 1)
		{
			// STATE 1: WAIT FOR BUTTON TO BE PRESSED

			// What does the robot do in this state?
			LATD = 0b00000000; // motors stopped

			// Does the robot need to change state?
			if (button == 1) state = 2;
		}
		else if (state == 2)
		{
			// STATE 2: WAIT FOR BUTTON TO BE RELEASED

			// What does the robot do in this state?
			LATD = 0b00000000; // motors stopped

			// Does the robot need to change state?
			if (button == 0) state = 3;
		}
		else if (state == 3)
		{
			// STATE 3: FORWARDS UNTIL BUTTON IS PRESSED

			// What does the robot do in this state?
			LATD = 0b00000101; // motors forward

			// Does the robot need to change state?
			if (button == 1) state = 4;
		}
		else if (state == 4)
		{
			// STATE 4: REVERSE UNTIL WHITE IS DETECTED

			// What does the robot do in this state?
			LATD = 0b00001010; // motors reverse

			// Does the robot need to change state?
			if (colour < white_threshold) state = 5;
		}
		else if (state == 5)
		{
			// STATE 5: MOTORS FORWARD TO BRAKE

			// What does the robot do in this state?
			LATD = 0b00000101; // motors forward

			// Robot changes state after 100ms
			Delay10KTCYx(20); // 100ms delay
			state = 1;
		}
	}
}
Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s