You are on page 1of 21

ECE230-03

Winter 2019
Worden Barr, Chris Comeau

Stacker Using
LED Matrices

ECE 230
Intro to Embedded Systems
Final Project
Winter 2019
Instructor: Dr. Michael Jo

Chris Comeau
Worden Barr

February 18, 2019


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Table of Contents
Introduction 3
Overview of Project 3
Fulfilment of ECE230 Final Project Requirements 3

User Guide 5
Before You Start 5
To Begin 6
Gameplay 6
Scoring 8

Hardware Design and Implementation 9


Circuit Diagram 9
Implementation 10
Inputs 10
Outputs 10

Software Design and Implementation 12


Initialize & Reset 13
Move Block 13
Place Block 13
New Screen 14
Game Over 14
Cycle Structure 15
Matrix Communication 15

Testing Procedure and Results 17


Individual Component Testing 17
Gameplay Testing and Iteration 17
Speed Bumps 19

Bill of Materials 20

References and Acknowledgements 21


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Introduction

Overview of Project
Using the PIC16F887 Microcontroller, we created a game
modeled off the fairly well-know arcade game, Stacker. Initially, we
were indecisive which game to implement, narrowing down our
options to either Tetris, Stacker, or Snake, all games we were very
familiar with. In the end, we decided that Snake was not as replayable,
and Tetris was too difficult due to the algorithm needed to rotate the
falling tetrominos and handle collisions. Thus, we set our minds on
implementing Stacker. Our goal in creating this project was to
demonstrate our understanding of the PIC architecture, I/O devices,
interrupts, and timers which we learned over the course of our ECE230
class.
In our version of stacker, the player is presented with a 6-LED-wide block bouncing left and right
on the bottom row of the game display. The player’s goal is to stack the LED blocks as high as possible in
order to obtain as high a score as they can.
Some additional features of our project include an 8-ohm loudspeaker which indicates, with a
short note, when an LED block has been placed on the tower and also indicates, with a long descending
note, when the game has been lost. The project also implements a scoring system, displayed on the LCD,
that keeps track of both the player’s score as well as the number of perfectly placed LED blocks in a row.
Lastly, the game speed linearly increases in pace as the game goes on, making the game more difficult as
the player progresses farther in the game.

Fulfilment of ECE230 Final Project Requirements


As the final project for our ECE230 course, certain conditions had to be satisfied at the very
minimum. These requirements were as follows:
1. The project must use the PIC16F887 (or other PIC microcontroller with approval)
2. The embedded circuit must include at least one sensor (input)
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
3. The embedded must include at least one actuator (output)
4. The embedded project must make use of at least one timer
5. The embedded project must make use of at least one interrupt
For our project, we utilized a single PIC16F887 microcontroller to interface with all of the other
parts to fulfill the first requirement. We met the second requirement by using a single pushbutton as the
user input for our system in order to play and control the game. Likewise, we met requirement three by
outputting to an LCD display, an 8 ohm loudspeaker, and four 8x8 LED matrices to create the gameplay.
The project also takes advantage of multiple timers in order make everything run smoothly and
predictably by using them for the delays of the game ticks and the LCD display commands in order to
fulfill the fourth requirement. The last requirement is fulfilled by using the CCP1 module to generate a
square wave for the loudspeaker to emit tones. This was done using the interrupt to toggle the pin tied to
the loudspeaker.
ECE230-03
Winter 2019
Worden Barr, Chris Comeau

User Guide

Before You Start


Check that the components of the system are complete and intact. Misplaced or damaged
components can lead to a malfunction of the entire system.

Figure 2.1 Overview of Stacker System


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

To Begin
Upon connecting the circuit to power, using the provided wall to barrel power supply, the
LED matrix and LCD screen should initialize by lighting up. From here, you are ready to begin
play. In the event that the LED or LCD screen does not light up or appears to be in an error state,
press the black RESET button located just to the right of the LED matrix.

Figure 2.2 RESET Button

Gameplay
The game begins with a 6 LED wide block sliding back and forth on the bottom row of
the LED matrix. Upon a user pressing the red USER BUTTON to the left of the LCD, the sliding
block will stop where it was at the time of the button press, and a new sliding block will appear
on the row above. However, upon a button press, if a piece of the sliding block is overhanging
the block on the row beneath, that overhanging section of the block will be lost, and the new
sliding block that appears on the row above will be just as short as the cut-off block below. In
addition, the game speed will increase as the user progresses higher and higher on the LED
matrix. If the user reaches the top of the LED matrix with their tower, the display will reset, and
the game will continue as before with the sliding block again at the bottom of the display. If, at
any point, the user misplaces an entire sliding bar, the game will end displaying the final score
on the LCD and GAME OVER on the game board. The objective of the game is to achieve the
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
highest score possible by stacking the blocks of LEDs, one on top of the other, for as long as
possible.

Figure 2.3 USER BUTTON Figure 2.4 Sample Gameplay Capture

Figures 2.5 & 2.6 GAME OVER Display Capture


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Scoring
Each successfully placed LED on each row of the game display will increase the user’s
score by 10 points. We also implemented a streak bonus in order to incentivise perfect play. This
happens when the player lands their placement exactly aligned with the previous row with no
missing blocks. This will increase the score they get by 10 points per perfect placement.

S core = Score + # Blocks landed × 10 + # Streak × 10

Figure 2.7 Sample Scoreboard Capture


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Hardware Design and Implementation

Circuit Diagram

Figure 3.1 Hardware Circuit Diagram


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Implementation

Inputs
The only vital user input we had for our system was a pushbutton. This button, referred to
above as USER BUTTON, served as the sole form of control the user needed to play the game.
The button allowed the user to stop the sliding blocks of LEDs as well as restart the game
whenever the user lost. The push button was wired up in such a way as to make it active-low,
utilizing internal pull-up resistors.
We also had a few other inputs that helped the system run internally. One of these was an
8 MHz high speed (HS) external crystal resonator instead of using the internal clock oscillator to
achieve more accurate time-keeping. We also made use of one of the unwired Port B analog pins
by taking advantage of the floating state. This is used for random sampling in the code to
generate pseudo-random numbers from a seemingly unpredictable source.

Outputs
Unlike our inputs, our system had several user outputs. Our outputs consisted of an LCD
display, an 8 ohm loudspeaker, and four 8x8 LED matrices.
For the LCD, in order to save on I/O pin usage, we configured it in both hardware and
software to run in 4-bit mode rather than 8-bit mode, allowing us to interface with the device
using only six pins.
For the 8 ohm loudspeaker, since the PIC16F887 microcontroller pins cannot output
more than a few milliAmps, and since the loudspeaker needs on the order of 100 mA to produce
an audible tone, we used the BS170 N-channel switching MOSFET to switch the current through
the loudspeaker on and off at a specified rate to produce the desired tone.
ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Figure 3.2 Four MAX7219 Chips Interfaced with Four 8x8 LED Matrices Figure 3.3 MAX7219 Chip

Lastly, for the four 8x8 LED matrices, we acquired a single unit of four cascaded LED
modules (Figure 3.2) such that the outputs of the first module were the inputs of the second
module and so on. Rather than having each row and column of the, in total, 8x32 LED matrix
individually interfaced with a single pin on the PIC16F887, the device we obtained came with
four MAX7219 microcontrollers (Figure 3.3) pre-connected to the LED arrays, allowing us to
interface with the entire array using a method similar to SPI with only 5 input pins: VCC,
Ground, Data In, Clock, and Load.

Figure 3.4 Scope Capture of MAX7219 DataIn Port with Bottom Row of LED
Matrix Lit as Follows: 11111000
ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Software Design and Implementation

The software system flow is depicted by flowchart/state machine below. This is a very
high level overview of how the program functions. The specifics in each state will be clarified in
sections below.

Figure 4.1 Software Flow Diagram


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Initialize & Reset


Initialize and reset are both very simple in that they have no computations or logic but
rather are responsible for getting the game ready to start. Initialize is responsible for setting up
the inputs and outputs for the system as well as initializing the LCD and the LED matrices. This
step will only need to run once. After all of the single time initialization steps have been
completed, the system then resets the game screen. This is a generic process that is used at the
start of any new game that may occur, regardless of whether the full system is reset or not. This
resets things such as score, position, block size, interrupts for tones, game speed, and clearing the
screen.

Move Block
The move block section is also fairly simple in that it is only responsible for the
movement calculation and animation of the block back and forth. The block has a position
horizontally within the column as well as a direction. The game makes the calculation for where
the block should be and then displays this on the corresponding column using the binary
representation of the block to light up the LEDs in that column. This happens repeatedly while
constantly check for if the user has pressed the button. If the user does press the button, the game
will enter the placing state.

Place Block
The place block section of the code handles a few different functions at the same time.
This section is response for the animation of placing the block, the calculation for the size of the
block for the next row, the score incrementing, making the placement sound, and speeding up the
game. It first calculates the size of the next block by taking the intersection between the placed
row and the previous row. The horizontal position of the next block is also pseudo-randomly
calculated. This is used to display the animation for the block that was just placed by flashing the
calculated row on and off a few times, while also incrementing the score each flash for a
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
seemingly smoothly incrementing score. This also triggers the sound to begin by switching the
CCP1 mode to the “Compare with toggle output” mode. The interrupt plays a tone for a few
periods before stopping and disabling the interrupt by changing the CCP1 mode back to disabled.
Once this animation is done the game then speeds up by decreasing the time between each game
tick. The game then decides if it should go to Game Over if the player lost by missing their
placement, New Screen if they have reached the top, or simply movement again if nothing
special happened.

New Screen
If the player reaches the top of the screen, the game will perform actions to create a new
screen. These actions are very similar to the reset discussed earlier, with a few key differences.
The most important differences are that score is not reset, and the the stack partially carries over
from the top. This means that the game takes the last row placed on the top and puts it on the
bottom to allow the player to continue from where they were before the new screen. Other than
this, the functionality is almost identical to that in Reset.

Game Over
The Game Over state is reached when the player makes a placement that does not
intersect the previous row. This disables the normal movement or placement animation in favor
of full screen-length display of the words “GAME OVER” using the LEDs. This is accompanied
by a new sound that instead moves downwards and stabilizes before ending. The score remains
on the LCD for the user to view. The system then waits for user input while flipping between the
words. Once the button is pressed, the game then enters the Reset stage and start the game over.
This would be functionally equivalent to pressing the dedicated reset button.
ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Figure 4.2 General Game Cycle Structure

Cycle Structure
Whenever the game performs calculations and then renders onto the display, the game
follows the same pattern almost without exception. This is so that the user input is the closest to
both what has been calculated and what has been displayed on the LED matrices. This makes the
game feel more responsive and less like the input is lagging behind the game. The structure also
allows us to separate and compartmentalize each section of code so that they are easy to expand
and modify in the future.

Matrix Communication
In order to drive the LED matrices, we had to interface with the MAX7219 chip. This
component took in three varying signals to convey the data required to control the LEDs. This is
depicted in the diagram above which shows how a signal is sent to the device. We managed to
accomplish communication such as this through the implementation of an existing Arduino
library onto the PIC16F887. This allowed us much easier interfacing with the LED matrices and
allowed us to do much more powerful operations in a shorter development timeframe. This saved
us a ton of time in the long run because it helped create the base for our project to work from and
is cited in the Resources and Acknowledgements section. This code was readily scalable and
versatile so that we could use it in any way we needed. It also clarified some questions we had
about the control protocol and how messages are sent to multiple instances of the device in series
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
with each other. We also pulled code from Arduino directly in the form of the shift out function,
which allowed us to use a pin with a clock to send a series of data bits easily.

Figure 4.3 Arduino shiftOut() function

Figure 4.4 MAX7219 Communication Example


ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Testing Procedure and Results

Our testing procedure was mostly iterative and was best tested through gameplay,
especially in the later stages of the project.

Individual Component Testing


We tested many of our components individually to isolate any problems and combine
each of the pieces in a more timely manner. The first and most important piece that we tested
was the LED matrix. We wanted to be able to control the matrix in the most basic form of
turning on some of the LEDs. We wrote a program using the code based on the Arduino library
in order to interface with the matrix and displayed varying forms of simple, constant patterns on
the matrix.
We complemented this by adding few buttons to the system and tested responsiveness
and controllability of the matrix with user input. This showed the ability to have a user’s actions
reflected accurately and expectedly on the display. This was important for us to test purely
system capabilities with respect to the display and without direct connection to the game because
we were still unsure about the game we would implement at the time.
We also created the LCD circuit and imported the previously made code to confirm that
we would easily be able to configure the LCD to display what we want. We then had all of the
components that would be general enough to be used in any of the games we were considering at
the time, which meant that we had to make a decision of which game to proceed forward with as
our project. We chose Stacker for sake of both relative simplicity and replayability compared to
the other options.
ECE230-03
Winter 2019
Worden Barr, Chris Comeau

Gameplay Testing and Iteration


After deciding on our game, we worked iteratively towards first implementing the key
features of the game, and then later implementing the added extra additions. The initial features
consisted of actions like the block bouncing back and forth and the user placing a block. The
bouncing block was somewhat difficult to debug due to the fact that it was hard to discern what
was happening if something was wrong. This was due to the position sometimes not syncing
with what was actually being calculated. We were able to debug this issue and move on to
placement of the block. We also found that the small button was not as user friendly as the large
tactile push button that we changed to.
We iteratively improved this from basic Y position incrementing to the next row without
any overlap detection to checking for how many landed to animating the placement. This
allowed us to start with a solid base that we improved as each piece worked. We then focused on
calculating score and game ending. The score was relatively simple in that the pieces to
implement mostly everything were already in place from other sections in the code. The last
piece that we wanted to implement in order to fulfill the base mechanics of the game was the
game over screen. Entering into the game over state had essentially already been outlined due
which left the animation and game pausing. We experimented with the animation and initially
attempted scrolling characters. We decided against this in favor of static switching characters due
to the slowness of the scrolling and ease of implementation. We then implemented the ability to
restart the game from this state which completed the base features we wanted in the game.
At this point, we wanted to add extra features to enhance the gameplay without being
overly complex. We decided that adding sound would be the most noticeable change that would
fit the scope of the project. We then added sound effects to both the placement and the game
over screen to make gameplay more complete. This took many tries to figure out exactly how to
implement the specific sound at a specific time. We also got feedback from other players on
what they thought fit the situation in terms of sound effects in order to create a better game. The
last small feature that we added was the streak bonus for when multiple perfect rows are placed
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
in succession. We found that this seemed more satisfying and rewarding for the user through
multiple individuals.

Speed Bumps
One of the larger issues we ran into during the project that had been persistent since
almost the start of the project was an apparent disjoint between the calculations and the display.
This had been arising due to the fact that we were using interrupts to drive our game ticking.
They would trigger every X ticks and do the main calculations for the game. We could not have
the display code within these interrupts as they bog down the interrupt due to the sending of the
data to the LED matrix taking a considerable amount of time compared to everything else. This
forced us to separate these so that the calculations alone executed in the interrupt. While this
worked in the beginning, as we added sections within the game tick in the interrupt, we noticed a
larger and larger discrepancy between what was calculated and what was displayed. This became
hard to play due to the user using feedback that did not correlate with what was happening to
play the game. Our solution to this issue was to pull the calculations out of the interrupt and
instead have game execute in a main loop that happens every game tick. This made the
calculation and the display happened almost together which made the game easier to play.
Another strange issue arose when we attempted to create the sound for the placement of
each row. We attempted to create the short pulse sound by enabling the CCP1 interrupt when we
wanted to make the noise and disabling it when we did not. This succeeded in creating the
desired sound effect, but also created a periodic, low frequency ticking noise. This was a difficult
issue to debug as it was hard to trace where exactly the noise was generated. The root of this
issue was actually due to the fact that despite the interrupt being disabled, the toggle on the
CCP1 pin still happens once every full clock cycle without calling our interrupt handler function.
This meant that we needed a different solution besides disabling the interrupts. The solution that
we arrived at after advice from classmates was to instead reconfigure the CCP1 module to a
disabled mode when we did not need to create sound.
Overall, we implemented a complete game that is both fun and simple to play which
creates a positive player experience. We could have added additional features such as a scrolling
ECE230-03
Winter 2019
Worden Barr, Chris Comeau
new game or scrolling game over, but felt that it would not enhance the game enough to warrant
them and instead we implemented other features during our limited time.

Bill of Materials

Qty Part Description Cost

1 PIC16F887 Used to run the game and for all inputs/outputs $0.00*

1 Large pushbutton switch Used for user input $0.00*

1 Small pushbutton switch Used for program reset $0.00*

1 Breadboard Large breadboard used to hold all parts $0.00*

1 16x2 LCD Display Used to display player’s score $0.00*

1 10 kΩ Resistor Used to connect LCD to power $0.00*

2 10 kΩ Potentiometer Used to control LCD brightness and loudspeaker $0.00*


volume

1 Loudspeaker Used to produce game noises $0.00*

1 BS170 NMOSFET N-channel switching MOSFET used to operate $0.00*


loudspeaker

1 22 Ω Resistor Used to limit current into loudspeaker $0.00*

2 22 pF Capacitor De-spiking capacitors across PIC power bus pins $0.00*

1 10 𝞵F Electrolytic Capacitor Used to absorb lower frequency AC noise across $0.00*


power busses

1 4 in 1 8x8 LED Matrix Used as game pixels for main gameplay display $10.95

Total $10.95
* Already possessed piece for no additional cost
ECE230-03
Winter 2019
Worden Barr, Chris Comeau

References and Acknowledgements

● MAX7219 LED Matrix Library for Arduino


○ Referenced and used to port control of LED matrix to the PIC16F887
● PIC16F887 Datasheet
○ Referenced in order to understand full control of PIC16F887
● MAX7219 LED Display Driver Datasheet
○ Referenced to understand LED matrix control, configurations, setup, and serial
signal format
● LCD 16x2 HJ1602A Display
○ Referenced to understand interfacing with LCD display to send characters for
score
● BS170 NMOSFET Datasheet
○ Referenced to confirm pin polarity to avoid damage to piece during use
● Arduino Playground LED Control Page
○ Referenced for controlling LED matrix and taking advantage of library

Special thank you to Dr. Michael Jo and the Rose-Hulman ECE Department for guiding
us through any issues we had and providing the resources to make this project possible by giving
us a knowledge base to use in the future. Also, thank you to our fellow ECE230 classmates for
input and feedback on the game as well as playing it.

You might also like