FROG FRENZY

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 code for a game that uses (x,y) coordinates.

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:

 

  • Practice coding loops
  • Review these key electronics understandings:
    • Binary state of a button as an input
  • 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.
  • Perform different roles when collaborating with peers during the design, implementation, and review stages of program development.

MICHIGAN INTEGRATED TECHNOLOGY COMPETENCIES FOR STUDENTS (MITECS)

Standards Alignment

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-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

 

Core Content Standards

Michigan Math Standards

5.G.2: Represent real world and mathematical problems by graphing points in the first quadrant of the coordinate plane, and interpret coordinate values of points in the context of the situation.

 

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 and create the code for a game.

PARTS

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

GPIO SETUP

OVERVIEW OF STEPS

Step 1: Frog Frenzy

Let's Make a Game that you can play with your Controller!

If you've already completed the Game Controller 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: Test your controller

Let's build some quick test code to make sure our controller works.

 

Grab a repeat forever block from the Loops menu and connect it below the setup controller block. Then, grab an if do else block from the Logic menu and place it inside the repeat forever block.

 

Change the 0.5 on the repeat forever block to 0.1. Next, grab a read controller buttons block from the Sensing menu and place it into the repeat forever block.

 

Now, grab a was controller block from the Sensing menu and place it into the input of the if do else block. Drag out a turn pin block from the Chip menu and place it into the first do of the if do else block. Change the pin to 25 (LED).

 

Right-click the turn pin block and select duplicate. Move the new block into the else do part of the if do else block. Change it from ON to OFF:

Once your program is ready, click CONNECT and then click START. When your program is running, when you press the up button, the LED on the Pico will turn on, and when you let it go it will turn off. If your test code works, then go ahead and click STOP.

 

Delete the repeat forever block and all of the blocks inside of it by dragging it to the trash can.

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 9: Lots of Variables!

We are going to make a game that we can play using the Console.

 

Our game will be simple - we will be able to move our character around using the controller. The goal is to get the food, and there will be an enemy character that chases our character. That's it, but it will be a lot of fun to play!

 

Our game will have to keep track of the positions for 3 things - our character, the food, and the enemy. Each character will have a horizontal position (left-right), which we will call x, and a vertical position (up-down), which we will call y. This means that we will need 6 variables to keep track of the positions of our 3 characters!

 

We will also need to keep track of the score for the game. Our character will get one point every time they get to the food, and they will lose one point if the enemy catches them.

 

Let's create all 7 variables. Click the Variables menu, and then click the Create variable... button. You'll do this 7 times, and make each of the following variables:

  • player x
  • player y
  • food x
  • food y
  • enemy x
  • enemy y
  • score

Once you have created all of your variables, click NEXT.

Step 10: Set the Values

We don't want our enemy to start off on top of our player, right? So let's set the starting places.

Click the Variables menu and grab the set block. Connect it below the setup controller block. Make sure the variable in that block is set to score. Grab a 0 block from the Values menu and place it into the set score block.

 

Right-click the set score block and select duplicate. Place the new block right below the set score block. Change the variable in the new block to player x. Do this again and change the new block's variable to player y. Repeat this two more times and set the two new blocks to enemy x and enemy y. Finally, change the value in the enemy x block from 0 to 15, and change the value in the enemy y block from 0 to 9:

Now where should the food be? We kind of want it to change up so we can chase it right? Drag out a set block from the Variables menu and connect it to the end of your program. Change the variable in the block to food x. Do this again and change the variable on the new block to food y.

 

Next, grab a random integer block from the Values menu and place it into the set food x block. Change the 1 to 0, and change the 100 to 15. Grab another random integer block and place it into the set food y block. Change the 1 to 0, and change the 100 to 9:

Click NEXT.

Step 11: The Game Loop

The code for almost every game uses a loop. Inside of the loop, the game's code will usually call a few functions. Usually, the loop calls functions like this:

  • read the inputs
  • move the characters
  • check for collisions or hits
  • check for scoring
  • display the characters and score
  • repeat!

Makes sense, right? That means we need to start with a loop. Drag out a repeat forever block and connect it to the end of the program. Then, grab a to do something block from the Functions menu and place it off to the right side of your program. Change the name of your new function to read controller:

Grab a read controller buttons from the Sensing menu and place it into the to read controller block. Then, grab an if do block form the Logic menu and place it below the read controller buttons block. Next, grab a was controller block from the Sensing menu and place it in the input of the if do block:

Click NEXT.

Step 12: Console Positions

Before we add more blocks, it's important to understand how the console works. Normally, when you use a print block, it sends letters or numbers to the console. But did you know that you can tell the console where you want those letters and numbers printed?

 

Look carefully at the image below. The console has columns and rows. We sometimes refer to the column as how far left or right a letter or number in the console is, and we sometimes say that is the letter or number's x position.

 

The console also has rows, referring to how far up or down a letter or number is in the console. This is also called the y position.

 

When we write the position of a letter or number, we write is as two numbers lie this: "(x,y)"

Console positions start in the top-left corner and increase as you move right and down.

 

Click NEXT.

Step 13: Reading the Controller Buttons

Now we want our controller to actually control our player's movements. Let's set that up.

 

When the up button gets pressed, we want the player character to move up 1 position. This means that we need the player y variable to go down by 1. We also want to make sure that the player y variable never goes below 0 or above 9 - so that it stays inside of the console. We will do this by subtracting 1 from the variable and using a constrain block to keep the value from going out-of-bounds.

 

Drag out a set block from the Variables menu and place it into the if do block. Change the variable to player y. Next, grab a constrain block from the Logic menu and place it in the input of the set player y block. Then, grab a _ + _ block and place it into the first input of the constrain block. Grab a player y block from the Variables menu and place it into the left side of the _ + _ block. Grab a 0 block from the Values menu and place it into the right side of the _ + _ block, and change the 0 to a 1. Next, change the + (plus) to a - (minus). Finally, change the 50 in the constrain block to 9:

 

Now, we can just copy our if do block for the other 3 buttons and make a few changes!

 

Right-click the if do block and select duplicate. Place the new if do block under the first one. Next, change the up button to down button, and change the - (minus) to a + (plus).

 

Then, duplicate the first if do block again and attach it below the last if do block. This time, change the up button to left button, change the two player y variables to player x, and change the 9 to 15.

 

Finally, duplicate the last if do block and attach the new block below the last if do block. Change the left button to right button and change the - (minus) to a + (plus):

Right-click the to read controller block and select Collapse Block. Then, grab a read controller block from the Functions menu and place it into the repeat forever block:

Click NEXT.



Step 14: Move the Enemy

Right now, our enemy's just standing there. Not a great foe, right? Let's write a function to make it chase us!

Grab a to do something from the Functions menu and place it off to the right side of your program. Change the name of the function to "move enemy". Drag a if _ = _ do block out of the Logic menu and place it in the to move enemy block.

 

Click the Blue Gear Icon. In the mini-workspace that opens up, grab the else if block and connect it below the if block to add an else if. Then, click the Blue Gear Icon to close the mini-workspace.

 

Grab an enemy x block from the Variables and place it on the left side of the _ = _ block. Then, grab a player x block from the Variables and place it on the right side of the _ = _ block. Change the = (equals) to a < (less than).

 

Finally, grab a change block from the Variables menu and place it into the first do of the if do block. Change the variable to enemy x, and change the 1 to 0.5:

 

Why 0.5? We want the enemy to move more slowly than the player can. If you want to make the game more challenging, you could increase this to 0.75 or even 1; or make it slightly less than 0.5 to make the game easier.

 

Right-click the _ < _ block and select duplicate. Place the new block into the else if input. Change the < (less than) to > (greater than).

 

Right-click the change enemy x block and duplicate it. Place the new block into the other do of the if do else if block. Change the 0.5 to -0.5 (negative):

Right-click the if do else if block and duplicate it. Place the new block right after the first if do else if block. Change all of the enemy x variables in the new block to enemy y, and change all of the player x variables in the new block to player y:

Right-click the to move enemy block and select Collapse Block. Then, grab a move enemy block from the Functions menu and place it into the repeat forever block:

Click NEXT.

Step 15: Did the Player Get Caught?

Our next function needs to check if the Enemy caught the player. If the enemy's position is the same as the player's position, then that means the player got caught and loses a point. After the player gets caught, we also want to reset the game - so let's start there.

 

Grab a to do something from the Functions menu and place it off to the right side of your program. Change the name of the function to "set up game".

 

Grab the repeat forever block and disconnect it from the program by dragging it straight down a little. Next, grab the set player x right after the set score block near the beginning of your program and place it into the to set up game block:

Next, drag out a set up game block from the Functions menu and connect it below the setup controller block. Then, grab the repeat forever block you moved earlier and connect it below the set up game block. Finally, right-click the to set up game block and select Collapse Block:

Grab a to do something from the Functions menu and place it off to the right side of your program. Change the name of the function to "check enemy". Then, grab a check enemy block from the Functions menu and place it into the repeat forever block:

Click NEXT.

Step 16: Enemy Check

Grab an if do block from the Logic menu and place it into the to check enemy block. Next, grab an and block and place it into the input of the if do block. Then, grab a _ = _ block from the Logic menu and place it into the left side of the and block.

 

Grab a player x block from the Variables menu and place it into one of the inputs of the _ = _ block. Then, grab a round block from the Values menu and place it into the other side of the _ = _ block. Change the round to round down. Finally, grab a enemy x block from the Variables menu and place it into the input of the round down block:

Right-click the _ = _ block and select duplicate. Place the new blocks into the other side of the and block. Change player x to player y and enemy x to enemy y in the new blocks.

 

Grab a change block from the Variables menu and place it into the if do block. Make sure it is set to the score variable and then change the 1 to a -1 (negative). Finally, grab a set up game block from the functions menu and connect it below the change score block:

Right-click the to check enemy block and select Collapse Block. Then, click NEXT.

Step 17: Nom Nom Nom

Now our game needs a function that checks to see if the player made it to the food.

 

If the player's position is the same as the food's position, then that means the player got the food and gets a point. After the player gets the food, we also want to reset the game.

 

Grab a to do something from the Functions menu and place it off to the right side of your program. Change the name of the function to "check food". Then, grab a check food block from the Functions menu and place it into the repeat forever block:

Grab an if do block from the Logic menu and place it into the to check food block. Next, grab an and block and place it into the input of the if do block. Then, grab a _ = _ block from the Logic menu and place it into the left side of the and block.

 

Grab a player x block from the Variables menu and place it into one of the inputs of the _ = _ block. Then, grab a food x block from the Variables menu and place it into the other side of the _ = _ block.

 

Right-click the _ = _ block and select duplicate. Place the new blocks into the other side of the and block. Change player x to player y and food x to food y in the new blocks:

Grab a change block from the Variables menu and place it into the if do block. Make sure it is set to the score variable and then change the 1 to a -1 (negative). Finally, grab a set up game block from the functions menu and connect it below the change score block:

Right-click the to check food block and select Collapse Block. Then, click NEXT.

Step 18: Print it Out

We only have one function left, and that's the function that prints everything out to the console.

 

Grab a to do something from the Functions menu and place it off to the right side of your program. Change the name of the function to "print game". Then, grab a print game block from the Functions menu and place it into the repeat forever block:

The first thing our function needs to do is clear the console of anything that was printed in it from before. Grab a console clear block from the Chip menu and place it in the to print game block.

 

Next, we need to print out each character. We can do this by setting the cursor position first, and then printing a letter for each character.

 

Grab a console set cursor position block and connect it below the console clear block. Delete the two 0 blocks in the console set cursor position block by dragging them to the trash can. Grab a player x block from the Variables menu and place it into the x input of the console set cursor block. Then grab a player y block and place it into the y input. Next, grab a print without new line block from the Chip menu and connect it below the console set cursor block. Finally, type an O into the "_" block:

What's the difference between a print block and a print without new line block? The normal print block sends letters and numbers to the console, and then it sends a Return/Enter right after. When we use the console set cursor position block, that Return/Enter can mess up the console, so that's why we want to use a print without new line block instead.

 

Let's print the food next. Right-click and duplicate the console set cursor block and connect it below the print without new line block. Change the player x and player y to food x and food y. Then, right-click and duplicate the print without new line block and connect it below the console set cursor block. Finally, change the O to a *:

Click NEXT.

Step 19: Print the Enemy

All that is left is printing the enemy. Right-click and duplicate the console set cursor block and connect it below the last print without new line block.

 

Delete the food x and food y by dragging them to the trash can. Then, right-click and duplicate the print without new line block and connect it below the last console set cursor block. Change the * to an X:

Grab a round block from the Values menu and place it into the first input of the last console set cursor block. Change the round to round down. Do this again for the other input.

 

Grab an enemy x block from the Variables menu and place it into the first round down block. Then place an enemy y block into the second round down block:

And finally, let's print our score!

 

Grab a console set cursor block from the Chip menu and connect it below the last print without new line block. Change the first 0 to 18 and change the second 0 to 5. Then, grab a print without new line block from the Chip menu and place it below the last console set cursor block. Type "Score: " into the "_" block. Notice the extra space at the end of "Score: ". Then, grab another print without new line block from the Chip menu and place it below the last print without new line block. Delete the "_" block. Then, grab a score block from the Variables menu and place it into the print without new line block:

Right-click the to print game block and select Collapse Block. Then, click NEXT.

Step 20: Play your game!

Click CONNECT, and then click START. Look out! The Enemy is chasing your character! Use your controller to stay away from the Enemy and get to the Food!

 

How high of a score can you get?

 

When you are finished playing your game, go ahead and click STOP, and then click NEXT.