Coast to Coasters

Share a drink across the world with internet-connected coasters! These internet-linked coasters notify when the other person is drinking alone and when you are drinking at the same time, providing a sense of connection.

Collaboration with Aaron Kurth, Lynn Sandberg, and Gregor Stodtmeister. Full Writeup

ARDUINO


/*
  Coast to Coasters

  Internet-connected drink coaster pairs respond to
  when the other coaster is being used. The same code
  can be flashed to both devices.

  @author Gregor Stodtmeister, Stephen Nomura
  @version 0.3 2016-02-10
*/


/* CONSTANTS & VARIABLES
------------------------------------------------------*/
const String myID = Particle.deviceID();

const int greenPins1 = D0;
const int greenPins2 = D1;
const int bluePins1  = D2;
const int bluePins2  = D3;
const int buttonPin  = D4;

int buttonState      = HIGH;
int buttonStatePrev  = HIGH;
int friendStatus     = 0;
int myStatus         = 0;

/* SETUP
------------------------------------------------------*/
void setup(){
  pinMode(buttonPin,  INPUT_PULLUP);
  pinMode(greenPins1, OUTPUT);
  pinMode(greenPins2, OUTPUT);
  pinMode(bluePins1,  OUTPUT);
  pinMode(bluePins2,  OUTPUT);
  Particle.subscribe("873907-drinking", eventHandler);
  nobodyDrinking();
}

/* LOOP
------------------------------------------------------*/
void loop(){
  monitorButton();
  updateLights();
  // monitoring other particle is also being called in
  // background, despite not being mentioned here
}

/* PRIMARY FUNCTIONS
------------------------------------------------------*/
void eventHandler(const char *event, const char *data){
  String dataString = String(data);

  // Chop up string into data chunks
  int delIndex = dataString.indexOf(':');
  String firstValue = dataString.substring(0, delIndex);
  String secondValue = dataString.substring(delIndex+1);

  // Assign to human-readable vars
  String theID = firstValue;
  int theStatus = secondValue.toInt();

  // If source of data isn't myself...
  if( myID != theID ){
    friendStatus = theStatus;
  }
}

int monitorButton(){
  buttonState = digitalRead(buttonPin);
  String dataToSend;
  if(buttonState != buttonStatePrev){
    
    // Button pressed
    if(buttonState == LOW){
      myStatus = 1;
      dataToSend = myID + ":" + myStatus;
      Particle.publish("873907-drinking", dataToSend);
    }
    
    // Button released
    if(buttonState == HIGH){
      myStatus = 0;
      dataToSend = myID + ":" + myStatus;
      Particle.publish("873907-drinking", dataToSend);
    }
  }

  delay(50); // Prevent bounce
  buttonStatePrev = buttonState;
}

void updateLights(){
  if( myStatus == 0 && friendStatus == 0 ) nobodyDrinking();
  if( myStatus == 1 && friendStatus == 0 ) drinkingAlone();
  if( myStatus == 0 && friendStatus == 1 ) friendDrinking();
  if( myStatus == 1 && friendStatus == 1 ) drinkingTogether();
}

/* LED STATE FUNCTIONS
------------------------------------------------------*/
void nobodyDrinking(){
  // Both LED Arrays OFF
  digitalWrite(greenPins1, 255);
  digitalWrite(bluePins1,  255);
  digitalWrite(greenPins2, 255);
  digitalWrite(bluePins2,  255);
}
void drinkingAlone(){
  // Both LED Arrays GREEN
  digitalWrite(greenPins1,   0);
  digitalWrite(bluePins1,  255);
  digitalWrite(greenPins2,   0);
  digitalWrite(bluePins2,  255);
}
void friendDrinking(){
  // Both LED Arrays BLUE
  digitalWrite(greenPins1, 255);
  digitalWrite(bluePins1,    0);
  digitalWrite(greenPins2, 255);
  digitalWrite(bluePins2,    0);
}
void drinkingTogether(){
  // Blink between:
  // Array 1 GREEN, Array 2 BLUE
  // Array 1 BLUE,  Array 2 GREEN
  digitalWrite(greenPins1,   0);
  digitalWrite(bluePins1,  255);
  digitalWrite(greenPins2, 255);
  digitalWrite(bluePins2,    0);
  delay(500);
  digitalWrite(greenPins1, 255);
  digitalWrite(bluePins1,    0);
  digitalWrite(greenPins2,   0);
  digitalWrite(bluePins2,  255);
  delay(500);
}