Connected Gym - Team Quantum
Made by K P, Lynn Sandberg, Andy Knapp, Joseph Johnson, Khanya Morolo, Gabriela Rubio, Stephen Nomura, David Hoysan, Jesse Park, John Soh and Ben Smith
Made by K P, Lynn Sandberg, Andy Knapp, Joseph Johnson, Khanya Morolo, Gabriela Rubio, Stephen Nomura, David Hoysan, Jesse Park, John Soh and Ben Smith
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.
Created: February 29th, 2016
To create an unobtrusive ecosystem of devices which enhances connectedness between gym participants and empowers gym management.
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.
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.
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.13.831 KB · Download / View
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.
//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
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.
#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
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.
#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
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.
This course charts the emergence of the now "connected world" to explore the possibilities for future products and connected spaces.
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.