GAME CONTROLLER

PIPER MAKE EDUCATOR RESOURCES SERIES

To do this project, you will need a Piper Make Extended Starter Kit. Get yours here:

Color us impressed with this tutorial using a color sensor!

To get started, head to Piper Make and hit this icon:

Time: 45 minutes

Age Range: 8+

Difficulty: Advanced

Students will build their own game controller and program the 14 buttons to mimic keyboard strokes or mouse movements to their favorite games. Take command of the maker movement by building and customizing a microcontroller to hack and create an arcade-ready game controller, a spatial mapping tool, or a robo-commander.

Note: There are step by step instructions for the students to follow in the tutorials included in each project on Piper Make. These provide directions both for writing code and for building the electronic circuits. The tutorials are well-defined and most students will be able to follow them with little assistance required.

LEARNING OBJECTIVES

Students will:

 

  • Create hardware using tools such as a screwdriver
  • Review key electronics understandings:
    • wire and pin positions for specific inputs and outputs
  • Practice computational concepts of
    • loops: running the same sequence multiple times
    • events: while a pin’s condition is on or off, another action happens
  • Create programs that use variables to store and modify data
  • Create programs that include events, loops, and conditionals
  • Decompose problems into smaller, manageable tasks which may themselves be decomposed
  • Create programs by incorporating smaller portions of existing programs, to develop something new or add more advanced features
  • Test and debug a program or algorithm to ensure it accomplishes the intended task

MICHIGAN INTEGRATED TECHNOLOGY COMPETENCIES FOR STUDENTS (MITECS)

Michigan’s Integrated Technology Competencies for Students (MITECS)

1B-CS-01: Describe how internal and external parts of computing devices function to form a system. Subconcept: Devices; Practice 7.2

1B-CS-02: Model how computer hardware and software work together as a system to accomplish tasks. Subconcept: Hardware & Software; Practice 4.4

1B-CS-03: Determine potential solutions to solve simple hardware and software problems using

common troubleshooting strategies. Subconcept: Troubleshooting; Practice 6.2

1B-AP-09: Create programs that use variables to store and modify data. Subconcept: Variables; Practice 5.2

1B-AP-10: Create programs that include sequences, events, loops, and conditionals. Subconcept: Control; Practice 5.2

1B-AP-11: Decompose (break down) problems into smaller, manageable subproblems to facilitate the program development process. Subconcept: Modularity; Practice 3.2

1B-AP-12 Modify, remix, or incorporate portions of an existing program into one’s own work, to develop something new or add more advanced features. Subconcept: Modularity; Practice 5.3

1B-AP-15 Test and debug (identify and fix errors) a program or algorithm to ensure it runs as intended. Subconcept: Program Development; Practice 6.1, 6.2

 

Language Objectives

Michigan ELA, Grade 3-8, Research, 8: Recall information from experiences or gather information from print and digital sources; take brief notes on sources and sort evidence into provided categories.

Michigan ELA, Grade 3-8, Range of Writing, 10: Write routinely over extended time frames (time for research, reflection, and revision) and shorter time frames (a single sitting or a day or two) for a range of discipline-specific tasks, purposes, and audiences.

 

WIDA ELD Standards

 

ELD-SI.K-3.Argue:

  • Ask questions about others’ opinions
  • Support own opinions with reasons
  • Clarify and elaborate ideas based on feedback
  • Defend change in one’s own thinking
  • Revise one’s own opinions based on new information

 

ELD-SC.2-3.Argue.Interpretive:

Interpret scientific arguments by

  • Identifying potential evidence from data, models, and/or information from investigations of phenomena or design solutions
  • Analyzing whether evidence is relevant or not
  • Distinguishing between evidence and opinions

CONCEPTS

Assemble a real working game controller that emulates buttons and mouse movements.

PARTS

Pico and Breadboard, 5 extra-long M-F jumper wires, Controller Printed Circuit Board Assembly (PCBA), controller pieces

GPIO SETUP

data pin: 2, latch pin: 3, clock pin: 4

OVERVIEW OF STEPS

Step 1: Frog Frenzy

We're going to build your very own game controller!

Your Game Controller is going to work by emulating buttons or mouse movements - basically, we will program the controller to be a mouse or be a keyboard (or both!)

If you've already completed the Frog Frenzy tutorial and you have already built your controller, you can skip to step 7. Otherwise, click NEXT.

Step 2: Grab your stuff

You'll need:

  • Pico and Breadboard
  • 5 extra-long M-F jumper wires
  • Controller Printed Circuit Board Assembly (PCBA)
  •  

You'll also need:

  • 1 - Controller top piece
  • 1 - Controller bottom piece
  • 3 - Controller spacer pieces
  • 2 - long screws
  • 4 - short screws
  • 4 - washers
  • 1 - screwdriver
  •  

Click NEXT.

Step 3: Build the Controller's Base

Okay first, let's put together our pieces.

Place the Controller bottom piece on a flat surface like a table to desk. Make sure the metal pieces inside of the bottom piece are facing down.

Put the four washers above the center 4 holes in the board. Then line up the holes of the the Controller PCBA (circuit board) and set it on top of the washers:

Next, place a short screw into each of the 4 holes in the Controller PCBA and use your screwdriver to tighten them:

Before you add any more of the wood pieces to your controller, it needs to be connected to your Pico. Click NEXT.

Step 4: Connect your controller

Before you begin building the circuit for your controller, make sure that the Pico is unplugged from your computer.

First, use one of the extra long M-F jumper wires to connect the DATA pin on the Controller PCBA to pin GP2 on the Pico. Next, use another extra long jumper wire to connect the LATCH pin to pin GP3. Then, connect the CLK pin to pin GP4 using another jumper cable

Now, connect the VCC pin on the Controller PCBA to the 3V pin on the Pico using one of the extra long jumper wires. Finally, connect the GND pin on the Controller PCBA to one of the GND pins on the Pico:

Double-check all of your connections. Once you are sure that they are correct, go ahead and plug your Pico into your computer. Then, click NEXT.

Step 5: How Does it Work?

The Piper Make Controller works by using a special kind of microchip called a shift register. Shift registers work by reading a bunch of inputs all at the same time, and then shifting them out and to the microcontroller that they are connected to:

When the Pico sends a pulse to the LATCH pin of the shift register, the shift register reads all of the buttons that it's connected to. If the button was pushed, it is read in as a "1", and if it was not pushed, it is read in as a "0". Each of these 1's or 0's is called a bit. 8 bits is called a byte.

When the Pico sends a pulse to the CLOCK pin of the shift register, the shift register sends the first bit of the byte to the Pico. Every time the Pico sends a pulse, another bit is sent to the Pico until all 8 bits have been sent.

Your controller has 14 buttons, so it uses two shift registers to capture all of them. This circuit has been around for a long time - did you know that your Piper Make controller uses almost the same circuit as the original Super Nintendo controller? Cool, right!?

Click NEXT.

Step 6: Finish building your Controller

Place the 3 wood spacer pieces over the Controller PCBA:

Then, place the top piece on the Controller and insert the two long screws into the holes on each side. Use your screwdriver to tighten them:

That's it! Your Controller is built and ready to be programmed! Click NEXT.

Step 7: The Setup Code for our Controller

The first part of our program needs to set up our controller. Just like we do with all programs, we need to begin by dragging out a start block from the Chip menu. Then, grab a setup controller block from the Sensing menu and connect it to the start block.

This block tells the Pico that there is a Controller connected to it, and it tells the Pico which pins it's connected to.

Choose the following options for the pin variables on the setup controller block:

  • data pin: 2
  • latch pin: 3
  • clock pin: 4

Click NEXT.

Step 8: Function Junction

We are going to give our controller a few different modes. If you've ever played games on your computer, you may have noticed that some games use the arrow keys, some games use the "w", "a", "s", and "d" keys, and some games use the mouse.

We are going to program our controller so that we can switch between those different modes. When we build our program, we will create functions named "arrow mode" and "mouse mode", and these functions will hold the blocks that make those modes work. We will also add a few other pieces that all of the modes will share, and we can do that with functions, too!

Step 9: Start Programming the Controller

Let's start with the first mode: arrow keys.

Start by dragging out a to do something block from the Functions menu. Rename your block "arrows mode". Next, grab a repeat forever block from the Loops menu and place it into the to arrow mode block. Change the wait time on the repeat forever block to 0. Then, grab a read controller buttons block from the Sensing menu and place it in the repeat forever block:

Why do we need the read controller buttons block? Because this is the block that tells the shift registers on the Controller to "shift in" and send all of the button's values to the Pico.

Click NEXT.

Step 10: Read a Button Press

Let's add blocks that will let us read our first button!

 

Each button press actually has two parts - the press, which is when you push the button down, and the release, which is when you let the button go. We will need to add blocks for both the press and the release for each button - yikes! That means there will be a lot of blocks, but the good news is that we can use the duplicate option when we right click a block to make building our program a little faster.

 

Start by grabbing an if do block from the top of the Logic menu, and connect it below the read controller buttons block. Next, grab a was controller up button pressed block from the Sensing block and place it into the if do block's input. Then, grab a turn pin block from the Chip menu and place it inside of the if do block. Finally, change the pin variable of the turn pin block to 25 (LED):

Click NEXT.

Step 11: Read a Button Release

Our code will read when the up button on the controller is pressed, so now we need to read when the button is released.

Right-click the if do block and select duplicate. Connect the new if do block below the first if do block.

Pull the was controller block out of the second if do block and set it off to the side. Grab a not block from the Logic menu and place it into the input you just removed the was controller block from. Then, drag the was controller block into the new not block. Finally, change the second turn pin block from ON to OFF:

Now, we need to actually call the arrow mode function. First, drag out a repeat forever block from the Loops menu and connect it below the setup controller block. Then, grab a arrow mode block from the Functions menu and place it inside of the repeat forever block. Then, change the wait time on the repeat forever block to 0:


Click NEXT.

Step 12: Test it out

Now is a good time to test your Controller to make sure it's going to work.

Click on the DIGITAL VIEW tab at the bottom of the screen to open it. Then, click CONNECT. Choose your Pico device form the pop-up menu, and then, click START.

The first thing you might notice when your controller and Pico is running a program are the GP2, GP3, and GP4 pins are flickering really fast - this is the Pico asking the controller for the button press information (GP3 and GP4), and the Controller sending it back (GP2).

When you press button 2 (UP) down on your Controller, the LED on the Pico will turn on. When you let the button go, the LED will turn off.

If your controller is working, great! If not, this a good time to go back over the steps to troubleshoot your wiring and your code.

Click STOP. If the Digital View is still open, click its tab to close it. Then click NEXT.

 

Step 13: It Disconnected!

You just clicked STOP, and normally, your Pico would stay connected - but this time it disconnected itself - but why?

There are a few devices and pieces of code that need to fully reset the controller when you are done running them - this clears out some memory inside of the Pico that the controller was using so that it's ready to go again the next time you need it.

Because the controller uses some extra resources inside of the Pico, you may need a few troubleshooting tips if your Pico stops connecting or running the programs properly on your computer.

Here are some things you can always try if something doesn't work correctly:
Check your program and your wiring to make sure they are correct.
Unplug your Pico, wait 5 seconds, and plug it back in.
Refresh your browser page.
Ready to code the rest of your Controller's program? Click NEXT.

Step 14: Make an LED flash Function

We have a couple of modes on our controller, so how are we going to be able to tell which one we're in? Well let's use that little LED on the Pico.

We can flash it one time for "arrow key" mode and two times for "mouse mode".

Grab a to do something block from the Functions menu and place it on its own in the workspace. Change the name of the function to "flash LED".

Grab a wait block from the Chip menu and place it into the to flash LED block. Change the wait time to 0.25 seconds. Then, drag out the turn pin 25 (LED) ON block from inside of the to arrow mode function and connect it below the wait block you just placed. Grab another wait block from the Chip menu and connect it below the turn pin block you just placed. Change its wait time to 0.25 seconds. Finally, drag out the turn pin 25 (LED) OFF block from inside of the to arrow mode function and connect it below the wait block you just placed:

Since "arrow key mode" will be the first mode on our controller, we want the LED to flash 1 time at the beginning of that function. Grab a flash LED block from the Functions menu and place it right above the repeat forever block inside of the to arrow mode block:

Click NEXT.

Step 15: Add Key Presses

Now we are ready to make our Controller press (and release) buttons!

We want to make button 2 (UP) on the controller press the Up Arrow key on the keyboard. To do this, grab a keyboard press block from the Actions menu and place it inside of the first if do block in the arrow mode function.

Change the aA variable on the keyboard press block to ⇧ (Up Arrow). Next, right click the keyboard press block and select duplicate. Place the new block inside of the second if do block. Change the press variable to release:

Let's program the Down Arrow Key next!

The easiest way to add a new key is to duplicate a key that you have already programmed. Remember that there are two parts - the press and the release, and you need both parts for each button.

Right click the first if do block and select duplicate. Place the new block below the last if do block and inside of the repeat forever block. Change the was controller block to down button and the keyboard press block to ⇩ (Down Arrow). Do the same thing with the seconds if do block. When you are finished, you should have 4 sets of blocks - 2 for up and 2 for down:

Repeat the steps above for the right and left arrow keys. When you are finished, you will have a total of 8 if do blocks. Double check that every other one releases the key by having a not block and is set to release:

Once you've double-checked all of your code, click NEXT.

Step 16: A few more buttons

Our program is getting really big!

Did you know that there are controls in the top-right corner of the workspace to make working with bigger programs easier? You can use these buttons to zoom in or out on your project:

There are a few more buttons to add: - the Spacebar key on button 5 - the Return/Enter key on button 6 - the Escape key on button 14

And we want to set button 11 as our "switch modes" button.

Let's start with the rest of the keyboard keys.

Right click the second-to-last if do block and select duplicate. Connect the new if do block after the last if do block. Do this again with the next if do block (the one that has the not block). Change the was controller blocks in the new if do blocks to button 5 and change the keyboard blocks to Space Bar:

Do this again two more times to set button 6 to the Return/Enter key and set button 14 to the Escape key:

Once you've double-checked all of your code so far, click NEXT.

Step 17: Mode Change

The last thing this function needs is a way to change the Controller's mode.

Our program will need 2 if do blocks, just like we do for all of the other buttons. Duplicate both of the if do blocks at the end of your program, and change the was controller blocks to button 11. Then, delete the keyboard press Escape buttons in the two new if do blocks:

We want our Controller to change its mode when button 11 is pressed and then released. That means we need a variable to keep track of when button 11 was pressed.

Click on the Variables menu and then click the Create variable... button. Name your new variable "mode pressed". Then, drag out the set mode pressed block and place it into the first empty if do block. Then, grab a true block from the Values menu and place it into the set mode pressed button:

Now, grab and drag out the not block in the last if do block. Grab an and block from the Logic menu and place it into the if do block where you just removed the not block. Put the not block back into the and block (it doesn't matter which side). Finally, grab a mode pressed block from the Variables menu and place it into the other side of the and block:

Click NEXT.

Step 18: Finish the Mode Change button

Our program now knows when button 11 was pressed and released, so the next step is to tell our program to set the mode pressed variable back to false and exit the loop it's in.

Right-click the set mode pressed block in the second-to-last if do block and select duplicate. Place the new block into the last if do block. Change the true to false. Then, grab an exit loop block from the Loops menu and place it right below the set mode pressed block you just added:

There is one more thing we need to do - we need to make sure that when our program starts, that the mode pressed variable is set to false.

Right-click the set mode pressed block in the last if do block (the one set to false) and select duplicate. Drag the new block all of the way to the top of your program and insert it right after the start block:

Our Controller's arrow key mode is ready to go! Click NEXT to try it out!

Step 19: Try it out!

That was a lot of blocks! You deserve an award for putting all of that together!

 

Before you run your program, click the Digital View tab at the bottom of the workspace. There is a switch on the left side of the Digital View. Click the switch to turn off the Digital View. This will make your controller run more smoothly.

 

First, let's click CONNECT and then click START. This will get our controller running. Right now, there is only an arrow key mode, but that's all we need to play most of the games in Pip's Arcade!

 

You can use the controller's left and right buttons to select a game, and you can use button 5 to choose a game. Use the direction buttons (1-4) and buttons 5 and 6 to play the games. To go back and choose a different game, use button 14.

 

Click the link below to open Pip's Arcade in a new tab:

When you are done and ready to add the mouse mode to your controller, close the tab with Pip's Arcade and click NEXT.

Step 20: Start building the Mouse Mode

Now that our arrow key mode is working, let's start building the mouse mode.

Scroll up to the top of your program. Start by right-clicking the to arrow mode block and selecting duplicate.

Drag the new function just off to the right of the original function. Change the name of the new function to mouse mode. Then, right click the to arrow mode block again. This time, select Collapse Block.

Now it's time to delete some blocks!

First, delete the 4 if do blocks what have a not block and are for the directional keys (up, down, left, right). Then, delete the 4 keyboard press blocks for the directional keys:

Next, grab a mouse click block and place it in the same if do block as the keyboard press Space Bar block. Then, delete the keyboard press Space Bar block.

Do the same thing with the next if do block. Then, change the first mouse click block from click to press. Change the second mouse click block from click to release.

Next, replace the keyboard press Return/Enter blocks with mouse click blocks. Make the same changes as before, and change them from left to right:

Click NEXT.

Step 21: More Mouse Mode

Go up to the beginning of the to mouse mode block.

 

When the Controller goes into mouse mode, we want the LED to flash 2 times, so right-click the flash LED block and select duplicate. Place the new flash LED block right under the original one.

 

Next, we need three variables to keep track of how we want to move the mouse cursor: one for the left-right movement (x), one for the up-won movement (y), and one to keep track of the cursor's speed.

 

Click the Variables menu and then click the Create variable... button. Name the new variable "move y". Drag out the set move y block and connect it right below the read controller buttons block. Do this again - name the new variable "move x" and place the set move x block right below the set move y block.

 

Grab a 0 block from the Values menu and place it inside of the set move y block. Then, grab and place another 0 block into the set move x block:

Click the Variables menu and then click the Create variable... button. Name the new variable "speed". Drag out the set speed block and connect it right below the second flash LED block. Grab a 0 block from the Values menu and place it inside of the set speed block. Then, change the 0 to 4:

Click NEXT.



Step 22: Make it Negative

Grab a set speed block from the Variables menu and place it into the if do block for the down button. Change the variable on the set speed block to move y. Then, grab the speed block from the Variables menu and place it into the set move y block.

 

Do this again, except place the block in the if do block for the right button, and change it so you are setting the move x variable:

Right-click the set move y block and select duplicate. Place the new block in the if do block for the up button. Pull out the speed block and set it to the side. Grab a _ + _ block from the Logic menu and place it into the set move y block. Put the speed block into one side of the _ + _ block.

 

Next, grab a 0 block from the Values menu and place it into the other side of the _ + _ block. Change the 0 to a -1, and change the + (add) to a × (multiply).

 

Finally, right click the set move y block that you've been working on and select duplicate. Place the new block in the if do block for the right button. Change the move y variable in the new block to move x:

We are almost there! Click NEXT.

Step 23: Almost There!

Now that our Controller's buttons are putting values into variables, we need to do something with those variables.

 

Grab an if do else block from the Logic menu and place it in between the if do block for the right button and the if do block for button 5. Then, grab an and block from the Logic menu and place it into the input of the new if do else block. Next, grab a _ = _ block from the Logic menu and place it into one side of the and block. Grab another _ = _ block and place it into the other side of the and block:

Grab a move x block from the Variables menu and place it into the left side of the first _ = _ block. Grab a 0 block from the Values menu and place it into the other side of the _ = _ block. Using a move y block, do the same thing with the other _ = _ block.

 

Right-click the set speed to 4 block at the top of the mouse mode function and select duplicate. Place the new block in the do part of the if do else block we are working on:

Grab a change speed by block from the Variables menu and place it into the else part of the if do else block we are working on. Change the 1 to 0.5.

 

Next, grab a mouse move block from the Actions menu and place it right below the change speed by block. Grab a round block from the Values menu and place it into the first (↔) input of the mouse move block. Grab another round block from the Values menu and place it into the second (↕) input of the mouse move block. Change both round blocks to round down:

Grab a move x block from the Variables menu and place it into the first round down block. Then, grab a move y block from the Variables menu and place it into the first round down block:

Go back to the beginning of your program by the start block.

 

Grab a mouse mode block from the Functions menu and place it below the arrow mode button in the repeat forever loop:

That's it! Double-check all of your work, and then click NEXT to try it out!

Step 24: Take it for a Spin!

Click CONNECT and then click START.

Remember that your Controller will start in arrow key mode. Click button 11 to change it. When you do, the LED on the Pico should blink twice. This means you are now in mouse mode. Try it out! Use the direction buttons (left, right, up, down) on your Controller to move the cursor on your screen. Use button 5 to left-click and use button 6 to right-click.

To go back to arrow key mode, just press button 11 again - and the LED should blink once.

Step 25: Congratulations!

You just built a really cool game controller! What are some ways to change it up? Could you add more buttons or add another mode? Experiment and have some fun with it!

When you're ready to try some new tutorials or projects, click EXIT to go back to the start screen.