by: Remington Frank

 

Flip and Stretch

The Flip and Stretch is a fun tool that reminds the user to stretch every half hour while sitting at their desk using a flip card display to demonstrate the stretch and an accelerometer to measure whether or not the user is performing the task.

 

Process Images and Review

The initial ideation sketch for the project is shown in the image above. Originally, the project was simply and LCD and speaker that told the user which stretch to complete and had a single LED to display whether or not the stretch was completed. To add more complexity to the build, the idea of a flip card display was added.

 

Pictured above is the original structural design for the flip card display. After carefully considering the functionality of the project, I decided to transition to a more though out and complex design. This required scrapping the above, laser cut build and building the acrylic model seen in the final photos.

 

Similar to the previous decision point, when choosing to transition to a more complex and sleek design, I had to abandon the use of the Nema 17 stepper motor shown in the image. This would cause me to also use a different motor driver than the A4988.

 

 

 

Discussion

From the in class demonstration of my idea, I gained some very useful feedback. For example, one reviewer stated the following, “Add a sound component so it lets you know if the stretch is over or if you are starting a new stretch.” I believe this is a very good idea and is a feature I was hoping to implement as seen in the original ideation phase of my project. Due to time constraints, I was unable to implement it, but I definitely will add this component in future revisions. Another valid concern was as stated, “User has the ability to cop out of the stretches and do them with minimal movement, so if it had more specific requirements, that might help.” I believe this was one of the biggest faults of my design and there are definitely ways to improve upon it. One of the recommended solutions was to use haptic sensors that the user would have to remain in contact with in order to conduct the stretch. I would, however, prefer to incorporate more accelerometers that would measure torso angle, arm angle, and the original hand position. These combined measurements would give a more accurate representation of whether or not the user is actually performing the stretch.

In terms of the final result, I am quite pleased with what I was able to accomplish in a short time. I definitely had to refrain from incorporating a lot of features I had originally planned to implement. That being said, the final result is representative of the major components I would have wanted a finished product to have. I also challenged myself with incorporating a more complex mechanical feature that I designed, fabricated, and built in a week’s time. Beyond the successes, the project definitely was lacking a finished element and should have had a container for the wiring and Arduino.

With regards to what I learned, I feel more confident in my rapid prototyping capabilities. While I have an established background in computer aided design, this project required a lot of quick decision making to meet the deadline which required my work to be very precise. Next time, I would have done more research prior to beginning the design portion. This would have saved me a lot of time from designing the original stand for the display and would have given me more of an opportunity to refine my final build.

 

While I do not intend to build the same stretch assistant, I definitely want to build more flip card displays. Potentially, if I construct enough of them, I can make a large array and use the flip cards as pixels in a larger visual display. or I can simply make flip card displays as seen in train stations. I quite like how they operate and find them incredibly satisfying, so the more the merrier.

 

Testing of the flip card display to accurately transition between stretches.

 

Functional Block Diagram and Electrical Schematic

Block diagram demonstrating inputs and outputs of the system and their relations.

 

Above image shows the electrical schematic for the build.

Code

/*---------------------------------------------------------------------
 * The following code operates the Flip and Stretch, an assistive device
 * that ensures the user is stretching every half hour while sitting at
 * their desk. The code is responsible for oeprating the flip card display
 * and intaking measurements from the accelerometer to ensure the user is
 * performing the stretches.
----------------------------------------------------------------------*/


#include <Stepper.h>

const int xpin = A0;
const int ypin = A1;
const int zpin = A2;

const int gLED = 9;
const int rLED = 10;

const int stepsPerRev = 200;



Stepper myStep = Stepper(stepsPerRev, 3, 5, 4, 6);

int x, y, z;
int stretch, stretchTime;
int prevStretch = 1;
unsigned long globalTime, checkTime, startStretch, endStretch, printTime;


void setup() {
  Serial.begin(9600);

  myStep.setSpeed(200);

  pinMode(gLED, OUTPUT);
  pinMode(rLED, OUTPUT);
}

void loop() {
  globalTime = millis();

  // Operate every half hour
  if(globalTime - checkTime >= 1800000){
    for (int i = 0; i < 3; i++) {
      conductStretches(); 
    }
    checkTime = millis();
    flipCards(26 - stretch);
  }
}

void flipCards(int card) {
  // Step difference between cards * numSteps / (numCards - 1)
  myStep.step(card * 100);
}

void conductStretches() {
  // Choose random stretch
  stretch = random(1, 10);
  stretchTime = 0;
  
  // Stretch 1: Wall Stretch
  // Desired Values
  // X: 318    Y:  382    Z: 352
  if(stretch == 1  || stretch == 4 || stretch == 7 || stretch == 10){
    Serial.println(" ");
    Serial.println("Beginning Stretch "); Serial.print(stretch);
    if(stretch < prevStretch) {
      // Step until 0 position (0 position = card 26)
      // Step to newStretch - 0 position
      flipCards(26 - prevStretch);
      flipCards(stretch);
    } else {
      // Step stretch - prevStretch
      flipCards(stretch - prevStretch);
    }
    startStretch = millis();
    endStretch = startStretch;

    // Does not end unless the stretch has been done for a total of ~15s
    while (endStretch - startStretch < 1000 || stretchTime < 600) {
      endStretch = millis();
      getPosition();

      if (y <= 400 && y >= 360) {
        stretchTime += 1;
        Serial.println(" ");
        Serial.println("Stretch 1 correct");
        Serial.println(stretchTime);
        digitalWrite(gLED, HIGH);
        digitalWrite(rLED, LOW);
      } else {
        digitalWrite(gLED, LOW);
        digitalWrite(rLED, HIGH);
        //light up red led
      }
    }
  }

  // Stretch 2: Standing Toe Reach
  // Desired Values
  // X: 317    Y:  250    Z:  348
  if(stretch == 2 || stretch == 5 || stretch == 8){
    Serial.println(" ");
    Serial.println("Beginning Stretch "); Serial.print(stretch);
    if(stretch < prevStretch) {
      // Step until 0 position
      // Step to newStretch - 0 position (0 position = card 26)
      flipCards(26 - prevStretch);
      flipCards(stretch);
    } else {
      // Step stretch - prevStretch
      flipCards(stretch - prevStretch);
    }
    startStretch = millis();
    endStretch = startStretch;

    // Does not end unless the stretch has been done for a total of ~15s
    while (endStretch - startStretch < 1000 || stretchTime < 600) {
      endStretch = millis();
      getPosition();

      if (y <= 284 && y >= 224) {
        stretchTime += 1;
        Serial.println(" ");
        Serial.println("Stretch 2 correct");
        Serial.println(stretchTime);
        digitalWrite(gLED, HIGH);
        digitalWrite(rLED, LOW);
      } else {
        digitalWrite(gLED, LOW);
        digitalWrite(rLED, HIGH);
        //light up red led
      }
    }
  }

  // Stretch 3: Outward Arm Reach
  // Desired Values
  // X: 256
  if(stretch == 3 || stretch == 6 || stretch == 9){
    Serial.println(" ");
    Serial.println("Beginning Stretch "); Serial.print(stretch);
    if(stretch < prevStretch) {
      // Step until 0 position (0 position = card 26)
      // Step to newStretch - 0 position
      flipCards(26 - prevStretch);
      flipCards(stretch);
    } else {
      flipCards(stretch - prevStretch);
    }
    startStretch = millis();
    endStretch = startStretch;

    // Does not end unless the stretch has been done for a total of ~15s
    while (endStretch - startStretch < 1000 || stretchTime < 600) {
      endStretch = millis();
      getPosition();

      if (x <= 450 && x >= 350) {
        stretchTime += 1;
        Serial.println(" ");
        Serial.println("Stretch 3 correct");
        digitalWrite(gLED, HIGH);
        digitalWrite(rLED, LOW);
      } else {
        digitalWrite(gLED, LOW);
        digitalWrite(rLED, HIGH);
      }
    }
  }

  prevStretch = stretch;
  
  // Call after successful stretch completed
  if(stretchTime >= 600){
      blinkSuccess();
  }
}

void getPosition() {
 // Function used to gather the user's body position.
  globalTime = millis();
  x = analogRead(xpin);
  y = analogRead(ypin);
  z = analogRead(zpin);

  if(globalTime - printTime >= 1000){
    Serial.println(" ");
    Serial.print("Coords:"); Serial.print(x); Serial.print(","); Serial.print(y); Serial.print(",");Serial.print(z);
    printTime = globalTime;
  }
}

void blinkSuccess(){
  // Blink the LED 5 times if user properly completed the displayed stretch
  for (int j = 0; j < 5; j++){
    digitalWrite(gLED, HIGH);
    delay(1000);
    digitalWrite(gLED, LOW);
    delay(1000);
  }
}