Download - David Weaver - UCI Internship Powerpoint
![Page 1: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/1.jpg)
UCI Internship: Creating a Positive Feedback Device for the Rehabilitation of Stroke PatientsStudent: David WeaverProfessor: David Reinkensmeyer
![Page 2: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/2.jpg)
Background Information• Professor Reinkensmeyer is a world class leader
in the field of Robotic Rehabilitation and is currently working on several interesting and important projects • In the past and currently, rehabilitation methods
have involved a therapist giving a patient step by step instructions on how to perform a certain action.• However, Professor Reinkensmeyer believes that
methods of rehabilitation that allow patients to explore during rehabilitation instead of just being told what to do would be highly beneficial.• This is territory he is currently exploring.
![Page 3: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/3.jpg)
So What I Was Tasked With
I was told to create a device that would use sound as a positive feedback mechanism to help stroke patients relearn a movement.• Good sounds would correlate with a correct movement • Bad sounds would correlate with an incorrect movement
![Page 4: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/4.jpg)
The Device
Based on these guidelines, I came up with the following device:• It would have two buttons: • When the therapist hit their respective button and moved the device, their
motion would be recorded. The patient would then try and copy the motion made by the therapist while holding down their own button. • The comparison would happen by breaking each of the recorded motions
into 4 sections (beginning, middle1, middle2, end), each of which had a corresponding tone. • Tones would then play according to the correctness of the patient’s motion
when their four sections were compared to the therapist’s four sections.
![Page 5: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/5.jpg)
So Making This a Reality…
(when you’re an unskilled high school
student)
![Page 6: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/6.jpg)
Creating the Device: The Tones
I created the tones for the device using music production software. Each of the four segments (Beginning, Middle1, Middle2, and End) would have a correct tone, and then 3 other tones which got progressively more and more incorrect.
![Page 7: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/7.jpg)
Creating the Device: 3D Printing
At first I was planning for the device to be a sphere.
Then I wanted it to be a sphere without curves
![Page 8: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/8.jpg)
Creating the Device: 3D Printing
Finally I arrived at the Cylindrical Design because:• It’s easy to print• It can be grasped in several different ways
![Page 9: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/9.jpg)
Creating the Device: Coding
• The most difficult part of the internship for me was learning to code. • However, after some tutoring and staring at the screen long enough,
it clicked. • By the end of the internship I had written a very long segment of code
that ran my entire program.• However, the microprocessor I was using (Arduino) did not have
enough RAM to run my entire program and so I had to splice the code into two different sections, each run by a separate board.• This ultimately looked like this…
//This code is synced to the board that has the accelerometer attached//Written by David Weaver
//library that allows transmission to the other board #include <SoftwareSerial.h>
//defined values that correlate to sound files#define START_SYMBOL 'Z'#define STANDARD_TONE 'a'#define COLON_START ':'#define S_B_C 'b'#define S_B_W1 'c'#define S_B_W2 'd'#define S_B_W3 'e'#define S_M1_C 'f'#define S_M1_W1 'g'#define S_M1_W2 'h'#define S_M1_W3 'i'#define S_M2_C 'j'#define S_M2_W1 'k'#define S_M2_W2 'l'#define S_M2_W3 'm'#define S_E_C 'n'#define S_E_W1 'o'#define S_E_W2 'p'#define S_E_W3 'q'
//describes the serial ports used to transfer information from board to boardSoftwareSerial mySerial(0, 1); //tx, rx
//defining axis pins#define ZPIN A0#define YPIN A1#define XPIN A2
//terms for the compare function#define DEFINE_1 1#define DEFINE_2 1#define DEFINE_3 3#define DEFINE_4 3#define DEFINE_5 6
//button pins#define PATIENT 7#define THERAPIST 8
//Array Size#define ARRAYSIZE 100
//delay for patient and doctor#define DELAY_TIME 100#define MOTION_SENSE 0.1
//defining structsstruct three_axis { float x; float y; float z;};
struct four_returns { float beginning; float middle1; float middle2; float ending;};
//functionsint button_read(int Pin);struct three_axis read_entire_accel(void);float magnitude_of_accel_read(struct three_axis dog);int move_check(void);struct four_returns array_divider(int counter, float* array);void compare_patient_and_doctor(struct four_returns* x, struct four_returns* y);struct four_returns ratio_multiplier(float ratio, struct four_returns x);
void setup(){ mySerial.begin(9600);// delay(1000);mySerial.println("Starting Program"); pinMode(PATIENT, INPUT); pinMode(THERAPIST, INPUT);
}
void loop(){ //----------------------------------------------------------------------------------------------------------------------------------------Therapist Button Press //status variable to check to see if the therapist has already pressed the button static int Therapist_Button_Pressed_Previously = 0; //array the therapist populates float one_array[ARRAYSIZE];
//declaring struct four_returns for therapist and patient static struct four_returns therapist_four_parts; static struct four_returns patient_four_parts; //counter for therapist static int therapist_counter = 0; //counter for patient static int patient_counter = 0; //checks if the therapist button is pressed
if (button_read(THERAPIST)) { Therapist_Button_Pressed_Previously = 1; //reset counter therapist_counter = 0;
/* //checks if the button has been pushed and the device is moving while( !move_check() ) { } Serial.println("Therapist movement checked");*/
while (button_read(THERAPIST) && therapist_counter < ARRAYSIZE) {
//this is going to be the read section struct three_axis therapist_readout = read_entire_accel(); one_array[therapist_counter] = magnitude_of_accel_read(therapist_readout); therapist_counter++; delay(DELAY_TIME); } //function that divides array therapist_four_parts = array_divider(therapist_counter, one_array);/* mySerial.print(therapist_four_parts.beginning); mySerial.print(", "); mySerial.print(therapist_four_parts.middle1); mySerial.print(", "); mySerial.print(therapist_four_parts.middle2); mySerial.print(", "); mySerial.print(therapist_four_parts.ending); mySerial.print('\n');*/// delay(2000); //play standard tone start_send(STANDARD_TONE); }
//----------------------------------------------------------------------------------------------------------------------------------------Patient Correct Button Press //checks if the patient button is pressed and the therapist has already gone if (button_read(PATIENT) && Therapist_Button_Pressed_Previously == 1) { Serial.println("Patient Button Pressed"); //reset counter patient_counter = 0;/* //checks if the button has been pushed and the device is moving while( !move_check() ) { } Serial.println("Patient movement checked");*/ while (button_read(PATIENT) && patient_counter < ARRAYSIZE) { //this is going to be the read section struct three_axis patient_readout = read_entire_accel(); one_array[patient_counter] = magnitude_of_accel_read(patient_readout); patient_counter++; delay(DELAY_TIME); } //function that divides array patient_four_parts = array_divider(patient_counter, one_array); float ratio = therapist_counter/patient_counter; patient_four_parts = ratio_multiplier(ratio, patient_four_parts ); /* mySerial.print(patient_four_parts.beginning); mySerial.print(", "); mySerial.print(patient_four_parts.middle1); mySerial.print(", "); mySerial.print(patient_four_parts.middle2); mySerial.print(", "); mySerial.print(patient_four_parts.ending); mySerial.print('\n'); delay(2000);*/ //compare to doctor compare_patient_and_doctor(&therapist_four_parts, &patient_four_parts); }
//----------------------------------------------------------------------------------------------------------------------------------------Patient Incorrect Button Press //if the therapist has not previously gone and the patient presses the buttonelse if (button_read(PATIENT) && Therapist_Button_Pressed_Previously == 0) {
Serial.println("Patient Button Pressed Incorrectly");delay(5000);
//play error tone }
}
//-----------------------------------------------------------------------------------------------------------------------------------------All of my Functions//function that debounces button and makes sure it has been pressedint button_read(int Pin) { int temp = digitalRead(Pin); if (temp == HIGH) { delay(1); if ( digitalRead(Pin) == HIGH) return 1; else return 0; } else return 0;}
//function that reads the accelerometerstruct three_axis read_entire_accel(void) { struct three_axis accelread; accelread.x = (float)analogRead(XPIN); accelread.y = (float)analogRead(YPIN); accelread.z = (float)analogRead(ZPIN); accelread.x = -0.02 * accelread.x + 5.0; accelread.y = -0.02 * accelread.y + 5.0; accelread.z = -0.02 * accelread.z + 5.0; return accelread;}
//this function finds the magnitude of the accel datafloat magnitude_of_accel_read(struct three_axis dog) {
// float final_magnitude = (dog.x + dog.y +dog.z); float final_magnitude = sqrt(pow(dog.x,2.0) + pow(dog.y,2.0) + pow(dog.z,2.0)); return final_magnitude;}
/*//function that checks to see if the device is moving when the button is pressedint move_check(void){ float old_mag = magnitude_of_accel_read(read_entire_accel()); delay (DELAY_TIME); //this allows one cycle to pass float current_mag = magnitude_of_accel_read(read_entire_accel()); Serial.println(abs(old_mag - current_mag)); if (abs(old_mag - current_mag) <= MOTION_SENSE) { return 0; } else return 1; }*///Function that divides out the sections of the arraystruct four_returns array_divider(int counter, float* array) { //creates the number needed to split the array into 4
int divided_by_four = counter/4; struct four_returns fourparts; fourparts.beginning = 0.0; fourparts.middle1 = 0.0; fourparts.middle2 = 0.0; fourparts.ending = 0.0; //--------------------------------------------------------------Splits the Beginning for (int x = 0; x < divided_by_four; x++) { fourparts.beginning += array[x]; } //fourparts.beginning /= divided_by_four; //--------------------------------------------------------------Splits Middle_One for (int x = divided_by_four; x < 2 * divided_by_four; x++) { fourparts.middle1 += array[x]; } //--------------------------------------------------------------Splits Middle_Two for (int x = 2 * divided_by_four; x < 3 * divided_by_four; x++) { fourparts.middle2 += array[x]; } //--------------------------------------------------------------Splits End for (int x = 3 * divided_by_four; x < 4 * divided_by_four; x++) { fourparts.ending += array[x]; } return fourparts; } //this function will compare patient and doctor datavoid compare_patient_and_doctor(struct four_returns* x, struct four_returns* y) {
//Calculates and plays tones for the beginning if (abs(x->beginning - y->beginning) <= DEFINE_1) start_send(S_B_C);
else if (abs(x->beginning - y->beginning > DEFINE_2) && abs(x->beginning - y->beginning) <= DEFINE_3) start_send(S_B_W1);
else if (abs(x->beginning - y->beginning > DEFINE_4) && abs(x->beginning - y->beginning) <= DEFINE_5) start_send(S_B_W2); else start_send(S_B_W3); delay(100);
//Calculates and plays tones for middle1 if (abs(x->middle1 - y->middle1) <= DEFINE_1) start_send(S_M1_C); else if (abs(x->middle1 - y->middle1 > DEFINE_2) && abs(x->middle1 - y->middle1) <= DEFINE_3) start_send(S_M1_W1); else if (abs(x->middle1 - y->middle1 > DEFINE_4) && abs(x->middle1 - y->middle1) <= DEFINE_5) start_send(S_M1_W2); else start_send(S_M1_W3); delay(100); //Calculates and plays tones for middle2 if (abs(x->middle2 - y->middle2) <= DEFINE_1) start_send(S_M2_C); else if (abs(x->middle2 - y->middle2 > DEFINE_2) && abs(x->middle2 - y->middle2) <= DEFINE_3) start_send(S_M2_W1); else if (abs(x->middle2 - y->middle2 > DEFINE_4) && abs(x->middle2 - y->middle2) <= DEFINE_5) start_send(S_M2_W2); else start_send(S_M2_W3); delay(100); //Calculates and plays tones for ending if (abs(x->ending - y->ending) <= DEFINE_1) start_send(S_E_C); else if (abs(x->ending - y->ending > DEFINE_2) && abs(x->ending - y->ending) <= DEFINE_3) start_send(S_E_W1); else if (abs(x->ending - y->ending > DEFINE_4) && abs(x->ending - y->ending) <= DEFINE_5) start_send(S_E_W2); else start_send(S_E_W3); delay(100);}//uses the ratiostruct four_returns ratio_multiplier(float ratio, struct four_returns x) { struct four_returns ratio_answer; ratio_answer.beginning = ratio * x.beginning; ratio_answer.middle1 = ratio * x.middle1; ratio_answer.middle2 = ratio * x.middle2; ratio_answer.ending = ratio * x.ending; return ratio_answer; }
void start_send(char a) { mySerial.write(START_SYMBOL); mySerial.write(COLON_START); mySerial.write(a);// delay(750);}
![Page 10: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/10.jpg)
The Final Product
![Page 11: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/11.jpg)
Now In Reality How Did It Work
• The device itself was able to compare simple movements (for example a sphere, a square, a ‘Z’, etc.) • However, complex movements were beyond it.• Also the tones I created to differentiate the varying degrees of
incorrectness were too similar to easily distinguish.• Therefore you could tell when the movement was right and when it
was wrong but not to what degree.• This meant it was not good for helping patients explore to find the
correct movement.
![Page 12: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/12.jpg)
What Happens Now
• The device will be passed onto another intern who will continue to work on it.• Maybe one day very far down the road, it will become a real medical
device.
![Page 13: David Weaver - UCI Internship Powerpoint](https://reader034.vdocuments.site/reader034/viewer/2022042819/55cbaba1bb61ebd2088b4612/html5/thumbnails/13.jpg)
Thank You
• A Big Thank You to Professor Reinkensmeyer for letting me work under him.• Thank you to all of the guys in the lab but a special thanks to Joan
Aguiler and Jaime Duarte who definitely helped me the most.• Thank you to Dr. Ross Viola for setting up this internship and
Catherine Rupp for making sure everything ran smoothly.• Finally, thank you UCI!