Microcontroller - A Beginners Guide - The Button Game

Microcontroller - A Beginners Guide - The Button Game

It's time to apply a bit of what was learned and create an actual game. This game uses a couple of push buttons, two sets of LEDs (2 rows of 7 LEDs). The object of the game is for two people to try to press their button the most times in the shotest amount of time. As the button is pressed, the LEDs are lit up one after another until the last LED is lit and that side wins. The winner is exposed by their side of LEDs flashing.

The circuit consists of two rows of LEDs, 7 LEDs on each row. Since there are 7 LEDs for each side, a single port can be used for each set, and there is still room for a push button on each port. One push button and 7 LEDs can be wired to 8 pins, or one port worth of pins. In the video, I use port B for one player's button and LEDs and port D for the other player's button and LEDs.

Three other programming fundamentals were also demonstrated in the video: arrays, encapsulation and a bit more information on variables. The arrays are used to simplify the variables used for each player. Instead of creating unique varibles for the button debouncing, button press and LEDs to be lit, a single variable was used for each containing an array of "2", one for each player. This also made encapsulation and repetitive code use much easier. If code is to be re-used in the program more than once, it makes sense to put that code in a special area called a function, or a method so it can be called whenever it is needed. since there were two players, we had identical code that was going to be used twice when the button press and release is tested and the code that is used to light up the LEDs.

Specifically, in the program, you will see a few new things. With the creation of new functions, we can essentially create what looks like new commands that the program will undestand. These functions are called ProcessPressedButton and ProcessReleasedbutton. With the help of the arrays, all that needs to be done is the array number (player number) be passed into these fnctions. In the program, the first thing you will notice is that there are a couple of statements with "void" at the beginning. These are called function prototypes. The language of C, or C++ requires these function prototypes to inform the compiler that these are used in the program before they are actuall defined. Notice that the functions are used in the program (within the main function) before the actual functions and code (after the main function). An alternative to this would be to actually put the main function at the end of the program, and remove the prototypes, but I personally like keeping the main function at the beginning for clarity. There is even a better alternative: to create a couple of library files that contain these new functions, but we have not gotten to this level of programming yet at this poing in the tutorial series.

You will also notice that there are integers (variables) outside of the main function (ignore the brackets and number 2 for now). This will force these variables to have a global scope. Ok, I know... I haven't discussed scope yet (not even in the video). Scope is where the declared variables will be used. If a variable is declared within a specific code block, like in a function, then the variable will live and die in this code block, and any code blocks within this block. For instance, if the variables are declared within the main function, these variables cannot be used within another function that resides outside the main function. If the variables are defined at the bottom most level (outside of any block), they become global, and any code block can use them.

Now the arrays... notice the [2] at the end of the global variables. This allows for two of these same variables to be created and differentiated by using a [0] or [1]. Why "0"? The numbers are indexed from 0, not 1. So, take the Pressed[2] as an example. This creates a variable called Pressed[0] and a Pressed[1]. Notice in the functions that I have a variable within the brackets. Encapsulation and arrays can provide some really cool features in programming.

#include
#include

void ProcessPressedButton(int ButtonPressed);
void ProcessReleasedButton(int ButtonReleased);
int Pressed_Confidence_Level[2];
int Released_Confidence_Level[2];
int Pressed[2];
int LEDNumber[2];
int main(void)
{
DDRB = 0b01111111;
DDRD = 0b01111111;
PORTB = 0b10000000;
PORTD = 0b10000000;

while (1)
{
if (bit_is_clear(PINB, 7))
{
ProcessPressedButton(0);
}
else
{
ProcessReleasedButton(0);
}
if (bit_is_clear(PIND, 7))
{
ProcessPressedButton(1);
}
else
{
ProcessReleasedButton(1);
}
}
}

void ProcessPressedButton(int ButtonPressed)
{
Pressed_Confidence_Level[ButtonPressed] ++;
if (Pressed_Confidence_Level[ButtonPressed] > 500)
{
if (Pressed[ButtonPressed] == 0)
{
Pressed[ButtonPressed] = 1;
if (ButtonPressed == 0) PORTB |= 1 << LEDNumber[ButtonPressed];
if (ButtonPressed == 1) PORTD |= 1 << LEDNumber[ButtonPressed];
LEDNumber[ButtonPressed] ++;
if (LEDNumber[ButtonPressed] >6)
{
for(int i=0;i < 10;i++)
{
if (ButtonPressed == 0) PORTB = 0b11111111;
if (ButtonPressed == 1) PORTD = 0b11111111;
_delay_ms(10);
if (ButtonPressed == 0) PORTB = 0b10000000;
if (ButtonPressed == 1) PORTD = 0b10000000;
_delay_ms(10);
}
LEDNumber[0] = 0;
LEDNumber[1] = 0;
PORTB = 0b10000000;
PORTD = 0b10000000;
}
}
Pressed_Confidence_Level[ButtonPressed] = 0;
}
}

void ProcessReleasedButton(int ButtonReleased)
{
Released_Confidence_Level[ButtonReleased] ++;
if (Released_Confidence_Level[ButtonReleased] > 500)
{
Pressed[ButtonReleased] = 0;
Released_Confidence_Level[ButtonReleased] = 0;
}
}
Back to blog

Leave a comment

Please note, comments need to be approved before they are published.