The Shrimp and Arduino

The Shrimp
circuit is an Arduino Uno substitute with a component cost of around one tenth the price of official Arduino boards. 

You can hand-make the circuit on breadboard or stripboard, learning about the components as you go, and remix the circuit freely for your needs.

Karate Game Mk2

posted 3 Dec 2017, 10:53 by Andy Lakin-Hall   [ updated 13 Dec 2017, 13:09 ]

Now I have a 3D printer, I thought I’d have a go at rebuilding the handheld karate game with a new smaller case. 

Case Design

I have designed the box shape in Tinkercad. It has two sections that fit together snugly. This is an early prototype for the box. I printed myself a dummy Arduino and PP3 battery that I could use for fitting without damaging anything. 

 

The lower section originally included a battery clip I downloaded from Thingiverse, but the clip part kept snapping off too easily. I redesigned the lower part to have a bulkhead to hold the battery in place instead.

I really want to have a 3D modelled character on the top of the box, and I want the box to be smaller to fit better in the hand. I designed the character in TinkerCAD using a flat design in Inkscape as a guide.

 


Tinkercad


The karate guy on the front fitted around the switches and LEDs without needing adjustment.

When I tried to print the top of the box with the character in place, the result was not great. I don't have a heated bed on the printer, so the lower layers of the print became warped, meaning the lid wouldn't fit on the box. I could print it upside down so the lid fitted, but the top surface of the box and character became really scraggy. In the end I printed the lid and character separately.

I have smoothed and painted the character with acrylic paint, and then sealed it with several coats of varnish to give it some protection from wear.

Circuit Design

With the original version, I made the circuit with stripboard. This time I wanted to make a proper etched board. The circuit board will fit in the lid and directly support the LEDs and switches on the front panel. This give me much more room than the proto-board directly on the Arduino, so I have included the 220R resistors for the LEDs and the 10K pull-down resistors for all of the switches directly on the circuit board.

Here's the standard circuit for connecting a switch.

See https://www.arduino.cc/en/Tutorial/Button

I haven’t etched my own circuit boards for years or more! The last time I used rub-down transfers and a Dalo etch-resist pen. These days there are more sophisticated ways of doing it. The method I want to try is simple toner transfer from a laser printer page.

I exported an SVG of the lid I’d designed in Tinkercad, and imported that into Inkscape. This meant I was able to build an accurate 2D virtual model of where all the components should fit in the front panel, and where I needed to have copper tracks on the circuit board. 

I was able to position all the components on one layer of the drawing, and then draw the connections between each component and another layer. Once all the connections were in place, I went back and filled in any large areas of copper, so that all that needed etching away was space between the tracks.

I printed the circuit onto paper to gauge the size of copper board to cut. I popped to Maplin and grabbed a bit of copper board for a couple of pounds. This gave me enough for three goes at making a board.

I cut off a section of board to fit the circuit design, and then printed the circuit in reverse onto ordinary copier paper. I cleaned the board with fine abrasive and then cleaned off all the grease and fingerprints with nail-polish remover.

With the board clean, I placed the reversed print face-down against the copper and held it in place with a little tape. I used a hot iron and a sheet of baking parchment to press the design firmly against the copper. I was able to check the transfer has darken place by peeking at one corner. The board was very hot, so I had to be careful not to get a burn. 

When I was confident that the toner transfer had taken place, I then had to dissolve away the paper. The recommendation was to do this with alcohol. I didn’t have isopropanol, so I tried vodka instead; which worked quite well.

With the design transferred to the board, it was ready for etching. I bought a small bottle of ferric chloride etchant from Maplin and a flat-bottomed plastic container from Poundland. The board was immersed in the etching solution and gently agitated until the exposed copper was dissolved away. This took about 20 minutes in all. I washed off the board in a large bucket of clean water and then soaked it in a bath of nail-polish remover to help dissolve away the toner. The rest of the ferric chloride went safely back in the bottle. The nail polish remover didn’t do a great job of removing the toner, but a quick polish with a fine abrasive block cleaned everything up.

There are a couple of tracks that look like they need separating, and I will test everything with my continuity tester to identify any short circuits before drilling the holes.

First assembly

Here is the circuit board fitted in place and connected to the OrangePip.

Some of the fly-leads to the OrangePip are slightly loose, so I will need to upgrade them to improve the connection. I uploaded the software I previously created for the game into the OrangePip and powered it with a PP3

All the LEDs work, the toggle switches and sound too, but the start button doesn't work because I made a mistake on the circuit board and forgot the biasing resistor. I'll redesign the PCB for the next iteration, but for this one I will try to put in some fly leads to work round the problem.

Karate Handheld Game Complete

posted 4 Dec 2016, 12:41 by Andy Lakin-Hall   [ updated 10 Dec 2016, 05:10 ]

A little while ago I partially completed the construction of my first serious Arduino project - to build a handheld electronic game like one I had when I was a kid.

This was Black Belt, by Action GT. It was brilliant. The LEDs lit up to show the attacks. You moved the arms and legs on the little man to block the attacks. The sounds were little synthesised screams, and when you missed an attack it laughed at you, and then returned your score by flashing the lights.

I remember it fitted neatly into my blazer pocket, and playing with it on the bus and on the walk to school. I loved it.

Sadly it started to malfunction. The contacts beneath the arms became worn away, and eventually the game became useless. (Sad face)

Fast forward several decades, and I start to find out about programmable microcontrollers, including Arduino. Eventually I learned enough about Arduino to attempt building my own version of Black Belt.


If you trawl back through this blog, you'll see all the steps in the build for this project. But this is the last. It's taken just under a year to complete the project. I was introduced to the Orange Pip Arduino Clone at the BETT exhibition in January 2016 and now it's early December.

I'm so glad I kept a blog of what I did. I've not a had a chance to fiddle with this for a long time, so I've forgotten everything about the project. I've got my first RaspberryJam event as an exhibitor next weekend, and I've got a few days free to go through my bits and pieces. I'd been meaning to tidy up the front panel properly. It's just a laser print with a fronting of clear sticky plastic. I'm quite pleased with the outcome.The insert I had previously made looked rather tatty where I'd bodged the mounting holes, and it looked grotty behind the box lid. 

The box itself is a bit bigger than I had originally planned, but this is what I could find in the local Pound Shop, and it does open up easily to see all the electronics inside.

Okay, if I had access to a 3D printer, I'd have made my own case, and made movable arms or something. But I'm still pleased with what I've made. Really happy.

Update - Little Tune at the start

I decided to add a little tune that will play when the start button is pressed.

I used Scratch to compose the sequence of tones - E, D, B, D, E, E, D, E. It sounds faintly oriental.

I found an Arduino reference that converts notes to the number codes required;

Note Code
B 123
D 294
E 330

Then using other sounds I've previously used in the game, I created the following function;

// play a tune

void play_tune() {
  tone(3, 330, 250); //E
  delay(100);
  tone(3, 294, 250); //D
  delay(100);
  tone(3, 123, 250); //B
  delay(100);
  tone(3, 294, 250); //D
  delay(100);
  tone(3, 330, 250); //E
  delay(100);
  tone(3, 330, 250); //E
  delay(100);
  tone(3, 294, 250); //D
  delay(100);
  tone(3, 330, 500); //E
  delay(1000);
}

I included the delay(1000); so there'd be a second delay after the tune plays before the game starts.

Then I hunted through the main loop until I found the section that detects when the red button is pressed;

    //The BUTTON has been pressed
    //Start the game
    GameOn = 1;
    Score = 0;
    interval = 3000;
    lastMillis = millis();
    play_tune();
    displayBinary(random(14)+1);  //set the LEDs to a random number

The command play_tune(); fits in just before the first random number displayed on the LEDs.

Game in Action

Here's a video of my game working.


Nunchuck Labyrinth Game Project

posted 30 Nov 2016, 02:22 by Andy Lakin-Hall   [ updated 30 Nov 2016, 02:27 ]

Now I know how to read data from the Wii Nunchuck, I thought I would try a (hopefully) simpler project that uses the X,Y control.

Labyrinth Game
I've already got one servo beng steered by the nunchuck, so why not two? I could use two servos to twist the knobs of a Labyrinth game - or at least, I hope I can. I need to check the Labyrinth knobs don't need too much force.
  1. Fix a pair of servos to the knobs of a Labyrinth game.
  2. Test the servo movements with my RC servo controller.
  3. Link both servos to Arduino Uno with Wii Nunchuck connected.
  4. Code so that moving the nunchuck rotates the servos.

Ta daa!

Now the really exciting bit.

It turns out that a Wii Balance board can also be read by an Arduino with a Bluetooth connection. So step 5 would be to control the Labyrinth by Wii Fit board.

I definitely don't now how to do that yet. But it sounds promising.


Pass a message to the 8x8 Matrix

posted 21 Aug 2016, 04:52 by Andy Lakin-Hall   [ updated 21 Aug 2016, 04:55 ]

I've been tinkering around, trying to learn how to get the 8x8 matrix to display a message. It's taken the whole morning to get right, but here is the working code, posted below.

The difficulty I was having was with the way Arduino code handles strings.

First, the string to hold the input typed in the serial monitor has to be defined with the line

String inString = "";    // string to hold input

Next, the function to write the message to the8x8 matrix has to have a parameter included in it's definition;

void matrix_write(String my_String) {

Then the line that calls the write to matrix function must include the string value defined at the start.

matrix_write(inString);

There is a limit to what you can type in which if you exceed the number of characters the thing goes wrong. I've not worked out how many characters this is yet.


The Code

/*************************************************** 
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED Matrix backpacks 
  ----> http://www.adafruit.com/products/872
  ----> http://www.adafruit.com/products/871
  ----> http://www.adafruit.com/products/870

  These displays use I2C to communicate, 2 pins are required to 
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

Adafruit_8x8matrix matrix = Adafruit_8x8matrix();
String inString = "";    // string to hold input

void setup() {
  Serial.begin(9600);
  Serial.println("8x8 LED Matrix Test");
  Serial.println("Type something to send to the matrix");
  
  matrix.begin(0x70);  // pass in the address

  smile();
  wink();
  smile();
}

static const uint8_t PROGMEM
  smile_bmp[] =
  { B00111100,
    B01000010,
    B10100101,
    B10000001,
    B10100101,
    B10011001,
    B01000010,
    B00111100 },

  wink_bmp[] =
  { B00111100,
    B01000010,
    B10000101,
    B10000001,
    B10100101,
    B10011001,
    B01000010,
    B00111100 };

void loop() {

    // Read serial input:
  while (Serial.available() > 0) {
    int inChar = Serial.read();
    inString += (char)inChar;
    
    // if you get a newline, print the string,
    // then the string's value:
    if (inChar == '\n') {
      matrix_write(inString);
      
      // clear the string for new input:
      inString = "";
        
    }
  }
  

}

void matrix_write(String my_String) {
      Serial.print("My String: ");
      Serial.println(my_String);
      
      my_String = String(" " + my_String);  //add a space in front of my string so it scrolls from the right edge correctly
      int howLong = my_String.length();     //find out how long my string is
      
    matrix.setTextSize(1);
    matrix.setTextWrap(false);  // we dont want text to wrap so it scrolls nicely
    matrix.setTextColor(LED_ON);
    for (int8_t x=0; x>=-6*howLong; x--) {    //multiply the length by -6 cos each character is 5 pixels plus a gap
      matrix.clear();
      matrix.setCursor(x,0);
      matrix.print(my_String);
      matrix.writeDisplay();
      delay(100);
    }
    smile();
    wink();
    smile();
}

void smile(){
    matrix.clear();
    matrix.drawBitmap(0, 0, smile_bmp, 8, 8, LED_ON);
    matrix.writeDisplay();
    delay(500);
}

void wink(){
    matrix.clear();
    matrix.drawBitmap(0, 0, wink_bmp, 8, 8, LED_ON);
    matrix.writeDisplay();
    delay(500);
}


Wii Nunchuck Tilt Sensing

posted 20 Aug 2016, 05:18 by Andy Lakin-Hall

After succeeding in sensing the Wii Nunchuck joystick to drive the servo, the next step is to detect the tilt.

I had to take the Nunchuck apart so I could get the orientation of the sensor board right, but here is a video of the servo and matrix display reacting to the tilt, either up or down.

As long as the board is aligned correctly, the arduino can sense whether it's upright or horizontal. There's a lot of wobbles in the data, so I needed to set a wide range of numbers which count as Up or Down, but it works in principle.


The Code

/*************************************************** 
  Display Up, Centre or Down on Adafruit 8x8 matrix
  and move a servo
  depending on the data from a Wii Nunchuck
 ****************************************************/

#include <Wire.h>
#include <Servo.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

Adafruit_8x8matrix matrix = Adafruit_8x8matrix();

Servo servoOnPin9;         // Define the servo

static uint8_t nunchuck_buf[6];   // array to store nunchuck data,
static const uint8_t PROGMEM
  smile_bmp[] =
  { B00111100,
    B01000010,
    B10100101,
    B10000001,
    B10100101,
    B10011001,
    B01000010,
    B00111100 },
    
  arrowUp_bmp[] =
  { B00011000,
    B00111100,
    B01111110,
    B11111111,
    B00011000,
    B00011000,
    B00011000,
    B00011000 },
    
  arrowDown_bmp[] =
  { B00011000,
    B00011000,
    B00011000,
    B00011000,
    B11111111,
    B01111110,
    B00111100,
    B00011000 },
    
  centre_bmp[] =
  { B00111100,
    B01000010,
    B10011001,
    B10100101,
    B10100101,
    B10011001,
    B01000010,
    B00111100 };

void setup() {
  Serial.begin(19200);
  
  
  servoOnPin9.attach(9);  // Set right servo to digital pin 9
  
  nunchuck_init(); // send the initilization handshake
  
  Serial.println("Nunchuck Test");
  
  matrix.begin(0x70);  // pass in the address
}
   
void loop() {

  //First Read data from the nunchuck
  nunchuck_get_data();

  // Then map nunchuk data to a servo data point
  int y_axis = map(nunchuck_buf[1], 32, 231, 0, 180); //read the joystick y
  int y_acc = map(nunchuck_buf[3], 32, 231, 0, 180); //read the y-accelerometer


//  Serial.print(y_acc,DEC);
//  Serial.print("\r\n");  // newline

// Uncomment below to see the data from the Nunchuck
// nunchuck_print_data();

  // Then change the output, depending on where the joystick it
  if (y_acc <= 70) {
                      matrix.clear();
                      matrix.drawBitmap(0, 0, arrowUp_bmp, 8, 8, LED_ON);
                      matrix.writeDisplay();
                      // move servo to up position
                      servoOnPin9.write(180);
                     }
    else {
          if (y_acc >=100) {
                            matrix.clear();
                            matrix.drawBitmap(0, 0, arrowDown_bmp, 8, 8, LED_ON);
                            matrix.writeDisplay();
                            // move servo to down position
                            servoOnPin9.write(0);
                           }
                              else {     
                                    matrix.clear();
                                    matrix.drawBitmap(0, 0, centre_bmp, 8, 8, LED_ON);
                                    matrix.writeDisplay();
                                    //move servo to middle position
                                    servoOnPin9.write(90);
                                   }
                            }
  }

//*****************************************************************

//
// Nunchuck functions
//

// initialize the I2C system, join the I2C bus,
// and tell the nunchuck we're talking to it
void nunchuck_init()
{ 
  Wire.begin();                      // join i2c bus as master
  Wire.beginTransmission(0x52);     // transmit to device 0x52
  Wire.write(0x40);            // sends memory address
  Wire.write(0x00);            // sends sent a zero.  
  Wire.endTransmission();     // stop transmitting
}

// Send a request for data to the nunchuck
// was "send_zero()"
void nunchuck_send_request()
{
  Wire.beginTransmission(0x52);     // transmit to device 0x52
  Wire.write(0x00);            // sends one byte
  Wire.endTransmission();     // stop transmitting
}

// Receive data back from the nunchuck, 
int nunchuck_get_data()
{
    int cnt=0;
    Wire.requestFrom (0x52, 6);     // request data from nunchuck
    while (Wire.available ()) {
      // receive byte as an integer
      nunchuck_buf[cnt] = nunchuk_decode_byte(Wire.read());
      cnt++;
    }
    nunchuck_send_request();  // send request for next data payload
    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5) {
     return 1;   // success
    }
    return 0; //failure
}

// Encode data to format that most wiimote drivers except
// only needed if you use one of the regular wiimote drivers
char nunchuk_decode_byte (char x)
{
  x = (x ^ 0x17) + 0x17;
  return x;
}

void nunchuck_print_data()
//Use this to view the direct feed from the Nunchuck
{ 
  static int i=0;
  int joy_x_axis = nunchuck_buf[0];
  int joy_y_axis = nunchuck_buf[1];

  int accel_x_axis = nunchuck_buf[2]; // * 2 * 2; 
  int accel_y_axis = nunchuck_buf[3]; // * 2 * 2;
  int accel_z_axis = nunchuck_buf[4]; // * 2 * 2;


  int z_button = 0;
  int c_button = 0;

  // byte nunchuck_buf[5] contains bits for z and c buttons
  // it also contains the least significant bits for the accelerometer data
  // so we have to check each bit of byte outbuf[5]
  if ((nunchuck_buf[5] >> 0) & 1) 
    z_button = 1;
  if ((nunchuck_buf[5] >> 1) & 1)
    c_button = 1;

  if ((nunchuck_buf[5] >> 2) & 1) 
    accel_x_axis += 2;
  if ((nunchuck_buf[5] >> 3) & 1)
    accel_x_axis += 1;

  if ((nunchuck_buf[5] >> 4) & 1)
    accel_y_axis += 2;
  if ((nunchuck_buf[5] >> 5) & 1)
    accel_y_axis += 1;

  if ((nunchuck_buf[5] >> 6) & 1)
    accel_z_axis += 2;
  if ((nunchuck_buf[5] >> 7) & 1)
    accel_z_axis += 1;

  Serial.print(i,DEC);
  Serial.print("\t");
  
  Serial.print("joy:");
  Serial.print(joy_x_axis,DEC);
  Serial.print(",");
  Serial.print(joy_y_axis, DEC);
  Serial.print("  \t");

  Serial.print("acc:");
  Serial.print(accel_x_axis, DEC);
  Serial.print(",");
  Serial.print(accel_y_axis, DEC);
  Serial.print(",");
  Serial.print(accel_z_axis, DEC);
  Serial.print("\t");

  Serial.print("but:");
  Serial.print(z_button, DEC);
  Serial.print(",");
  Serial.print(c_button, DEC);

  Serial.print("\r\n");  // newline
  i++;
}

Connecting Wii Nunchuck Connector to Arduino

posted 19 Aug 2016, 03:54 by Andy Lakin-Hall   [ updated 20 Aug 2016, 03:10 ]

Back in 2013 I bought a Wii Nunchuck adapter from Proto-Pic. This little bit of circuit board plugs straight into the Nunchuck plug, without having to damage it or strip the connector off.

There are four pins on the bottom of the adapter, and in the photo below they can be seen from the top side of the board;

 Symbol Function
 - GND
 + Power
 d data
 c clock


I want to make a test project that reads the Nunchuck and moves the servo. There's a handy reference project at https://create.arduino.cc/projecthub/mtashiro/control-servos-using-wii-nunchuk-9136bd?f=1.

The code in the reference project is based on work here https://todbot.com/blog/2007/10/25/boarduino-wii-nunchuck-servo/ and the code shared here http://todbot.com/arduino/sketches/wii_nunchuck_servo/wii_nunchuck_servo.pde.

Further reference about the Nunchuck can be found at http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck

This project uses two servos, but I've only got one - so I'll keep only code fro the x-axis.

This project uses pin 9 for the right servo, and I've previously used pin 9 for my servo, so I'll keep the right servo, and delete the left.

I've got a green wire from d which goes to analogue pin 4, and a yellow wire from c to analogue pin 5. The + wire goes to the +3.3v output, and the - wire goes to GND.

The servo is connected on pin 9.


Arduino and Wii Nunchuck Reference Project

posted 14 Aug 2016, 13:49 by Andy Lakin-Hall   [ updated 19 Aug 2016, 02:44 ]

Hunting around on the Arduino support site, I came across a project where a Wii Nunchuck is used to control a pair of servos. https://create.arduino.cc/projecthub/mtashiro/control-servos-using-wii-nunchuk-9136bd?f=1

I can use the code here to compare with my Picaxe Nunchuck project, to see how the Arduino addresses the Wii hardware. From a first glance, there are some similarities, so I'm hopeful that it will make sense.

What I'd like to do is use data from the nunchuck's accelerometers to sense launch and apogee. That's going to be a tall order to get right, so I'll split that into two elements;

  1. Sensing when the rocket turns over at apogee.
  2. Sensing the launch.
There could also be a third element, where the accelerometer data gets logged to an SD card - but that's REALLY complicated. Long term, I see that the Genuino 101 has accelerometers built in, so I might ultimately move on to one of those.

Arduino Servo

posted 14 Aug 2016, 13:33 by Andy Lakin-Hall

Next project is to conect my Kona328 Orangepip Arduino Uno compatible to a servo.
Micro Servo
I'm using the micro servo from my Picaxe Wii Nunchuck project.

This servo has three wires - brown, red and orange. 


Brown needs to go to ground. Red goes to the power rail. Orange is the control lead.

My Orangepip is currently connected to my Adafruit Mini 8x8 LED Matrix with I2C Backpack, and as it's currently working, I don't want to disconnect it.

I'll include the matrix so it does a three seconds countdown, and then activates the servo.

Adafruit Feather 32u4 Adalogger

posted 9 Aug 2016, 01:34 by Andy Lakin-Hall   [ updated 9 Aug 2016, 04:46 ]

Thinking about a new avionics system for the water rocket, ideally I'd like a microcontroller system that detects apogee, releases a parachute, sounds a locator alarm and logs the altitude.

I've got no idea if this is possible, but here's a link to a possible controller.

https://shop.pimoroni.com/collections/arduino-microcontrollers/products/adafruit-feather-32u4-adalogger https://shop.pimoroni.com/collections/arduino-microcontrollers/products/adafruit-feather-32u4-adalogger

This controller will run with a 3.3v LiPo battery, making it very light. The problem will be that servos run at higher voltages - typically 5 to 6 volts. I'll need a Servo shield for the Feather. Adafruit do stacking headers for their Feather microcontrollers called "Featherwings." https://learn.adafruit.com/adafruit-8-channel-pwm-or-servo-featherwing/downloads?view=all

The servo needing a larger a battery is the problem, as that takes me back to 4x AA batteries, which is really heavy, defeating the point of a lightweight system. On the other hand, LiPo batteries are vulnerable to crash impact and a damaged cell can spontaneously ignite in a spectacular fashion. Do I want to risk that, or wil NiMh cells be a better option?

What I need to do next is take some lessons on batteries from the DroneRacing community.

Karate Game Firmware Update

posted 12 Mar 2016, 09:52 by Andy Lakin-Hall

I have done some updates to the Karate game firmware.

First, the system has been updated to make the game get faster and faster.

The line interval = interval - 50; // bit faster subtracts 50 milliseconds from the interval each round.

I have found this gives a good length of game before it gets too fast to keep up.

Next I have updated the scoring system.

Now it separates the Tens and units and displays them on different LED flashes, with different beep sounds.

First it does the tens, by dividing the score by ten and giving a high bleep and flash on LED1.

Next it takes just the units value by dividing by modulo 10 

for (int i = 0;i<Score % 10 ;i++) {

        LowBleep();
        FlashLED2();
        //delay(500);
        }

I have also added a routine that makes the score replay if a switch is toggled in standby mode.

Here is the updated code

/*
Karate 2 
Andy Lakin-Hall
March 2016

 */
 

 int GameOn = 0;
 int ledPin[] = {10,11,12,13};
 int val = 0;
 const int BUTTON = 2;  //Sets the name Button to be the number 2
 
 int TogglePin[] = {5,6,7,8};  //sets which pins the toggle switches are connected to

 int ToggleState[] = {1,2,3,4};      //for recording the toggle position
 int lastToggleState[] = {1,2,3,4};  //for recording the previos toggle position
 int LEDstate[] = {1,2,3,4};         //recording the LED states
 
 unsigned long lastMillis = 0;   // will store the last time the button was pressed
 unsigned long currentMillis = 0;   // will store the last time the button was pressed
 int long interval = 3000;           // time allowed for play clock (milliseconds)
 
 int brightness = 0;    // how bright the LED is for the fade out
 int fadeAmount = 5;    // how many points to fade the LED by
 
 int Score = 0;

// ************************************************************************
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pins 10 to 13 as an output.
  // and and pins 5 to 8 as input.
  for (int i =0;i<4;i++)
  {
    pinMode (ledPin[i], OUTPUT);    //set each LED as an output
    pinMode (TogglePin[i], INPUT);  //set each toggle switch as an input
    
  }

  pinMode(BUTTON, INPUT);  //set the Button (on pin 2) as an input
  
  //Set up the initial toggle positions
  for (int i =0;i<4;i++)
  {
    ToggleState[i] = digitalRead(TogglePin[i]);  //read in the Toggle switch positions
    lastToggleState[i] = ToggleState[i];         //copy the current Toggle states to memory
  }
  
}

// ************************************************************************
// ************************************************************************
// the main loop function runs over and over again forever
void loop() {
  ToggleCheck();
  
  if (digitalRead(BUTTON) == LOW) {
    if (GameOn == 0) {
      //if the game is in standby. Flash the LEDs until the BUTTON is pressed
      AllLEDsOn();
      delay (50);
      AllLEDsOff();
      delay (50);          
    }
    else {
      //The game is running. Check to see that the time hasn't run out.
      currentMillis = millis();
      if(currentMillis - lastMillis >= interval) {
      //The time has run out!
      
      //If the time has run out, check to see if all the LEDs are off.
      if(LEDstate[1] == 0 && LEDstate[2] ==0) {
        //All the LEDs are off. Do another round
        interval = interval - 50; // bit faster
        lastMillis = millis();
        displayBinary(random(14)+1);  //set the LEDs to a random number
        keeai();
      }
      else {
      //If any LEDs are still on, that means the player has lost. Do the game end sequence
      GameEndSequence();
      //Wait a second before going into standby
      delay (1000);
      }
      }
    }
    
  }
  else
  {
    //The BUTTON has been pressed
    //Start the game
    GameOn = 1;
    Score = 0;
    interval = 3000;
    lastMillis = millis();
    displayBinary(random(14)+1);  //set the LEDs to a random number
    
        
  }
}

// ************************************************************************
// ************************************************************************
// Display a number as a binary on the LEDs
void displayBinary(byte numToShow)
{
 for (int i=0;i<4;i++)
  {
    if (bitRead(numToShow, i)==1)
    {
      digitalWrite(ledPin[i], HIGH);
      LEDstate[i] = 1;
    }
    else
    {
      digitalWrite(ledPin[i], LOW);
      LEDstate[i] = 0;
    }
  } 
}

// ************************************************************************
// do a keeai
void keeai() {
  tone(3, 300, 200);
  delay(100);
  tone(3, 44, 250);
}

// ************************************************************************
//do a Ha
void Ha()
{
  tone(3, 44, 250);
}

// ************************************************************************
//do a laugh
void HaHaHa()
{
  tone(3, 65, 300);
  delay(400);
  tone(3, 55, 400);
  delay(600);
  tone(3, 44, 500);
  
}

// ************************************************************************
//All LEDs ON
void AllLEDsOn()
{
  for (int i=0;i<4;i++) {
  digitalWrite(ledPin[i], HIGH);
  }
}

// ************************************************************************
//All LEDs OFF
void AllLEDsOff()
{
  for (int i=0;i<4;i++) {
  digitalWrite(ledPin[i], LOW);
  }
}

// ************************************************************************
// Check if the Toggles have moved
void ToggleCheck()
{
  for (int i =0;i<4;i++)
  {
    ToggleState[i] = digitalRead(TogglePin[i]);  //read the Toggle switch positions
    
    if (ToggleState[i] != lastToggleState[i]) {
      Ha();
      if(GameOn ==1){
        Score++;
      }
      //remember the change
      lastToggleState[i] = ToggleState[i];
      //flip the corresponding LED
      if (LEDstate[i] == 1) {
      digitalWrite(ledPin[i], LOW);
      LEDstate[i] = 0;
      }
      else {
      digitalWrite(ledPin[i], HIGH);
      LEDstate[i] = 1;
      }
      if (GameOn == 0) {
        //show the score
        AllLEDsOff();
        DisplayScore();
      } 
    }
  }

}

// ************************************************************************
//Game End Sequence
void GameEndSequence()
{
    //turn off the LEDs
      AllLEDsOff();
      //Do the laugh
      HaHaHa();
      delay(1000);
      DisplayScore();
}

// ************************************************************************
void DisplayScore() {
      //Now bleep the score
      
      //First the Tens
      //find the integer value of the Tens digit of score
      if (Score>9) {
        for (int i = 0;i<Score/10;i++) {
        HighBleep();
        FlashLED1();
        //delay(500);
        }
      
       //find the integer value of the final digit of score

       AllLEDsOff();
       delay(1000);
      }
       //Now the units
       for (int i = 0;i<Score % 10 ;i++) {
        LowBleep();
        FlashLED2();
        //delay(500);
        }
      
        delay(1000);
        AllLEDsOff();
      GameOn = 0;
}

// ************************************************************************
//do a high bleep
void HighBleep()
{
  tone(3, 300, 250);
}

// ************************************************************************
////do a low bleep
void LowBleep()
{
  tone(3, 100, 250);
}

// ************************************************************************
//FlashLED()
void FlashLED1() {
  digitalWrite(ledPin[1], HIGH);
  delay (200);
  digitalWrite(ledPin[1], LOW);
  delay (300);
}
// ************************************************************************
//FlashLED()
void FlashLED2() {
  digitalWrite(ledPin[2], HIGH);
  delay (200);
  digitalWrite(ledPin[2], LOW);
  delay (300);
}
// ************************************************************************

1-10 of 30