Hand Trainer for Muscle Spasticity

Have a look at this project for a Hand Trainer for Brain Injury Related Muscle Spasticity

This project originally began as a university project for my microcontrollers class, however I decided to share it here for others to see also.

There are two main parts to this project. One is the embedded system side which the user would interact with, the other is the webserver side.

In this tutorial I will not be going through all the parts indivdually as there is simply just too much involved, although the wiring is well documented visually and the code is well commented. If you have any specific questions feel free to contact me.

The hand trainer is designed to be used as an aid in the health care industry for the rehabilitation of a person with muscle spasticity of the hand. It can be difficult for persons who have developed spasticity due to some form of brain injury, for example: violent impact victims and stroke victims, to stay motivated during their rehabilitation. This may be because the current rehabilitation exercises are not engaging, or that the patient is not seeing results fast enough. The hand trainer can be used to make rehab more engaging by having different levels to complete, also the data recorded from the training sessions will be collated after each session meaning the after just a few sessions the user can view their statistics and see their improvements if any.

A series of buttons will be connected to the MKR1000 via a I/O expander chip, these buttons shall be arranged in a manner that sit under your fingers if you were to lay your hand naturally on a flat surface, and one button left and right of your thumb. This should cover the range of motion of all your digits.

Beside each button there will be an LED which will light up and indicate to the user which button they should press. The LEDs will light up in certain sequences, depending on the difficulty level that is selected, this is done using a rotary encoder to choose an option on the LCD. The user will follow the LEDs and press the corresponding buttons. Every time the user completes a session the time that it takes for them to complete a sequence will be sent via Wi-Fi to a web interface, where the data will be stored. This enables the health care professional/designated carer or the user themselves, to log on and compare their average session times from the start of their rehabilitation to their most recent session.

This will enable the user to see whether they have improved and to what degree. This should motivate the user to continue their rehabilitation if they are seeing tangible results, as opposed to simply gauging how well they are doing based on how they feel. The fact that the user must follow a sequence ensures that the user stays attentive and interested in the exercise.

This project may be complex at first for a beginner, if you’re having difficulty try start with some of our easier tutorials to build your knowledge first.

Links to what you’ll need:

3x Breadboard

1x Arduino MKR1000

Assorted Resistors (330, 10k, 1M)

1x Rotary Encoder (KY-040/HKT1062) with 15×16.5mm Cap

1x 1.8″ 128×160 Colour TFT Display SPI (ST7735)

1x Push to Make Button 12x12x7.3mm

1x MCP23017 I/O Expander

10x Green LEDs

Assorted Jumper Wires

1x USB Cable

Libraries you will need:

Capacitive Touch Library

MCP23017 I/O Expander Library

TFT LCD Display Library

Related Posts:

Hand Trainer Results Table

How does it work?

The development of this project was challenging at times and has taken multiple iterations to get to its current state. One of the main development decisions I had to make was whether to use tactile buttons or a matrix-based touchpad as the user input. Although a touchpad would have been a more elegant solution, I decided to use a series of push to make buttons. I made this decision as I feel that the users of the hand trainer would benefit more from the practice of exerting force while pressing on the button, rather than simply touching the touchpad. The inherent haptic feedback of a physical button may be a more familiar process for older users that may not be as accustomed to touchpads, additionally the colourful caps for the buttons may help engage small children.

Skip to Video Explanation Please

I have wired the buttons in an active High orientation. This means that the MKR1000 will read a button press as “HIGH” or binary 1, I have also wired an LED between the negative side of the button and ground. This means that when I want to play a sequence on the LEDs I can simply set the respective I/O pin to HIGH, it also means however when the user is trying to follow the sequence and they press the button, it will connect VCC to Ground via the button and the LED, thus lighting the LED and again indicating that the button has been successfully pressed.


Incorporating the Rotary Encoder was a necessary element for the project, being able to detect clockwise and counter clockwise rotations as well as a button press made this a clear choice. It has been implemented to allow the user to navigate the menu displayed on the LCD screen. A rotary encoder is used to determine the angular position of a rotating shaft. Inside the encoder there are evenly spaced contact pads, that are connected to the common pin and two other contact pins A and B. As we turn the dial either A or B will contact the common pins and will both generate an output signal. If A comes in contact with the common pad first and then B comes in contact with the common pad, then we determine that the encoder has been rotated clockwise, and if B is to contact the common pads first and then followed by A we determine the dial to have been turned counter clockwise.

Pin CLK is the output pulse of A and pin DT is the output pulse of B. The pulses A and B output will be out of phase by 90 degrees and we can infer that when A changes state if the logic level of the pulses do not match, then B != A, thus the dial was turned clockwise, and if they do match then B = A and the dial was turned counter clockwise. See Appendix 1.6 for graphical explanation. I decided that if the encoder was rotated clockwise that I would increment a counter, and if the current value of the counter was greater than it previous value, I would move the selected level on the LCD up by one, and conversely if the rotation was counter clockwise, I would decrement the counter and move the selected item on the LCD down by one.

Before a sequence of LEDs can be played, the user is required to place their hand on a metal resting plate, which acts as a sensor to determine if the user if ready to begin. When the user moves their hand close to the sensor, the metal plate and their hand create a rudimentary capacitance. When the send pin changes state, it will change the state of the receive pin after some time, the delay between changes is defined by an RC time constant, R being the resistor value and C being any capacitance at the receive pin plus any capacitance present, i.e A hand on the sensor plate. The line ‘Sensor.capacitiveSensor(30);’ will take a reading of 30 samples of how long it takes for the change in send pin to arrive at the receive pin, it should return a higher value if there is a higher capacitance or if there is a hand on the sensor. I’ve decided that a value higher than 2000 is returned from the function that there is definitely a hand present. The sequence of LEDs will then be played, and the level can begin.


Check out a brief explainer video below, for a quick overview!

Initially I had planned to use an Arduino Uno in conjunction with the MKR1000 communicating via Serial communications to ensure I had enough pins for all my peripherals. After some research I discovered the MCP23017 Input/Output (I/O) Expander, giving an additional 16 I/O pins with only two pins used to connect the chip to the MKR1000 via I2C. This enabled me to remove the Arduino Uno from the circuit and made the project look more polished. To use the MCP23017, I have tied the Reset pin to VCC, and pulled the 3 address pins to ground to set the I2C address to be 0. I have utilised the Wire.h library to facilitate the I2C communications from the chip to the MKR1000. I began by reading the datasheet for the IC and researching online how communications between these types of IC’s normally work.

Skip to Code Please

Although it was educational to understand how accessing, reading, and writing to the chip’s registers allowed me to control its operation. I decided it was more prudent to use a library in effort to keep the code as concise as possible. By interfacing the chips Interrupt pins with the Arduinos interrupt pin, I was able to trigger an interrupt on the MKR1000 via the MCP23017s I/O pins. Then calling the function ‘mcp.getLastInterruptPin()’ I was able to determine which input triggered the interrupt, I could then check the results of ‘mcp.getLastInterruptPin()’ with the expected button press, showing an X if incorrect and showing a Tick if correct.

In terms of displaying information to the user, I opted to go with a Thin Film Transistor Liquid Crystal Display (TFT LCD) Screen in colour. I thought this would look more modern than the common 16×2 LCD screens which do not provide colour displays and are less pixel dense. This screen communicates via SPI and is handled by including SPI.h library in the Arduino sketch. I originally purchased the LCD in an assorted package of components and unfortunately it was unbranded, with no markings or indication of the part number. After some research I discovered it was using a common ST7735 chip and I was able to find a library to assist me with incorporating it into my project. Using this library made it a lot easier to use the LCD however, it still took time to work out how to display shapes and designs, rather than just plain text. I was able after some time to create some animations of a Tick and ‘X’ and a rotating circular loading symbol, which I think really added professionalism and flair to the project.

The final aspect to implement was sending the data to my personal website via HTTPS. This was my first time manually creating and sending a HTTP(S) request. Initially I tried to send it via simple HTTP however as the website is HTTPS encrypted it would not accept a HTTP request. I was able to upload the WiFi101 Firmware Updater sketch and add my domain graycode.ie to the list of SSL domains in the Wi-Fi chips firmware. After this I was able to successful perform a ‘GET’ request from my website, to confirm that it was communicating correctly, I was then able to construct my ‘POST’ request and troubleshoot it until it worked, now that I knew the connection to the site was working. I created a PHP file that received and processed the data being posted to the website and saved this to a CSV file. Once I confirmed this was operating correctly, I then wrote a small PHP script on the webpage I wanted to display my data on. This script is able to read through the CSV file iteratively and print the values to the correct cells in a HTML table.



Now open the Arduino IDE and copy the code below

If you don’t know how to do this, check out our Arduino Sketch set up tutorials and youtube videos.

Check out the information about different Arduino IDE specific functions given on Arduino documentation to learn more.

Below are shown two different sets of code, the first is the code used to set up the webpage receiving the data and the second is the code uploaded to the MKR1000.

Ensure you have included the correct libraries and have wired the circuits correctly before uploading the code as it may save you a lot of time. For this project I have heavily commented the code and will not be running through it verbally for this reason. If you have any issues please do not hesitate to contact me for help.

Here are some libraries you may need: Capacitive Touch Library, MCP23017 I/O Expander Library and TFT LCD Display Library.

Below is the Website PHP POST Script used to save the incoming data to a CSV file.

  
// This code shows is Website PHP POST Script
<?php			
$time = date("l jS \of F Y h:i:s A");
$level = $_POST['level'];
$runTime = $_POST['result'];
$numCor = $_POST['right'];
$numRng = $_POST['wrong'];
$file = 'CSVfileName.csv';
$data = $time.",".$level.",".$runTime.",".$numCor.",".$numRng;
file_put_contents($file, $data . PHP_EOL, FILE_APPEND);
?>

Below is the Website HTML (WordPress Based) which is used to display the received data in a table form. You can see the result of this here.

  
// This code shows how I displayed the data on my website
<?php get_header();
$basePath = get_template_directory_uri();
$oldPath = "{$basePath}/old/"; ?>
<div>
    <div>
        <?php
        the_post();
        the_content();
        ?>		
     <?php
echo "<html><body><table class=\"table table-striped\">\n\n";
echo "<thead class=\"thead-dark\">
<tr>  
      <th scope=\"col\">Date</th>
      <th scope=\"col\">Level Difficulty</th>
      <th scope=\"col\">Time Taken (secs) </th>
      <th scope=\"col\"># Correct Presses</th>
      <th scope=\"col\"># Incorrect Presses</th>
</tr>
  </thead>";
  echo "<tbody>";
$f = fopen("https://examplewebsite.com/url/CSVfilename.csv", "r");
      while (($line = fgetcsv($f)) !== false) {
            echo "<tr>";
           foreach ($line as $cell) {
               echo "<td>" . htmlspecialchars($cell) . "</td>";}
           echo "</tr>\n";}
     fclose($f);
     echo "\n</tbody></table></body></html>";
  ?>
  </div>
</div>
<?php get_footer();?>

You can find the code for the MKR1000 part of the system at this link. The code is too long to display on this webpage. If you have any issues please let me know.

Uploaded by Joel Gray

24/06/2021

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x