Introduction: Work It Out: an Interactive Fitness Motivation System

In this tutorial, you will use Lilypad Arduino to make an interactive fitness motivational system. The system uses a sensor to collect health data from the user, based upon this information, a visual output is displayed on the user's shirt.

Step 1: Materials

For this project, you will need the following materials:


Arduino Hardware:
2x - LilyPad SimpleSnaps
2x - LilyPad SimpleSnap Protoboard
2x - LilyPad XBee (breakout boards)
2x - LilyPad XBee 1mW Trace Antenna - Series 1
 1 - LilyPad Programmer
 1 - LilyPad Accelerometer ADXL335
 1 - LilyPad Power Supply
 1 - AAA Battery
A variety of LilyPad LEDs
***NOTE: For this project, I used a 60 LEDs in a variety of colors, however, you do not have to use as many, it just depends on the design of your LED display. Be mindful that some colors require more battery power. 


Other Materials:
- Alligator clips
- A t-shirt or another type of garment
- Extra fabric (I used about a yard)
- Fabric Pencils
- Pencil, Eraser, and Markers (this will help you design how you )
- Tape, Ruler, and Scissors
- Conductive thread
- Needle and thread (use two different colors to help identify positive and negative connections)
- Foam/felt 
- Sewing Machine (optional)
- Velcro (optional)




Step 2: Garment Design

In this step you will work on designing your LED display(s). You first need to consider how many displays you want to have. I used three different display.

Plan the aesthetic and electrical layout of your piece.
I found it helpful to uses sketches and Fritzing diagrams as I worked. However, you do not have to do this, you can work directly on your garment.
 
LED Display.
Sketch out how you want the visual display to look. The key thing to focus on here is the spacing between lights. to help with this, create a grid for each display. For this project, I placed my LEDs one-inch apart. This allowed me to go back and sew the positive and negative connections at every half-inch (See images).   

Shirt Layout.
You need to decide where each component is going to go and figure out how you will sew them together. You want to try to have as few thread crossings as possible. The photos below show the Fritzing layout for my shirt. In this project, you will use a power supply. It is helpful if you place the power supply close to your LilyPad board.



Transfer the sketch to your garment. 
There are multiple ways you can transfer your sketches to the garment:

Non-Permanent Marker
You can use fabrics pencils, chalk or any other non-permanent marker to transfer your design to the garment. Use double sided tape to temporarily attach LIlyPad pieces to your garment. This will give you a good sense of what your final piece will look like. It will also keep everything in place and, as long as the tape sticks, make your sewing easier. Use a ruler to draw sewing paths for the conductive thread.

Template
Using the Fritzing diagram, you can create a template. Print out a copy of your diagram, you make have to play around with the sizing to get the hardware pieces the right size. Use tape to hold the template in place on your garment--this will keep the template from moving while sewing. Use a ruler to draw sewing paths for the conductive thread.

*** NOTE: I find it helpful to use colored markers to trace over the conductive paths--this helps distinguish the positive and negative currents from each other.

Step 3: XBee Configuration

In order for your XBees to communicate with each other, you need to configure them. Follow the steps below:

1. Download the appropriate software.

Download and install the following software for your operating system: Coolterm (http://freeware.the-meiers.org/) and the FTDI Driver (http://www.ftdichip.com/FTDrivers.htm). Once you have installed these items, be sure to re-start your computer.

*** NOTE: If you already have Arduino installed, you probably already have the FTDI Driver installed as well. It comes with the Arduino Software package.


2. Label the XBees.

Before configuring the Xbees, first label them so that they are easier to distinguish. I used different color (green and pink) Post-Its to distinguish one XBee from the other.  These colors will be used to identify the XBees for the remainder of this tutorial.

3. Configure the XBees :: Connection Step Up

To enable the XBees to communicate, they must first be configured so that they know how to send information to each other. To do this you'll need to use CoolTerm, a terminal program which allows you to communicate with hardware connected to your serial port.

a) Plug your GREEN Xbee into the Lilypad Xbee board, using the visible guide lines inscribed on the board. Ensure that the pins are properly lined up, and that the Xbee is not plugged in upside down. Connect the FTDI Breakout board to the male headers on the Lilypad Xbee board and plug in the USB cable to both the board and your computer.

b) On a Mac: Go to your Applications folder and open CoolTerm.

    On a PC: Go your the directory where you installed Coolterm, and click CoolTerm.exe

c) In the Menu bar, select Connection > Options. Under the 'Serial Port' tab on the left, select a Baudrate of '9600'.  Then, under the 'Terminal' tab, turn 'Local Echo' on by checking the box.

4. Configure the GREEN XBee:

To configure your XBee, you need to use “AT Commands”. Before AT commands can be executed, the XBee must first be put into ‘Command Mode’. You can do this by typing ‘+++’ into the Coolterm window, which it should respond to with an ‘OK’ message. Do not click the <ENTER> key afterwards, or it won’t work!

*** NOTE: Coolterm will exit from Command Mode in less than 30 seconds, so try not to leave the window idle. If you aren’t getting an ‘OK’ in response, type in ‘+++’ again to re-enter Command Mode.



a) For the two XBees to talk to each other, they must have the same PAN ID. To set a PAN ID of say, 3456, you would type:

ATID3456
<ENTER>

You should then receive an ‘OK’ message — if not, make sure you’ve pressed <ENTER>, and also that you’re still in Command Mode). You can check your PAN ID at any time simply by typing ATID (with no parameters).

*** NOTE: If you are in a setting where many pairs of Xbees are being configured to talk to each other, EACH PAIR must have a different set of PAN IDs.


b) Next, let’s set up a 'my id' for our specific XBee. To set a 'my id' of 2 for our first XBee, type:

       ATID2
              <ENTER>

To check that this worked, type 'ATMY'. Coolterm should echo back '2'.

c) Prepare the first XBee so that it will be able to the second XBee. To do this, we need to set a ‘destination ID’, by typing:

       ATDL1
              <ENTER>

This will set the destination device to ‘1’.

d) To save the configurations, type:

       ATWR
              <ENTER>


This is an important step. If you don’t write the settings to the Xbee, all settings will be deleted after the XBee is unplugged!


e) Click the ‘Disconnect’ button in CoolTerm to end the session, and then unplug the XBee from your computer.

5. Configure the PINK XBee:

a) Unplug the USB from the computer. Remove the GREEN Xbee from the Lilypad Xbee board and plug the PINK Xbee into the board. Then plug the USB cable back into your computer.

b) In Coolterm, select the “Connect” icon in the Menu bar. From here, you will continue with the same steps as with the GREEN Xbee, except that you will change the following parameters:

Pan ID: ATID3456
Individual ID: ATMY1
DL Address: ATDL2

Remember to save the settings using 'ATWR'.


6. Chat Testing (optional)
If you have two computers and two FTDI Breakout boards, you can test to see if your two XBees are talking to each other. To do this"

a) Plug the Xbees into the Lilypad Xbee boards. Then plug the FTDI Breakout Boards into the Lilypad Xbee boards, and connect them to the computers using your mini-USB cables.

b) On each computer, open Coolterm if it is not already open.

c) Select ‘Connect’ in the Menu bar.

d) Select Connection > Send String. Using this Send String function, you can send messages to each other’s computers.

e) Once you have confirmed they are talking, disconnect your XBees.

Step 4: Sewing

Sewing your garment
As with the last step, there are multiple ways you can sew your pieces to your garment. Personally, I used the sewing machine method listed below:

Sewing Machine
If you have never used a sewing machine before, do not fret, it is not hard to learn. Use the sewing machine manual to learn how to thread the machine and needle--most machines have instructions included on the physical machine as well. Near the needle/foot of the machine, there should be a compartment to hold the "bobbin." The bobbin is the thread that appears on the underside of your garment. The sewing machine manual should also give you quick instructions on how to create a bobbin. If you would like to practice using the machine, create a bobbin and practice sewing the outline of a square on a piece of paper. However, if you feel comfortable using the machine, continue to the next step.

Your conductive thread will act as your bobbin. Using the template you created, sew over the conductive lines. To help you distinguish the positive paths from the negative paths, use two different colors of thread. I tend to use black thread for the negative paths and red thread for the positive. You want to make sure to go over each path twice, extending the paths a little further. This is especially important where your paths "turn," and will insure the current flows smoothly. 

- LED Displays: For the LED displays, it is easier if you sew down one side of each LED and "tear" away your paper template.


Hand-stiching  
If you do not feel comfortable using the sewing machine, you may also hand-stitch your hardware. If you chose this method, I suggest you use a paper template, this will be a big help in distinguishing between the positive and negative paths--as with the above method, you want to extend your paths out a little. Carefully "tear" away your paper template. Once your paths are sewn, you can start hand stitching your hardware pieces. 

***Tip(s): When hand-stitching your hardware onto your garment, you want to make sure to tie off the ends. I find it helpful to tie the ends three times, this help insures the knot will not slip through.

*** NOTE :: In the images, my positive paths are represented by grey thread, while the red thread is used for the negative paths.

Step 5: Programming Your Garment

Arduino Code
To make programming easier and to help with troubleshooting, I broke the code into three sections:

1. LED Display
2. Accelerometer reading
3. XBee Communication


The next three steps discuss how I programmed each of the above sections.

Step 6: Programming Your Garment | LED Display

Once I had my LED displays laid out, I chose to sewn them to a separate piece of fabric, this gave me three "pads" to work with. Using alligator clips, I connected my pieces based on my sketch/Fritzinf diagram.

Arduino Hardware Used
1 - LilyPad SimpleSnap
1 - LilyPad SimpleSnap Protoboard
1 - LilyPad XBee (breakout boards)
1 - LilyPad XBee 1mW Trace Antenna - Series 1
50 - LEDs in a variety of colors (these were sewn to three pieces of fabric)
1 - LilyPad Programmer
1 - LilyPad Power Supply
1 - AAA Battery


LED Display Code
The below code was adapted from the Arduino Blink! example. It uses a if-else loop to determine 

// the following sets up the variables and pins used in the code
       // the following describe the pins used for the light pads

              int led = 5;
              int led2 = 9;
              int led3 = 11;
              int steps = 7; // this was used to make sure the LED displays worked properly

// the setup routine runs once when you press reset
void setup() {               
       // initialize the digital pins as an outputs
             pinMode(led, OUTPUT);    
             pinMode(led2, OUTPUT);
             pinMode(led3, OUTPUT);
}


// the loop routine runs over and over again forever
void loop() {

      // code used to determine which set of lights to output
          if (steps <= 5)  
               {
                   digitalWrite(led, HIGH);   // turn the first LED display on (HIGH is the voltage level)
                   delay(1000);               // wait for a second
               }
          else if ((steps > 5) && (steps < 10))
               { 
                   digitalWrite(led2, HIGH);   // turn the second LED display on (HIGH is the voltage level)
                   delay(1000);               // wait for a second
               }
          else if (steps > 10)
               {
                   digitalWrite(led3, HIGH);   // turn the third LED display on (HIGH is the voltage level)
                   delay(1000);               // wait for a second   
               }
          else
               {
      return 0;
    }
   
delay(sampleDelay); // delay before next reading

}

Step 7: Programming Your Garment | Accelerometer Reading

In this step, you will need to determine which axis will be used to track your user's "steps." You want to make sure this axis is placed vertically on the shirt. In this example, I chose to use the y-axis. Before adjust coding, you will need to determine the threshold of the y-axis--this is required so you will know when a "step" has taken place. This may sound confusing, but the code below will use comments to further describe what I am talking about.  Again, alligator clips were used to connect the pieces based on the sketch template/Fritzing diagram.

Arduino Hardware Used
1 - LilyPad SimpleSnap
1 - LilyPad SimpleSnap Protoboard
1 - LilyPad XBee (breakout boards)
1 - LilyPad XBee 1mW Trace Antenna - Series 1
1 - LilyPad Programmer
1 - LilyPad Accelerometer ADXL335


Accelerometer Code
The below code was adapted from the Arduino Accelerometer example.

// these constants describe the pins. They won't change:
const int xpin = A5;                  // x-axis of the accelerometer
const int ypin = A2;                  // y-axis
const int zpin = A3;                  // z-axis (only on 3-axis models)

int sampleDelay = 500;   // number of milliseconds between readings
void setup()
{
      // initialize the serial communications:
     Serial.begin(9600);

     //Make sure the analog-to-digital converter takes its reference voltage from
     // the AREF pin

     pinMode(xpin, INPUT);
     pinMode(ypin, INPUT);
     pinMode(zpin, INPUT);
}

void loop()
{
     float oldy= 0;
     float threshold = 0;
     int x = analogRead(xpin);

     // add a small delay between pin readings.  I read that you should
    // do this but haven't tested the importance

       delay(1);
       int y = analogRead(ypin);

    // add a small delay between pin readings.  I read that you should do this but haven't tested the importance
       delay(1);

       int z = analogRead(zpin);

    /* zero_G is the reading we expect from the sensor when it detects no acceleration. 
       Subtract this value from the sensor reading to get a shifted sensor reading. */


      float zero_G =512;

   /* scale is the number of units we expect the sensor reading to change when the
       acceleration along an axis changes by 1G. Divide the shifted sensor reading by
       scale to get acceleration in Gs. */


       float scale =102.3;

       /*Serial.print(((float)x - zero_G)/scale);
         Serial.print("\t"); */


     // for this project, we are  printing out the 'y' values, this will help determine the threshold:
       
    threshold = oldy - ((float)y - zero_G)/scale;
    Serial.print("y =");
    Serial.print(((float)y - zero_G)/scale);
    Serial.print("; threshold=");
    Serial.println(threshold);


    /* Serial.print(((float)z - zero_G)/scale);
        Serial.print("\n"); */


    if (threshold > 1.3)    // The value of your threshold may change, you need to test and determine what your threshold will be
    steps++;
  
    Serial.print("steps =");
    Serial.print(steps);

     // delay before next reading:

     delay(sampleDelay);
}

Step 8: Programming Your Garment | XBee Communication

XBee Communication
You have configured your XBees so they can talk to each other, now you need to add the code that will allow them to send and receive  information. 


In the global section of your code (located right above, void setup), you want to add the following line:

SoftwareSerial xbee(5,6); // indicates the pins to which you have your XBee connected

In the void setup section of your code ( want to add the following lines:
// initialize the serial communications:
  Serial.begin(9600);
// set the Xbee serial to be 9600
  xbee.begin(9600);


Have your GREEN XBee (this XBee should be connected to the Accelerometer) to "send" code, insert the following into void setup section of your code:
// read the value from xbee
  sensorValue = xbee.read();


To allow your PINK XBee to "receive" code, insert the following into void loop() section of your code:
// read the value from xbee
  sensorValue = xbee.read();

Step 9: Programming Your Garment | Accelerometer Complete Code

Below is the complete Arduino code for the Accelerometer:

/*
Work Out!
Here is the sample code used to create a wearable system that uses an accelerometer to count the number of
steps a user takes. The system stores this value in a variable and outputs a visual display based upon the
number.
Below is the code used. */

// the following sets up the variables and pins used in the code

// the following describe the pins used for the light pads

int led = 5;
int led2 = 9;
int led3 = 11;
// int steps = 7;

// these constants describe the pins used for the accelerometer:
const int xpin = A5; // x-axis of the accelerometer
const int ypin = A2; // y-axis
const int zpin = A3; // z-axis (only on 3-axis models)

// number of milliseconds between readings
int sampleDelay = 500;
// the global "steps" variable describes the variable used to determine the output of lights:

int steps = 0;

SoftwareSerial xbee(5,6);

// the setup "starts" everything:

void setup() {

// initialize the serial communications:
Serial.begin(9600);
// set the Xbee serial to be 9600
xbee.begin(9600);
// initialize the digital pins as an output and the accelerometer pins as inputs:
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(xpin, INPUT);
pinMode(ypin, INPUT);
pinMode(zpin, INPUT);

}

// the loop routine runs over and over again forever:

void loop() {

// accelerometer code used to determine the variable 'steps'

// the following flot variables are being used to help determine the threshold for "steps":

float oldy= 0;
float threshold = 0;
//read the value from xbee
sensorValue = xbee.read();
//serial port that prints what was read to confirm it has been received
Serial.print("; Sensor Value =");
Serial.write(senorValue);
// pin readings for x, y, z:
int x = analogRead(xpin);
delay(1); //add a small delay between pin readings. I read that you should do this but haven't tested the importance
int y = analogRead(ypin);
delay(1); //add a small delay between pin readings. I read that you should do this but haven't tested the importance
int z = analogRead(zpin);

/* zero_G is the reading we expect from the sensor when it detects no acceleration. Subtract this value from the sensor reading to get a shifted sensor reading. */
float zero_G =512;

/* scale is the number of units we expect the sensor reading to change when the acceleration along an axis changes by 1G. Divide the shifted sensor reading by scale to get acceleration in Gs. */
float scale =102.3;

// for this project, we are not printing out the 'x' values, but if you want them printed:
//Serial.print(((float)x - zero_G)/scale);
//Serial.print("\t");


// for this project, we are printing out the 'y' values, this will help determine the threshold:
threshold = oldy - ((float)y - zero_G)/scale;
Serial.print("y =");
Serial.print(((float)y - zero_G)/scale);
Serial.print("; threshold =");
Serial.println(threshold);


// for this project, we are not printing out the 'z' values, but if you want them printed:
// Serial.print("\t");
// Serial.print(((float)z - zero_G)/scale); // Serial.print("\n");

if (threshold > 1.3)
steps++;
Serial.print("steps =");
Serial.print(steps);

// code used to determine which set of lights to output:
if (steps <= 5) {
digitalWrite(led, HIGH); // turn the first LED display on (HIGH is the voltage level)
// delay(1000); // wait for a second
//digitalWrite(led, LOW); // turn the first LED display off by making the voltage LOW
// delay(1000); // wait for a second

SoftwareSerial.println("A");
}
else if ((steps > 5) && (steps < 10)) {
digitalWrite(led2, HIGH); // turn the second LED display on (HIGH is the voltage level)
// delay(1000); // wait for a second
// digitalWrite(led2, LOW); // turn the second LED display off by making the voltage LOW
// delay(1000); // wait for a second

SoftwareSerial.println("B");

}
else if (steps > 10) {
digitalWrite(led3, HIGH); // turn the third LED display on (HIGH is the voltage level)
// delay(1000); // wait for a second
//digitalWrite(led3, LOW); // turn the third LED display off by making the voltage LOW
// delay(1000); // wait for a second

SoftwareSerial.println("C");
}

else {
return 0;
}
// delay before next reading:
delay(sampleDelay);
}

Step 10: Programming Your Garment | LED Display Complete Code

/*

Work Out! Here is the sample code used to create a wearable system that uses an accelerometer to count the number of steps a user takes. The system stores this value in a variable and outputs a visual display based upon the number. Below is the code used. */

#include <SoftwareSerial.h>

// the following sets up the variables and pins used in the code:
// the following describe the pins used for the light pads
:

int led = 5;
int led2 = 9;
int led3 = 11;
//int steps = 7;

// these constants describe the pins used for the accelerometer:

const int xpin = A3; // x-axis of the accelerometer
const int ypin = A5; // y-axis
const int zpin = A2; // z-axis (only on 3-axis models)

//number of milliseconds between readings

int sampleDelay = 500;

// the global "steps" variable describes the variable used to determine the output of lights:

int steps = 0;

SoftwareSerial xbee(5,6);

// the setup "starts" everything:

void setup() {

// initialize the serial communications:

Serial.begin(9600);

// set the Xbee serial to be 9600

xbee.begin(9600);

// initialize the digital pins as an output:

pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(xpin, INPUT);
pinMode(ypin, INPUT);
pinMode(zpin, INPUT);

}

// the loop routine runs over and over again forever:

void loop() {

int sensorValue = 0;

// accelerometer code used to determine the variable 'steps'

// the following flot variables are being used to help determine the threshold for "steps":

float oldy= 0;
float threshold = 0;
int counter = 0;

//read the value from xbee

sensorValue = xbee.read();

//serial port that prints what was read to confirm it has been received

Serial.print("; Sensor Value =");
Serial.write(sensorValue);

// pin readings for x, y, z:

int x = analogRead(xpin); delay(1);

//add a small delay between pin readings. I read that you should do this but haven't tested the importance

int y = analogRead(ypin); delay(1);

//add a small delay between pin readings. I read that you should do this but haven't tested the importance

int z = analogRead(zpin);


/* zero_G is the reading we expect from the sensor when it detects no acceleration. Subtract this value from the sensor reading to get a shifted sensor reading. */

float zero_G =512;

/* scale is the number of units we expect the sensor reading to change when the acceleration along an axis changes by 1G. Divide the shifted sensor reading by scale to get acceleration in Gs. */

float scale =102.3;

// Print values

// for this project, we are not printing out the 'x' values, but if you want them printed:

//Serial.print(((float)x - zero_G)/scale);
//Serial.print("\t");

// for this project, we are printing out the 'y' values, this will help determine the threshold:

threshold = oldy - ((float)y - zero_G)/scale;
Serial.print("y =");
Serial.print(((float)y - zero_G)/scale);
Serial.print("; threshold =");
Serial.println(threshold);

// for this project, we are not printing out the 'z' values, but if you want them printed:

// Serial.print("\t");
// Serial.print(((float)z - zero_G)/scale);
// Serial.print("\n");

if (threshold > 1.3)

steps++;

Serial.print("steps =");

Serial.print(steps);

// code used to determine which set of lights to output:

if (steps <= 5) {

digitalWrite(led, HIGH); // turn the first LED display on (HIGH is the voltage level)
// delay(1000); // wait for a second
//digitalWrite(led, LOW); // turn the first LED display off by making the voltage LOW
// delay(1000); // wait for a second
SoftwareSerial.println("A");
}

else if ((steps > 5) && (steps < 10)) {

digitalWrite(led2, HIGH); // turn the second LED display on (HIGH is the voltage level)
// delay(1000); // wait for a second
// digitalWrite(led2, LOW); // turn the second LED display off by making the voltage LOW
// delay(1000); // wait for a second
SoftwareSerial.println("B");
}

else if (steps > 10) {

digitalWrite(led3, HIGH); // turn the third LED display on (HIGH is the voltage level)
// delay(1000); // wait for a second
//digitalWrite(led3, LOW); // turn the third LED display off by making the voltage LOW
// delay(1000); // wait for a second
SoftwareSerial.println("C");

}

else {

return 0; }

// delay before next reading:

delay(sampleDelay);

}