Introduction: Left or Right? Memory Game

Unfortunately I don't have any pictures because I have already undone the whole thing,

but basically we'll be making a little memory game that makes you remember 7 times a random Left or Right. Using 2 infrared motion sensors the Arduino will look if you raised the corresponding hand. If you got it right all 7 times, the game is finished. Otherwise, it resets automatically after telling you what you did wrong.

You will need:

  • 1 Arduino UNO (and of course a Arduino to USB cable)
  • 2 infrared motion sensors
  • LCD Display
  • 9 volt adapter
  • solder and some soldering iron.
  • AC '97 connector and some smaller connectors (see pictures in next step)
  • 1 small button
  • 10K Ohm resistor
  • 1 large breadboard
  • 2 long RED wires, 2 long BLACK wires, 1 long GREEN wire and 1 long BLUE wire. (between 30-40 cm)
  • smaller wires; I recommend 2 red, 1 black, 2 yellow, 1 blue, 1 brown and 1 gray wire.
    This is to remember what you're doing by color.
  • 1 painting canvas: 120cm by 40cm.
  • duct tape
  • 1 Stanley knife (crafting knife)

Let's set up our hardware.

Step 1: Setting Up Your Hardware a Bit More Conveniently

Our sensors and LCD display have to be connected to our breadboard.

For convenience, I soldered(?) some of the wires to connectors.

Let's take our LCD, the ac '97 connector, 2 of the 2 piece connectors and the following SMALL wires:

  • 1 red
  • 1 black
  • 1 grey
  • 1 brown.

We'll be using red wires for everything that has to got to the PLUS. Black wires for the MINUS or GND. (ground).

Now we have to be careful; the wires need to be sticked in according to our LCD. Do you see the 4 metal thingies poking out? Next to them are the following letters:
GND -----

VCC -----

SDA -----

SCL -----

You'll want to attach your wires to the AC connector so that it will attached to those corresponding names.
GND is black, VCC red, SDA grey, and SCL brown.

Then, solder the black and red wire next to each other in a 2 piece connector,
and do the same to the gray and brown wires.

We'll move on to the motion sensor. This one has 3 pins; a MIN, PLUS and the one that gives back the signal to your Arduino. Now we'll be using the long wires: a red and black one for each of the sensors, than for consistency the bLue one for Left and the gReen one for Right.

when attaching the wires, make sure the sensor is 'sensing' away from you with the pins on the top.

Then, from left to right, attach the wires like this: BLACK, GREEN for Right, BLUE for LEFT, and the RED one.

These ends all get their own little connector.
It might also be convenient to twirl the wires a bit so they stay together just enough.

Let's start attaching everything to our Arduino using our breadboard!

Step 2: Attaching Everything to the Arduino Using Our Breadboard

To make sure everything is going to fit into the canvas later on,
lay your LCD on top of the short side of the breadboard. Your Arduino goes on the left-bottom side of the breadboard.


Let's begin by attaching our LCD.
Attach the red and black into the breadboard PLUS and MINUS (remember? Red is PLUS, Black is MINUS).

the wire that is attached on your LCD to "SDA" (in my case, that is the gray wire, but make sure what it is before poking it into your Arduino!) goes all the way to your Arduino in the matching "SDA" pin.

The brown wire - or the SCL wire, goes to the SCL pin on your Arduino.

---------------------------------------------------------- Left and Right Motion Sensor

For both sensors, poke the red and black wires into plus and min. Make sure you're only using one side of your breadboard! The blue (LEFT) wire goes into pin 2. The green (RIGHT) into pin 3.

---------------------------------------------------------- Reset Button

For resetting the game, we'll also attach a simple button. Because we're already using lots of red and blue wires, I used a different color code. We'll use the 2 yellow wires and 1 blue wire.

To make this button work properly, we'll use a pull-up resistor. The resistor is 10K Ohm.

make sure the button is attached to the breadboard near the middle line, so you have enough space for the wires. Also, if your button behaves weird, turn it 90 degrees. (in my case, sometimes it did the exact opposite. It had to do with the in and output).

Attach 1 yellow wire at one end of the button, the other one at the other end. The wire at the plus side of the button goes directly into the PLUS of the breadboard. The other yellow wire goes to pin 5. Here's where the resistor comes in: right in between the button and the wire going to pin 3. The resistor goes sideways into a random slot on your breadboard. In the same row, attach the blue wire and make it go to the MINUS on your breadboard.

Last but not least: use 1 red wire that goes from the breadboard PLUS to the Arduino 5V pin. Attach 1 black wire from the MINUS on the breadboard to the GND (next to the 5v pin!). Now your Breadboard and other hardware is attached to the Arduino.

Let's get into the software!

Step 3: Software: What Do We Want and What Do We Need? Setup & Loop

First of all, you need the LiquidCrystal_I2C Library to get your LCD working. Import via Sketch > Include Library > Manage Libraries and search for 'LiquidCrystal I2C' and then choose version 1.1.2 from "Frank de Brabander">. Also Include it.

Now, let's define our sensors and button.

We'll also need to define a recovery time to give our sensor time between every move. Note that some names are in Dutch, but since they're variables you can give them your own names.

I've set the recovery time to 5 seconds (5000 milliseconds).
Defining the needed variables:

Changing the MaxArray will result into more numbers that you'll need to remember in game.
iCounter will count later on in which turn you are. ButtonState will be used for resetting. Then there is LS for LeftSensor and RS for RightSensor.

----------------------------------------------------------------- Setup

In our setup, we'll start the LCD, set our pins and show an introductory text.
Let's also reference to a function we'll make later on; a Reset the Game function, that will play whenever you make a mistake or when you push the button.
In the setup, this will actually be more of a 'start the game', but since we'll be using it mostly as a reset, we'll call it Reset.

LCD.begin tells us the amount of colums, rows and then something specific that the reference told me I had to put in. We'll turn on the backlight, and set our cursor to the upperleft of our screen.

We'll set our pins to the values in the #define and tell them that we want Input from them!
To be sure, we clear the screen, print after a space "Left Right Game", let it show for 2 seconds and say Go.

These functions are pretty self explanatory so I won't pay more attention to them further on.
Then we'll call the ResetGame function that we'll be writing in the next sections.

----------------------------------------------------------------- Loop

In our loop, a couple things have to happen: every turn our random value of the Array of left's and right's has to be checked with what we actually did. This code is a little bit more demanding if you're a beginning programmer but I'll try to explain. (here's all the code in our loop!)

The LRArray has 7 values in it: they're either a 0 or a 1. We'll be defining later on that 0 stands for Left, 1 means Right. Our iCounter counts every turn. The DetectMove function will see which hand we raised. If our left sensor senses us, the function DetectMove will give us back a 0.
Let's give you an example.
Let's say we're on turn 3. Then iCounter is 2. Why? Because an Array starts counting at 0. So our first turn is 0, our second is 1 and our third turn is 2.

then the computer will do:

if (LRArray[2] != DetectMove()).

But then you probably think: didn't you say that DetectMove only gives you back a 0 or 1? That's right!

The 2 is our turn. It simply tells us which variable within our Array we should be going to test.
Let's say that on turn 3 (so iCounter = 2), you have to raise your Right hand; so that's 1. But, you forgot and raised your left hand!

if (LRArray[ place 2, which value is 1] != 0 (Because DetectMove detected you raised left).

1 is not (!=) 0. So we'll Display and Error and Reset the Game.
Note those are both functions we haven't written yet.

means you haven't made a mistake (yet), so we'll go to the next turn. (++ means increment by 1.)

then last: we'll ask:

if our counter has reached 7 and thus is the same value as our MaxArray (remember, counting starts at 0 so we already had 7 turns!)

You apparantly haven't made any mistakes and you'll get a very warm congratulations. After that, the game will reset.

Let's start writing our functions!

Step 4: Adding in Our Functions: Starting/resetting a Game Ad Filling Our Array With Random Left's and Right's

-------------------------------------------- ResetGame(void)

Whoa! That's a lot. Let's go through this!

Whenever we start a game, we want to start at the first turn. So, iCounter becomes 0.
Then we want to Create or Fill our LRArray with random Left's and Right's. We will be making a function for this later on. The next part is just some text.

Then we get a for loop. We want to print out all our letters in the LRArray. We'll start at 0 using int i = 0.
i has to go up by one until it reaches the value of MaxArray: then it has printed all letters. (namely, 7!).
Once again, after executing this bit of code, i has to go up using i++.
We'll use the j to print our letters correct on the screen, next to each other with 1 space.
See the lcd.setCursor(j,2); - everytime j will increment by 2 so the letters are printed neatly.

If this is done, we want to give to user a bit of time to remember the L's and R's. Set your delay to 4000 milliseconds.

Then Clear the screen, print Go! wait 1 second. This function is finished.
Let's go to the CreateLRArray!

-------------------------------------------- int CreateLRArray()

randomSeed is there to make sure your first random number is really random.
once again, until we reach the amount we need, we want to fill our LRArray.
LRArray[0] = either 0 or 1, that is random.

LRArray[1] = either 0 or 1

Continuing all the way until i reaches maxArray.

Once again, don't forget that Left is 0, Right is 1!

Step 5: Adding in Our Functions: Detecting What You Did!

-------------------------------- int DetectMove(void)

We start with a Do-While loop, because this always has to run at least once before it is checked if it should run (again).

LS is filled with a HIGH or LOW. High is TRUE, Low is FALSE. Or, High = 1, Low = 0. This is a boolean. It's on, or it's off. The sensor will be on HIGH when he senses something. We'll do a mini-delay in between to make sure Left and Right can't be sensed at the same time (in which case both would be HIGH and thus crashing our program).
We'll also do this for our button: We read the button. When we press it, it is HIGH --> it is true.
if (buttonState) means that we're asking: is our Button true? (is it high?). Then we reset the game because someone wants to start over.
We will continue this block of code as long as both the LS and the RS haven't sensed anything.

If it does have, we'll wait for 5 seconds. See the i--? This means the i goes down. We'll print that the player has to wait. We're doing this so the player has some time in between turns.

Then we'll print Go again. Don't worry about writing go even if the turn has gone wrong; that will be checked in a matter of such milliseconds that you'll hardly see the Go at all if you made a mistake.
Now, our function was checked in our loop, remember? So if LS is true --> return 0. For right, return 1.

Now Our game works. Except, the user doesn't really know yet if he did well or not. We'll make two last functions: 1 displaying a congratulations text and one displaying the error.

Step 6: Adding in Our Functions: Response to the Player

------------------------------------------ void DisplayMadeAnError()

"You made a mistake" printed out. Then we'll check what the wrong was; if the LRArray's value was 0 (he needed a Left), that means you raised Right. So, print "You should have raised left".

In the else, it means the opposite.

------------------------------------------ void DisplayWellDone()

Should be self-explanatory! :)

Now our Arduino should work.

However, you might notice that

  1. It's not very pretty with all those wires
  2. Even though you're sitting still and in the middle, the sensors are picking up your body heat.

The sensors do not only sense what is right in front of them. Also, what is next or diagonal to them.
We're going to fix this using paper and we're going to hand our screen and sensors in canvas.

Step 7: Making It Pretty!

Get your Stanley knife out, your canvas and measure your lcd Screen.

We're going to cut in the middle of our canvas, before the woorden bar (make sure the canvas' long side is horizontal). ONLY CUT THE CANVAS! The wooden bar will keep our screen in place.

Once you cut it out so that the screen pokes through the canvas, but the green board attached to it is still behind the canvas, you can start duct taping your Arduino and breadboard in place. Try to keep everything neat. It helps to also duct tape some of the wires.

Cut 2 holes a good distance away from each other; these are for your sensors. Once again, make sure to measure the radius of your sensors before cutting, you don't want to cut too much. (Your sensor will fall through).

This is why you need the adapter: Since you uploaded your program onto your Arduino, we'll stop using the USB cable.

Be creative and make sure everything still works. Then you are done! :D

Hope you enjoy!