This gym ecosystem connects a gym member’s wristband, locker, mirror, and weight equipment in order to build a community, improve workouts, and optimize usage.

0

Goal and Vision

To create an unobtrusive ecosystem of devices which enhances connectedness between gym participants and empowers gym management.

0

Design Process

Step 1: User Research

We visited gyms in the Pittsburgh area, ranging in usefulness and cost. We spoke to users of the gym and employees to develop insights which informed our ideation process.

Step 2: Create Object Inventories

We took inventories of the objects and devices in gyms to discover what opportunities existed. 

Step 3: Develop Ideation and System Mapping

We met as a team to discuss our individual ideas, develop criteria for narrowing down to the best idea, and we silently voted on our favorite ecosystem concept. 

Step 4: Creation 

We created a video scenario, and five prototypes, a dumbbell, barbell, mirror, wristband, and locker that were connected.

Step 5: Test

We tested the connected devices to make sure they all synced and worked with the desired scenario.

0

Prototyped Solutions

Our prototyped solutions build a community within the gym infrastructure. These devices help facilitate sharing knowledge between beginners and advanced gym members. These devices also improve a gym member’s workout through notifications of which machines are free and by tracking sets and reps, this helps increase efficiency of the gym equipment usage, and can help administration schedule equipment maintenance.

These connected devices include: a wristband, a dumbbell, a barbell, a mirror, and a locker. 

0
Whiteboarding the Device Interaction
Screen shot 2016 03 01 at 4.44.14 pm.thumb
0
Developing Ideas
Screen shot 2016 03 01 at 4.44.36 pm.thumb
0
Storyboarding the Scenario
Screen shot 2016 03 01 at 4.44.05 pm.thumb
0

The Connected Mirror

The iPads that display information in the Magic Mirror are displaying information through their web browsers. The browsers are loading up webpages that respond in real-time to events sent from the Photons. Since the Photons cannot connect directly to the iPads, events are routed through an intermediary system built on our web server. PHP, JS/jQuery, and Server Sent Events (SSE) are the core technologies used. When an event is fired from a photon, the following sequence is executed:

1 - A Photon pings the command file on our web server using a GET request. Data is passed via URL parameters. This is our makeshift API.

2 - The command file interprets the Photon's request and records the passed data to a static text file. This is our makeshift database.

3 - A special data stream script is set up to watch the data file. If it notices any changes, it will broadcast the new data out to any listening web clients.

4 - The iPads receive the data and respond by updating what they show on their screens.
We chose SSE over Websockets because we did not need bidirectional communication. We chose SSE over AJAX polling because we wanted faster response times and a reduced server load.  

0
Server code for running magic mirror backend and interface pages.
0
Connected Mirror
Img 5240 1024.thumb
0
Inside the Connected Mirror
Img 5239 1024.thumb
0

The Connected Locker

The Connected Locker is the starting point at the gym. Traditional lockers are generally not safe and the emotional attachment between the user and the object is very low. By allowing the user to open the locker with the Connected Wristband and reminding the user where the locker is, we empower the user to enhance the locker experience for the moment they are using the gym.  

Once the user opens the Connected Locker with the Connected Wristband, it sends a notification alerting the user of his locker number. This gives the user an increased sense of security because he'll now be alerted when the locker is accessed by anyone else. Furthermore, throughout the workout session, the user can check his locker number by tapping any of the mirrors in the gym. This saves him from losing his locker, which ties back to the increased sense of security.

0
Code for the Locker
//Locker code
//Reads the hall effect sensor and actuates the solenoid to read the locker

//Set pins
int hallpin = A0;
int solenoidPin = D1;
int hallEffectValue = 0;

void setup()
{
  pinMode(hallpin, INPUT); //Reads the hall effect sensor
  pinMode(solenoidPin, OUTPUT); //Moves the solenoid
  Serial.begin( 9600 ); //Read serial for insta-feedback!
}

void loop()
{
  //read hall effect value
  hallEffectValue = analogRead(hallpin);
  if (hallEffectValue < 100){ //Performs this sequence if the magnet is near.
    digitalWrite(solenoidPin, HIGH); //Unlocks the locker
    Particle.publish("lockernum", "23"); //send information to ifttt/Kana's apple watch!!
    delay(500); //Wait a few seconds to open the door
  }
  else digitalWrite(solenoidPin, LOW); //close the lock after a few seconds
  Serial.print( "Sensor reading is: " ); //Writes the hall effect value to the serial monitor
  Serial.println( hallEffectValue );
  delay(500);
}
Click to Expand
0
Diagram of the Locker Circuit
Locker diagram   copy.thumb
0
Connected Locker
Img 5228 1024.thumb
0
Wiring of Connected Locker
Img 5229 1024.thumb
0

The Connected Barbell

The user activates the Connected Barbell via the Connected Wristband. This activation sends an event to the Magic Mirror, which provides a welcome message. A set and rep count then display and increment as the user completes their routine . Once the routine is complete, the Connected Barbell deactivates and the user moves on. The Magic Mirror then displays machine availability. With the Connected Barbell, the user no longer needs to use rudimentary recording methods like pencil and paper to track their fitness goals and workout progress.

This device uses a Hall Effect sensor to replicate RFID tracking via the Connected Wristband. Using a Hall Effect sensor allowed us to place a magnet in the wristband to mimic user identification. To increment reps and sets, the device then uses an ultrasonic rangefinder. The ultrasonic rangefinder readings are continuously captured and two sets of rolling averages are maintained and compared. Differences between the two sets indicate that the direction of motion of the barbell has reversed indicating the completion of a set. Activation occurs when the user lifts the barbell upward, prompting an event that increments reps and displays those reps through the Magic Mirror device. 

0
Connected Barbell Code
#include "HttpClient.h" //Include HTTPClient Library

int i=0;
int reps=0;
int numOfReadings=45;
int div1=22;
int div2=22;
double averageDistance1;
double averageDistance2;
int readings[45];
int echoPin=D2;
int initPin=D3;
unsigned long pulseTime=0;
unsigned long distance=0;
unsigned long total1=0;
unsigned long total2=0;
int hallPin=D0;
int hallRead;
int blueLed = D7;
int arrayIndex = 0;

int threshold=5;
int delayTime=50;

//Initialize HTTP Client and variables
HttpClient http;
http_request_t request;
http_response_t response;

//Default HTTP Header settings
http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { NULL, NULL }
};

void setup()
{
  pinMode(initPin , OUTPUT);
  pinMode(echoPin,INPUT);
  pinMode(hallPin,INPUT);
  pinMode(blueLed, OUTPUT);

  Serial.begin(9600);

  //Initialize the readings array
  for (int thisReading = 0; thisReading < numOfReadings; thisReading++)
  {
    readings[thisReading] = 0;
  }

    //HTTP rrequest setup/configuration. No changes should be made
    request.hostname = "nomu.co";
    request.port = 80;
    request.body = NULL;

}

void loop()
{
  Login1(); //Check for hall effect reading

  Repetitory();

  //logsoneout();

  delay(100);
}

void Login1()
{
  hallRead= digitalRead(hallPin);

  if (hallRead==LOW)// checks user in
  {
    Serial.println("checkin");
    i++;
    //Particle.publish("reg");
    request.path = "/lab/photon-gym-mirror/command.php?event=checkin";
    http.get(request, response, headers);
    delay(3000);
    request.path = "/lab/photon-gym-mirror/command.php?event=set-start";
    http.get(request, response, headers);
    delay(1000);
  }
}

void Repetitory()
{
  while((i%2)==1)
  {
    digitalWrite(initPin, HIGH);                    // send 10 microsecond pulse
    delayMicroseconds(10);                          // wait 10 microseconds before turning off
    digitalWrite(initPin, LOW);                     // stop sending the pulse
    pulseTime = pulseIn(echoPin, HIGH);             // Look for a return pulse, it should be high as the pulse goes low-high-low
    distance = pulseTime/58;                        // Distance = pulse time / 58 to convert to cm.

    if (arrayIndex>0 and arrayIndex<23)
    {
      total1 = total1 - readings[arrayIndex]; // subtract the last distance
      readings[arrayIndex] = distance;        // add distance reading to array
      total1 = total1 + readings[arrayIndex];  // add the reading to the total
    }
    if (arrayIndex>=23 and arrayIndex<=45)
    {
      total2 = total2 - readings[arrayIndex];           // subtract the last distance
      readings[arrayIndex] = distance;                // add distance reading to array
      total2 = total2 + readings[arrayIndex];
    }

    arrayIndex++;
    if(arrayIndex>=45)
    {
      arrayIndex=0;
    }


    digitalWrite(blueLed, HIGH);
    delay(delayTime);
    digitalWrite(blueLed, LOW);

    //Serial.println(distance);
    //Serial.println(averageDistance1);
    //Serial.println(averageDistance2);
    //Serial.println("New Reading");

    averageDistance1 = total1 / div1;      //calculate the average distance over 0.5 seconds                      // Distance = pulse time / 58 to convert to cm.
    averageDistance2 = total2 / div2;      //calculate average distance over second 0.5 seconds

    if (averageDistance1 > averageDistance2 + threshold && arrayIndex == 44)// checks for change in direction=1 rep
    {
      reps++;

      request.path = "/lab/photon-gym-mirror/command.php?event=reps-increment";
      http.get(request, response, headers);

      //Troubleshooting
      //Serial.println("Rep Complete");
      //Serial.println(averageDistance1);
      //Serial.println(averageDistance2);

      if(reps>=5)
      {
        reps=0;
        delay(1000);
        request.path = "/lab/photon-gym-mirror/command.php?event=set-end";
        http.get(request, response, headers);
        delay(3000);
        request.path = "/lab/photon-gym-mirror/command.php?event=set-start";
        http.get(request, response, headers);
        delay(1000);
      }
    }
    logsoneout();
    //delay(50);
  }
}

void logsoneout()
{
  if (digitalRead(hallPin)==LOW)// checks user out, resets rep counter
  {
    i++;
    Serial.println("Logout");
    request.path = "/lab/photon-gym-mirror/command.php?event=set-end";
    http.get(request, response, headers);
    reps=0;
    delay(3000);
    request.path = "/lab/photon-gym-mirror/command.php?event=checkout";
    http.get(request, response, headers);
    delay(2000);
  }
}
Click to Expand
0
Connected Barbell
Barbell4 1024.thumb
0

The Connected Dumbbell

The user activates the Connected Dumbbell via the Connected Wristband. This activation sends an event to the Magic Mirror, which provides a welcome message. A set and rep count then display and increment as the user completes their routine . Once the routine is complete, the Connected Dumbbell deactivates and the user moves on. The Magic Mirror then displays machine availability. With the Connected Dumbbell, the user no longer needs to use rudimentary recording methods like pencil and paper to track their fitness goals and workout progress. 

This device uses a Hall Effect sensor to replicate RFID tracking via the Connected Wristband. Using a Hall Effect sensor allowed us to place a magnet in the wristband to mimic user identification. To increment reps and sets, the device then uses a tilt sensor. Activation occurs when the user curls the dumbbell upward, prompting an event that increments reps and displays those reps through the Magic Mirror device. 

0
#include "HttpClient.h"

//Initialize HTTP Client and variables
HttpClient http;
http_request_t request;
http_response_t response;

//Default HTTP Header settings
http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { NULL, NULL }
};

//Initializes the hall effect sensor variable and tilt sensor variable
int hallPin = D2;
int tiltPin = D3;

//Records the state of the hall effect sensor and tilt sensor
int tiltState = 0;
int hallState = 0;

//Tracks dumbbell position rep counting, activation, and deactivation
int dumbbellStatus = 0;
int dumbbellPosition = 0;

//Tracks reps and sets
int repCounter = 0;
int setCounter = 0;


void setup ()
{

  //Set the hall effect and tilt sensors as input
  pinMode (hallPin, INPUT);
  pinMode (tiltPin, INPUT);

  //HTTP rrequest setup/configuration. No changes should be made
  request.hostname = "nomu.co";
  request.port = 80;
  request.body = NULL;
  //request.path = "/lab/photon-gym-mirror/command.php?event=checkin";

}


void loop ()
{

monitorRFID();
monitorReps();

}


/*The monitorRFID function handles the activation and deactivation 
of the device (via a hall effect sensor)*/
void monitorRFID()
{

  //Reads the status of the hall effect sensor
  hallState = digitalRead (hallPin);

  //If a magnet is present and the dumbbell isn't already activated...
  if (hallState == LOW && dumbbellStatus == 0)
  {

    //Send a checkin event to the magic mirror
    request.path = "/lab/photon-gym-mirror/command.php?event=checkin";
    http.get(request, response, headers);

    //Delay for five seconds to prevent overlap
    delay (5000);

    //Send a set start event to the magic mirror
    request.path = "/lab/photon-gym-mirror/command.php?event=set-start";
    http.get(request, response, headers);

    //Note that the dumbbell is currently activated
    dumbbellStatus = 1;
    
  }


  //Reads the status of the hall effect sensor
  hallState = digitalRead (hallPin);

  //If the magnet is present and the dumbbell is already activated
  if (hallState == LOW && dumbbellStatus == 1)
  {

    //Send a checkout event to the magic mirror
    request.path = "/lab/photon-gym-mirror/command.php?event=checkout";
    http.get(request, response, headers);

    // Delay five seconds to prevent overlap
    delay (5000);

    //Note that the dumbbell is currently inactivated
    dumbbellStatus = 0;

  }
}


/*The monitorReps function handles the rep-counting feature of the
connected dumbbells (via a tilt sensor)*/
void monitorReps()
{
  //Read the status of the tilt sensor
  tiltState = digitalRead (tiltPin);

  //If the dumbbells are activated...
  if (dumbbellStatus == 1)
  {

    //And if the tilt sensor has been activated
    if (dumbbellPosition == 0 && tiltState == HIGH)
    {

      //Set the dumbbell position
      dumbbellPosition = 1;

      //Increment the rep counter for later use
      repCounter++;

      //Send a rep increment event to the magic mirror
      request.path = "/lab/photon-gym-mirror/command.php?event=reps-increm      ent";
      http.get(request, response, headers);

      //Delay for one second to prevent overlap
      delay(1000);

    }

    //If the tilt sensor is deactivated
    else if (dumbbellPosition == 1 && tiltState == LOW)
    {

      //Set the dumbbell position
      dumbbellPosition = 0;

      //Delay for one second to prevent overlap
      delay(1000);

    }

    //Once the rep count reaches five...
    if (repCounter == 5)
    {

      //Send a set end event to the magic mirror
      request.path = "/lab/photon-gym-mirror/command.php?event=set-end";
      http.get(request, response, headers);

      //Set the rep count to zero
      repCounter = 0;

      //Increment the set count
      setCounter++;

      //Delay for seven seconds to prevent overlap
      delay(7000);
    }

    //If the set count is equal to or greater than one...
    if (setCounter >= 1)
    {

      //Send a set start event to the magic mirror (indicating a new set)
      request.path = "/lab/photon-gym-mirror/command.php?event=set-start";
      http.get(request, response, headers);

      //Decrement the set count
      setCounter--;
    }

  }

}
Click to Expand
0
Connected Dumbbell
Img 5236 1024.thumb
0
Wiring of Connected Dumbbell
Img 5237 1024.thumb
0

Personal Wristband

To replicate the experience of a personal wearable device, we utilized a simple foam core model containing a rare earth magnet to trigger the hall effect sensors embedded in each of our proty

0
Connected Wristband
Img 5233 1024.thumb
0

Reflections and Next Steps

After much ideation and iteration we have discovered that in any connected gym solution, it is important to account for many different stakeholders. Through out process we were very focused on the experience of the gym-goer, and making that experience as seamless as possible. Now that we have prototyped the gym-goer solutions and it is time to test the devices with gym members for user feedback. Additionally, we realize that the solution would require a data scientist team for the solution to effectively be implemented and be of high value to the gym. We realize that some gyms might find this doable and some might not. In the future we would like to develop concepts that would be easier for a gym to adopt without heavy data analysts and scientists working on algorithms to bring meaning. 

0
IoT - Connected Gym
Lynn Sandberg - https://www.youtube.com/watch?v=6zJ5WJQhgus
0
IoT Team 1 Final Demo
sohjjw - https://youtu.be/IGVDOlowGeU
x
Share this Project

Highlighted Project:
Courses

49-713 Designing for the Internet of Things

· 2 members

This course charts the emergence of the now "connected world" to explore the possibilities for future products and connected spaces.


Focused on
About

This gym ecosystem connects a gym member’s wristband, locker, mirror, and weight equipment in order to build a community, improve workouts, and optimize usage.