Introduction
We created an assistive device for an older adult that would improve a certain aspect of their daily routine or bring more positivity to their life. We collaborated with our Osher client, Fredrick, and communicated with him throughout the process of the project to help us figure out the design for our intervention. The problem we decided to tackle was how we could make Fredrick’s daily exercise routine more interesting by creating a guide and friend that could not only carry the routine sequence but make the process more engaging.
What We Built
Our device is a hand-sized interactive device that will act as your exercise guide and companion that will shuffle your exercise routine and encourage you to finish each session. The device will say the exercise title through speakers and it will also display the exercise title on its screen in the front. You communicate to the device when you have completed that exercise by making a loud sound (this means that the environment you are working out in should not have too many loud noises or disturbances). The device will track your overall progress with the exercise routines and at the very end, it will congratulate you that you have accomplished all the exercises.
Final Product
Animation of how the device works overall
TinkerCad
The main interaction stimulated in TinkerCAD.
The celebration when the workout is finished
Physical Mockups
To learn more about our prototypes, click here
Narrative Sketch
To map out all the interactions Frederick might have with the exercise companion, we developed storyboards of different use scenarios.
How We Got Here
We initially interviewed Fredrick and brainstormed multiple ideas with him. In the end, we decided to pursue the exercise companion because it was the most feasible, and Fredrick also agreed that it would be something fun and useful for him.
To see our full interview story click here
The basic concept was to have a device that would shuffle his exercise routines. He would press the button to shuffle the exercise routine and the device would countdown each exercise for Fredrick to follow along. There would also be LED lights to track the overall progression of the routine. But as we got into the specifics, we changed and developed our device to better solve the problem:
- Adding voice feedback
The first time we revealed to Fredrick what we were making, we had a button that he would be able to press every time he completed a workout. However, he raised the concern that it would be very cumbersome to get up to press the button every time, therefore, this was when we decided to use sound to go to the next workout.
2. Instead of two touch screen faces on opposite ends, we used a 16×2 LCD screen
In our first final prototype, we decided to have a cubic screen with a face that acts as the “personality” of the device and changed according to the progression and accomplishment of the exercises. Another screen was in the back to have the title of the routines, in case Fredrick did not hear the exercises being called out through the speakers. However, we realized this was a little unnecessary and would add bulk to our physical size, therefore, we simplified this concept by using the form of the 16×2 LCD screen as the mouth of the device. The eyes of the mouth would be cut out from the body of the device and placed with acrylic on top to be able to see LED lights inside. The LED lights in the eyes would then flash to animate the face.
3. Adding multiple routines with a rotary encoder
We realized if we shuffled all the workout exercises, it would be difficult changing back and forth from a standing position to a floor exercise. Therefore, this is when we incorporated workout categories for Fredrick’s exercises. Instead of shuffling all the exercises, we would shuffle the exercises in a category. Thus we replaced the button we planned to use before, to a rotary encoder, where the dial part of the rotary encoder would be able to switch between categories, and the button is able to shuffle the exercises in that category.
4. Congratulatory responses
As we developed our idea of the exercise companion, we wanted to animate the device, even more, to give it more personality. Therefore, we added features where the device would congratulate you at the end of the workout and play a song that you can choose. This detail we hope would allow the user to enjoy the device more.
To see this please look at the video of the interaction under the section, Final Product.
Conclusions and Lessons Learned
During our presentation, one of the verbal comments was that the device had “an infantile appeal” to it. We thought this was very interesting where we did not mean to make it appear like that at all, in fact, we tried to create the device so that it would appear as a neutral face. Perhaps to make it more friendly, we could animate the expressions and have them more lifelike that way. Looking at our written feedback we also received feedback that stated our device’s appearance was “cute” and they “love the look”. This shows us that our device may have successfully taken a neutral ambiguous look and that is why people are having different reactions to it – it is up to the user to determine the mood of the face. For our case, our user is Fredrick and during our meetings with him to show our device, he enjoyed the appearance. Moving forward, it may be better to include more “faces” to make the device more lively, as pointed out in one of the comments. One of the biggest limitations, however, comes from the LCD display, which has limited ability to display graphics or animation.
In our written comments, more than one person wrote that they were afraid that the user may “game the system” by actively skipping over the exercise right away. This may be the case, but for our client’s specific situation, he did his exercises daily anyways and only needed this tool to make his routines more interesting. The device is not meant to push him to do the exercises, therefore, this would not have been a problem. If we were to design something for the purpose of helping users exercise, then we could include a mandatory timer for each exercise.
Another comment we received was that “to display the time remaining”. We initially had this feature, but our client declined it as he told us that he wanted to take charge of how long he would spend doing an exercise. He did not want the device to rush him. We think through this project, we learned that designing a device for a one person’s needs makes the device’s functions very specific, therefore, when other’s try to imagine using it, they might not always realize the background information behind it and will not be able to relate to the device as much.
Working remotely was a new experience for all of us, and although it becomes more time-efficient without the scheduling of physical meetings and the making, communicating was more difficult. It was not always very clear what each person was doing and the pace of work was difficult to track as well. The Gantt sheet was good to help us schedule what we needed to accomplish, but what was most effective was actually meeting through the Zoom meetings. Since members of the group did not meet, accountability for accomplishing work was also very individualized, which can be difficult for people facing different situations. This experience made us realize how important physical meetings were. On the other hand, working remotely has turned out to be a better experience than we expected. Even though we cannot have in-person interaction which is important for any activity, we can still communicate effectively through technology if we have the resolution. For example, brainstorming as a group may become harder or different, but with the whiteboard feature on Zoom, it is actually quite easy and engaging.
We really enjoyed talking with the Osher students and making these interesting devices where we didn’t need to think about the cases for multiple users and just one. We hope to take our plans for this project and actually create it in real life sometime in the future and finally be able to hold our hard work in our hands.
Our biggest takeaway from this project would be seeing how important the research and communication with the users are. By talking and understanding our client, Fredrick, our design was changed and guided by his needs. Without this information, the device would not have been as useful and meaningful as it is. This would apply to our future projects as well where we want to focus more time on planning and building a strong foundation of study and research for a design project that I am doing. In addition, we have learned that everyone has their own standard of what a good device or product should be. In the process of designing, we start by envisioning the device in our perspectives. Then it is crucial to communicate with the actual users to find what is working and what is off. Oftentimes there may be features that the designers thought is important but not so by the users, or features that the users value but are not considered by the designers.
Technical Details
Tinkercad link: https://www.tinkercad.com/things/0RXfOLjEqfM
Breadboard Image
Code
/*Exercise Companion * Zerui Huo * The code makes a robot-shaped device show the exericise names through the selected workout set. It goes to the next execise when it detects sound that has volume over the threshold. It also shows reward when the user finishes a group of exercises or the whole set. A newpixel strip shows the progress through the workout. *Pin mapping: pin | mode | description ------|--------|------------ 6 INPUT This pin represents the press button on a rotary encoder. 7 OUTPUT The pin that controls the Neopixel ligt strip/stick 8 INPUT The pin that connects to the microphone that sense any audio input from the user. 10 OUTPUT The pin that controls one of the two speakers. 13 OUTPUT The pin that controls one of the two speakers. A0 INPUT The pin that represents the rotary turner on the a rotary encoder. A3 OUTPUT Used as digital pin to control LEDS light. A4 OUTPUT Used as digital pin to control LEDS light. VCC The pin for power to go into the Arduino pro mini.Connected to a 9V battery. *Credit to example codes or reference: *The code that generates the custom characters in LCD is written in the help of the website https://maxpromer.github.io/LCD-Character-Creator/. *The code for the neopixel light strip is written by refering to the information in the website https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-use. It is a turtorial on how to use the neopixel library. *Note: In each workout set, exercises requiring similar pose are put into groups. Tree pose, for example, is grouped with other yoga exericise with standing pose. The workout sets always have the same groups of exercises,but the sequence of the groups is randomized every time. In addition, the sequence for exerices in each group is also randomized. */ //Included the needed Libraries #include <Wire.h> #include <LiquidCrystal.h> #include <Adafruit_NeoPixel.h> //Defining the "audio files" for the exerice names #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 //Naming all the pins according to stimulation in TinkerCad //Remember to change the pin according to your wiring const int ROTARY_BUTTON = 6; const int ROTARY_TURNER = A0; const int MICROPHONE = 8; const int SPEAKER1 = 10; const int SPEAKER2 = 13; const int NEOPIXELSTRIP = 7; const int LED1 = A3; const int LED2 = A4; //Setting the constant ints. Fre stands for the frequency to check a specific timer. Period is the period for some events to last. const int LED_COUNT = 6; const int SELECTINGFRE = 100; const int MICROPHONEFRE = 20; const int AUDIOPERIOD = 60; const int STRIPPERIOD = 100; //Global varibales that change //Timers for "run without block" unsigned long selectingTimer = 0; unsigned long microphoneTimer = 0; unsigned long audioTimer = 0; unsigned long stripTimer = 0; int on_off = 1; int select = 1; int cursor = 0; int row; int column = 0; int rowIncrement = 0; int columnIncrement = 0; int num_of_groups; //Lists that store informations //The set names String sets[] = {"Yoga Set", "Weights", "Aerobics"}; //The list that tells the row number that a set starts and ends int set_row[] = {0, 2, 4, 8}; //Example workout sets. The "0" represents a null, and the device will go to the next group of exercises in the set. String exercise[][3] = { {"Jumping Jack Jumping Jack Jumping Jack", "Cobbler Pose", "Abdominal Plank"}, {"hee", "ha", "yo"}, {"Tree Pose", "dance", "Upward Facing Dog"}, {"Cat-cow", "Knee-to-chest", "0"}, {"Knees-to-chest", "Hip flexor", "Torso rotation"}, {"Tree pose", "Full body", "Child's Pose"}, {"Cat-cow", "Crescent warrior", "0"}, {"Ab plank", "Cobbler Pose", "0"}, }; //Micmic the SD card that stores the audio files of the names of the exercise int exercise_audio[][3] = { {NOTE_C3, NOTE_D3, NOTE_E3}, {NOTE_F3, NOTE_G3, NOTE_A3}, {NOTE_B3, NOTE_C4, NOTE_D4}, {NOTE_E4, NOTE_F4, NOTE_F5}, {NOTE_G4, NOTE_A4,NOTE_B4}, {NOTE_C5, NOTE_D5, NOTE_E5}, {NOTE_F5, NOTE_G5, NOTE_A5}, {NOTE_B5, NOTE_C6, NOTE_D6}, }; //Creating the custom characters for the "face" of the robot //surprise face byte SURPRISE_06[] = { B00000, B00001, B00010, B00100, B01000, B01000, B01000, B01000 }; byte SURPRISE_07[] = { B01111, B10000, B00000, B00000, B00000, B00000, B00000, B00000 }; byte SURPRISE_08[] = { B11110, B00001, B00000, B00000, B00000, B00000, B00000, B00000 }; byte SURPRISE_09[] = { B00000, B10000, B01000, B00100, B00010, B00010, B00010, B00010 }; byte SURPRISE_16[] = { B01000, B01000, B01000, B01000, B00100, B00010, B00001, B00000 }; byte SURPRISE_17[] = { B00000, B00000, B00000, B00000, B00000, B00000, B10000, B01111 }; byte SURPRISE_18[] = { B00000, B00000, B00000, B00000, B00000, B00000, B00001, B11110 }; byte SURPRISE_19[] = { B00010, B00010, B00010, B00010, B00100, B01000, B10000, B00000 }; //smiley face byte SMILE_04[] = { B00000, B00000, B00000, B00000, B00000, B00001, B00010, B00100 }; byte SMILE_05[] = { B00000, B00000, B00000, B01000, B11000, B00100, B00010, B00001 }; byte SMILE_010[] = { B00000, B00000, B00000, B00010, B00010, B00101, B01000, B10000 }; byte SMILE_011[] = { B00000, B00000, B00000, B00000, B00000, B00000, B10000, B01000 }; byte SMILE_16[] = { B10000, B01000, B00100, B00010, B00001, B00000, B00000, B00000 }; byte SMILE_17[] = { B00000, B00000, B00000, B00000, B00000, B10000, B01111, B00000 }; byte SMILE_18[] = { B00000, B00000, B00000, B00000, B00000, B00001, B11110, B00000 }; byte SMILE_19[] = { B00001, B00010, B00100, B01000, B10000, B00000, B00000, B00000 }; // generating a random sequence for exerices in each exercise group int * generate_randnumb_exercise(int min, int length) { static int rando[10]; for (int i = min; i < min + length; i++) { rando[i - min] = i; } randomSeed(digitalRead(A5)); for (int i = 0; i < 200; i++) { int rand1; int rand2; int old_rand1; int old_rand2; rand1 = random(0, length - 1); rand2 = random(0, length - 1); old_rand1 = rando[rand1]; old_rand2 = rando[rand2]; rando[rand1] = old_rand2; rando[rand2] = old_rand1; } return rando; } // generating a random sequence for exerice group in set1 int * generate_randnumb_set1(int min, int length) { static int rando2[10]; for (int i = min; i < min + length; i++) { rando2[i - min] = i; } randomSeed(digitalRead(A5)); for (int i = 0; i < 200; i++) { int rand1; int rand2; int old_rand1; int old_rand2; rand1 = random(0, length - 1); rand2 = random(0, length - 1); old_rand1 = rando2[rand1]; old_rand2 = rando2[rand2]; rando2[rand1] = old_rand2; rando2[rand2] = old_rand1; } return rando2; } // generating a random sequence for exerice group in set2 int * generate_randnumb_set2(int min, int length) { static int rando3[10]; for (int i = min; i < min + length; i++) { rando3[i - min] = i; } randomSeed(digitalRead(A5)); for (int i = 0; i < 200; i++) { int rand1; int rand2; int old_rand1; int old_rand2; rand1 = random(0, length - 1); rand2 = random(0, length - 1); old_rand1 = rando3[rand1]; old_rand2 = rando3[rand2]; rando3[rand1] = old_rand2; rando3[rand2] = old_rand1; } return rando3; } // generating a random sequence for exerice group in set3 int * generate_randnumb_set3(int min, int length) { static int rando4[10]; for (int i = min; i < min + length; i++) { rando4[i - min] = i; } randomSeed(digitalRead(A5)); for (int i = 0; i < 200; i++) { int rand1; int rand2; int old_rand1; int old_rand2; rand1 = random(0, length - 1); rand2 = random(0, length - 1); old_rand1 = rando4[rand1]; old_rand2 = rando4[rand2]; rando4[rand1] = old_rand2; rando4[rand2] = old_rand1; } return rando4; } //Pointers that refers to the sequence of exercise/exercise groups int *sequenceExercise = generate_randnumb_exercise(0, 3); int *sequenceSet1 = generate_randnumb_set1(set_row[0], set_row[1] - set_row[0]); int *sequenceSet2 = generate_randnumb_set2(set_row[1], set_row[2] - set_row[1]); int *sequenceSet3 = generate_randnumb_set3(set_row[2], set_row[3] - set_row[2]); //set up of the lcd const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //set up the neopixel strip Adafruit_NeoPixel strip(LED_COUNT, NEOPIXELSTRIP, NEO_GRB + NEO_KHZ800); //defining the color for the neopixel strip uint32_t deep_sky_blue = strip.Color(0, 191, 255); //Supplemental Functions //Functions for selecting a workout set //Determine which set the rotary turner is "pointing at" int which_set () { int error_angle = 30; int potenValue = analogRead(ROTARY_TURNER); int set = 0; //Display the name of set 1 when the potentiometer is at 0 degree if (potenValue <= 1023 * error_angle / 300) { set = 1; return set; } else if (potenValue >= 512 - 1023 * error_angle / 300 && potenValue <= 512 + 1023 * error_angle / 300) { set = 2; return set; } //set 3 else if (potenValue >= 1023 * (1 - 1 * error_angle / 300)) { set = 3; return set; } } //Display the name of the workout set that is currently looking at void select_set() { int buttonState = digitalRead(ROTARY_BUTTON); int set; set = which_set(); String text = sets[set - 1]; int startingColumn = ceil((16 - text.length()) / 2); lcd.setCursor(2, 0); lcd.print("Select a Set"); if (on_off == 1) { lcd.setCursor(startingColumn, 1); lcd.print(text); } if (on_off == 0) { lcd.setCursor(startingColumn, 1); lcd.print(" "); } //When the pressbutton on rotary encoder is pressed if (buttonState == LOW) { select = 0; if (set == 1) { row = *sequenceSet1; num_of_groups = set_row[1]-set_row[0]; Serial.println(row); } if (set == 2) { row = *sequenceSet2; num_of_groups = set_row[2]-set_row[1]; Serial.println(row); } if (set == 3) { row = *sequenceSet3; num_of_groups = set_row[3]-set_row[2]; Serial.println(row); } lcd.clear(); lcd.setCursor(3, 0); lcd.print("Lets Begin!"); delay(1500); lcd.clear(); //Call the function robot_face to show a smiley face on the lcd robot_face("smiley"); delay(2000); lcd.clear(); audioTimer = millis(); } } //Sumplementary function for display exercise name onto the LCD display //This function scroll the text when it is too long to display on the 16-digit screen void scrollLeft(String string, int row) { int length = string.length(); if (millis() - selectingTimer > SELECTINGFRE) { if (cursor + 1 <= length ) { cursor = cursor + 1; } if (cursor + 1 > length) { cursor = 0; } selectingTimer = millis(); lcd.clear(); } String text = string.substring(cursor); lcd.setCursor(0, row); lcd.print(text); } //Function that show the name of the current exercise void display_text(String string) { int length = string.length(); if (length <= 16) { lcd.setCursor(ceil((16 - length) / 2), 0); lcd.print(string); } if (length > 16 && length < 32) { int indexofSpace = string.indexOf(" "); String firstWord = string.substring(0, indexofSpace); String secondWord = string.substring(indexofSpace + 1); if (firstWord.length() > 16) { scrollLeft(firstWord, 0); } if (firstWord.length() <= 16) { lcd.setCursor(ceil((16 - firstWord.length()) / 2), 0); lcd.print(firstWord); } if (secondWord.length() > 16) { scrollLeft(secondWord, 1); } if (secondWord.length() <= 16) { lcd.setCursor(ceil((16 - secondWord.length()) / 2), 1); lcd.print(secondWord); } } if (length >= 32) { scrollLeft(string, 1); } if (string == "end") { lcd.setCursor(ceil((16 - 11) / 2), 0); lcd.print("The workout"); lcd.setCursor(ceil((16 - 11) / 2), 1); lcd.print("is finished"); } } //This micmics the function of the mini mp3 player, which plays a audio record of the name of the exercise. void play_audio(int audio) { while (millis() - audioTimer < AUDIOPERIOD) { tone(SPEAKER1,audio); tone(SPEAKER2,audio); } noTone(SPEAKER1); noTone(SPEAKER2); } //Rolling the light on the Neopixel light strip as a reward when a exercise group is finished void light_up_strip() { while (millis() - stripTimer < STRIPPERIOD) { int redColor = random(0, 255); int greenColor = random(0,255); int blueColor = random(0, 255); for (int i=0;i < 6; i++) { strip.setPixelColor(i,strip.Color(redColor,greenColor,blueColor)); } strip.show(); } strip.clear(); } //That function that put the custom characters onto the lcd void robot_face(String face) { if (face == "surprise") { //Create the custom characters lcd.createChar(0, SURPRISE_06); lcd.createChar(1, SURPRISE_07); lcd.createChar(2, SURPRISE_08); lcd.createChar(3, SURPRISE_09); lcd.createChar(4, SURPRISE_16); lcd.createChar(5, SURPRISE_17); lcd.createChar(6, SURPRISE_18); lcd.createChar(7, SURPRISE_19); //write the characters to their places lcd.setCursor(6, 0); lcd.write(byte(0)); lcd.setCursor(7, 0); lcd.write(1); lcd.setCursor(8, 0); lcd.write(2); lcd.setCursor(9, 0); lcd.write(3); lcd.setCursor(6, 1); lcd.write(4); lcd.setCursor(7, 1); lcd.write(5); lcd.setCursor(8, 1); lcd.write(6); lcd.setCursor(9, 1); lcd.write(7); } if (face == "smiley") { //Create the custom characters lcd.createChar(0, SMILE_04); lcd.createChar(1, SMILE_05); lcd.createChar(2, SMILE_010); lcd.createChar(3, SMILE_011); lcd.createChar(4, SMILE_16); lcd.createChar(5, SMILE_17); lcd.createChar(6, SMILE_18); lcd.createChar(7, SMILE_19); //write the characters to their places lcd.setCursor(4, 0); lcd.write(byte(0)); lcd.setCursor(5, 0); lcd.write(1); lcd.setCursor(10, 0); lcd.write(2); lcd.setCursor(11, 0); lcd.write(3); lcd.setCursor(6, 1); lcd.write(4); lcd.setCursor(7, 1); lcd.write(5); lcd.setCursor(8, 1); lcd.write(6); lcd.setCursor(9, 1); lcd.write(7); } } //Simple function that turn the led on and off void ledSwith(String command) { if (command == "on"){ digitalWrite(LED1,HIGH); digitalWrite(LED2,HIGH); } if (command == "off"){ digitalWrite(LED1,LOW); digitalWrite(LED2,LOW); } } //The function that determines what happens when the workout set is finished void end() { display_text("end"); delay(2000); lcd.clear(); display_text("Great Job!"); delay(2000); lcd.clear(); robot_face("smiley"); int redColor = random(0, 255); int greenColor = random(0,255); int blueColor = random(0, 255); //The for loop rolls the lgiht on the LED light strip until the device is powered off for (int i=0;i < 6; i++) { strip.setPixelColor(i,strip.Color(redColor,greenColor,blueColor)); strip.show(); delay(400); if (i==5) { i = -1; redColor = random(0, 255); greenColor = random(0,255); blueColor = random(0, 255); } } } void show_exercise() { //Displaying the name of the exercise by feeding the word to function display_text() //If the selected workout set is set 1 if (row < set_row[1]) { row = *(sequenceSet1 + rowIncrement); column = *(sequenceExercise + columnIncrement); // columnIncrement in the if-statement should be set to the number of columns in each row //The if statement checks if the exercise group is finished if (exercise[row][column] == "0" || columnIncrement == 3) { rowIncrement = rowIncrement + 1; columnIncrement = 0; row = *(sequenceSet1 + rowIncrement); column = *(sequenceExercise + columnIncrement); ledSwith("on"); robot_face("surprise"); light_up_strip(); lcd.clear(); ledSwith("off"); audioTimer = millis(); //to check if the set is finished if (rowIncrement == set_row[1]) { end(); } } display_text(exercise[row][column]); play_audio(exercise_audio[row][column]); } //If the selected workout set is set 2 if (row >= set_row[1] && row < set_row[2]) { row = *(sequenceSet2 + rowIncrement); column = *(sequenceExercise + columnIncrement); // columnIncrement in the if-statement should be set to the number of columns in each row if (exercise[row][column] == "0" || columnIncrement == 3) { rowIncrement = rowIncrement + 1; columnIncrement = 0; row = *(sequenceSet2 + rowIncrement); column = *(sequenceExercise + columnIncrement); ledSwith("on"); robot_face("surprise"); light_up_strip(); lcd.clear(); ledSwith("off"); audioTimer = millis(); //to check if the set is finished if (rowIncrement == set_row[2] - set_row[1]) { end(); } } display_text(exercise[row][column]); play_audio(exercise_audio[row][column]); } //If the selected workout set is set 3 if (row >= set_row[2] && row < set_row[3]) { row = *(sequenceSet3 + rowIncrement); column = *(sequenceExercise + columnIncrement); // columnIncrement in the if-statement should be set to the number of columns in each row if (exercise[row][column] == "0" || columnIncrement == 3) { rowIncrement = rowIncrement + 1; columnIncrement = 0; row = *(sequenceSet3 + rowIncrement); column = *(sequenceExercise + columnIncrement); robot_face("surprise"); ledSwith("on"); light_up_strip(); lcd.clear(); ledSwith("off"); audioTimer = millis(); //to check if the set is finished if (rowIncrement == set_row[3] - set_row[2]) { end(); } } display_text(exercise[row][column]); play_audio(exercise_audio[row][column]); } } //This funtion controls the neopixel strip to show the progress through the set void show_progress(int num_of_groups) { int lightedPixel = (rowIncrement*6)/num_of_groups; for (int i=0;i < lightedPixel; i++) { strip.setPixelColor(i,deep_sky_blue); } strip.show(); } void setup() { // Setting up the pins pinMode(ROTARY_BUTTON, INPUT_PULLUP); pinMode(ROTARY_TURNER, INPUT); pinMode(SPEAKER1, OUTPUT); pinMode(SPEAKER2, OUTPUT); pinMode(MICROPHONE,INPUT_PULLUP); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); //Setting up for the lcd screen lcd.begin(16, 2); lcd.setCursor(2, 0); lcd.print("Lets Exercise!"); delay(1500); lcd.clear(); //Initiate the Neopixel Strip strip.begin(); strip.show(); //Initiate Serial Print Serial.begin(9600); } void loop() { while (select == 1) { select_set(); //Timer to make the chosen workout set "flash" if (millis() - selectingTimer > SELECTINGFRE) { if (on_off == 1) { on_off = 0; } else { on_off = 1; } selectingTimer = millis(); } } if (millis() - microphoneTimer > MICROPHONEFRE) { int buttonState = digitalRead(MICROPHONE); if (buttonState == LOW) { audioTimer = millis(); stripTimer = millis(); columnIncrement = columnIncrement + 1; lcd.clear(); } microphoneTimer = millis(); } show_exercise(); show_progress(num_of_groups); }
Schematic and Design Files
Comments are closed.