Thursday, September 10, 2009

Brico Geek Contest Entry

Well guys I didn't win the Brico Geek Contest, but I had fun working with the idea. I did make up a board layout, and parts list. I will sell those to anyone interested, if nothing else to pay for my time invested. The code is included after the split. I will even make up kits for someone if they want to buy one. I may even be so inclined as to build the whole thing for the right price.

For my contest entry I decided to do a Whack-A-Mole style game. I made a 8 LED field that based on the random number generator made one LED light up for a predetermined time frame. Each LED has a corresponding button that should be pushed when the LED is lit. The successful "hit" will give an increment in the score, and a failure will decrement the score based on the level of play attained so far. The game play is simple, and becomes a simple hand eye coordination practice. I doubt that the way it is set up anyone could really beat it all the way through, as the higher your level the quicker the "mole LED" changes positions, and at the fastest it is less than 50ms.

The final version of this project will have illuminated buttons, and some form of speaker for 8 bit glorious mono sound. The code for the game is as follows...

/* incldes tlc5940 library for the TI 16 LED Driver IC, Library by Alex Leone , 2009-02-03
Basic Pin setup:
------------
ARDUINO |
(analog pin 3)17|-> failureLedPin
(analog pin 2)16|-> successLedPin
(analog pin 1)15|-> button8
(analog pin 0)14|-> RandomSeed /input ---u----
13|-> SCLK (pin 25) OUT1 |1 28| OUT channel 0
12|-> button1 OUT2 |2 27|-> GND (VPRG)
11|-> SIN (pin 26) OUT3 |3 26|-> SIN (pin 11)
10|-> BLANK (pin 23) OUT4 |4 25|-> SCLK (pin 13)
9|-> XLAT (pin 24) . |5 24|-> XLAT (pin 9)
8|-> button2 . |6 23|-> BLANK (pin 10)
7|-> button3 . |7 22|-> GND
6|-> button4 . |8 21|-> VCC (+5V)
5|-> button5 . |9 20|-> 2K Resistor -> GND
4|-> button6 . |10 19|-> +5V (DCPRG)
3|-> GSCLK (pin 18) . |11 18|-> GSCLK (pin 3)
2|-> button7 . |12 17|-> SOUT
1| . |13 16|-> XERR
0| OUT14|14 15| OUT channel 15
------------ --------

- Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
(cathode) in OUT(0-15).
- +5V from Arduino -> TLC pin 21 and 19 (VCC and DCPRG)
- GND from Arduino -> TLC pin 22 and 27 (GND and VPRG)
- digital 3 -> TLC pin 18 (GSCLK)
- digital 9 -> TLC pin 24 (XLAT)
- digital 10 -> TLC pin 23 (BLANK)
- digital 11 -> TLC pin 26 (SIN)
- digital 13 -> TLC pin 25 (SCLK)
- The 2K resistor between TLC pin 20 and GND will let ~20mA through each
LED. To be precise, it's I = 39.06 / R (in ohms). This doesn't depend
on the LED driving voltage.
- (Optional): put a pull-up resistor (~10k) between +5V and BLANK so that
all the LEDs will turn off when the Arduino is reset.

If you are daisy-chaining more than one TLC, connect the SOUT of the first
TLC to the SIN of the next. All the other pins should just be connected
together:
BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
XLAT on Arduino -> XLAT of TLC1 -> XLAT of TLC2 -> ...
The one exception is that each TLC needs it's own resistor between pin 20
and GND.

This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
Do not use analogWrite(...) on these pins.

The buttons are 4 leg momentary buttons with a 1K ohm pull down resistor to ground, and +5V on the other side
The successLedPin and failureLedPin have 150 ohm resistors to limit the current draw, these should probably be 300 - 400 but these are what I had available.

The game is just like the original Whack-A-Mole you played at carnivals, and fairs, but the scoring mey be different. An LED Lights up and you hit the button that relates to it.
A successful hit will increment your score. for every 10 points you go up a level. For every 10 levels you go to the next level of difficulty.
for the first level of difficulty a miss-hit does not harm your score, but each level of difficulty added means more challenge, so a miss-hit on the 2nd difficulty makes your
score go down by 1, and on the 3rd level of difficulty your score goes down by 2 each miss-hit., and finally on the 4th level of difficulty you lose 3 points per miss-hit.

The speed increases as your levels go up, and each level of difficulty has a faster time delay as well, so at level 9 on the 3rd level of difficulty, your "moles" are screaming
fast.

The 5 LEDs attached to the IC that are not the moles are a score keeper for each hit. 4 yellow, and one green. If no LEDS for your score are on, then you have 0 points for
that level, if all 4 yellow LEDS are on you have 4 points, with the green one on you have 5 points plus the first ones (1 yellow and the green = 6, 2 yellow and the green = 7,
4 yellow and the green = 9). For any more score information that that use the Serial monitor from the arduino program on your computer.

The 2 LEDS attached to the analog i/o's are for success and failure on your button hits. A successful hit makes the orange LED on A2 light up, and a failure lights up a Red LED
on A3.

Game Interpretted to Arduino by Charles D. Stutzman Sr. 08/11/2009

*/

#include "Tlc5940.h"

#define button1 12
#define button2 8
#define button3 7
#define button4 6
#define button5 5
#define button6 4
#define button7 2
#define button8 15
#define statusLedPin 16
#define failureLedPin 17


int cheat = 0;

int buttonstate1;
int buttonstate2;
int buttonstate3;
int buttonstate4;
int buttonstate5;
int buttonstate6;
int buttonstate7;
int buttonstate8;

int ledPinstate1;
int ledPinstate2;
int ledPinstate3;
int ledPinstate4;
int ledPinstate5;
int ledPinstate6;
int ledPinstate7;
int ledPinstate8;

int mole;

int scoreCard = 0;
int level = 0;
int levelmultiplied;
int timesThrough = 0;
int timerMod = 20;

int buttonactive;
long randNumber;
long* sharerandNumber = &randNumber;

int statusLedState;
int* sharestatusLedState = &statusLedState;

int failureLedState;
int* sharedfailureLedState = &failureLedState;

int start = 0;


void setup()
{
/* Call Tlc.init() to setup the tlc.
You can optionally pass an initial PWM value (0 - 4095) for all channels.*/
Tlc.init(4095);
Serial.begin(9600);
randomSeed(analogRead(0));
pinMode(button1, INPUT);
pinMode(button2, INPUT);
pinMode(button3, INPUT);
pinMode(button4, INPUT);
pinMode(button5, INPUT);
pinMode(button6, INPUT);
pinMode(button7, INPUT);
pinMode(button8, INPUT);
pinMode(statusLedPin, OUTPUT);
pinMode(failureLedPin, OUTPUT);
}

void loop()
{
if (start == 0){
Tlc.clear();
blinkAllMoleLEDs();
blinkAllMoleLEDs();
start++;
}
scoreCard = scoreCard + cheat;
randNumber = random(0, 8);
*sharerandNumber = randNumber;
switch (randNumber){
case 0:
mole = button1;
break;
case 1:
mole = button2;
break;
case 2:
mole = button3;
break;
case 3:
mole = button4;
break;
case 4:
mole = button5;
break;
case 5:
mole = button6;
break;
case 6:
mole = button7;
break;
case 7:
mole = button8;
break;
}
levelmultiplied = level * 5;
switch (timesThrough){
case 0:
timerMod = 10;
break;
case 1:
timerMod = 7;
break;
case 2:
timerMod = 4;
break;
case 3:
timerMod = 1;
break;
}

buttonstate1 = LOW;
buttonstate2 = LOW;
buttonstate3 = LOW;
buttonstate4 = LOW;
buttonstate5 = LOW;
buttonstate6 = LOW;
buttonstate7 = LOW;
buttonstate8 = LOW;
for (int delaycounter = 55; delaycounter > levelmultiplied; delaycounter--) {
Tlc.set(randNumber, 2095);
Tlc.update();
if (buttonstate1 == LOW){
buttonstate1 = digitalRead(button1);
if (mole == button1){
if (buttonstate1 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button1){
if (buttonstate1 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate1 = HIGH;
if (mole == button1){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}
}


if (buttonstate2 == LOW){
buttonstate2 = digitalRead(button2);
if (mole == button2){
if (buttonstate2 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button2){
if (button2 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate2 = HIGH;
if (mole == button2){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}
}

if (buttonstate3 == LOW){
buttonstate3 = digitalRead(button3);
if (mole == button3){
if (buttonstate3 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button3){
if (buttonstate3 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate3 = HIGH;
if (mole == button3){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate4 == LOW){
buttonstate4 = digitalRead(button4);
if (mole == button4){
if (button4 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button4){
if (buttonstate4 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate4 = HIGH;
if (mole == button4){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate5 == LOW){
buttonstate5 = digitalRead(button5);
if (mole == button5){
if (buttonstate5 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button5){
if (buttonstate5 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate5 = HIGH;
if (mole == button5){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate6 == LOW){
buttonstate6 = digitalRead(button6);
if (mole == button6){
if (buttonstate6 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button6){
if (buttonstate6 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate6 = HIGH;
if (mole == button6){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate7 == LOW){
buttonstate7 = digitalRead(button7);
if (mole == button7){
if (buttonstate7 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button7){
if (buttonstate7 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate7 = HIGH;
if (mole == button7){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}

if (buttonstate8 == LOW){
buttonstate8 = digitalRead(button8);
if (mole == button8){
if (buttonstate8 == HIGH){
scoreCard++;
statusLedState = HIGH;
}
} else if (mole != button8){
if (buttonstate8 == HIGH){
scoreCard - timesThrough;
failureLedState = HIGH;
}
}
}else {
buttonstate8 = HIGH;
if (mole == button8){
statusLedState = HIGH;
}else {
failureLedState = HIGH;
}

}
digitalWrite(statusLedPin, statusLedState);
digitalWrite(failureLedPin, failureLedState);
Tlc.set(randNumber, 00);
Tlc.update();
if (level < 0){ level = 0; scoreCard = 0; } else { switch(scoreCard){ case 0: Tlc.set(8, 00); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 00); break; case 1: Tlc.set(8, 1500); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 00); break; case 2: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 00); break; case 3: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 00); Tlc.set(12, 00); break; case 4: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 1500); Tlc.set(12, 00); break; case 5: Tlc.set(8, 00); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 6: Tlc.set(8, 1500); Tlc.set(9, 00); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 7: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 00); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 8: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 00); Tlc.set(12, 2500); break; case 9: Tlc.set(8, 1500); Tlc.set(9, 1500); Tlc.set(10, 1500); Tlc.set(11, 1500); Tlc.set(12, 2500); break; } } Tlc.update(); delay(timerMod); if (scoreCard > 9){
level ++;
scoreCard = 0;
}
if (scoreCard < 0){ level --; scoreCard = 9; } statusLedState = LOW; failureLedState = LOW; Tlc.set(14,0000); Tlc.set(15,0000); Tlc.update(); } Serial.print(timesThrough); Serial.println(" is the current amount of times you have gone through all 10 levels."); Serial.print(level); Serial.println(" is the current level."); Serial.print(level); Serial.print(scoreCard); Serial.println(" is the current score."); delay(50); if (level > 9){
Tlc.clear();

for (int delaycounter = 0; delaycounter < 13; delaycounter++) { Tlc.set(delaycounter, 1500); Tlc.update(); delay(100); } Tlc.clear(); Tlc.update(); level = 0; timesThrough ++; } if (timesThrough > 3 ){
Serial.println("You are a god!!!!! No one can move that fast, or you cheated.");
timesThrough = 0;
level = 0;
Tlc.clear();

for (int delaycounter = 0; delaycounter < 13; delaycounter++) { Tlc.set(delaycounter, 1500); Tlc.update(); delay(100); } for (int delaycounter = 13; delaycounter > 1; delaycounter--) {
Tlc.set(delaycounter, 00);
Tlc.update();
delay(100);

}
blinkAllMoleLEDs();
blinkAllMoleLEDs();

}
}
void blinkAllMoleLEDs(){
Tlc.set(0, 1000);
Tlc.set(1, 1000);
Tlc.set(2, 1000);
Tlc.set(3, 1000);
Tlc.set(4, 1000);
Tlc.set(5, 1000);
Tlc.set(6, 1000);
Tlc.set(7, 1000);
Tlc.update();
delay(100);
Tlc.set(0, 00);
Tlc.set(1, 00);
Tlc.set(2, 00);
Tlc.set(3, 00);
Tlc.set(4, 00);
Tlc.set(5, 00);
Tlc.set(6, 00);
Tlc.set(7, 00);
Tlc.update();
delay(100);
Tlc.set(0, 1000);
Tlc.set(1, 1000);
Tlc.set(2, 1000);
Tlc.set(3, 1000);
Tlc.set(4, 1000);
Tlc.set(5, 1000);
Tlc.set(6, 1000);
Tlc.set(7, 1000);
Tlc.update();
delay(100);
Tlc.set(0, 00);
Tlc.set(1, 00);
Tlc.set(2, 00);
Tlc.set(3, 00);
Tlc.set(4, 00);
Tlc.set(5, 00);
Tlc.set(6, 00);
Tlc.set(7, 00);
Tlc.update();
delay(100);
Tlc.set(0, 1000);
Tlc.set(1, 1000);
Tlc.set(2, 1000);
Tlc.set(3, 1000);
Tlc.set(4, 1000);
Tlc.set(5, 1000);
Tlc.set(6, 1000);
Tlc.set(7, 1000);
Tlc.update();
delay(100);
Tlc.set(0, 00);
Tlc.set(1, 00);
Tlc.set(2, 00);
Tlc.set(3, 00);
Tlc.set(4, 00);
Tlc.set(5, 00);
Tlc.set(6, 00);
Tlc.set(7, 00);
Tlc.update();
delay(100);
Tlc.clear();
}

The cheat variable is there so you can debug the platform, and make sure the code works through the full game. I have pictures and video of the prototype setup, and I will post them later.

Article continued after the jump...