This class, Introduction to Physical Computing, has covered both the technical and design of electronic devices in depth.  These teachings and practice culminated in this final project: creating an assistive device for someone else. Specifically, these devices were designed for older individuals who we could have a significant impact on.  Our group, Enrique’s Gizmos, collaborated with an older individual, Enrique, in order to ideate and develop our device. Initially, we met with Enrique to brainstorm different challenges and annoyances in his life that we could possibly solve.  This meeting concluded with our challenge: to create a device that could help motivate older individuals to exercise. This meeting was documented here: https://courses.ideate.cmu.edu/60-223/s2018/work/initial-meeting-documentation/ .  After deliberating and prototyping different possibilities to achieve this, our group decided to create the FitBox.  The FitBox is a fitness tracker, planner, and motivator. Some initial circuits and designs were brought to a showcase to be given feedback.  This meeting was documented here: https://courses.ideate.cmu.edu/60-223/s2018/work/team-enriques-gizmos/ .  After receiving feedback on our design for the FitBox, we worked towards the final iteration, and showcased the device and how it could help to Enrique, the other older individuals who worked with the other groups, and other participants at a design fair.

 

The FitBox is a fitness planner, tracker, and motivator.  It is a wearable, rechargeable, device similar in design to a beeper.  Firstly, the device creates an exercise routine based off of different exercises including goals and rests which are displayed on a screen on the front.  The goals of these exercises change depending on the user’s previous performance. For example, if the user completed all repetitions of an exercise, the next time the exercise is done, the goal number of repetitions would be higher.  If the user had to skip some repetitions, the goal would be lower next time. The FitBox also tracks a users performance. It can act as a timer or track and record steps or repetitions of an exercise. When the user completes an exercise, a melody is played to notify them that they completed the exercise, and to provide a congratulations to help motivate them to continue exercising.  The device motivates by recording previous personal records on exercises, too. It stores all this information and, even if the device loses power, will remember it when it is powered again through its rechargeable battery.

 

The Fitbox in its entirety

The back of the Fitbox has velcro straps to hook around your belt

The inside of the Fitbox is very compact with very few wires

Different angle of the inside of the Fitbox

The LCD lets you know when the Fitbox is setting up (calibrating the accelerometer)

Going through the planking exercise

When you finish an exercise, rest for 15 seconds

When you press “pause”, this screen pops up

 

When Enrique decides to begin his exercise for the day, he goes to his shelf, where his fitbox sits. He puts the fitbox on his belt, and pushes the “play” button to begin his routine.  A countdown begins and he readies himself for exercise. When the countdown completes, the screen changes and tells him to do a plank for thirty seconds. After that time is up, the box plays a jingle to tell him that this time is up. After a short resting period the fitbox prompts him that is is time for the next exercise. He completes a few more exercises, but gets tired and decides to skip his daily walk of 1000 steps. At the end of that day’s workout routine, the screen tells him that he has set a new personal record for planking.

The next day he returns to his fitbox for his daily exercise. After the initial countdown, the first exercise begins: planks. However this time he notices that his goal has increased to thirty-two seconds. He feels good about the progress he is making. That day when he reaches that walking portion, Enrique sees that his goal has decreased. He feels like he can accomplish this new walking goal and sets off on an enjoyable stroll.

 

The device we decided to create to tackle the problem of fitness motivation, was, admittedly, a complex one.  The features we deemed necessary such as a compact size to make it wearable and motion tracking proved rather difficult, and the road to our final FitBox was wrought with trial-and-error, difficult decisions, and breakdowns.  In the end, we had to consider what was necessary and what wasn’t for a minimally viable product. Our finished device expanded beyond the minimum, but different features had to be removed or changed along the way.

It should also be noted that our final build plan including our schedule and final features of the device changed, as well.  They proved useful to keep the design and build process on track and working toward a known goal, but as progress was made and difficulties found, both had to be changed to fit the current situations.

An initial major hurdle was creating a method of recording motion.  One of our major design parameters was ergonomics. We wanted the FitBox to be something that Enrique could use without much difficulty or interference into his normal routine: if it was inconvenient to use, then it likely wouldn’t be used.  We thought of two feasible means of recording motion. The first was to have some type of button or pressure sensor that could be put on the bottom of one’s shoe. The second was to use an accelerometer to record and compare the accelerations of the device and correlate them with a movement.  After some serious discussion, the latter option was chosen. The pressure sensor would likely be more robust and simpler, but it would limit the types of motions that could be recorded to ones where pressure of the user’s foot on the floor changes such as walking or squats. It also would have been quite cumbersome and unseemly as wire or special shoe covering/attachment would be needed.  This would get in the way of the user’s normal range of motion and would push them away from using the device. The accelerometer was more complex, but would be easier to integrate into the system and would open up the device to a much wider range of applications.

This decision was maintained to the final product, but the complexities of the accelerometer and signal processing did create multiple challenges and effected the final use of the device.  The actual processing of the accelerations read proved, in theory, much simpler and robust than was expected. It simply compared what it saw when the user was exercising to what it read when the user wasn’t.  To our surprise, this method was able to fairly accurately measure repetitions of most movements whether moving fast or slow. Other features had to be created to accommodate this, though, and this did affect the final FitBox by causing the user to have to stand still for approximately 15 seconds so as to allow the FitBox to figure out what it looked like when the user was standing still.  This was a slight, but, seemingly necessary inconvenience that was created for the user in the final device. The development of this also pushed our build off schedule by one or two days from final build plan.

Working on optimizing the circuitry, with prototype Fitbox shown

One of the most impactful issues was not creating a device that worked, however.  It was creating a device that was usable based on the criterion stated above: specifically compact and wearable.  These characteristics that we deemed necessary for the final device to be a success greatly impacted our timeline and gave rise to many unforeseen issues.

In order to create a device that was as small as possible, all of the electronics had to be packed as close together as possible in a housing that would hold it in that shape.  This involved trying to decrease the number of wires used and attach all of the electronic components to thin boards. Attaching the electronics to the board was not difficult and was done fairly quickly.  Designing how to pack the electronics as close together as possible, though, took quite a bit of time and planning. In our final design plan, we expected designing how the circuit would be placed inside the housing to take only a day or less, but it ended up taking two or three days due to the limitations on ways we could connect and place the electronics in such constrained quarters.

How we wanted the layout to fit in the box

After soldering the Arduino Nano, Piezo buzzer, and accelerometer

How the buttons on the front panel were soldered to the rest of the circuit

We thought Enrique might not be wearing a belt the day of the final crit so we fashioned a belt out of rope for him

Fitting the LCD screen into the front panel

After soldering everything, we needed to dimension the walls of the box so we held everything together

The finalized Fitbox

After creating a reasonably sized design and creating a housing to fit around it, other issues due to the cramped size arose.  Most notably was a significant bug in the system where, if the device was moved too vigorously, the program and device would freeze.  We spent days trying to solve this problem that we never predicted would happen. It appears that the issue is possibly due to a connection that shakes loose when moved, however, after inspection both visually and with multimeters, the bad connection could not be found.  The complexity of solving this problem along with time constraints forced us to try and minimize the problem instead. By placing all of the circuitry inside the housing and securing it as well as possible, we reduced movements of electronics relative to each other. This drastically reduced how often it froze.  This issue, however, used up the final couple of days that we had planned for some simple exercise trials and a few other simple features like a low battery light. These features could not be added due to the freezing issue and, instead, we focused on creating a final product that was efficacious in its base purpose: to plan, track, and motivate exercising.  In further iterations, an integrated circuit would likely help negate this issue and the other extra features could be added to overall better the FitBox experience.

One of the preeminent features that had to be removed in order to create a viable device due to these time constraints was the dock.  In the final design plan, the dock would be a place the FitBox could plug into to give it more functionality (a menu to choose exercises, more buttons) and to charge at.  Due to the time constraints caused by the above issues and challenges, this aspect had to be completely neglected. This led to other features such as a sleep mode to also not be incorporated.  There wasn’t enough time to both deal with the above issues and add these many planned, useful features. Due to time constraints, efficacy and viability had to be held paramount.

 

Final Thoughts:

There were three major suggestions that were common in our feedback. First, the buzzer used should have been easier to hear. Second, people would like the ability to add or remove exercises from the list. Third, a more ergonomic design was desired. In regards to the louder buzzer, during most of our testing we were using the device without a completed enclosure in a small, fairly quiet room. At the crit, we had finished putting the top wood panel on the fitbox, there was significant background noise, and the room was high ceilinged. We had not noticed how quiet the buzzer was before that, but in the crit environment, it was barely audible. This would be fairly easy to change by simply switching the buzzer for a more powerful model and cutting small holes for the sound to be heard.

A number of people also commented on the physical form of the fitbox. Although it was small compared to its features, it could have been made smaller and more ergonomic. Specifically, moving the screen to the top of the box would have allowed the used to read the information displayed when actually wearing the device.  We hadn’t thought about that, and that would significantly change our project, especially when it comes to assembling the hardware. Our final version was taped together to allow for ease of access to the electronics (namely, the reset button), but this attachment method left the fitbox feeling unrefined. Both of these changes would be easy to implement, but we ran out of time for the final critique.  

Many people also asked for the ability to add or remove exercises. We were planning to do that with a dock so that the actual fitbox wouldn’t need extra buttons, but unfortunately we also ran out of time to do that. We definitely wanted this function as well, because we didn’t know what Enrique would want and we wanted to make sure that we covered all the bases to ultimately create a product that he would use.

One major takeaway from working with other people was that we’re very similar and it felt very natural to discuss these projects and daily life problems with them although we do see different problems within designs. It surprised us that Enrique didn’t consider himself as older and couldn’t really come up with any problems he had but he was able to suggest a lot of ideas for his friends who are presumably around the same age. We wished we could have met with him more, it might have been better to start the final project in the beginning of the semester by just meeting our older friends and brainstorming to flesh out ideas but not actually build anything until the end of the semester. That would help with gathering techniques throughout the semester because we would have in mind what we want to make, sort of like reading a homework assignment before the material is taught in class.

Overall, this project was an incredible learning experience.  We decided to tackle a fairly complex problem and some complex technology, but this added to the experience.  Through trial-and-error, debugging, and designing a technology such as the FitBox, we pushed our technical and design skills: testing what we could do.  This did cause some instances where design and ergonomics were held at the forefront while practicality and timeliness fell to the wayside, but this helped us learn all the more.  From being pressed by time and technology, we had to learn how to manage time, how to reign in an idea and create a minimally viable product, and had to solve problems we never could have predicted.  Our design knowledge also was pushed by designing the FitBox for someone else. Working with Enrique was delightful and we are very proud of what we were able to create.

Schematic

#include <EEPROM.h>

#include <MPU6050_tockn.h>

#include <MPU6050_tockn.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "pitches.h"


MPU6050 mpu6050(Wire);
LiquidCrystal_I2C lcd(0x3F, 16, 2);

// notes in the melody:
int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};

const int playButton = 5; //switch for play/pause
bool play = 0; //
bool buttonPressed = 0;
bool finishedForTheDay = 0;
bool countdownPlayed = 0;
const int skipButton = 8;
const int piezoPin = 7;
const int randomizeButton = 6;
const int muteButton = 9;
const int charger = 11;

long timer = 0;  //generic timer
long dockTimer = 0;
int steps = 0;  //number of steps
int sslimit = 155; //limit that determines if user is standing still or moving
int stepOn = 0;  //generic variable I used to check if the user is mid-step
bool mute = 0;
bool charging = 0;

//exercise = [accel threshold, goal rep, current rep, skip/paused, personal record]
//int pause[5] = {0, 0, 0, 0, 0};
const int numExercises = 7; //number of exercises including pause

//int exercises[][5] = { {pause},
//  {walk}, {squats}, {calfRaise}, {stepUps},
//  {straightLegRaise}, {bentKneeRaise}, {backExtension}
//};
unsigned int exercises[numExercises][5] = {
  {sslimit, 1000, 0, 0, 1000}, //0. walk
  {sslimit, 10, 0, 0, 10}, //1. squat
  {sslimit, 6, 0, 0, 6}, //2. calf raises
  {0, 10, 0, 0, 10}, //3. arm raises
  {0, 600000, 0, 0, 50000}, //4. biking
  {sslimit, 20, 0, 0, 10}, //5. rowing
  {0, 900000, 0, 0, 10000}, //6. dancing
};

String nameExercises[numExercises] = {
  "walk ",
  "squat ",
  "calf raise ",
  "arm raise ",
  "biking ",
  "rowing ",
  "dance ",
};

int pausedTime = 0; //keeps the time when pause is pressed
int function = 0; //used to keep track of what was printed

const int numDailyExercises = 7; //number of exercises he should do daily
int dailyExercise[numDailyExercises] = {3, 2, 1, 4, 5, 0, 1}; //keeps track of which activities he should do for the day
int currentExercise = 0; //index to note which exercise is currently being done in dailyExercise
int currentReps;
int goal;  //goal number of steps
int goalPlc = 0;  //where to write the next segment on the display
int goalWrt = 0;  //variable to make sure the user has a different number of steps before writing another segment
int i = 0; //index for keeping track of which PR was printed


void setup() {
  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(piezoPin, melody[thisNote], noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    // stop the tone playing:
    noTone(piezoPin);
  }
  Serial.begin(9600);
  //saveData();
  getData();

  lcd.init();  //initializes lcd
  lcd.backlight();  //turns on lcd backlight
  lcd.print("Setting up");
  lcd.setCursor(0, 1);
  lcd.print("Please dont move");
  Wire.begin();
  pinMode(13, OUTPUT);
  pinMode(playButton, INPUT_PULLUP);
  pinMode(skipButton, INPUT_PULLUP);
  pinMode(randomizeButton, INPUT_PULLUP);
  pinMode(muteButton, INPUT_PULLUP);
  pinMode(charger, INPUT);
  digitalWrite(13, HIGH); //to visualize set up with Arduino's onboard LED
  mpu6050.begin();  //begins accelerometer setup
  mpu6050.calcGyroOffsets(true);  //calculates gyroscope starting position
  recal(); //recalibrates acceleration and sets new steady state value
  digitalWrite(13, LOW); //turns off onboard LED when initial calibration is done
}

void loop() {
  //check if charging first
  if (digitalRead(charger)) {
    charging = 1;
  }
  if (!charging) {
    if (!digitalRead(playButton) && !buttonPressed) {
      Serial.println("BUTTON PRESSED");
      buttonPressed = 1;
      play = !play;
    }

    else if (digitalRead(playButton)) {
      buttonPressed = 0;
    }

    if (play) {
      if (!finishedForTheDay) {
        Serial.println("playing");
        if (playTracking()) {
          finishedReps();
        }
      }
      if (finishedForTheDay) {
        resetExercises();
      }
    }

    if (!play || finishedForTheDay) {
      //Serial.println("paused");
      pauseTracking();
    }

    if (!digitalRead(skipButton)) {
      skipExercise();
    }

    if (!digitalRead(muteButton)) {
      mute = 1;
    }

    if (digitalRead(muteButton)) {
      mute = 0;
    }
  }

  else if (charging) {
    //dockMenu();
    if (!digitalRead(randomizeButton)) {
      randomizeExercises();
    }
  }
  //Serial.println("function: " + String(function));

}


//recalibrates
void recal() {
  lcd.clear();
  lcd.print("Setting up");
  lcd.setCursor(0, 1);
  lcd.print("Please dont move");
  int ssXmax = -500;  //generic placeholder variables
  int ssYmax = -500;
  int ssZmax = -500;
  timer = millis();
  while (millis() - timer < 5001) { if ((millis() - timer) % 50 == 0) //reads the accelerometer every 50 milliseconds for 5 seconds and makes placeholders maximums { int xacc = mpu6050.getAccX() * 100; int yacc = mpu6050.getAccY() * 100; int zacc = mpu6050.getAccZ() * 100; if (xacc > ssXmax) {
        ssXmax = xacc;
      }
      if (yacc > ssYmax) {
        ssYmax = yacc;
      }
      if (zacc > ssZmax) {
        ssZmax = zacc;
      }
    }
  }
  sslimit = ssXmax + ssYmax + ssZmax + 10; //adds maximum accelerations with a bias term to create standard ssLimit to compare readings to
  for (int i = 0; i < numExercises; i++) { //update the acceleration for each repped exercise if (exercises[i][0] * 100 > 0) {
      exercises[i][0] = sslimit;
    }
  }
}

void countdown() {
  countdownPlayed = 1;
  if (function != 1) {
    lcd.clear();
    lcd.setCursor(14, 1);
    lcd.print("||");
    lcd.setCursor(0, 0);
    lcd.print("Exercise will");
    lcd.setCursor(0, 1);
    lcd.print("begin in ");
    function = 1;
    timer = millis();
  }
  while (millis() <= timer + 5000) { //print every second if ((millis() - timer) % 1000 == 0) { //print time left until starting lcd.setCursor(9, 1); lcd.print(String(5 - ((millis() - timer) / 1000)) + " "); } } //delay(250); } //run fxn when unpaused (button press) bool playTracking() { //Serial.println("sslimit: " + String(sslimit)); //countdown only before first exercise of the day if (!countdownPlayed) { //currentExercise = 0; countdown(); } lcd.setCursor(14, 1); lcd.print(">>");
  int foo = dailyExercise[currentExercise]; //for easier reading
  //Serial.println("foo: " + String(foo));
  //Serial.println("testing: " + String(walk[1]));
  Serial.println("limit: " + String(exercises[foo][0]));
  //Serial.println("goal: " + String(exercises[foo][1]));
  //Serial.println("current: " + String(exercises[foo][2]));
  //Serial.println("PR: " + String(exercises[foo][4]));
  Serial.println("current exercise: " + String(currentExercise));
  int goal = exercises[foo][1];  //goal number of reps
  //int goalSeg = goal / 16; //number of steps per display segment lighting up

  mpu6050.update();  //updates accelerometer with new reading
  //check if this is a timed exercise or not
  if (exercises[foo][0] * 100 > 0 && millis() - timer > 50) //reads accelerometer every 50 milliseconds
  {
    int xacc = mpu6050.getAccX() * 100; //reads accelerometer X,Y, and Z accelerations and scales them up by 100 to better see on the plotter
    int yacc = mpu6050.getAccY() * 100;
    int zacc = mpu6050.getAccZ() * 100;
    Serial.println(String(mpu6050.getAccX() * 100) + " " + String(mpu6050.getAccY() * 100) + " " + String(mpu6050.getAccZ() * 100) + " " + String(exercises[foo][2] * 10)); //prints out data for plotter
    if (stepOn == 0) { //adds a step if reading is above ssLimit; toggles on/off if user croses the ssLimit threshold
      if (xacc + yacc + zacc > exercises[foo][0]) {
        exercises[foo][2]++;
        stepOn = 1;
      }
    }
    if (xacc + yacc + zacc < exercises[foo][0]) {
      stepOn = 0;
    }
    if (function != 2) {
      lcd.clear();
      Serial.println(nameExercises[foo]);
      lcd.print(nameExercises[foo] + String(exercises[foo][1]) + "   ");
      lcd.setCursor(0, 1);
      lcd.print("Current: ");
      function = 2;
    }
    lcd.setCursor(9, 1); //sets cursor to after "Current: "
    lcd.print(String(exercises[foo][2]));  //writes number of reps
    timer = millis();  //updates timer
  }

  //if this is a timed exercise, then dont count reps, count time
  if (exercises[foo][0] == 0) {
    Serial.println("timed function");
    if (function != 3) {
      timer = millis();
      lcd.clear();
      if (exercises[foo][1] < 60000) { lcd.print(nameExercises[foo] + String(exercises[foo][1] / 1000) + "s "); } else if (exercises[foo][1] >= 60000){
        lcd.print(nameExercises[foo] + String(exercises[foo][1] / 60000) + "min");
      }
      lcd.setCursor(0, 1);
      lcd.print("Current: ");
      function = 3;
    }
    exercises[foo][2] = millis() - timer + pausedTime;
    if (millis() > timer + 1000) {
      lcd.setCursor(9, 1); //sets cursor to after "Current: "
      lcd.print(String(exercises[foo][2] / 1000));
    }
  }

  //check if goal was hit for that exercise
  if (exercises[foo][2] >= exercises[foo][1]) {
    return true;
  }
  return false;
}


void finishedReps() {
  int foo = dailyExercise[currentExercise]; //for easier reading
  if (!mute) {
    for (int thisNote = 0; thisNote < 8; thisNote++) {

      // to calculate the note duration, take one second divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      int noteDuration = 1000 / noteDurations[thisNote];
      tone(piezoPin, melody[thisNote], noteDuration);

      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      // stop the tone playing:
      noTone(piezoPin);
    }
  }

  if (function != 4) {
    lcd.clear();
    lcd.print("You're done with");
    lcd.setCursor(0, 1);
    lcd.print("this exercise!");
    function = 4;
    delay(3000);
  }

  //if this is the last exercise then say you're done for the day
  if (currentExercise == numDailyExercises - 1) {
    pausedTime = 0;

    finishedExercise();
  }

  //if it's not the last exercise then move onto the next one
  else if (currentExercise < numDailyExercises) {
    if (function != 6) {
      lcd.clear();
      lcd.print("Rest for 15 sec");
      timer = millis();
      while (millis() <= timer + 15000) {
        //print every second
        if ((millis() - timer) % 1000 == 0) {
          //print time left until starting
          lcd.setCursor(0, 1);
          lcd.print(String(15 - ((millis() - timer) / 1000)) + " ");
        }
      }
      delay(250);
      function = 6;
    }
    currentExercise++;
    lcd.clear();
    lcd.print("Moving on");
    if (exercises[foo][0] == 0) {
      timer = millis();
    }
    pausedTime = 0;
    delay(2000);
  }
}


//runs when switch is on pause
void pauseTracking() {
  play = 0;
  if (function != 7) {
    lcd.clear();
    lcd.print("PAUSED");
    Serial.println("paused");
    lcd.setCursor(0, 1);
    lcd.print("press to play");
    lcd.setCursor(14, 1);
    lcd.print("||");
    //delay(3000);
    if (finishedForTheDay) {
      lcd.setCursor(0, 1);
      lcd.print("done for the day");
      delay(2000);
      lcd.clear();
      lcd.print("press play");
      lcd.setCursor(0, 1);
      lcd.print("to reset");
      //delay(1000);
    }
    function = 7;
  }

  exercises[dailyExercise[currentExercise]][3] = 1;
  //if it's a timed exercise then record the time when it was paused
  if (exercises[dailyExercise[currentExercise]][0] == 0) {
    pausedTime = exercises[dailyExercise[currentExercise]][2];
  }
}


//runs when skip button is pressed
void skipExercise() {
  if (function != 9) {
    lcd.clear();
    lcd.print("skipped exercise");
    function = 9;
  }
  exercises[dailyExercise[currentExercise]][3]++;
  if (currentExercise == numDailyExercises - 1) {
    pausedTime = 0;
    if (!mute) {
      for (int thisNote = 0; thisNote < 8; thisNote++) {

        // to calculate the note duration, take one second divided by the note type.
        //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
        int noteDuration = 1000 / noteDurations[thisNote];
        tone(piezoPin, melody[thisNote], noteDuration);

        // to distinguish the notes, set a minimum time between them.
        // the note's duration + 30% seems to work well:
        int pauseBetweenNotes = noteDuration * 1.30;
        delay(pauseBetweenNotes);
        // stop the tone playing:
        noTone(piezoPin);
      }
    }
    finishedExercise();
  }
  currentExercise++;
  pausedTime = 0;
  delay(1000);
}

void finishedExercise() {
  saveData();
  if (!mute) {
    for (int thisNote = 0; thisNote < 8; thisNote++) {

      // to calculate the note duration, take one second divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      int noteDuration = 1000 / noteDurations[thisNote];
      tone(piezoPin, melody[thisNote], noteDuration);

      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      // stop the tone playing:
      noTone(piezoPin);
    }
  }
  if (function != 8) {
    lcd.clear();
    lcd.print("You finished");
    lcd.setCursor(0, 1);
    lcd.print("for today!!");
    delay(3000);
    function = 8;
  }
  finishedForTheDay = 1;
  pauseTracking();
}


void randomizeExercises() {
  for (int i = 0; i < numDailyExercises; i++) { dailyExercise[i] = random(0, numExercises); } Serial.println("Exercises randomized!"); } void showPR() { if (millis() > dockTimer + 30000) {
    Serial.println(exercises[dailyExercise[i]][4]);
    dockTimer = millis();
    i++;
    if (i == numDailyExercises) {
      i = 0;
    }
  }
}


void resetExercises() {
  lcd.clear();
  lcd.print("resetting");
  delay(1000);
  //lcd.print(String(hour()) + ":" + String(minute()));
  //make new reps and reset current reps
  for (int i = 0; i < numExercises; i++) { //check if PR was beat if (exercises[i][2] > exercises[i][4]) {
      exercises[i][4] = exercises[i][2];
      lcd.clear();
      lcd.print("You beat your");
      lcd.setCursor(0, 1);
      lcd.print(nameExercises[i] + " PR");
      delay(1500);
      Serial.println(exercises[i][4]);
      lcd.clear();
      lcd.print("Your new record");
      lcd.setCursor(0, 1);
      lcd.print("is: ");
      if (exercises[i][0] * 100 > 0) {
        lcd.print(String(exercises[i][4]));
      }
      else if (exercises[i][0] * 100 == 0) {
        lcd.print(String(exercises[i][4] / 1000));
      }
      //function = 5;
      delay(2000);
    }
    //if exercise was skipped/paused, decrease number of reps
    if (exercises[i][3] == 1) {
      if (exercises[i][0] * 100 > 0) {
        if (exercises[i][1] > 2) {
          exercises[i][1] -= 2;
        }
      }
      else if (exercises[i][0] == 0) {
        if (exercises[i][1] > 2000) {
          exercises[i][1] -= 2000;
        }
      }
      exercises[i][3] = 0;
    }
    //if not skipped, increase reps by 2 and time by 2 sec
    else if (exercises[i][3] == 0) {
      if (exercises[i][0] * 100 > 0) {
        exercises[i][1] += 2;
      }
      else if (exercises[i][0] == 0) {
        exercises[i][1] += 2000;
      }
    }
    exercises[i][2] = 0;
  }

  //randomizeExercises()
  recal();
  lcd.clear();
  lcd.print("done resetting!");
  //lcd.setCursor(0, 1);
  //lcd.print("press to play");
  play = 1;
  countdownPlayed = 0;
  currentExercise = 0;
  finishedForTheDay = 0;
  delay(2000);
}


void saveData()
{
  int addr = 0;
  for (int ex = 0; ex < numExercises; ex++)
  {
    EEPROM.put(addr, exercises[ex][1]);
    addr = addr + 2;
    EEPROM.put(addr, exercises[ex][3]);
    addr = addr + 2;
    EEPROM.put(addr, exercises[ex][4]);
    addr = addr + 2;
  }
}

void getData()
{
  int addr = 0;
  for (int ex = 0; ex < numExercises; ex++)
  {
    EEPROM.get(addr, exercises[ex][1]);
    addr = addr + 2;
    EEPROM.get(addr, exercises[ex][3]);
    addr = addr + 2;
    EEPROM.get(addr, exercises[ex][4]);
    addr = addr + 2;
  }
}

/*************************************************
 * Public Constants
 *************************************************/

#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978