Introduction: RepWrap - Device to Keep Track of Duration and Repetitions for Physiotherapy Exercises (breadboarded Prototype)

About: Artist, perpetual protovator. Don't mistake me for someone who actually knows stuff!
I've been given a series of exercises to do by the physiotherapist, but I'm rubbish at doing them so every little thing I can do to make them less of a chore is A Good Thing.

I prototyped a simple arduino device to take care of doing the counting of the repetitions and durations because watching a stopwatch wasn't quite working for me. The RepWrap uses LED flashes and vibrations to let me know when to finish a stretch or change legs or whatever. The LEDs give me a 3 second countdown at the end of each hold, then the vibe gives me some changeover/rest time. The combination of sight, touch and sound mean that I can do my exercises whilst listening to music or with my eyes closed (useful when trying to squeeze in an early morning set before going to work!).



In this instructable I'll show you the simple breadboard layout and code to use to make your own RepWrap.

You will need:

The electronics
  • Arduino-compatible microcontroller (I'm using a RBBB from Modern Device)
  • A breadboard (Only if your microcontroller requires it. If you're using a regular Arduino board, you won't need it. I'm using a Maplin AD100)
  • An LED (You should probably use a 330ohm or similar resistor in series with it too...) Your microcontroller may already have an integral LED attached to pin 13, but I found this wasn't visible enough for my needs.
  • A pager motor (I'm using one of these pager motors)
  • 9V PP3 Battery (it's easier to put a little more boogie into your exercises if you're not leashed to a computer by a USB cable...)
  • Battery clip and 2.1mm plug power jack (wired up to be centre-positive)
  • 2 lengths of wire to extend the motor leads (I'm using single core so I can plug it into the breadboard)
  • 2 x Jumper leads long enough to reach between the GND pin on your controller and the selection pins for number of reps and length of duration.

Other materials
  • Rubber band
  • Masking tape
  • Insulation tape
  • Pen
Tools you may need
  • Soldering iron, solder and stand etc
  • Something to strip the ends of insulation off the wire
  • Scissors


And if you're wondering about the name:
The plan is to eventually build this circuit into a sleeve worn around the forearm. There'll probably be a few more instructables en route...
In the meantime I'm using this version to try and get a feel for what needs to go into the final design.


Step 1: The Code


The code builds off Arduino documentation such as

Knight Rider 2 for using arrays for pin set-ups
Button was what I was looking at right at the beginning (note to self: for v2 should probably add a resistor between GND and the flying leads...)

Download the physio.pde file (or copy the code from below) and upload to your Arduino microcontroller in the usual manner.

/*
RepWrap v1
nikki pugh | April 2011 | www.npugh.co.uk

Vibration motor attached to pin 12
LED attached to pin 13
Repetition pins 2-6
Duration pins 7-11

*/

// variables:

int repNumbers[5] = { //array storing a selection of repetition values
10,12,20,24,30};

int repPins[] = {
2, 3, 4, 5, 6 }; // an array of pin numbers to which rep buttons are attached
int repPinCount = 5; // the number of rep options (i.e. the length of the array)

int durationLengths[5] = { //array storing a selection of duration/hold values in seconds
10,12,15,20,30};

int durationPins[] = {
7, 8, 9, 10, 11 }; // an array of pin numbers to which duration buttons are attached

int durationPinCount = 5; // the number of duration options (i.e. the length of the array)

//flashes are used as an indication that the hold duration is nearly over
int flashOn = 750; // length of time countdown flashes last for
int flashOff = 250; // length of time countdown flashes off for
int flashRep = 3; // no of flashes
int flashTime = (flashRep*(flashOn+flashOff));

int changeover = 3000; // length of time between reps , milliseconds

int repState = 0; // variable for reading the selector status
int durationState = 0; // variable for reading the selector status

int thisRepPin = 0; // other variables
int thisDurationPin = 0;
int thisRepNumber = 0;
int thisDurationLength = 0;
int repNumber = 0;
int durationLength = 0;
int repStateFound = 0;
int durationStateFound = 0;

// constants:
const int buzzPin = 12; // the number of the buzzer pin
const int LEDPin = 13; // the number of the LED pin


void setup() {
// initialize pins as an outputs:
pinMode(LEDPin, OUTPUT);
pinMode(buzzPin, OUTPUT);


int thisRepPin;
// the array elements are numbered from 0 to (pinCount - 1).
// use a for loop to initialize each pin as an output:
for (int thisRepPin = 0; thisRepPin < repPinCount; thisRepPin++) {
pinMode(repPins[thisRepPin], INPUT); // set pin to input
digitalWrite(repPins[thisRepPin], HIGH); // turn on internal pullup resistors
pinMode(repPins[thisRepPin], OUTPUT); //set pin to output
}

int thisDurationPin;
// the array elements are numbered from 0 to (pinCount - 1).
// use a for loop to initialize each pin as an output:
for (int thisDurationPin = 0; thisDurationPin < durationPinCount; thisDurationPin++) {
pinMode(durationPins[thisDurationPin], INPUT); // set pin to input
digitalWrite(durationPins[thisDurationPin], HIGH); // turn on internal pullup resistors
pinMode(durationPins[thisDurationPin], OUTPUT); //set pin to output
}

Serial.begin(9600); // open the serial port at 9600 bps
} //end set up

void loop(){

//start signal
for (int i=0;i<flashRep;i++) {
digitalWrite(LEDPin, LOW);
delay(flashOff);
digitalWrite(LEDPin, HIGH);
delay(flashOn);
digitalWrite(LEDPin, LOW);
}
digitalWrite(buzzPin, HIGH);
delay(changeover);
digitalWrite(buzzPin, LOW);


//read the Rep pins, when you find one that is LOW, that is the one that has been selected
thisRepPin = 0;
repStateFound = 0;
while(repStateFound==0){
repState=digitalRead(repPins[thisRepPin]);
if (repState == LOW) { //has been connected to ground
repStateFound = 1;
Serial.print(thisRepPin);
Serial.println(" repStateFound = 1");
}
if (repState == HIGH){
repStateFound = 0;
Serial.print(thisRepPin);
Serial.println(" repStateFound = 0");
thisRepPin++;
}

}

thisRepNumber = thisRepPin;
Serial.print("thisRepNumber: ");
repNumber = repNumbers[thisRepNumber];
Serial.println(repNumbers[thisRepNumber]);


//read the Duration pins, when you find one that is LOW, that is the one that has been selected
thisDurationPin = 0;
durationStateFound = 0;
while(durationStateFound==0){
durationState=digitalRead(durationPins[thisDurationPin]);
if (durationState == LOW) {
durationStateFound = 1;
Serial.print(thisDurationPin);
Serial.println(" durationStateFound = 1");

}
if (durationState == HIGH){
durationStateFound = 0;
Serial.print(thisDurationPin);
Serial.println(" durationStateFound = 0");
thisDurationPin++;
}

}

thisDurationLength = thisDurationPin;
Serial.print("thisDurationLength: ");
durationLength = durationLengths[thisDurationLength];
Serial.println(durationLength);
durationLength = durationLength*1000;

thisDurationPin = 0;


//switch pins off to save power
for (int thisRepPin = 0; thisRepPin < repPinCount; thisRepPin++) {
digitalWrite(repPins[thisRepPin], LOW); // turn off all rep pins
}
Serial.println("rep pins switched off");
for (int thisDurationPin = 0; thisDurationPin < durationPinCount; thisDurationPin++) {
digitalWrite(durationPins[thisRepPin], LOW); // turn off all duration pins
}
Serial.println("duration pins switched off");


//now on to the exercises

for (int count=0;count<repNumber;count++) { //repeat this cycle as many times as there are repetitions
delay(durationLength-flashTime); //wait for the duration length minus the length of time for the countown flashes

for (int i=0;i<flashRep;i++) { //do the countdown flashes
digitalWrite(LEDPin, LOW);
delay(flashOff);
digitalWrite(LEDPin, HIGH);
delay(flashOn);
digitalWrite(LEDPin, LOW);
//that rep is now finished

}
Serial.println(count+1); //how many reps have we done?
// buzz the motor for a changeover
digitalWrite(buzzPin, HIGH);
delay(changeover);
digitalWrite(buzzPin, LOW);

} //end of set


//long buzz to signal the end of the set
digitalWrite(buzzPin, HIGH);
delay(7000);
digitalWrite(buzzPin, LOW);

//flash the LED so signal the end of the set - when you see this you need to power down or start another set
while (true) {
digitalWrite(LEDPin, HIGH);
delay(500);
digitalWrite(LEDPin, LOW);
delay(1000);
}


} //end loop

Step 2: The Circuit


Solder extra wire onto the leads of your motor if necessary and make sure you know your LED's anode from its cathode.

The illustration shows a basic layout, although if you're using an actual Arduino board, you may want to make use of some of those extra GND pins :)

If you're using a breadboard as I am, then no problem - everything can run off the same GND pin (see photos).


Rep lead: One end to GND, the other to one of digital pins 2 to 6
Duration lead: One end to GND, the other to one of digital pins 7 to 11
LED: Anode (shorter leg) to GND, cathode (longer leg) to pin 13
Motor: One lead to GND and the other to pin 12

Power up your board and you should be good to go...

Nice touches include labelling up the rep and duration pins so you don't have to remember which one corresponds to which value and using a rubber band to hold the battery in place on the underside of the board.

Try and arrange all your wires so that you can hold the whole assembly comfortably and without dislodging anything.

Once you come to the end of a set (with the LED blinking continuously), choose your new settings and then hit the reset button for the changes to take effect.

Finally, do your exercises so those changes can take effect too! DO IT!




Arduino image source