Blog 3: State Machines on the PIC microcontroller. Seán Cleary

Introduction

In this sprint, the process of creating a state machine in c code, so that it could be uploaded onto a PIC microcontroller was examined. After a lecture on state machines, we were left to create our own state machine based on the rtos code for the basic kernel. This state machine was to incorporate the message systems from the fourth piece of example code, which allowed tasks to send messages to one another.

We were left to create a state machine ourselves based off of these directives. The state machine was specified to have:

  • Two input tasks
  • Two output tasks
  • One state machine task

And it was specified to use messages in order to send information between tasks. Beyond this, it was up to us to figure out how to implement this code, using the previous RTOS example codes we had worked on as examples. 

Our state machine code

 For our state machine, we decided to create code that would simulate a car moving between different speeds. Those different speeds were:

  • Fast
  • Slow
  • Idle/Default

The car was to start in the idle/default state, and inputs in the kernel were to modify it so that it could go into either fast or slow speeds. The inputs would be used to send messages to the state machine, which would inform the state machine of which input had been pressed.

The state machine when working as intended should have been able to move between speeds, starting in an idle state and being able to move to fast and slow speeds. However due to issues, such as the input tasks always running, the speed was not displayed correctly. e.g. since output one would say moving to "Moving to slow", even when it was in the fast state and not moving to slow 

In this code, much like the RTOS example nine, the inputs would be given in the form of commands written in the terminal which the code can interpret. 

Jason's state machine template

Figure 1: Jason's code working

In Jason's state machine template, the switch on the PIC acts as the input. When it is pressed it is pressed it cycles between the four different states (Not including startup state). These four different states send messages to the different tasks, giving them instructions. States one and two send messages to the first output, while states three and four send messages to the second output.

When the button is pressed, the onboard green LED light will flash for a number of seconds. The second input in this piece of code is the potentiometer that is present on the board. When this potentiometer is adjusted, it also affects the onboard led, causing it to flash with different intensities. If the potentiometer is fully closed, the LED is effectively off, while if it is fully open it will will flash at full intensity.

While the code was running, the LCD would also display what message was being sent, for example if it was in state four it would display "sending 4 to out2" indicating that it was sending the integer value four to the second output.

In Jason's code, the potentiometer and buttons are initialised, so that they can be used as inputs.

Figure 2: The two inputs. Input one is the button, and input two is the potentiometer.

  

These inputs are further initialised in the "main( )" function that runs on startup.


 

Figure 3: The two inputs being initialised in main


 Comparisons and Contrasts

In our state machine code the inputs into the code took the form of typed terminal commands, while in Jason's code they were goverened by button presses. The fact we were using terminal commands made it much more difficult to print anything out to the terminal, as it would be conflicting with what the user was typing.

In Jason's code, the majority of the code for the inputs is contained within if statements, preventing it from running when it is not intended.

I also noticed that while I have message queues on the inputs and state machine, but not outputs, Jason's code has message queues on the state machine and output, but not inputs. This is because the outputs are only used for sending messages.

A comparison between Jason's kernal code and my own, is that the state machine is rather similar in structure. In my own code I had the message poll at the start of the state machine, with if else statements below that took account of the state and the input (I had if else statements however the newest version of the code had a case statement).

Unlike my code, Jason's code does not have a kernel task. This is because this code does not take in inputs in the terminal as typed commands, instead taking in inputs from the potentiometer and button. This means that the kernel task is not needed, with only the input tasks being required. The input one task handles the button, while input two handles the potentiometer.

Comments

Popular posts from this blog

Blog 1 - Igor Kapusniak