Cameron BakerTaylor Ballard
Published

Play Simon and Track Your Memory Skills

Capture and store your wins and losses as you play the Simon game. Send yourself an email if someone else is playing your Simon.

BeginnerFull instructions provided1 hour758
Play Simon and Track Your Memory Skills

Things used in this project

Hardware components

Internet Button
Particle Internet Button
×2
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
Note: The USB Cable comes with the Internet Button and must be connected to a sufficient power supply. Our project used a portable battery.
×2
SparkFun Triple Axis Accelerometer Breakout - LIS3DH
SparkFun Triple Axis Accelerometer Breakout - LIS3DH
Note: This exact accelerometer was not used. The accelerometer used in our system is built into the internet button. If you are using a newer internet button, you will not need to purchase this part.
×1
PowerBlock
Note: This powerblock was used for our project because it was able to power both photons at once. You may use any power source you choose.
×1
Particle Wi-Fi Flex Antenna
One of these were connected to each photon to create a stronger connection between them and the Wi-Fi we were using. It saved time and energy trying to reconnect the devices to the Wi-Fi.
×2

Software apps and online services

Google Sheets
Google Sheets
Maker service
IFTTT Maker service
Google - Gmail

Story

Read more

Schematics

Circuit Diagram

This diagram includes the additional accelerometer. This accelerometer is only necessary if your internet button is an older model. The diagram also includes the two Wi-Fi antennas. These are only needed if you feel your photon has poor internet connection.

Code

Player one Simon game code.

Arduino
This code will go on Player_1 photon in the .ino file. Be sure to include SimoN.cpp and SimoN.h also attached. Also, include the standard internet button library. When you add the other files make sure to label them SimoN or the code will not work. Make sure one there is only one include statement for both the internet button or the SimoN code set. You may need to delete a set of include statements once everything is in place.
After you place this in the .ino file, press the + button in the top right side of the IDE. This will add a .h and a .cpp. Name them SimoN and paste the appropriate codes within them.
// This #include statement was automatically added by the Particle IDE.
#include "SimoN.h"

// This #include statement was automatically added by the Particle IDE.
#include <InternetButton.h>

SimoN s = SimoN();

void setup() {
    s.setup();   
}

void loop() {
    s.loop();
}

Player one SimoN.cpp code

Arduino
This will be the included .cpp file for the Player_1 code.
#include "SimoN.h"
 
SimoN::SimoN(){

}

void SimoN::setup() {
    b = InternetButton();
    solution = new Position[0];
    solutionSize = 0;

    state = Welcome;

    difficulty = 3;
    successMax = 0;
    successCount = 0;
    
    
    RGB.control(true);
    b.begin();
    b.allLedsOff();
}

void SimoN::loop() {
    switch (state) { 
        case Welcome: 
            welcome();
            break;
        case Ready: 
            ready();
            break;
        case Showing:
            show();
            break;
        case ListeningDown:
            listenDown();
            break;
        case ListeningUp:
            listenUp();
            break;
        case CompleteSuccess:
            celebrate();
            break;
        case Failed:
            fail();
            break;
    }
}

void SimoN::welcome() {
    b.playSong("C4,8,E4,8,G4,8,C5,8,G5,4");
    b.allLedsOn(0,20,20); 
    delay(500);
    b.allLedsOff();
    
    flash(Top, true, true);
    flash(Right, true, true);
    flash(Bottom, true, true);
    flash(Left, true, true);
    state = Ready;
}

void SimoN::demo() {
      b.ledOn(11, 25, 0, 0);
            b.ledOn(1, 25, 0, 0);

            b.ledOn(2, 0, 0, 25);
            b.ledOn(3, 0, 0, 25);
            b.ledOn(4, 0, 0, 25);

            b.ledOn(5, 12, 12, 0);
            b.ledOn(6, 12, 12, 0);
            b.ledOn(7, 12, 12, 0);

            b.ledOn(8, 0, 25, 0);
            b.ledOn(9, 0, 25, 0);
            b.ledOn(10, 0, 25, 0);
    
    delay(10000);
}

void SimoN::ready() {
    Position read = anyButtonOn();
    
    switch (read) {
        case None:
            return;
        case Top:
            difficulty = 2;
            break;
        case Right:
            difficulty = 2;
            break;
        case Bottom:
            difficulty = 2;
            break;
        case Left:
            difficulty = 2;
            break;
    }
    celebrate();
}

void SimoN::setColor() {
    if (difficulty < 10) {
        RGB.color(255, 0, 0);
        return;    
    }
    if (difficulty < 15) { 
        RGB.color(0, 0, 255);
        return;
    }
    if (difficulty < 30) { 
        RGB.color(120, 120, 0);
        return;
    }
    
    RGB.color(0, 255, 0);
}

void SimoN::start() {
    //b.allLedsOn(0,20,20); 
    //delay(500);
    //b.allLedsOff();
    
    successMax = 0;
        
    generate(difficulty);
    setColor();
    
    state = Showing;
}

void SimoN::generate(int size) {
    solutionSize = size;
    solution = new Position[solutionSize];
    
    for (int i = 0; i < size; i++) {
        while(true) {
            Position next = (Position) random(4);
            
            if (i-2 >= 0 && next == solution[i-1] && next == solution[i-2]) {
                continue;
            }
            
            solution[i] = next;
            break;
        }
    }
}

void SimoN::show() {
    for (int i = 0; i < successMax + 1; i++) {
        Position next = solution[i];
        flash(next, true, true);
        delay(100);
    }
    
    successCount = 0;
    state = ListeningDown;
}

void SimoN::listenDown() {
    Position read = anyButtonOn();
    if (read == None) {
        return;
    }
    
    if (solution[successCount] == read) {
        flash(read, false, true);
        state = ListeningUp;
        return;
    }

    state = Failed;
}


void SimoN::listenUp() {
    Position read = anyButtonOn();
    
    if (read == None) {
        unflash();
        
        successCount++;
        
        if (successCount > successMax) {
                if (successCount == solutionSize) {
                    Particle.publish("GREAT","2", 60, PUBLIC);
                    state = CompleteSuccess;
                    return;
                }
    
            successMax++;
            
            delay(1000);
            state = Showing;
            return;
        }
        
      
        state = ListeningDown;
        return;
    }
    
     if (solution[successCount] != read) { 
         state = Failed;
         return;
     }
}

SimoN::Position SimoN::anyButtonOn() {
    if (b.buttonOn(1)) {
        return Top; 
    }
    if (b.buttonOn(2)) {
        return Right; 
    }
    if (b.buttonOn(3)) {
        return Bottom; 
    }
    if (b.buttonOn(4)) {
        return Left; 
    }
    return None;
}

void SimoN::celebrate() {
    flash(Top, false, false);
    flash(Right, false, false);
    flash(Bottom, false, false);
    flash(Left, false, false);
    b.playSong("C4,8,E4,8,G4,8,C5,8,G5,4");
    Particle.publish("GAMESTART","1", 60, PUBLIC);
    //b.allLedsOn(0, 255, 0);
    delay(300);
    b.allLedsOff();
    
    delay(500);
    difficulty++;
    start();
}



void SimoN::flash(Position p, bool timed, bool sound) {
    switch (p) {
        case Top:
            b.ledOn(11, 255, 0, 0);
            b.ledOn(1, 255, 0, 0);
            if (sound) { b.playNote("C4",4); }
            break;
        case Right:
            b.ledOn(3, 0, 0, 255);
            b.ledOn(2, 0, 0, 255);
            b.ledOn(4, 0, 0, 255);
            if (sound) { b.playNote("E4",4); }
            break;
        case Bottom:
            b.ledOn(6, 120, 120, 0);
            b.ledOn(5, 120, 120, 0);
            b.ledOn(7, 120, 120, 0);
            if (sound) { b.playNote("G4",4); }
            break;
        case Left:
            b.ledOn(9, 0, 255, 0);
            b.ledOn(8, 0, 255, 0);
            b.ledOn(10, 0, 255, 0);
            if (sound) { b.playNote("C5",4); }
            break;
        case None: 
            delay(100);
            return;
    }
    if (timed) {
        b.allLedsOff();
    }
}

void SimoN::unflash() {
    // TODO: stop sound
    b.allLedsOff();
}

void SimoN::fail() {
    flash(solution[successCount], false, false);
    b.playNote("C2",1);
       Particle.publish("OHNO","0", 60, PUBLIC);
    for( int a = 0; a < 3; a = a + 1 )
    {
        
        b.allLedsOn(255,0,0); 
        RGB.brightness(255);
        delay(500);
        b.allLedsOff();
        RGB.brightness(1);
        delay(500);
    }

    RGB.color(0, 0, 0);
    RGB.brightness(255);
    state = Welcome;
}

    

Player one SimoN.h code

Arduino
This will be the included .h file for the Player_1 code.
#include "InternetButton/InternetButton.h"
 
class SimoN {
 enum Position: int { Top = 0 , Right = 1, Bottom = 2, Left = 3, None = -1};
  
 public:

  SimoN();

  void
    setup(),
    loop();
    
 private: 
    
  void 
    welcome(),
    demo(),
    ready(),
    setColor(),
    start(),
    generate(int size),
    show(),
    listenDown(),
    listenUp(),
    celebrate(),
    flash(Position p, bool timed, bool sound),
    unflash(),
    fail();

 public: 
  
  Position anyButtonOn();
  InternetButton b;

  Position *solution;
  int solutionSize;

  enum State: int { Welcome, Ready, Showing, ListeningDown, ListeningUp, CompleteSuccess, Failed };
  State state;

  int difficulty;
  int successMax;
  int successCount;
};
    
    

Player two Simon game code.

Arduino
This code will be loaded onto your second photon to act as Player_2. You will need to add the internet button library and have only one include statement for it. For this, the EMAI GRAP and GRAH are used in IFTTT to complete the email and graphing features.
// This #include statement was automatically added by the Particle IDE.
#include <InternetButton.h>
InternetButton b = InternetButton();
void setup() {
    //s.setup();
    Particle.subscribe("OHNO",GRAH);
    Particle.subscribe("GREAT",GRAP);
    Particle.subscribe("GAMESTART",EMAI);
    b.begin();
}

void loop(){

    //How much are you moving in the x direction? (look at the white text on the board)
    int xValue = b.readX();

    //How about in the y direction?
    int yValue = b.readY();

    //And the z!
    int zValue = b.readZ();

    //This will make the color of the Button change with what direction you shake it
    //The abs() part takes the absolute value, because negatives don't work well
    b.allLedsOn(abs(xValue), abs(yValue), abs(zValue));

    //Wait a mo'
    delay(1000);
    b.allLedsOff();
}

void EMAI(const char *event, const char *data){
    pinMode(D7,OUTPUT);
    digitalWrite(D7,HIGH);
    delay(1000);
    digitalWrite(D7,LOW);
    Particle.publish("GameStart","1", 60, PUBLIC);
    Particle.publish("SFG",".5", 60, PUBLIC);
}


void GRAP(const char *event, const char *data){
    pinMode(D7,OUTPUT);
    digitalWrite(D7,HIGH);
    delay(1000);
    digitalWrite(D7,LOW);
    Particle.publish("SFG","2", 60, PUBLIC);
}
void GRAH(const char *event, const char *data){
    pinMode(D7,OUTPUT);
    digitalWrite(D7,HIGH);
    delay(1000);
    digitalWrite(D7,LOW);
   Particle.publish("SFG","1", 60, PUBLIC);
}

Credits

Cameron Baker

Cameron Baker

1 project • 1 follower
Taylor Ballard

Taylor Ballard

1 project • 2 followers
This is my MEGR 3171 class account

Comments