Arduino Simon

11Jan12

I My son got a great Xmas present in the shape of a Starter Kit for Arduino  from Oomlout. After doing some of the basic projects I decided we needed something that we could get our teeth into. After a little pondering Simon came out as a worthwhile challenge. Back in the 80s I’d written a version of Simon that was published in Commodore Computing International, so I thought it would be fun to do a hardware version. A bit of poking around the web revealed that this has been done before, but I decided to start from scratch rather than copying the design and code from others (otherwise where’s the fun?).

I expected that this would be a project that might take a few weekends of tinkering, but in the end I had a playable system done in around 90 minutes. Arduino/Processing is a really productive environment, especially if you’re already familiar with electronics prototyping and a bit of C.

The electronics

  • Lights – 4 LEDs (Red, Green, Yellow and Blue) between digital output pins and ground with appropriate series resistors.
  • Sound – a piezo buzzer between a digital output pin and ground.
  • Buttons – 4 – between ground and digital inputs. Right now I have 10k pull up resistors, but they’re probably not necessary. Tip – twist the legs of PCB mount buttons through 90 degrees to stop them pinging out of the breadboard.

The code

I’ll let the code speak for itself, but I’ve put it at the bottom to avoid breaking the flow of things[1]. Update 17 Jan – the original code is below, but revised code is on github.

Todo

  • Change the tones so that the match up with the original Simon.
  • Check for when a correct sequence of 20 is entered, and do some sort of winning ritual (right now the array will just overflow).
  • Resequence the inputs. Blue was on Pin 13, but that was before I discovered that Pin 13 is special.
  • Make use of the internal pull up resistors for the buttons (and ditch the 10K ones on the board).
  • Progressively speed things up when the sequence gets longer.
  • Put the code up on Github.

And then

The kids have really got into playing with this, so I’ve bought some components to transfer things onto a more permanent stripboard based version.

I’m also tempted to see if I can transfer things over to an MSP430 based microcontroller. That would be much cheaper to make a permanent toy out of (especially since TI send out free samples), but it brings with it the extra challenge of having to multiplex inputs and outputs as the MSP430s aren’t graced with the number of pins found on Arduino’s ATMega chip. This would probably involve Charlieplexing the LEDs and coming up with a resistor ladder for input.

Update 22 Jan – I did some follow up posts covering the stripboard build and with some diagrams of the original.

[1] The code:

  const int led_red = 1;         // Output pins for the LEDs
  const int led_green = 2;
  const int led_yellow = 3;
  const int led_blue = 4;
  const int buzzer = 5;		 // Output pin for the buzzer
  const int red_button = 10;     // Input pins for the buttons
  const int green_button = 11;
  const int yellow_button = 12;
  const int blue_button = 9;     // Pin 13 is special - didn't work as planned
  long sequence[20];             // Array to hold sequence
  int count = 0;                 // Sequence counter
  long input = 5;                // Button indicator

  /*
  playtone function taken from Oomlout sample
  takes a tone variable that is half the period of desired frequency
  and a duration in milliseconds
  */
  void playtone(int tone, int duration) {
    for (long i = 0; i < duration * 1000L; i += tone *2) {
      digitalWrite(buzzer, HIGH);
      delayMicroseconds(tone);
      digitalWrite(buzzer, LOW);
      delayMicroseconds(tone);
    }
  }

  /*
  functions to flash LEDs and play corresponding tones
  very simple - turn LED on, play tone for .5s, turn LED off
  */
  void flash_red() {
    digitalWrite(led_red, HIGH);
    playtone(1915,500);
    digitalWrite(led_red, LOW);
  }

  void flash_green() {
    digitalWrite(led_green, HIGH);
    playtone(1700,500);
    digitalWrite(led_green, LOW);
  }

  void flash_yellow() {
    digitalWrite(led_yellow, HIGH);
    playtone(1519,500);
    digitalWrite(led_yellow, LOW);
  }

  void flash_blue() {
    digitalWrite(led_blue, HIGH);
    playtone(1432,500);
    digitalWrite(led_blue, LOW);
  }

  // a simple test function to flash all of the LEDs in turn
  void runtest() {
    flash_red();
    flash_green();
    flash_yellow();
    flash_blue();
  }

  /* a function to flash the LED corresponding to what is held
  in the sequence
  */
  void squark(long led) {
    switch (led) {
        case 0:
          flash_red();
          break;
        case 1:
          flash_green();
          break;
        case 2:
          flash_yellow();
          break;
        case 3:
          flash_blue();
          break;
      }
      delay(50);
  }

  // function to build and play the sequence
  void playSequence() {
    sequence[count] = random(4);       // add a new value to sequence
    for (int i = 0; i < count; i++) {  // loop for sequence length
      squark(sequence[i]);             // flash/beep
    }
    count++;                           // increment sequence length
  }

  // function to read sequence from player
  void readSequence() {
   for (int i=1; i < count; i++) {               // loop for sequence length
      while (input==5){                          // wait until button pressed
        if (digitalRead(red_button) == LOW) {    // Red button
          input = 0;
        }
        if (digitalRead(green_button) == LOW) {  // Green button
          input = 1;
        }
        if (digitalRead(yellow_button) == LOW) { // Yellow button
          input = 2;
        }
        if (digitalRead(blue_button) == LOW) {   // Blue button
          input = 3;
        }
      }
      if (sequence[i-1] == input) {              // was it the right button?
        squark(input);                           // flash/buzz
      }
        else {
          playtone(3830,1000);                   // low tone for fail
          squark(sequence[i-1]);                 // double flash for the right colour
          squark(sequence[i-1]);
          count = 0;                             // reset sequence
      }
    input = 5;                                   // reset input
    }
  }

  // standard sketch setup function
  void setup() {
    pinMode(led_red, OUTPUT);      // configure LEDs and buzzer on outputs
    pinMode(led_green, OUTPUT);
    pinMode(led_yellow, OUTPUT);
    pinMode(led_blue, OUTPUT);
    pinMode(buzzer, OUTPUT);
    pinMode(red_button, INPUT);    // configure buttons on inputs
    pinMode(green_button, INPUT);
    pinMode(yellow_button, INPUT);
    pinMode(blue_button, INPUT);
    randomSeed(analogRead(5));     // random seed for sequence generation
    //runtest();
  }

  // standard sketch loop function
  void loop() {
    playSequence();  // play the sequence
    readSequence();  // read the sequence
    delay(1000);     // wait a sec
  }


4 Responses to “Arduino Simon”

  1. 1 Nicholas Hargreaves

    Chris,

    That’s pretty cool. How old is your son now?

    I got the main board as a Christmas present also, but haven’t fired it up yet.

    Nick

  2. 3 Joe Maissel

    Fun post. Thank you!


Leave a reply to Joe Maissel Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.