CSCI 100 Assignment 5

Links

For those who are looking for project ideas:

Binary Counter Project

This is a complex project, but you can learn a lot by doing it. Here are some of the things you can learn:

Overview

The completed structure will uses an Arduino microcontroler to display a 5-bit binary number on five LEDs. When a LED is lit, it represents a 1; when it is not lit, it represents a 0. There will be a slide switch that will select whether the binary number should increment or decrement, and another slide switch that selects whether the binary number should change state because of the user pressing a pushbutton or because a certain amount of time has elapsed since the last state change.

The project will be developed in the following stages, which are outlined in more detail below.

  1. Set up the FSM event loop, and use it to flash a LED on and off at a 1 Hz rate.
  2. Extend the next-state part of the FSM to create a 1 Hz 2-bit up counter, using the Serial Monitor to view the changes in the counter’s state.
  3. Implement a 1 Hz 5-bit up counter, still using the Serial Monitor to view the changes in the counter’s state.
  4. Add a switch to select whether the counter will count forwards (“up’) or backwards (“down”).
  5. Add a button to cause the state to change instead of elapsed time intervals.
  6. Add a switch to select between pushbutton and timed state changes.

Implementation Details

  1. Set up the FSM event loop, and use it to flash a LED on and off at a 1 Hz rate.

    The “FSM Event Loop” is the loop() function of your Arduino project. For an FSM it consists of four parts:

    1. Read control inputs (if there are any), and wait for the transition event
    2. Compute the next state
    3. Make the transition from the current state to the next state
    4. Display outputs, based on the current state

    This structure is called an “event loop” because part a is where the code waits for an event to occur, which causes it to proceed onto the next part. After processing the event by executing the next three parts of the loop, the code returns to the top, where it waits for the next event to occur.

    Since these four parts repeat endlessly, they could actually be coded in any order without any real effect on the behavior of the machine, as long as each step occurs exactly once per iteration of the loop() function. This is not an obvious concept, so don’t worry if it doesn’t make total sense. The sequence given is a “logical” sequence given the formal structure of finite state automata, so we can just work with that.

    For the first version of the project, start by entering comment lines for each of the four parts inside the loop() function definition.

    For this version, there are no control inputs, and the transition event is nothing other than the passage of time. In future versions, the first part is where the code will use digitalRead() to get the values of the switches and buttons.

    Since we want the LED to flash on and off at 1Hz, there will have to be two transitions per second (one to turn the LED on, and another to turn it off). Use a delay() statement in the first part of the event loop. So it will take two iterations of the event loop for one complete period of the 1 Hz flash rate.

    To represent the state of the machine, use global integer variables that will always have either the value 0 or 1. Since Arduino int variables are sixteen bit values, this design wastes 15/16 of the variable. You can reduce the wastage by using 8-bit integers instead of 15: the type uint8_t will accomplish this. But it still wastes 7/8 of the memory you need. But trying to use a more efficient way of storing the needed state information would require more storage to access the individual bits because one byte is the minimum amount of storage the microcontroller can store at at time in memory. As with the note about the order of the parts in the event loop, if this concept isn’t clear yet, just go with the flow for now!

    To compute the next state the code needs to invert the value of the variable: if it is 0 make it 1; if it is 1 make it 0. There are two ways to accomplish this task. The clear way (provided you understand if statements):

    if (current_state == 0) { next_state = 1; } else { next_state = 0; }

    Or the lazy way:

    next_state = 1 - current_state;
  2. Extend the next-state part of the FSM to create a 1 Hz 2-bit up counter, using the Serial Monitor to view the changes in the counter’s state.

    In this step, you will need two variables for the current state and another two variables for the next state. Since these bits will correspond to the rightmost two bits of a binary number, you can use numbers at the end of the variable names to indicate which is which. Pick your own numbering scheme: the right most bit could be 0 because it is in the 20 position, or it could be 1 because it is in the position that has a value of 1.

    For now, use the Serial Monitor to show the states of the two current state variables in part d of the event loop. Call Serial.begin() inside setup(); call Serial.print() to print the left bit, and call Serial.println() to print the right bit.

    But how to compute the next state each time? There are a couple of techniques that would seem reasonable, but which will make the code very hard to extend to 3, 4, or more bits. Here are the two rules to use:

    • The right bit always changes
    • The left bit changes only if the right bit is currently 1

    Use an if statement to test the value of the left bit. There is a shortcut you can use: in the Arduino (C++) language, a varable with the value 0 is false, and a variable with the value 1 is true. So if the variable x is an integer that is either 0 or 1, the following two statements are equivalent:

    if (x == 1) { ... } if (x) { ... }

    The second statement may seem obscure, but programmers with only a modest amount of experience will understand and use it because it saves typing 5 whole keystrokes! So it makes sense to get used to seeing/using it now.

  3. Implement a 1 Hz 5-bit up counter, still using the Serial Monitor to view the changes in the counter’s state.

    This step is the same as the previous step, but you need to figure out the rules for changing the states of the other three bits.

  4. Add a switch to select whether the counter will count forwards (“up’) or backwards (“down”).
  5. Add a button to cause the state to change instead of elapsed time intervals.
  6. Add a switch to select between pushbutton and timed state changes.