Project tutorial
Personal Gym Timer

Personal Gym Timer © GPL3+

A hardware timer to support your gym workout, and can influence you to complete the exercises in predefined time period.

  • 2 views
  • 0 comments
  • 0 respects

Components and supplies

Necessary tools and machines

Apps and online services

About this project

When you go to the Gymnasium for you exercises, most of your time wast for other stuff, like checking your mobile phone for messages, chatting with other people and you take a lot more than accepted rest time in between workout sets. As a fact you know that resting in between workout sessions more than accepted time period reduces the efficiency of the exercise thus decay the results.

As a solution, this Personal Gym Timer can keep track of workout rep time, rest time and number of sets and when the time elapses, it can alert you visually and audibly. This way it encourage you to get the maximum results from you time at the gym.

First the two PCB s (Control Circuit and SSD Cct) were toner transferred and etched using ferric-chloride.

SSD cct was soldered. It has one large size Red SSD which shows the current number of set and two small Green SSD s which shows the up counting workout time or down counting rest time.

Then the Control cct was assembled. It is a dual layer PCB. The three SSD s are controlled using a Serial to parallel shift register with multiplexing.

Two 18650 li-ion battery were series connected to get 7.4V minimum to drive the circuits. A Battery Monitoring Circuit was used to avoid the over charge, over discharge and shot circuit conditions.

Enclosure openings were created for three SSD s, two large push buttons, charging ports, other control toggle switches and indicators.

Arduino Nano was programmed and tested whether the control inputs and indicators are working. Components and circuits were assembled to the enclosure. Additional Rotary encoder with push button was installed for further developments. Battery pack and the charger was tested and installed.

All the components were Installed and the enclosure was closed.

Final tests were done. When the timer turned on, it can operate in two basic modes, Auto mode and Set mode. When in auto mode, you just have to press the Green push button and start the workout. It will count up 60 seconds for workout and count down 30 seconds for rest. Then it will increase the number of sets (large red SSD) by one ( new number of sets is 2) and count up 60 seconds then count down 30 seconds for rest. This work out time and rest time can change in three preset value combinations like;

  • 45 seconds workout / 30 seconds rest
  • 60 seconds workout / 30 seconds rest
  • 90 seconds workout / 45 seconds rest

or you can programme this times as you wish.

Code

Gym timer CodeArduino
/*=============================================
    Program : Personal_Gym_timer
    Author  : wickPro-PC\wickPro
    Time    : 12:47 PM
    Date    : 3/11/2018
    Coded by: Pramod C Wickramasinghe
    E-mail  : wick.pro@gmail.com
    Mobile  : +94774585875
  =============================================*/

#define LATCH 6 // shift register latch pin
#define CLK 5
#define DATA 4

#define DISP_1 7 // 1st seven segment common pin
#define DISP_2 8
#define DISP_3 9

#define workoutLed A0
#define restLed A1
#define t0 A2
#define t1 A3

#define modeSwitch 10 // select between auto mode and manual mode
#define workoutBtn 2 // start workout 
#define restBtn 3 // start rest

#define buzzer A4

int _delay = 250; // refresh display
int _wait = 1000;  // counter time = one second in millis
int countDigit_1, countDigit_2 ; // 1st digit counter variable
int countDigit_3 = 1;

int w1stMax, w2ndMax, r1stMax, r2ndMax;

byte pushCount_w, pushCount_r = 0;
byte autoCount = 1;

boolean val_toggle = true; // check the counter's status and initialize
boolean endOf_rest = true;
boolean endOf_workout = false;
boolean currentButtonState_w;
boolean currentButtonState_r;
boolean lastButtonState_w = LOW;
boolean lastButtonState_r = LOW;
boolean DISP_state = LOW;
boolean modeToogle_auto;
boolean modeToggle_manual;

unsigned long currentMillis = 0;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void buzz(char when) {
  switch (when) {
    case 'w': // end of rest
      digitalWrite(buzzer, HIGH);
      delay(100);
      digitalWrite(buzzer, LOW);
      delay(100);
      digitalWrite(buzzer, HIGH);
      delay(100);
      digitalWrite(buzzer, LOW);

    case 'r': // end of workout
      digitalWrite(buzzer, HIGH);
      delay(200);
      digitalWrite(buzzer, LOW);
  }
}

void showDigit(int digit) {
  switch (digit) {
    case 20:    // show dash (-) == 0b00000001
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK , MSBFIRST , 1);
      digitalWrite(LATCH, HIGH);
      break;

    case 30:    // show dot (.) == 0b10010000
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK , MSBFIRST , 16);
      digitalWrite(LATCH, HIGH);
      break;

    case 0:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 238);
      digitalWrite(LATCH, HIGH);
      break;

    case 1:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 40);
      digitalWrite(LATCH, HIGH);
      break;

    case 2:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 205);
      digitalWrite(LATCH, HIGH);
      break;

    case 3:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 109);
      digitalWrite(LATCH, HIGH);
      break;

    case 4:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 43);
      digitalWrite(LATCH, HIGH);
      break;

    case 5:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 103);
      digitalWrite(LATCH, HIGH);
      break;

    case 6:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 231);
      digitalWrite(LATCH, HIGH);
      break;

    case 7:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 44);
      digitalWrite(LATCH, HIGH);
      break;

    case 8:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 239);
      digitalWrite(LATCH, HIGH);
      break;

    case 9:
      digitalWrite(LATCH, LOW);
      shiftOut(DATA, CLK, MSBFIRST, 47);
      digitalWrite(LATCH, HIGH);
      break;

    default:
      break;
  }
}

void blankDisp() {
  digitalWrite(DISP_1, LOW);
  digitalWrite(DISP_2, LOW);
  digitalWrite(DISP_3, LOW);
  DISP_state = LOW;
}

void countUpto() {
  if (digitalRead(t0) == 1 && digitalRead(t1) == 0) {
    w1stMax = 9;
    w2ndMax = 5;
    r1stMax = 9;
    r2ndMax = 2;
  } else if (digitalRead(t1) == 1 && digitalRead(t0) == 0) {
    w1stMax = 9;
    w2ndMax = 8;
    r1stMax = 9;
    r2ndMax = 5;
  } else if (digitalRead(t0) == 0 && digitalRead(t1) == 0) {
    w2ndMax = 7;
    r2ndMax = 4;
    if (countDigit_2 > 6) {
      w1stMax = 5;
    } else {
      w1stMax = 9;
    } 
    if (countDigit_2 > 3) {
      r1stMax = 5;
    } else {
      r1stMax = 9;
    }
  } else {
    //never gonna happen
  }
}

void timer(char when) {
  switch (when) {

    case 'w':   // w for Workout in manual mode
      if (val_toggle == false) {
        val_toggle   = true;
        countDigit_1 = 0;
        countDigit_2 = 0;
        autoCount += 2;
      }
      if (millis() - currentMillis > _wait) {
        currentMillis = millis();
        countDigit_1++;
        countUpto();
        if (countDigit_1 > w1stMax ) {
          countDigit_1 = 0 ;
          countDigit_2++;
          if (countDigit_2 > w2ndMax) {
            countDigit_2  = 0;
            val_toggle    = false;
            endOf_workout = true;
            endOf_rest    = false;
            buzz('r');
          }
        }
      }
      break;

    case 'r':    // r for Rest in auto mode
      if (val_toggle == false) {
        val_toggle   = true;
        countDigit_1 = r1stMax;
        countDigit_2 = r2ndMax;
        autoCount += 2;
      }
      if (millis() - currentMillis > _wait) {
        currentMillis = millis();
        countDigit_1--;
        countUpto();
        if (countDigit_1 < 0 ) {
          countDigit_1 = r1stMax;
          countDigit_2--;
          if (countDigit_2 < 0) {
            countDigit_2  = r2ndMax;
            val_toggle    = false;
            endOf_rest    = true;
            endOf_workout = false;
            countDigit_3++; // count no of sets
            buzz('w');
            if (countDigit_3 > 3) {
              countDigit_3 = 1;
            }
          }
        }
      }
      break;

    case 'W':   // "W" for workout in auto mode
      if (val_toggle == false) {
        val_toggle   = true;
        countDigit_1 = 0;
        countDigit_2 = 0;
      }
      if (millis() - currentMillis > _wait) {
        currentMillis = millis();
        countDigit_1++;
        countUpto();
        if (countDigit_1 > w1stMax ) {
          countDigit_1 = 0 ;
          countDigit_2++;
          if (countDigit_2 > w2ndMax) {
            //countDigit_2 = 0;
            countDigit_1 = r1stMax;
            countDigit_2 = r2ndMax;
            val_toggle    = false;
            endOf_workout = true;
            endOf_rest    = false;
            pushCount_w++;
            buzz('r');
          }
        }
      }
      break;

    case 'R':   // "R" for rest in manual mode
      if (val_toggle == false) {
        val_toggle   = true;
        countDigit_1 = r1stMax;
        countDigit_2 = r2ndMax;
      }
      if (millis() - currentMillis > _wait) {
        currentMillis = millis();
        countDigit_1--;
        countUpto();
        if (countDigit_1 < 0 ) {
          countDigit_1 = r1stMax;
          countDigit_2--;
          if (countDigit_2 < 0) {
            countDigit_2  = r2ndMax;
            val_toggle    = false;
            endOf_rest    = true;
            endOf_workout = false;
            pushCount_r++;
            countDigit_3++;
            countDigit_1 = 0;
            countDigit_2 = 0; // count no of sets
            buzz('w');
            if (countDigit_3 > 3) {
              countDigit_3 = 1;
            }
          }
        }
      }
      break;

    default:
      break;
  }
}

void checkButtons () {

  currentButtonState_w = digitalRead(workoutBtn);
  currentButtonState_r = digitalRead(restBtn);

  if ((millis() - lastDebounceTime) > debounceDelay) {

    if (currentButtonState_r != lastButtonState_r) {
      if (currentButtonState_r == HIGH) {
        pushCount_r++;

        //Serial.print("pushCount_r = ");
        //Serial.println(pushCount_r);

        if (pushCount_r == 2) {
          pushCount_r = 0;
        }
      }
    }
    lastButtonState_r = currentButtonState_r;

    if (currentButtonState_w != lastButtonState_w) {
      if (currentButtonState_w == HIGH) {
        pushCount_w++;

        if (digitalRead(modeSwitch) == HIGH) { // set to true if auto mode
          endOf_workout = false;
          autoCount     = 0;
          val_toggle    = false;
          countDigit_3  = 1;
        }

        //Serial.print("pushCount_w = ");
        //Serial.println(pushCount_w);

        if (pushCount_w == 2) {
          pushCount_w = 0;
        }
      }
      lastButtonState_w = currentButtonState_w;
    }
    lastDebounceTime = millis();
  }
}

void modeInitiate(char mode) {

  switch (mode) {
    case 'a':         // "a" for auto mode
      if (modeToogle_auto == true) {
        //countDigit_1 = 0;
        //countDigit_2 = 0;
        //countDigit_3 = 1;
        //val_toggle   = true;
        endOf_rest      = false;
        endOf_workout   = false;
        autoCount       = 13;
        modeToogle_auto = false;
        //modeToggle_manual = false;
        //Serial.println("done auto");
      }
      break;

    case 'm':       // "m" for manual mode
      if (modeToggle_manual == true) {
        //countDigit_1      = 0;
        //countDigit_2      = 0;
        //countDigit_3      = 1;
        endOf_rest        = false;
        endOf_workout     = false;
        modeToggle_manual = false;
        //Serial.println("done manual");
      }
      break;

    default:
      break;
  }
}

void setup() {

  //Serial.begin(115200);

  pinMode(LATCH, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(DISP_1, OUTPUT);
  pinMode(DISP_2, OUTPUT);
  pinMode(DISP_3, OUTPUT);
  pinMode(modeSwitch, INPUT);
  pinMode(workoutBtn, INPUT);
  pinMode(restBtn, INPUT);
  pinMode(t0, INPUT), (t1, INPUT);
  pinMode(workoutLed, OUTPUT);
  pinMode(restLed, OUTPUT);
  pinMode(buzzer, OUTPUT);
}

void loop() {

  countUpto();

  //Serial.print("pushCount_r = ");
  //Serial.println(pushCount_r);

  //Serial.print("pushCount_w = ");
  //Serial.println(pushCount_w);

  checkButtons();

  modeToogle_auto = true;
  //modeToggle_manual = false;

  modeInitiate('m');

  if (pushCount_w % 2 != 0) {
    digitalWrite(workoutLed, HIGH);

  } else {

    digitalWrite(workoutLed, LOW);
  }
  if (pushCount_r % 2 != 0) {
    digitalWrite(restLed, HIGH);
  } else {
    digitalWrite(restLed, LOW);
  }

  if (endOf_workout == false && pushCount_w % 2 != 0) {
    timer('W');
  } else if (endOf_rest == false && pushCount_r % 2 != 0) {
    timer('R');
  }

  blankDisp();
  showDigit(countDigit_1);
  digitalWrite(DISP_1, HIGH);
  delayMicroseconds(_delay);

  blankDisp();
  showDigit(countDigit_2);
  digitalWrite(DISP_2, HIGH);
  delayMicroseconds(_delay);

  blankDisp();
  showDigit(countDigit_3);
  digitalWrite(DISP_3, HIGH);
  delayMicroseconds(_delay);


  while (digitalRead(modeSwitch) == HIGH) {       // true when auto mode

    modeToggle_manual = true;
    //modeToogle_auto   = false;

    modeInitiate('a');

    if (endOf_workout == false) {
      timer('w');        // w for Workout
    }
    else if (endOf_rest == false) {
      timer('r');       // r for Rest
    }

    //Serial.print("Auto Count = ");
    //Serial.println(autoCount);

    if (autoCount > 12) {    // stop after three sets
      endOf_rest    = true;
      endOf_workout = true;
      checkButtons();

      if (millis() - currentMillis > _wait / 3) {
        currentMillis = millis();

        if (DISP_state == HIGH) {
          blankDisp();
          showDigit(20);
          digitalWrite(DISP_1, HIGH);
          digitalWrite(DISP_2, HIGH);
          digitalWrite(DISP_3, HIGH);
          DISP_state = LOW;
        } else {
          blankDisp();
          showDigit(30);
          digitalWrite(DISP_1, HIGH);
          digitalWrite(DISP_2, HIGH);
          digitalWrite(DISP_3, HIGH);
          DISP_state = HIGH;
        }
      }
    }

    if (endOf_rest == false || endOf_workout == false) {

      blankDisp();
      showDigit(countDigit_1);
      digitalWrite(DISP_1, HIGH);
      delayMicroseconds(_delay);

      blankDisp();
      showDigit(countDigit_2);
      digitalWrite(DISP_2, HIGH);
      delayMicroseconds(_delay);

      blankDisp();
      showDigit(countDigit_3);
      digitalWrite(DISP_3, HIGH);
      delayMicroseconds(_delay);

    }
  }
}

Schematics

Gym timer Full Schematic
Uploads2ftmp2fff70e45a 7663 4741 b1e7 8dd302df6ba32fgymaddon control copy oxuwiwa1xu
Controll Cct
Uploads2ftmp2f6460d680 e201 4cd7 a1ed 26e9d9998ce12fcontrollcct ethcxwsxyo
SSD Cct
Uploads2ftmp2f8be8d858 6c8e 4184 9122 811cdff382792fssd q756jx5ivp

Comments

Similar projects you might like

Arduino Deep Fridge Timer

Project showcase by Shahariar

  • 2,462 views
  • 4 comments
  • 8 respects

Personal Weather Station (Arduino+ ESP8266 + Thingspeak)

Project tutorial by Jayraj Desai

  • 63,204 views
  • 34 comments
  • 126 respects

Coin Op Personal Vending Machine

Project tutorial by comptek4

  • 3,093 views
  • 13 comments
  • 24 respects

Retro View Timer

Project tutorial by yilmazyurdakul

  • 909 views
  • 1 comment
  • 2 respects

Wake Up Timer

Project showcase by Fatih Çil

  • 471 views
  • 0 comments
  • 7 respects

Personal Healthcare Assistant PHA

Project tutorial by Technomadic

  • 17,488 views
  • 7 comments
  • 148 respects
Add projectSign up / Login