ButtonMash Crossing

Made by Melanie Zeng, whagen and Brian Xiao

Found in Diot 2019: Social Objects - Part 3

A set of augmented objects to allow pedestrians at stop light to interact with other pedestrians on the other side of the street.

0

Conceptual Design

We were interested in transforming what is normally a boring waste of time into a fun playful experience. We found that crossing the street is an interesting daily scenario. It's too short to be even realized. But people are still too impatient to wait for the street light. From our observation in the CMU campus, jaywalking is a common scene. Sometimes people can get impatient easily and push the push-to-walk button a lot to fulfill their desire of urging the light changing time. While they push the button many times, they are spreading some sort of negative emotions. The less patience and tolerance people give to each other, the more inappropriate behaviors and safety risks can occur. 

So we decided to create a pair of gamified objects with which pedestrians can challenge each other to see who can win the game. The game needs two sides of the pedestrians to participate. Once both people press the start button, the neopixel will light up to indicate that the game has started. Within a limited time (before they can go across the street), they will press the game button as fast as they can and the first person reaches the threshold number will win the game. We believe that adding this simple tug-of-war type game will make waiting to cross the street more entertaining.

0

User Feedback

We explained the concept to our potential users. I found that some of them are reluctant to use the shaker because they worry that they would be unsanitary. So we decided to change the game input to be buttons which requires less hand exposures from people and can potentially integrate with the push-to-walk buttons in the future.  

0

Storyboard

0

Making Process

1. Building the circuit

We had one starter button, one game button and one neopixel on each device. We also carefully soldered the game button to the jumper wires. 

0

2. Sharing data in the cloud

We first learned how to make the two devices communicate with either other. To implement it in our game, we programmed the game to only start when both sides of the players are in ready state.

0

3. Programming the game

We then drafted the state flow of the game and built the code without adding complicated light effects. In this step, we built and tested the code piece by piece so that it's easier for us to debug it. According to the National Association of City Transportation Officials, an average wait time at red light is 60 - 90 seconds. Assuming someone takes 1 second to press a button on average, we decided to make 50 times as a threshold that won't take too long or too short.

0

4. Testing the concept

0
WhatsApp Video 2019 02 16 at 1 07 03 PM
Wyatt Hagen - https://youtu.be/poI8yjMKGpo
0

5. Adding lighting animations

After testing the devices and making sure they are working properly, we tweaked the lighting effects in the ready state, the game state, the winner's side and the loser's side. We were careful to choose the colors so that they are not similar or contradict with the traffic light colors.

0
Light animation
Melanie Zeng - https://youtu.be/S3detzjlO8w
0

6. Making the high fidelity prototype

0

Technical Specs

0

List of Parts:

1. 2 Breadboards

2. 2 Particle Argons

3. 2 USB Micro B Cables

4. 2 Neopixels

5. 2 Push Buttons

6. 2 Buttons

7. 20 Jumper Wires

0
Circuit Diagram
Whatsapp image 2019 02 17 at 2.10.05 pm
0
State Diagram
State diagram
0

Code

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

#include <math.h>

int startButtonPin = D5;
int buttonPin = D7;    
int ledPin = D2;       

int counter = 0;
bool buttonState; //current game button state
bool lastButtonState = HIGH; //previous game button state
bool startButtonState; //starter button state

long lastPublishedAt = 0;
int publishAfter = 10000;

bool myState = false; //indicate my ready state
bool yourState = false; //indicate the other person's ready state

#define PIXEL_PIN D2
#define PIXEL_COUNT 14
#define PIXEL_TYPE WS2812

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

void setup() {

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(startButtonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  Particle.subscribe(  "gameStart" , handleSharedEvent ); // Subscribe to game starting event
  Particle.subscribe(  "gameEnd" , handleSharedEvent );  // Subscribe to game ending event 
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  startButtonState = digitalRead(startButtonPin);
  buttonState = digitalRead(buttonPin);

  if (startButtonState == LOW) {
      publishStartingEvent();
  }
      
  if (myState == true and yourState == true){
      counts();
      //standby animation beginning
      breathe();
      }
      
  if (counter >= 50){
      publishEndingEvent();
      //winner animation
        uint32_t a = strip.Color(22, 0, 123); // Blue
        uint32_t b = strip.Color(173, 12, 232); // Purple
        uint32_t c = strip.Color(255, 0, 121); // Violet
        uint32_t d = strip.Color(232, 46, 12); // Red
        uint32_t e = strip.Color(255, 116, 0); // Orange
         
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, a); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, b); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, c); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, d); // set a color 
           strip.show();
           delay( 35 );
        }
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, e); // set a color 
           strip.show();
           delay( 35 );
        }          for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, a); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, b); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, c); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, d); // set a color 
           strip.show();
           delay( 35 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(i, c); // set a color 
           strip.show();
           delay( 35 );
        } 
      counter = 0;
  }

}

void counts()
{
   if (buttonState == LOW and lastButtonState == HIGH){
       counter += 1;
    } 
     lastButtonState = buttonState;
}

void publishStartingEvent() // Publish function for the starting event 
{

  // check that it's been 10 secondds since our last publish
  if( lastPublishedAt + publishAfter < millis() )
  {

      String eventName = "gameStart" + System.deviceID();

      // then we share it out
      Particle.publish( eventName, "data goes here" );

      // And this will get shared out to all devices using this code

      // we just pubished so capture this.
      // lastPublishedAt = millis();
      myState = true;
  }

}

void publishEndingEvent() // Publish function for the ending event
{

  // check that it's been 10 secondds since our last publish
  if( lastPublishedAt + publishAfter < millis() )
  {

      String eventName = "gameEnd" + System.deviceID();

      // then we share it out
      Particle.publish( eventName, "data goes here" );

      // And this will get shared out to all devices using this code

      // we just pubished so capture this.
      // lastPublishedAt = millis();
      myState = false;
      yourState = false;
      
    }
      
}



void handleSharedEvent(const char *event, const char *data){ // Only need one handle event function for both events 

    // Let's check the event name
    String eventName = String( event ); // convert to a string object

    // We can use this to check if our event name contains the
    // id of this device

    String deviceID = System.deviceID();

    // device id = 0123456789abcdef
    // event = "diot/2019/paired/0123456789abcdef"

    if( eventName.indexOf( deviceID ) != -1 ){
      // if we get anything other than -1
      // the event came from this device.
      // so stop doing stuff
      return;
    }
    
    if(eventName.startsWith("gameStart")){

        yourState = true;

    }
    
    if(eventName.startsWith("gameEnd")){
        
        myState = false;
        yourState = false;
        //loser animation
        uint32_t f = strip.Color(100, 0, 0); // Deep Red
        uint32_t x = strip.Color(0, 0, 0); // OFF

        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(6, f); // set a color 
           strip.setPixelColor(5, f); // set a color 
           strip.setPixelColor(4, f); // set a color 
           
           strip.setPixelColor(1, x); // set a color 
           strip.setPixelColor(2, x); // set a color 
           strip.setPixelColor(3, x); // set a color 
           strip.setPixelColor(7, x); // set a color 
           strip.setPixelColor(8, x); // set a color 
           strip.setPixelColor(9, x); // set a color 
           strip.setPixelColor(10, x); // set a color 
           strip.setPixelColor(11, x); // set a color 
           strip.setPixelColor(12, x); // set a color 
           strip.setPixelColor(13, x); // set a color 
           strip.setPixelColor(14, x); // set a color 

           strip.show();
           delay( 10 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(5, f); // set a color 
           strip.setPixelColor(4, f); // set a color 
           strip.setPixelColor(3, f); // set a color 
           
           strip.setPixelColor(1, x); // set a color 
           strip.setPixelColor(2, x); // set a color 
           strip.setPixelColor(6, x); // set a color 
           strip.setPixelColor(7, x); // set a color 
           strip.setPixelColor(8, x); // set a color 
           strip.setPixelColor(9, x); // set a color 
           strip.setPixelColor(10, x); // set a color 
           strip.setPixelColor(11, x); // set a color 
           strip.setPixelColor(12, x); // set a color 
           strip.setPixelColor(13, x); // set a color 
           strip.setPixelColor(14, x); // set a color 

           strip.show();
           delay( 10 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(3, f); // set a color 
           strip.setPixelColor(4, f); // set a color 
           strip.setPixelColor(5, f); // set a color 
           
           strip.setPixelColor(1, x); // set a color 
           strip.setPixelColor(2, x); // set a color 
           strip.setPixelColor(6, x); // set a color 
           strip.setPixelColor(7, x); // set a color 
           strip.setPixelColor(8, x); // set a color 
           strip.setPixelColor(9, x); // set a color 
           strip.setPixelColor(10, x); // set a color 
           strip.setPixelColor(11, x); // set a color 
           strip.setPixelColor(12, x); // set a color 
           strip.setPixelColor(13, x); // set a color 
           strip.setPixelColor(14, x); // set a color 

           strip.show();
           delay( 10 );
        }

        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(2, f); // set a color 
           strip.setPixelColor(3, f); // set a color 
           strip.setPixelColor(4, f); // set a color 
           
           strip.setPixelColor(1, x); // set a color 
           strip.setPixelColor(5, x); // set a color 
           strip.setPixelColor(6, x); // set a color 
           strip.setPixelColor(7, x); // set a color 
           strip.setPixelColor(8, x); // set a color 
           strip.setPixelColor(9, x); // set a color 
           strip.setPixelColor(10, x); // set a color 
           strip.setPixelColor(11, x); // set a color 
           strip.setPixelColor(12, x); // set a color 
           strip.setPixelColor(13, x); // set a color 
           strip.setPixelColor(14, x); // set a color 

           strip.show();
           delay( 10 );
        }
        
        for( int i = 0; i < strip.numPixels(); i++ ){
           strip.setPixelColor(1, f); // set a color 
           strip.setPixelColor(2, f); // set a color 
           strip.setPixelColor(3, f); // set a color 
           
           strip.setPixelColor(4, x); // set a color 
           strip.setPixelColor(5, x); // set a color 
           strip.setPixelColor(6, x); // set a color 
           strip.setPixelColor(7, x); // set a color 
           strip.setPixelColor(8, x); // set a color 
           strip.setPixelColor(9, x); // set a color 
           strip.setPixelColor(10, x); // set a color 
           strip.setPixelColor(11, x); // set a color 
           strip.setPixelColor(12, x); // set a color 
           strip.setPixelColor(13, x); // set a color 
           strip.setPixelColor(14, x); // set a color 

           strip.show();
           delay( 10 );
        }
    }
}


 /* Calc the sin wave for the breathing color led led */
float breathe(){

  float val = (exp(sin(millis()/800.0*M_PI)) - 0.36787944)*108.0;

  uint16_t i;
  uint32_t c = strip.Color(123, val, 123);
  uint32_t d = strip.Color(val, 100, val);
  uint32_t o = strip.Color(0, 0, 0); //off

  for(i=0; i< strip.numPixels(); i++) {
    strip.setPixelColor(i, c );
    
  }
  strip.show();

}
Click to Expand
0

Illustration

0
ButtonMash Crossing
Melanie Zeng - https://youtu.be/oniKodlHzgs
x
Share this Project

Courses

49713 Designing for the Internet of Things

· 18 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.


About

A set of augmented objects to allow pedestrians at stop light to interact with other pedestrians on the other side of the street.

Created

February 18th, 2019