You are on page 1of 56

Equine Versatile Pressure-Sensing Mat

50 Shades of Neigh

Jordan Hagood

Benjamin Stone

Stefanie Panzenhagen

Ed Shen

BE 420 – Biomedical Engineering Design II

February 20, 2017

1
Executive Summary
Therapeutic horseback riding is an equine-assisted activity that can be used for various purposes,
including addressing physical, social, learning, sensory, and psychological needs. The benefits of
therapeutic riding include improved fine motor skills, improved balance, core strengthening, social
skill development, and sensory stimulation. Most studies that have been conducted to assess the
effectiveness of therapeutic riding have focused on changes in gait, posture, strength, coordination,
depression, pain, anxiety, and quality of life. Many of these studies relied solely on qualitative
data, such as instructor observation. Due to the limited amount of quantitative data on this type of
therapy, it is difficult to prove the benefits that have been associated with therapeutic riding.
Lakeland Center for Therapeutic Riding Research is a nonprofit provider of therapeutic riding and
specifically has a need for a pressure measurement system that fits with their bareback pad and
Australian saddle. For this reason, the Equine Versatile Pressure-Sensing Mat, a force sensor
embedded bareback pad, has been developed to quantitatively track the contact pressure applied
by the rider to the horse during therapeutic riding sessions.

The Equine Versatile Pressure-Sensing Mat provides a solution to the lack of quantitative data in
the field of therapeutic riding. This flexible mat contains an embedded array of 16 pressure sensors
that collect pressure data in the gluteal region during riding sessions. A real-time data display
indicating if the rider's pressure is shifted more to the right or the left is conveyed via two LED
lights on the breadboard, one corresponding to the left side of the gluteal region, and one to the
right. The LED lights light up red when the corresponding side has higher contact pressure applied.
A rechargeable battery powers the electrical components. After a riding session has been
completed, a flash drive with the stored data from the session can be uploaded to the Lakeland
Center for Therapeutic Riding Research computer to be used for research purposes. A graphical
user interface (GUI) has been uploaded to the same computer that allows the user to easily store
and process the data collected on the flash drive. This data can be analyzed graphically and by a
ratio calculation, allowing the trainer to track the progress of each rider over time.

The device has been tested and has met many of the product specifications and performance
requirements set forward. However, there are some features that have not yet been completed. The
main features yet to be implemented include embedded LED arrays, a PCB board, and electrical
housing that can hold all of the electrical components. Because of this, we recommend that the
device not be sent to Lakeland Center for Therapeutic Horseback Riding.

The cost to develop the device was $475.35, with the sensors, battery, and fabric contributing the
highest amounts. Considering the features the device encompasses and the price compared to
similar products, this device is an excellent investment and step towards a solution in proving the
effectiveness of therapeutic riding as a whole.

i
Table of Contents

I. Introduction and Design Specifications .......................................................... 1

II. Design Overview ............................................................................................ 3

III. Summary of Design Changes ......................................................................... 9

IV. Design Construction Details ......................................................................... 12


Mechanics & Materials Subsystem .............................................................................................. 13
Circuit Configuration Subsystem ................................................................................................. 17
Data Processing Software Subsystem .......................................................................................... 18
User Interface Subsystem ……………………………………………………………………….. 20

V. Verification and Validation .......................................................................... 26


Subsystem Testing ............................................................................................................26
Design Testing ..................................................................................................................31
Client Testing ....................................................................................................................34
Feasibility and Merit Criteria Assessment ........................................................................35
Failure Modes & Effects Analysis ....................................................................................38

VI. Budget ........................................................................................................... 39

VII. Conclusions & Recommendations ............................................................... 41

VIII. Personnel and Responsibilities ..................................................................... 42

IX. Appendices ................................................................................................... 44

i
I. Introduction and Design Specifications
Design Problem Description and Client Background
Therapeutic horseback riding is an equine-assisted activity that can be used for various purposes,
including addressing physical, social, learning, sensory, and psychological needs. The benefits
of therapeutic riding include improved fine motor skills, improved balance, core strengthening,
social skill development, and sensory stimulation. Most studies that have been conducted to
assess the effectiveness of therapeutic riding have focused on changes in gait, posture, strength,
coordination, depression, pain, anxiety, and quality of life. Many of these studies relied solely
on qualitative data such as instructor observation. Due to the limited amount of quantitative data
on this type of therapy, it is difficult to prove the benefits that have been associated with
therapeutic riding. For this reason, a solution is needed to develop a measurement system that
quantitatively tracks the contact pressure applied by the rider during therapeutic riding sessions.
Lakeland Center for Therapeutic Riding Research is a nonprofit provider of therapeutic riding
and specifically has a need for a pressure measurement system that fits with their bareback pad
and Australian saddle.

Intended Use
This Equine Versatile Pressure-Sensing Mat is intended to be used during therapeutic horseback
riding sessions at Lakeland Center for Therapeutic Riding Research. The device can support up
to 200 pounds and is intended to be used in dry, equestrian conditions. The mat can be used on
Hilton (the mechanical horse at Lakeland Center), any bareback pad, or horse when using the
appropriate layer(s) of the device. The device provides live feedback and post session analysis
regarding the shift in weight of the rider during riding sessions.

Unintended Use
This device is not intended to be used in non-equestrian settings or with riders greater than 200
pounds. The mat is not intended to be used with more than one rider on it at a time. It is also not
intended to be used in wet conditions, such as in the rain or snow.

Special Features
The device recalibrates itself upon start-up so that accurate data can be collected from the force
sensors. The LED lights on left and right sides of the mat can give trainers instant feedback, so
the trainers can help the riders to adjust the riders' form.

1
Design Specifications
The following table shows the design specifications that the Equine Versatile Pressure-Sensing
Mat meets in its current state.

1. Performance 1.1 Accurate within 10% of true values


1.2 Sampling rate of 4 Hz
1.3 Measures loads up to 200 pounds
1.4 Can view the LED lights from 75 feet away
2. Environment 2.1 For indoor and outdoor use
2.2 Not for use in wet conditions
3. Human 3.1 6 steps to store data on computer app
Factors 3.2 5 steps to look at data analysis once data has been stored
3.3 2 representations of data collected provided on computer app
3.4 < 6 steps to set up the device on the horse
3.5 Comfort rating of ≥ 7 / 10 on rider surveys
3.6 Easily accessible on/off switch on the battery
3.7 Easily accessible data record switch
4. Dimensions 4.1 Design can be implemented to fit with the Equicizer bareback
pad
4.2 Design can be implemented to fit with the Australian saddle
4.3 Electrical housing unit fits in standard saddle bag
4.4 Total weight of mat does not exceed 10lbs
5. Maintenance 5.1 < 6 steps to clean the device - cleaning would involve
vacuuming the top layer and wiping dust off the bottom layer,
wiping the dust out of the housing, and wiping dust off the exposed
wires
5.2 Accessible and replaceable force sensors
5.3 Rechargeable 5V battery for sensors and LED lights
6. Safety 6.1 The alignment indicator line moves by < 1 inch to either the
right or left of center
6.2 Device does not make any loud or sudden noises
6.3 Wires are not exposed to riders
7. Animal 7.1 Horse trainer approved for use on a horse
Considerations

2
II. Design Overview
This section explains how the Equine Versatile Pressure-Sensing Mat functions to provide
quantitative pressure measurements. The features included in the design are discussed as well as
brief descriptions of the four subsystems that make up the device. The next section delves deeper
into the functions of the four subsystems and how they work independently of each other.

Basic Overview

Lakeland Center for Therapeutic Riding Research had two major needs for this device – reliable
data that can be used to support the qualitative analyses concluding that therapeutic horseback
riding contributes positively to recovery and real-time feedback that allows the trainer to correct
the riders’ position during riding sessions. Along with real-time feedback, the trainers wanted post-
session feedback that quantitatively tracks the rider's progress. Lakeland Center for Therapeutic
Riding works with riders on horses with bareback pads, on horses with the Australian saddle, and
on a mechanical horse with bareback pads. Therefore, the device needed to accommodate various
bareback pads, saddles, horses, and a mechanical horse.

The Equine Versatile Pressure-Sensing Mat, shown in Figure 1, meets all of these needs. The top
layer of the mat contains an array of 16 pressure sensors embedded in the fabric, centered around
the gluteal region of the rider. To make sure the data collected from the sensors is reliable, the
program collecting the data calibrates the sensors automatically when the device is turned on. After
the riding session has ended, the data can be uploaded via a USB port to a computer.

Figure 1. The Equine Versatile Pressure-Sensing Mat. The mat contains 16 pressure sensors
embedded in the fabric and 2 LED arrays. Electrical wiring is housed in the electrical housing
unit, and data can be uploaded via flash drive.

3
The Equine Versatile Pressure-Sensing Mat also provides a real-time data display indicating if the
rider's pressure is shifted more to the right or the left. This information is conveyed through the
use of an LED array on both sides of the mat. The LED arrays light up on the side corresponding
to the side with the highest contact pressure, as shown in Figure 2. This lets the trainers know
where the rider's weight has shifted in real-time, allowing them to correct the rider's position during
the riding session rather than post-session.

Figure 2. The Equine Versatile Pressure-Sensing Mat’s as it would conform over a horse. If the
contact pressure is highest on the rider’s right gluteal region, the LED array shown lights up.

As indicated by the name, the Equine Versatile Pressure-Sensing Mat design is versatile and can
work with different riders, horses, and bareback pads. Using a dual layer system, the mat
accommodates use with the Australian saddle. The top layer is equipped with hook and loop straps
on the bottom that attach to different bareback pads. The hook and loop keeps the mat in place
during riding sessions. The top layer can then attach to a bottom layer via the hook and loop straps.
The bottom layer is made of waffle neoprene, a non-slip material that can be used on top of any
saddle. The non-slip material provides enough friction to keep the mat in place during riding
sessions.

Additional features include two alignment indicator lines: one down the middle of the mat and one
at the back at the mat indicating where the back of the rider's gluteal region should be. The
indicator lines are dark markings on the mat and are used to center the rider on the mat in order to
maintain accurate sensor positioning. Another feature includes the electrical housing box, which
increases the safety of the device by minimizing the exposed electrical components.

A Raspberry Pi is used to control this measurement system, which provides a USB port for data
transfer. A 5V rechargeable battery pack is used to power the electrical components of this device.

4
The Raspberry Pi and battery pack are housed in a custom box, 3D-printed box made out of
poly(lactic acid). The box fits in a standard-sized saddle bag, which is provided to the riders by
Lakeland Center for Therapeutic Riding Research.

A GUI (graphical user interface) was uploaded onto a Lakeland Center for Therapeutic Riding
Research computer that allows the user to import the data. Once the data is imported to a computer
using a flash drive, the user can maneuver through the interface to look at the data in 3 forms:
pressure measurements, a graph comparing the left and right sections’ contact pressure over time,
and a ratio calculation (total time when the rider’s contact pressure is higher on the left 8 sensors
compared to total time when the rider’s contact pressure is higher on the right 8 sensors).

5
How it Works

The Equine Versatile Pressure-Sensing Mat is used to measure the pressure generated between the
rider and the horse during a riding session using an array of 16 force sensors. Figure 3 shows the
path the of the pressure data, from data collection to data transfer. The specific data collected from
the sensors are in the form of a voltage. The voltage data is converted to pressure data using a
calibration curve specific to each sensor.

Figure 3. The path of data, from data collection to final data transfer that allows the Equine
Versatile Pressure-Sensing Mat to collect and store pressure measurements during a riding session.

The microprocessor in the device records values from the chosen sensor at a sampling frequency
of 4 Hz in order to prevent any aliasing the data. This ensures that, as the rider transfers their

6
weight from one side of the horse to the other, the microprocessor records the change without
missing a shift in pressure from one side to the other. Once data has been collected from the
sensors, the microprocessor converts it into pressure values and then perform the following tasks:
calculates a running average for the left 8 sensors, calculates a running average for the right 8
sensors, and stores the data to a flash drive for later processing.

Running averages for the left and right regions are then compared and used to provide live
feedback to the instructor. By taking the running averages, flickering due to noisy data is avoided.
If the running average for the right gluteal region is higher than the left, the microcontroller turns
on the LED array on the right side of the mat red and the LED array on the left side green. That
LED stays lit until the running average for the left gluteal region is higher than the right. If the
running averages for the left and right sides are within 10 percent of each other the LED arrays
turn orange. This allows the instructor to see, in real-time, upon which side of the horse the rider
is placing the most contact pressure.

The microcontroller saves the pressure data into a large array in a text file on the flash drive. Rows
of this array correspond to a sampling time, and each column corresponds to the sensor from which
the data came. This text file is then uploaded to the GUI on a Lakeland Center for Therapeutic
Riding Research computer. The GUI allows the user to save the data and categorize it based on
the date, rider, and session number.

Subsystem Descriptions

The Equine Versatile Pressure-Sensing Mat is divided into four subsystems, Mechanics and
Materials, Circuit Configuration, Data Processing, and User Interface.

The Mechanics and Materials subsystem was responsible for designing the mat to securely fit on
a bareback pad and Australian saddle. The mat houses two sheets of foam and a layer of fabric
embedded with sensors. This subsystem relates to the Circuit Configuration subsystem, as this
subsystem detailed how the sensors were to be embedded in the mat.

As mentioned above, the Circuit Configuration subsystem was closely related to the Mechanics
and Materials subsystem, and it was also related closely to the Data Processing subsystem. This
subsystem is comprised of all electrical components of the device, including powering all
components, designing the layout of all components, and wiring all components together. The
Circuit Configuration subsystem, as indicated in the name, also determined how the sensors were
configured in the mat. The configuration of the sensors determined the placement of the sensors
in the mat and the method that the sensors were wired with the microprocessor. The distribution
of sensors was important because the goal of this design was to accurately measure the rider’s
pressure shifts. The sensors were divided into 2 sections (left and right); the Data Processing
subsystem then compares pressure data collected from the 2 sides. The LED array on the side
experiencing more pressure then lights up.

The Data Processing subsystem utilizes the pressure data measured by the sensors in the mat to
provide trainers with live feedback during the riding session while also saving the data to be used
later in the User Interface. When the rider places a majority of the contact pressure one on side,

7
the LED arrays corresponding to that side will turn red to alert the trainer, while the other side
turns green. Live data processing of the pressure data is carried out in a Raspberry Pi with a
program coded in Python. One of the biggest challenges this subsystem faced was choosing the
frequency in which the Raspberry Pi would sample the sensors, currently set at around 4Hz.
Another challenge of this subsystem was choosing how many samples to use in creating a running
average for the left and right gluteal region in order to provide the live feedback via LED arrays,
currently set at 3.

The User Interface subsystem takes the data from a flash drive (from the Data Processing
subsystem) and stores it onto a Lakeland Center for Therapeutic Riding Research computer. The
subsystem also works to provide various representations of the data so that the user does not have
to manipulate the data to get meaningful results. This specifically includes providing a graph and
ratio calculation. The graph compares the left and right gluteal regions’ contact pressure over time,
while the ratio calculation refers to the total time when the rider’s contact pressure is higher on the
left 8 sensors compared to total time when the rider’s contact pressure is higher on the right 8
sensors. One challenge of this subsystem was how to store the data in an organized manner.
Ultimately, the client expressed interest in categorizing the data by rider and session number.

8
III. Summary of Design Changes
Mechanics & Materials Subsystem
The sensor arrangement has been changed based on the results of the sensor placement
performance test (page 29). It was determined that 4 fewer sensors were needed and that the
arrangement shown in Figure 4 would collect enough data to accurately assess the balance of the
rider.

Figure 4. The new sensor arrangement determined as a result of the sensor placement performance
test.

The mat, with the dimensions compatible with the Equicizer bareback pad, was too large to fit on
top of the Australian saddle. Because of this, the same design, implementing the dual layer system,
was used with different dimensions to create a mat to go on top of the Australian saddle. The
Australian mat has two less sensors to accommodate for size. The dimensions and sensor
arrangement are shown in Figure 5.

9
Figure 5. The mat designed for use with the Australian saddle. The sensor arrangement shows 2
less sensors. One from the back of the mat on each side was removed to accommodate the size of
the Australian saddle.

Circuit Configuration Subsystem


Since the sensor number was changed from 20 to 16, only 2 ADC and 4 op amps were needed for
the circuit. This change made the final circuit board smaller.

Data Processing Software Subsystem


With the sensor arrangement being changed from 20 to only 16 sensors, the matrices being created
and saved are 16 by 1 matrices. To prevent the LEDs from flickering back and forth between the
right and left side of the mat when equal pressure is being applied, an additional code was added
to turn on the LED lights on both sides when the pressures are within 10 percent of each other.
Another change was the shift from 4 individual LEDs to a single larger square LED array on each
side. This reduces the amount of wiring needed from the LEDs to the microcontroller.

User Interface Subsystem


With the sensor arrangement changing from 20 to 16 sensors, the data analytics portion of this
subsystem has changed only slightly – the graph and ratio calculation now only uses a 16 x n array
instead of 20 x n to do any data manipulation. This design change is justified as described above
due to the sensor placement testing.

In addition, the erase button is not included in this subsystem. During the construction of the code,
a function was discovered that simply moved the files from the flash drive to a folder on the

10
computer rather than make copies. By using this function, there was no need for an erase data
button.

There has also been a slight change in the visual layouts of the screens. These slight modifications
occurred so that the layout is compatible with Python software.

11
IV. Design Construction Details
The current final design is shown in Figures 6 and 7. Figure 6 shows the mat on top of Hilton, and
Figure 7 is a larger view of the circuit configuration with all of the sensors wired to the breadboard.

Figure 6. The Equine versatile Pressure-Sensing Mat mounted on Hilton with the circuit shown
in the background.

12
Figure 7. Sensors, Raspberry Pi and battery were wired together as shown above.

Mechanics & Materials Subsystem


The Mechanics and Materials subsystem consists of the outer layer of the mat that encloses two
sheets of foam and a layer of fabric embedded with 16 sensors. The three components are shown
in Figure 8.

Figure 8. The three components of the Equine Versatile Pressure-Sensing Mat enclosed by use
of a zipper.
13
To construct the outer cover of the top layer of the mat, two identical 31" x 19" sheets of microfiber
suede and a 24" x 1.5" strip were cut out of a larger piece of fabric. A template was made to round
each of the corners on the two larger sheets. The radius of the curve used was 1.5". The template
was traced onto each larger sheet and each of the corners were cut out using fabric scissors. The
72" zipper was then sewn onto the two sheets, attaching them. The extra strip of fabric was used
to seal the back of the covering; any excess fabric from this strip was removed to avoid interference
with the zipper. A layout of the unzipped outer cover is shown in Figure 9.

Figure 9. The unzipped outer microfiber suede layer of the mat.

Two 30" x 18" sheets of foam were cut out to fit inside the outer cover of the top layer of the mat.
This was done using a utility knife.

The mat developed for the Australian saddle is shown in Figure 10.

14
Figure 10. The mat designed with dimensions specifically for the Australian saddle shown on top
of the Australian saddle. This mat was designed with two layers, the top one similar to the mat for
the Equicizer bareback pad, and the bottom neoprene layer to prevent slipping.

To make the mat for the Australian saddle, the same thing was done, with two identical 17" x 12"
sheets of microfiber suede. A 36" zipper was used to attach the two sheets, and the remaining
opening was sewn directly together. A layout of the zipped outer cover for the Australian mat is
shown in Figure 11.

15
Figure 11. The mat designed to fit with the Australian saddle.
To implement the dual layer system, hook and loop pieces were sewn onto the bottom of the mat
designed for the Australian saddle, and corresponding hook and loop pieces were adhered to the
neoprene layer. The two layers are shown detached side by side in Figure 12.

Figure 12. The two layers of the dual layer mat designed for the Australian saddle. The
corresponding hook and loop pieces can be seen. The top layer is on the left and the neoprene layer
is on the right.

Two sheets of foam were cut out from a larger piece of foam, one 30" x 18" and one 16" x 11", to
fit inside the mat for the Equicizer bareback pad and for the Australian saddle, respectively.

To embed the sensors, two 30" x 18" sheets made of a PVC blend, to mitigate stratching, were cut
out. 0.25" above each sensor location, a 1" hook and loop was sewn onto the inside of each sheet.
One sheet had the hook side of the hook and loop, and the other sheet had the loop side of the hook
and loop. The sheets were attached to each other with the hook and loop aligned. 2.5" long and 2"
wide pockets were sewn around the hook and loop and where the sensors were to be placed. One
side of the fabric was cut above the hook and loop to allow access to the sewn pockets. The layer
of embedded sensors is shown in Figure 13.

16
Figure 13. The layer of embedded sensors. Each pocket has a hook and loop piece used to keep
the sensors in place. The sensors are centered in the pockets with the pucks taped to the sensor to
prevent them from sliding. The distances between sensors are shown in Figure 4.

A prototype of the electrical housing was made, however, it was not implemented due to
dimensional errors.

Circuit Configuration Subsystem


The circuit of the device was composed of a Raspberry Pi Model 3B, which was used to collect
and process the pressure data, 2 analog-to-digital converters (MCP3008), 4 quad op amps
(LM224N), and 16 pressure sensors (FlexiForce A401). The pressure sensors were wired to the op
amps to amplify the input signals. Each quad op amp was connected to 4 sensors, and there was
individual output pin on the op amp to allow the signal to be sent to the ADCs. The analog output
from the op amps was converted to digital signal by the ADC, which held up to 8 input channels
from op amps. The digital signal output from the ADC was then sent to Raspberry Pi. The sensors
wasa divided into groups, left and right, on the pad, centered at the middle line indicated on the
pad. There were also two groups of LED lights connected to the Raspberry Pi, which was
programmed to light up according to pressure change. The Raspberry Pi was programmed to
calculate which side experienced more pressure and lit up the LED to update trainers the rider's
current status. The arrangement of the sensors is shown in the Materials and Mechanics section
(Figure 4), and the wiring of sensors, op amps, and ADCs is shown in Figure 14.

17
Figure 14. The schematic of the circuit system not including inputing to Raspberry Pi. 16 force
sensors were used for this sensing mat, and the amplified signal from the sensors were fed into
ADC, which then output to Raspberry Pi. Note that the resistors shown in the schematic are not
the actual resistor values.

The device is powered by a rechargeable battery, and it can be turned on by the switch in the
housing implemented by the Data Processing Subsystem. Once the device is turned on, the device
automatically calibrates the sensors, which then send force signals to op amp, ADC, and the signals
are processed by the Raspberry Pi to determine the side experienced more pressure.

Data Processing Subsystem


To construct the data processing subsystem, python code was created using the Python IDLE
version 3.6 on the Raspberry Pi. The code for the Data Processing software is separated into four
major sections: the initial program setup; the analog to digital converter function; variable/port
setup and calibration; and the main program loop. The code for the Data Processing Subsystem is
shown in Appendix A.

The initial program setup section of the data processing subsystem is where any additional modules
that are needed for the program to run correctly on the Raspberry Pi are loaded and named. The
first additional module loaded is "time" which sets up and starts the internal clock to help with
timing during the program. The second loaded is "os" which sets the path that the program follows.
To be able to use the GPIO pins of the Raspberry Pi as inputs and outputs "RPi.GPIO" was loaded
and renamed as GPIO for easier use throughout the program. The last module loaded is "numpy"
which allows for better matrix manipulation inside the program, it is loaded as np. The final line
of the initial program setup section defines the numbering format that will be used for the GPIO
pins as BCM.

18
The second section of the code is the analog to digital converter function, which uses several inputs
from the code to read the values of all eight channels on the ADC. This function is defined as
readadc, and it takes five inputs in order to properly read all 8 channels of the ADC's. The required
inputs are: the channel number that is being read, the clock pin, the mosi pin, the miso pin, and the
cs pin. The last three of the inputs are used to define the input and output pin numbers coming
from the ADC and going to the Raspberry Pi. Inside the function several GPIO pins are defined as
outputs and the clock is turned on. With a bit of bit manipulation, the channel number is converted
to the five-bit number that corresponds to the channel and the sampling mode that the ADC is
supposed to sample. From here the five-bit number is sent to the ADC using the first for-loop and
then the second for-loop receives the value for the desired pin back from the ADC. The benefit of
writing this as a function is that it allows the same section of code to be used to sample both ADC
chips by just changing the input variables when the function is called to those that correspond to
the correct ADC chip.

The variable and port setup section of the Data Processing Subsystem defines variables as well as
setting up the GPIO ports. This section defines the pin locations for the clock, miso, mosi, and cs
pins that are going to be used for each ADC. After the pin locations are defined the GPIO pins
corresponding to the pin locations are setup to be either input or output pins from the Raspberry
Pi. The last things defined in this section are the two matrix's that will store the values from the
eight sensors on each side, these matrices are prefilled with ones. The calibration portion of this
section utilizes the analog to digital converter function from earlier in the code to sample each
sensor 20 times and average the values for each sensor. This is done when no one is sitting on the
mat. The averaged values for each sensor are then stored in a matrix and subtracted from the values
recorded later in the program.

The main program loop is where the main code that runs the Data Processing subsystem is written
since it needs to be run over and over again in a specific order to function correctly. The loop is
contained inside a "try" section that has an "except" for a keyboard interrupt that ends the program
and cleans up the GPIO pins to make prototyping easier. The main loop code is then held inside a
while-loop to allow the program to continuously run until a keyboard interrupt occurs, the final
code will replace the keyboard interrupt with a switch to end the program. Currently there is no
set sampling frequency; rather the program is being run as fast as it can run through the while loop
once after which it starts the loop again.

Inside the while-loop there are two for-loops one for sampling the eight sensors connected to one
ADC and another for sampling the sensors connected to the other ADC. Inside each for-loop the
function readadc is used to read the value of one sensor from the ADC, then it is converted to a
voltage and stored in the matrix responsible for storing the values of the sensors. Once the matrix
is compiled from each ADC the values are then converted from voltage to pressure by multiplying
each sensors value by that sensors calibration curve and have the zero values subtracted to show
the change form when no weight is applied. After the values have been converted to pressure the
matrix is analyzed to see which side of the mat has more pressure, and then the side corresponding
to the side with higher pressure has its LEDs turn red and the other side has its LEDs turn green.
If the values for each side ar within 10 percent then both sides have the LEDs turn orange. Finally,
the matrix is saved to a text file on the USB device connected to the Raspberry Pi.

19
User Interface Subsystem
Figure _ shows the final flow of information through the User Interface subsystem. This
subsystem was coded completely in Python and specifically utilized Tkinter (Python's GUI
package). Once the GUI was completely coded and tested, it was uploaded to the client's computer.

Figure 15. The complete flow of information through the User Interface subsystem of the Equine
Versatile Pressure-Sensing Mat.

20
To begin the creation of the GUI, a "skeleton" of the program was built by creating 5 empty
screens. This was accomplished using Tkinter's frame function to create 5 different frames that
the program switches between with the use of buttons. The 5 screens are shown in Figure 16,
Figure 17, Figure 18, Figure 19, and Figure 20.

Each screen was then given a title that prompted the user to select a button. The prompt was coded
into the program using Tkinter's label function. The prompt "What do you want to do?" was coded
into Screen 1, Screen 4, and Screen 5. The prompt "Enter the session information" was coded onto
Screen 2. The prompt "Select a riding session" was coded onto Screen 3.

Next, all of the buttons were encoded onto each screen using Tkinter's button function. On Screen
1 shown in Figure 16, 2 buttons were created: "Upload new data" and "Look at previous data." On
Screen 2 shown in Figure 17, 3 buttons were created: "Select file from flash drive & destination,"
"Enter," and "Back." On Screen 3 shown in Figure 18, 3 buttons were created: "Select file,"
"Enter," and "Back." On Screen 4 shown in Figure 19, 4 buttons were created: "Ratio Calculation,"
"Graphical Display," "Raw Data," and "Restart." On Screen 5 shown in Figure 20, 2 buttons were
created: "Upload Another File" and "Continue to Data Analysis."

Finally, 2 fill-in-the-blank entry boxes were added to Screen 2 using Tkinter's entry function. The
entry boxes were labeled with "Rider name" and "Session #." All the completed screens are shown
below.

Figure 16. Screen 1 of the GUI created for the User Interface subsystem, which functions to
upload data and provide different representations of the data.

21
Figure 17. Screen 2 of the GUI created for the User Interface subsystem, which functions to
upload data and provide different representations of the data.

Figure 18. Screen 3 of the GUI created for the User Interface subsystem, which functions to
upload data and provide different representations of the data.

Figure 19. Screen 4 of the GUI created for the User Interface subsystem, which functions to
upload data and provide different representations of the data.

22
Figure 20. Screen 5 of the GUI created for the User Interface subsystem, which functions to
upload data and provide different representations of the data.

The next step in creating the program was adding events to the buttons allowing them to change
the frame. This portion was coded using Tkinter's lambda function. Specifically, on Screen 1, an
event was added to the "Upload New Data" button to allow pushing the button to switch the
program to Screen 2. Again, on Screen 1, an event was added to the "Look at Previous Data"
button to allow pushing the button to switch the program to Screen 3. An event was added to the
"Enter" button on Screen 2 to allow pushing the button to switch the program to Screen 5. An
event was added to the "Enter" button on Screen 3 to allow pushing the button to switch the
program to Screen 4. An event was added to the "Back" button on Screen 3 to allow pushing the
button to switch the program to Screen 1. Furthermore, an event was added to the "Restart" button
on Screen 4 to allow pushing the button to switch the program to Screen 1. Finally, an event was
added to the "Upload Another File" and "Continue to Data Analysis" buttons to allow pushing the
button to switch to Screen 2 and Screen 4.

Next, all functions utilized in the program needed to be created. To begin, the Move_File function
was created to move a data file from the flash drive to a location specified by the user. To create
this function, Tkinter's askopenfilename function was first used to open file explorer. When the
user selects a file from the file explorer, that file name is saved. Tkinter's askdirectory function
was used to open file explorer; when the user selects a folder, the path is saved. The file previously
selected is then moved to the path the user selected using Python's shutil function.

Next, the Rename_File function was created. The function renames the file that was previously
uploaded. The user types into the 2 entry fields on Screen 2, and when the user selects "Enter,"
the file is renamed based on their entries. The file is renamed using Python's os.rename function.

The Select_File_Data was created to select a file to analyze. This function uses the
askopenfilename function to again open the file explorer. The user selects a file, and that file name
is stored for later use.

The Ratio function was created to provide a ratio of time where the rider's contact pressure was
higher on the left or right sides. To create this function, the file chosen from the Select_File_Data
function was read into the function. The file is converted into a matrix of integers. The columns

23
correspond to the sensors (16) and the rows in each file correspond to the number of samples.
First, the sums of each row are taken. Next, the sums of the first 8 values in each row are taken.
Then, the sums of the first 8 values are divided by the sum of each row. If that percentage is
greater than 50, a counting index is increased by 1. To calculate the final ratios, k is divided by
the number of samples. A pop-up message showing this ratio was created using Tkinter's Tk
function. Figure 21 shows an example of a pop-up message that this function creates.

Figure 21. An example of the pop-up created by the Ratio function in the User Interface subsystem
of the Equine Versatile Pressure-Sensing Mat.

The Graph function was created to provide a visual representation of the average left and right
contact pressures over time. It first averages the left halves and right halves of each row. Then, it
uses matplotlib's pyplot function to plot the averages over time. It uses the function plt.show to
create a pop-up of the plot. Figure 22 below shows an example of a plot created by the Graph
function.

Figure 22. An example of the plot created by the Graph function in the User Interface subsystem
of the Equine Versatile Pressure-Sensing Mat.

24
The Raw_Data function was created to open the notepad data file. This function uses the data file
specified in the Select_File_Data function. It uses the subprocess.Popen function to open the
notepad file.

Once all the functions were created, the events to make them happen needed to be added to buttons
already in the program. Again, this portion was coded using Tkinter's lambda function.
Specifically, the Move_File function was added to the "Select File" button on Screen 2. The
Rename_File function was added to the "Enter" button on Screen 2. The Select_File_Data
function was added to the "Select File" on Screen 3. The Graph function was added to the
"Graphical Display" button on Screen 4. The Ratio function was added to the "Ratio Calculation"
button on Screen 4. Finally, the Raw_Data function was added to the "Raw Data" button on Screen
4.

25
V. Verification and Validation

Subsystem Testing

Sensor Placement Test Plan


Type of Test: Performance
Equipment Needed: Hilton, 4 subjects, large paper, bareback pad
Location: M206
Total Time: 1 day
Personnel: Jordan, Stef, Ed, Ben, Jordan
Test Objective: Determine the best placement of the sensors for accurate data collection
Criteria for Success: This is not definable. Based on results from this test, we will determine how
to adjust our anatomical sensor placement to best fit a variety of riders.
Procedure:
1. Place bareback pad on Hilton
2. Place white paper on Hilton
3. Subject sits on Hilton
4. Research assistant draws on the paper in marker around the butt of the participant
5. Repeat with 4 total subjects
Results:
The test was conducted with all 4 members in the group. Although we don't have a large variation
in our size, we thought we could represent the majority of the riders that are going to sit on the
mat. Based on the trace of the gluteal regions drawn on the fabric sheet, we decided only 16 sensors
are needed to cover all the necessary region for measuring pressure shift. The 16 sensors will be
placed to focus on the pressure directly under the buttocks, so the sensors originally planned to
measure pressure under the leg were moved towards the buttocks region. Therefore, only 16
sensors were planned to be used in the prototype.

26
Australian Saddle Sensor Reduction Test Plan
Type of Test: Performance
Equipment Needed: Hilton, 1 subject, Australian saddle,
Location: M206
Total Time: 1 day
Personnel: Jordan, Stef, Ed, Ben, Jordan
Test Objective: Determine if the reduction in sensors to accommodate the Australian saddle
impacts the accuracy of the device to indicate which side the rider has shifted their weight
Criteria for Success: The LED lights light up corresponding to how the rider has shifted their
weight
Procedure:
1. Place the Australian saddle on Hilton
2. Place the Australian mat with both layers on top of the Australian saddle
3. Turn the device on and collect data
4. Monitor the LED lights to ensure they are changing with the rider's weight shifts
Results:
Not yet complete.

27
Circuit Configuration Testing
Sensor Performance Test
Type of Test: Performance
Equipment Needed: Raspberry Pi, force sensors
Location: M203
Total Time: 1 hour
Personnel: Ed, Ben
Test Objective: To test if the circuit with 16 sensor works with Data Processing Software and the
program outputs pressure data
Criteria for Success: Pressure data is generated on the program, and the power light on the circuit
board is turned on
Procedure:
1. Add Python code into the SD card for Raspberry Pi and run the code.
2. Apply pressure to one sensor to check if the voltage value changes on the screen
3. Apply pressure to two sensors to check if one side of LEDs light up when more pressure
in applied on that side.
4. Apply pressure to four sensors to check if one side of LEDs light up when more pressure
in applied on that side.
5. Apply pressure to six sensors to check if one side of LEDs light up when more pressure
in applied on that side.
6. Apply pressure to ten sensors to check if one side of LEDs light up when more pressure
in applied on that side.
7. Apply pressure to sixteen sensors to check if one side of LEDs light up when more
pressure in applied on that side.
Results:
The Raspberry Pi was able to collect accurate force data sent from the sensors, as the forces shown
on the screen were close to the actual weight applied; However, the LEDs kept flickering even
though more pressure was applied to one sensor. Also, when the sensors were put into the pockets
on the middle layer, the force data from sensor 5, 6, 7 and 8 remained constant below 1 even though
more pressure were applied.

28
Data Processing Software Test Plan
Data Processing Software Functionality Test
Type of Test: Performance
Equipment Needed: Computer monitor, keyboard, mouse, DMM
Location: BIC
Total Time: 4 hours
Personnel: Ben, Ed
Test Objective: Determine if the data processing software functions properly
Criteria for Success: The criteria of success for this test are broken down into five parts, with one
corresponding to each segment of the software. This first is that the data collection software must
work. The second is that the data conversion from the recorded values to actual pressure values
must work. Third the data saving software needs to be able to save the converted data to the USB
drive. Fourth the software must be able to determine which side of the mat has more pressure on
it. Finally, the LED lights must turn on when the side they are on has more pressure being
applied to it.
Procedure:
1. Turn the device on
2. Firmly press on every sensor with a known value of force, 1 kg of weight should work, to
ensure that the program has a chance to record a value from each sensor. This will verify
that the data collection software is working
3. While pressing on each sensor individually ensure that the LEDs on the same side of the
mat that he sensor is on turn on when the sensor is pressed. This insures the data analysis
software and LED light control software is working.
4. Turn the device off
5. Remove the USB drive and plug it into a computer.
6. Open the newly created text file on the USB drive. Check that the drive has a test file
with the data from this test session saved to it. This will prove whether or not the data
saving software is functioning.
7. Finally look at the values saved for each sensor when the weight is applied to them. This
value should correctly match the amount of force that was applied to the sensor during
testing. If the values match within a 95% confidence interval then this proves that the
data conversion software is functioning.
Results:
As mentioned in the Sensor Performance Test above, the data processing software was able to
collect force data from each sensor and the data was relatively accurately, so the first and second
part of the test was satisfied. In addition, the User Interface subsystem was able to use the data
provided from the Data Processing Software and plots were generated from the data, so the third
part was satisfied. Based on the force data shown on the screen, it seemed the software should be
able to determine which side had more weight, so the fourth part was satisfied as well. However,
the LED for the side experienced more pressure did not stay on, so the fifth part was not
satisfied.

29
User Interface Test Plan
User Interface Functionality Test
Type of Test: Performance
Equipment Needed: Laptop with Python downloaded
Location: N/A
Total Time: 1 hour
Personnel: Stef
Test Objective: Determine if the computer app functions properly
Criteria for Success: four screens in the app; each button leads to the correct next step; app
allows you to upload and store a text file of data; app allows you to see a graph and ratio
calculation of data
Procedure:
1. Click on each button
2. Determine if each button led to the correct next step
3. Go through app and determine if four different screens were present
4. Attempt to upload and store a text file of data from the flash drive
5. Ensure that graphical display and ratio calculation are displayed upon pressing each
corresponding button
Results:
Each button correctly led to the next step. Each button had a function that occurred when they
were pressed. Uploading and storing a text file from a flash drive was successful. The graphical
display and ratio calculation were displayed upon pressing each corresponding function. Based
on these results, the app works successfully.

30
Design Testing

16-Sensors on the Final Prototype Board Performance Test


Type of Test: Performance
Equipment Needed: Raspberry Pi, 16 sensors, a prototype board with sensors, User Interface
Software
Location: M203
Total Time: 2 hours
Personnel: Ed, Ben, Stef
Test Objective: To test if the circuit (with 16 sensors) on the prototype board works with Data
Processing Software and gives pressure data, and live feedback works
Criteria for Success: Pressure data is generated and User Interface is able to use the collected
data to show pressure change, and the LED lights turned on when sensors (8) on one side
experiencing more pressure than the other side
Procedure:
1. Turn on the Raspberry Pi and run the code installed in the Pi.
2. Apply pressure on different side of the mat to check if the LEDs on that side light up
Results:
The Data Processing Software was able to collect force data from each sensor and calculate the
weight difference experienced by two groups of sensors, but the subsystem was not able to keep
the LEDs on to show the difference.

31
Device Set-Up Test Plan
Type of Test: Human Acceptance
Equipment Needed: Mat, sensor layer, electrical components, battery, electrical housing, Hilton,
saddlebag
Location: BIC
Total Time: 1 hour
Personnel: Jordan, Ed, Ben
Test Objective: Determine the number of steps required to successfully use the device for one
session
Criteria for Success: The device should take no more than 6 steps to set up
Procedure:
1. Place and center mat on the desired apparatus (Hilton or Australian saddle)
2. Turn the battery on
3. Calibrate device
4. Place electrical components in the saddlebag
5. Place saddlebag on the apparatus in the desired location
Results:
Not yet complete.

32
Mat for the Equicizer Bareback Pad Dimensions Test Plan
Type of Test: Performance
Equipment Needed: Hilton, mat designed for the Equicizer bareback pad
Location: M206
Total Time: 1 hour
Personnel: Jordan
Test Objective: Determine the fit of the mat on the Hilton relative to the mat's dimensions.
Criteria for Success: The mat's dimensions allow it to flex smoothly over Hilton without creating
any ripples or folds in the material.
Procedure:
1. Place the mat on Hilton
2. Sit on the mat
3. Determine if there are any ripples or folds in the material that would require dimension
changes
Results:
Based on eye inspection of the four members in the group, the mat was able to flex smoothly
over Hilton without creating any ripples or folds in the material, and it was also able to fit over
the Equicizer bareback pad.

Mat for the Australian Saddle Dimensions Test Plan


Type of Test: Performance
Equipment Needed: Australian saddle, Hilton, mat designed for the Australian saddle
Location: M206
Total Time: 1 hour
Personnel: Jordan
Test Objective: Determine the fit of the mat on the Hilton relative to the mat's dimensions.
Criteria for Success: The mat's dimensions allow it to flex smoothly over the Australian Saddle
without creating any ripples or folds in the material.
Procedure:
1. Place the mat on the Australian saddle on top of Hilton
2. Sit on the mat
3. Determine if there are any ripples or folds in the material that would require dimension
changes
Results:
Based on eye inspection, the mat fit relatively well on the Australian saddle. It was obvious that
the mat did conform to the shape of the saddle when put on, but no discomfort was felt when
people sat on it over the Australian saddle.

33
Client Testing

Comfort Test Plan


Type of Test: Human Acceptance
Equipment Needed: Both mats (with finished sensor layer), Hilton, Australian saddle
Location: M206
Total Time: 30 minutes
Personnel: Jordan
Test Objective: Determine the comfort of both mats with the sensors and pucks underneath the
foam layer
Criteria for Success: The pucks should not cause any discomfort to the rider while on the mat on
Hilton or on the mat on the Australian saddle
Procedure:
1. Assemble the mat with the layer of sensors and pucks
2. Place mat on Australian saddle then Hilton
3. Sit on mat assess comfort
Results:
No discomfort was felt from the pucks when people sat on the mat on Hilton or on the mat on
Australian saddle.

34
Feasibility and Merit Criteria Assessment

Live Feedback Test Plan


LED Performance Test
Type of Test: Performance
Equipment Needed: Mat, sensor layout, electrical components, battery, electrical housing,
Hilton, saddlebag
Location: BIC
Total Time: 1 hour
Personnel: Stef, Jordan, Ben, Ed
Test Objective: Determine if the live feedback mechanism functions properly on Hilton;
determine at what distance trainer can see the live feedback mechanism
Criteria for Success: LEDs are visible 75 feet away; if rider leans one side, the LEDs on the
corresponding side light up
Procedure:
1. Device is set-up on Hilton
2. Subject sits on Hilton and leans one way
a. Research assistant should determine if the corresponding lights turned on
3. Subject leans the other way
a. Research assistant should determine if corresponding lights turned on
4. Another research assistant should be standing 75 feet away and be able to see LED lights
light up
Results:
This test was not performed due to that the LEDs were not available.

35
Maintenance Test Plan
Type of Test: Human Factors
Equipment Needed: subject, complete device, Lysol wipes, battery charger
Location: M203
Total Time: 1 hour
Personnel: Stef, Jordan
Test Objective: determine how easy the device is to regularly maintain
Criteria for Success: < 6 steps to clean and maintain device
Procedure:
1. Take battery out and plug into charger
2. Clean the mat using a Lysol wipe
3. Clean electrical housing unit with Lysol wipe
4. Research assistant should record how many steps each task requires
Results:
Not yet complete.

36
User Interface Usability Test
Type of Test: Human Acceptance
Equipment Needed: 2 subjects
Location: N/A
Total Time: 1 hour
Personnel: Stef
Test Objective: Ensure that the computer app is easy to use and has minimal steps
Criteria for Success: > 7/10 average on surveys asking if the app is easy to use; < 10 steps to
upload data; < 10 steps to look at graphical display and ratio calculation
Procedure:
1. Each subject will briefly be instructed on how to use the program
2. Subject is instructed to upload data
a. Researcher counts the number of steps the user takes to do this
3. Subject is instructed to look at a graphical display and a ratio calculation
a. Researcher counts the number of steps the user takes to do this
Results: The user takes 6 steps to upload data. The user takes 5 steps to look at a graphical display
or ratio calculation. The average rating on ease of use of the app for 2 subjects was 8/10. Based
on these results, the app is deemed acceptable for use based on ease of use and steps required.

37
Failure Modes & Effects Analysis

Mat for the Equicizer Bareback Pad Sliding Test Plan


Type of Test: Safety
Equipment Needed: Mat and Hilton
Location: M206
Total Time: 1 hour
Personnel: Jordan
Test Objective: Determine if the mat slides on the Hilton during a 30-minute riding session
Criteria for Success: The mat does not slide horizontally more than 1 inch from the original
position, as determined by the alignment indicator.
Procedure:
1. Center the mat on Hilton
2. Ride on Hilton for 30 minutes
3. Measure the displacement of the alignment indicator
Results:
After a 30-minute riding session, the mat was did not slide more than 1 inch from its original
position.

Mat for the Australian Saddle Sliding Test Plan


Type of Test: Safety
Equipment Needed: Dual layer mat designed for the Australian saddle, the Australian saddle, and
Hilton
Location: M206
Total Time: 1 hour
Personnel: Jordan
Test Objective: Determine if the mat slides on the Australian saddle during a 30-minute riding
session
Criteria for Success: The mat does not slide horizontally more than 1 inch from the original
position, as determined by the alignment indicator.
Procedure:
4. Center the mat on the Australian saddle
5. Place the Australian saddle on Hilton
6. Ride on Hilton for 30 minutes
7. Measure the displacement of the alignment indicator
Results:
Not yet complete.

38
VI. Budgeting
Table 1. The final costs, organized by subsystem, of building a prototype of the Equine Versatile
Pressure-Sensing Mat.
Mechanics
& Materials
Subsystem
Part # Part Name Vendor Unit Cost/Unit Quantity Shipping/Handling Total
Microfiber
13029418 Joann 36" x 54" $9.99 1 N/A $9.99
Suede Fabric
Waffle ¼" x 34"
N/A $10.99 1 $7.99 $18.98
Neoprene x 36"
Antistatic
McMaster- ¾" x 36"
87035K55 Polyurethane $21.68 1 14.97 $36.65
Carr x 36"
Foam Sheet
1"x
B06XBVS8KN Hook & Loop Amazon $9.99 1 N/A $9.99
393.12"
ZIPBR10-101- Zipper
Zipper ½"x72" $10.49 1 $6.99 $17.48
0580-Y-072IN Shipper
3D Print Rose-
N/A Electrical Hulman 1 $4.35 1 N/A $4.35
Housing BIC
3D Print Rose-
N/A Electrical Hulman 1 $4.05 1 N/A $4.05
Housing BIC
Mechanics &
Materials
$101.49
Subsystem
Subtotal

Circuit
Configuratio
n Subsystem
Uni Cost/Uni Quantit Shipping/Handlin
Part # Part Name Vendor t t y g Total
FlexiForce Standard FlexiForce Sensors
Tekscan 4 $80.30 4 N/A $159.20
Model A401 A401
USB Battery Pack for
Raspberry Pi - Adafruit
1566 1 $39.95 1 N/A $39.95
10000mAh - 2 x 5V Industries
outputs
Raspberry Pi 3 Model Adafruit
3055 1 $35.00 1 N/A $35.00
B Industries
Arrow
LM224N Quad Op amp Electronic 1 $0.342 10 N/A $3.49
s
MCP3008 - 8-Channel
Adafruit
856 10-Bit ADC With SPI 1 $3.75 5 N/A $18.75
Industries
Interface
Flora RGB
1260 Smart NeoPixel versio Walmart 4 $7.95 2 $6.27 $22.17
n2
Tactile Switch Adafruit
1489 15 $4.95 1 N/A $4.95
Buttons Industries
Adafruit
1988 GPIO Ribbon Cable 1 $2.95 1 N/A $2.95
Industries

39
Assemble Pi Cobbler Adafruit
2029 1 $6.95 1 9.47 $16.42
Plus-breakout cable Industries
Adafruit
239 Full sized breadboard 1 $5.95 1 N/A $5.95
Industries
16 GB Card with Adafruit
1583 1 $14.95 1 $9.18 $24.13
Noobs 2.1 Industries
Clear safe lock U.S.
81103 1 $3.72 1 $9.50 $13.22
container, lock lids Plastic
Adafruit
1484 Led Matrix 1 $20.345 2 N/A $20.69
Industries
Circuit
Configuration $366.8
Subsystem 7
Subtotal

User
Interface
Subsystem
Part # Part Name Vendor Unit Cost/Unit Quantity Shipping/Handling Total
SanDisk Cruzer-Fit
IDSDCFUF16G 16GB USB 2.0 Flash Amazin 1 $6.99 1 N /A $6.99
Drive
User Interface
$6.99
Subtotal

Overall Total $475.35

40
VII. Conclusions & Recommendations
Conclusions

Currently the prototype is comprised of the two finished mats with the pockets to be added for the
sensors on each mat. The sensors are fully wired to the circuit and raspberry pi, and a PCB has
been made for the circuit but has not yet been implemented. The Data Processing Subsystem is
fully functioning and capable of sampling, calibrating and preforming a zero offset for every
sensor. The User Interface currently has all of the screens needed and background functions written
and has been turned into a desktop application that can analyze the data saved. This means that the
current prototype is capable of recording values from all of the sensors inside the mat in response
to an applied force and print the data recorded to a text file for analysis later. As of now the design
is well on its way to meet all design specifications but currently have full functionality because
four of the sensors are experiencing abnormal reading inside their pockets on the mat. Also,
without the circuit being soldered to the PCB it wasn't possible to determine the final dimensions
of the electrical housing which is why that is missing as well.

Recommendations

At this time there are several recommendations that need to be completed before the device is fully
functional. The first is that the sensors need to be recalibrated inside the pockets on the mat to
eliminate the variability in how tight each pocket is from affecting the data being recorded. The
next recommendation is that the circuit be transferred from the prototyping board to the PCB so
that the final electrical housing can be made. Once the housing is made all of the electrical
components can then be placed in the housing. The new LED arrays need to have a housing created
for them to protect them from the outside environment also allow them to be attached to the mat.
The last recommendation is that the remaining testing be completed once these other
recommendations are done so that it is possible to prove that the Versatile Equine Pressure Sensing
Mat is safe and effective to use.

41
VIII. Personnel and Responsibilities
This section lists the personnel assigned to and descriptions for each responsibility necessary for
the construction and testing of the Equine Versatile Pressure-Sensing Mat. Table 2 lists each
responsibility and corresponding lead personnel.

Table 2. The descriptions and personnel for each responsibility identified in the construction and
testing of the Equine Versatile Pressure-Sensing Mat.
Responsibility Description Personnel
Construction of the  Cut and sew the physical mat Jordan
Mechanics &  Sew pockets for sensors inside mat
Materials Subsystem  3D print electrical housing unit
 Test the subsystem throughout construction
Construction of the  Connect all wiring, LED lights, battery, and sensors Ed
Circuit Configuration in a PCB prototyping board
Subsystem  Test the subsystem throughout construction
Construction of the  Create software on Raspberry Pi to sample sensors Ben
Data Processing and save data to flash drive
Software Subsystem  Create software on Raspberry Pi to control LED
lights
 Create software on Raspberry Pi to calibrate sensors
 Test the subsystem throughout construction
Construction of User  Create software to allow user to upload data to Stef
Interface Subsystem computer
 Create software for data analytics of uploaded data
 Test the subsystem throughout construction
Client Contact  Contacted client for all questions, concerns and Jordan
discussions
 Send memo to client each week
Memo Drafting  Draft a memo to update Dr. Rogge and client of All
weekly progress
Agenda Drafting  Create agendas for design review meetings with Dr. Stef
Rogge
Final Device Testing  Test the final performance of the device for All
performance, environmental concerns, safety
concerns, human factors, maintenance procedures,
and geometry
Retrieval / Return of  Retrieve Hilton for device testing from Lakeland Ed
Hilton Center
 Returned Hilton to Lakeland Center
CDD Drafting  Create final documentation describing construction All
of the device
CDD Revisions  Revise and finalize details of final documentation All
describing the construction of the device

42
IX. Appendix A: Data Processing Subsystem Code
import time
import os
import RPi.GPIO as GPIO
import numpy as np

GPIO.setmode(GPIO.BCM)
DEBUG = 1

# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)


def readadc(adcnum, clockpin, mosipin, misopin, cspin):
if ((adcnum > 7) or (adcnum < 0)):
return -1
GPIO.output(cspin, True)

GPIO.output(clockpin, False) # start clock low


GPIO.output(cspin, False) # bring CS low

commandout = adcnum
commandout |= 0x18 # start bit + single-ended bit
commandout <<= 3 # we only need to send 5 bits here
for i in range(5):
if (commandout & 0x80):
GPIO.output(mosipin, True)
else:
GPIO.output(mosipin, False)
commandout <<= 1
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)

adcout = 0
# read in one empty bit, one null bit and 10 ADC bits
for i in range(12):
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)
adcout <<= 1
if (GPIO.input(misopin)):
adcout |= 0x1

GPIO.output(cspin, True)

adcout >>= 1 # first bit is 'null' so drop it


return adcout

# change these as desired - they're the pins connected from the

43
# SPI port on the ADC to the Cobbler ADC 1
SPICLK1 = 11
SPIMISO1 = 9
SPIMOSI1 = 10
SPICS1 = 7

# SPI port on the ADC to the Cobbler ADC 2


SPICLK2 = 18
SPIMISO2 = 23
SPIMOSI2 = 24
SPICS2 = 8

# set up the SPI interface pins


GPIO.setup(SPIMOSI1, GPIO.OUT)
GPIO.setup(SPIMISO1, GPIO.IN)
GPIO.setup(SPICLK1, GPIO.OUT)
GPIO.setup(SPICS1, GPIO.OUT)

# set up the SPI interface pins


GPIO.setup(SPIMOSI2, GPIO.OUT)
GPIO.setup(SPIMISO2, GPIO.IN)
GPIO.setup(SPICLK2, GPIO.OUT)
GPIO.setup(SPICS2, GPIO.OUT)

# define matrix and fills matrix with ones to help with calibration
matrix = np.ones(16)
matrix2 = np.ones(16)
matrix3 = np.ones(16)
zeromatrix = np.zeros(16)

# define LED Pins


LED1 = 20
LED2 = 21

# set up LED Pins


GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)

# create file to save data to


f = open('result.txt','w')

# Sample each sensor 20 times and average the values for each sensor as part of Zeroing the
sensors
for x in range(20):
for channel in range(8):
# read the analog pin

44
val1 = readadc(channel, SPICLK1, SPIMOSI1, SPIMISO1, SPICS1)

# convert adc to voltage


matrix[channel] = val1*(3.3/1023)

# hang out and do nothing for a .1 second


time.sleep(0.01)

for channel in range(8):


# read the analog pin
val2 = readadc(channel, SPICLK2, SPIMOSI2, SPIMISO2, SPICS2)

# convert adc to voltage


matrix[channel+8] = val2*(3.3/1023)

# hang out and do nothing for a .1 second


time.sleep(0.01)

matrixyint = matrix-[0.822, 0.814, 0.821, 0.811, 0.854, 0.833, 0.849, 0.814, 0.801, 0.805,
0.834, 0.804, 0.816, 0.773, 0.804, 0.773]
matrixcal = matrixyint*[40.65, 42.37, 49.26, 43.29, 45.45, 44.05, 46.08, 47.62, 47.39,
39.22, 43.10, 41.32, 46.73, 43.29, 36.76, 32.15]
roundmatrix = np.around(matrixcal,decimals = 2)
matrixabs = np.absolute(roundmatrix)
zeromatrix = zeromatrix + matrixabs
subzero = zeromatrix/20

try:
while True:
for channel in range(8):
# read the analog pin
val1 = readadc(channel, SPICLK1, SPIMOSI1, SPIMISO1, SPICS1)

# convert adc to voltage


matrix[channel] = val1*(3.3/1023)

# hang out and do nothing for a .1 second


time.sleep(0.01)

for channel in range(8):


# read the analog pin
val2 = readadc(channel, SPICLK2, SPIMOSI2, SPIMISO2, SPICS2)

# convert adc to voltage


matrix[channel+8] = val2*(3.3/1023)

45
# hang out and do nothing for a .1 second
time.sleep(0.01)

# convert voltage to pressure


matrixyint = matrix-[0.822, 0.814, 0.821, 0.811, 0.854, 0.833, 0.849, 0.814, 0.801, 0.805,
0.834, 0.804, 0.816, 0.773, 0.804, 0.773]
matrixcal = matrixyint*[40.65, 42.37, 49.26, 43.29, 45.45, 44.05, 46.08, 47.62, 47.39,
39.22, 43.10, 41.32, 46.73, 43.29, 36.76, 32.15]
matrixzero = matrixcal - subzero
mavg = (np.array(matrixzero) + np.array(matrix2) + np.array(matrix3))/3
roundmatrix = np.around(mavg,decimals = 2)
matrixabs = np.absolute(roundmatrix)

# LED code here


sum1 = sum(matrixabs[0:8])
sum2 = sum(matrixabs[8:16])

if (sum1 >= 1.10*sum2):


GPIO.output(LED1, 1)
GPIO.output(LED2, 0)
elif (sum2 >= 1.10*sum1):
GPIO.output(LED1, 0)
GPIO.output(LED2, 1)
else:
GPIO.output(LED1, 1)
GPIO.output(LED2, 1)

# save matrix to text file


smatrix=str(matrixabs) + '\n\r'
f.write(smatrix)
print(smatrix)
matrix3 = matrix2
matrix2 = matrixabs

except KeyboardInterrupt:
GPIO.cleanup()
print('end')
f.close()

46
Appendix B: User Interface Subsystem Code

### MAIN PROGRAM


from __future__ import division
import Tkinter as tk
import Tkinter
from tkFileDialog import askdirectory

LARGE_FONT= ("Verdana", 12)

class FileName(object):
def __init__(self,filename):
self.filename = filename

dest = FileName(None)
src = FileName(None)

def movefile():
import shutil
from Tkinter import Tk
from tkFileDialog import askopenfilename
Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
filename = askopenfilename()
global src
src.filename = filename

with open(filename, 'r') as f:


text = f.read()
text = text.replace('\n', '')
text = text.replace('\r', ' ')
text = text.replace(' ',' ')
text = text.replace(' ',' ')
text = text.replace('[ ','')
text = text.replace('[ ','')
text = text.replace(']',' ')
text = text.replace(' ', ' ')
text = text.replace(' ', ' ')
text = text.replace('/t','')
text2 = [float(x) for x in text.split(' ') if x != '']

with open(filename, 'w') as f:


f.write(text)

Tk().withdraw()
filename = askdirectory()
global dest

47
dest.filename = filename
shutil.move(src.filename, dest.filename)

class SeaofBTCapp(tk.Tk):

def __init__(self, *args, **kwargs):

tk.Tk.__init__(self, *args, **kwargs)


container = tk.Frame(self)

container.pack(side="top", fill="both", expand = True)

container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)

self.frames = {}

for F in (Screen1, Screen2, Screen3, Screen4, Screen5):

frame = F(container, self)

self.frames[F] = frame

frame.grid(row=0, column=0, sticky="nsew")

self.show_frame(Screen1)

def show_frame(self, cont):

frame = self.frames[cont]
frame.tkraise()

class Screen1(tk.Frame):

def __init__(self, parent, controller):


tk.Frame.__init__(self,parent)
label = tk.Label(self, text="What do you want to do?", font=LARGE_FONT)
label.pack(pady=10,padx=10)

button = tk.Button(self, text="Upload new data",


command=lambda: controller.show_frame(Screen2))
button.pack()

48
button2 = tk.Button(self, text="Look at previous data",
command=lambda: controller.show_frame(Screen3))
button2.pack()

class Screen2(tk.Frame):

def __init__(self, parent, controller):


tk.Frame.__init__(self, parent)

dest=FileName(None)
button1 = tk.Button(self, text="Select file from flash drive & destination",
command=lambda: movefile())
button1.pack()

label = tk.Label(self, text="Enter the session information", font=LARGE_FONT)


label.pack(pady=10,padx=10)

self.label = tk.Label(self, text = "Rider name")


self.label2 = tk.Label(self, text = "Session #")

e1 = tk.Entry(self)
e2 = tk.Entry(self)

self.label.pack()
e1.pack()
self.label2.pack()
e2.pack()

def renamefile():
import os
global src
nameofdoc = os.path.basename(src.filename)

old_file_name = (str(dest.filename) + "\ ".strip() + str(nameofdoc))


new_file_name = (str(dest.filename)+'\ '.strip() + str(e1.get())+str(e2.get())+".txt")
os.rename(old_file_name, new_file_name)
global dest
dest.filename = new_file_name

button4 = tk.Button(self, text = "Enter",


command=lambda: [controller.show_frame(Screen5), renamefile()])
button4.pack()

49
button5 = tk.Button(self, text="Back",
command=lambda: controller.show_frame(Screen1))
button5.pack()

class Screen3(tk.Frame):

def __init__(self, parent, controller):


tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Select a riding session", font=LARGE_FONT)
label.pack(pady=10,padx=10)

def getFileName():
from Tkinter import Tk
from tkFileDialog import askopenfilename
Tk().withdraw() # we don't want a full GUI, so keep the root window from appearing
filename = askopenfilename()
global dest
dest.filename = filename

button1 = tk.Button(self, text="Choose file", command=lambda: getFileName())


button1.pack()

button2 = tk.Button(self, text="Enter",


command=lambda: controller.show_frame(Screen4))
button2.pack()

button3 = tk.Button(self, text="Back",


command=lambda: controller.show_frame(Screen1))
button3.pack()

class Screen4(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)

# RATIO CALCULATION FUNCTION


def RatioCalc():
global dest
import numpy as np

# importing file and extracting data matrix


filename = dest.filename
with open(filename, 'r') as f:
text = f.read()
text2 = [float(x) for x in text.split(' ') if x != '']

50
data2=[];
for i in xrange(0, len(text2), 16):
data = text2[i:i+16]
data1 = np.array(data)
data2.append(data1)
data0 = np.array(data2)
data0.sum(0)

# sum of each row


sum_ = np.sum(data0, axis=1).tolist()

# sum of first 8 values in each row


data3 = data0[:,0:8]
sum2 = np.sum(data3, axis = 1).tolist()

# percentage of first 8 sensors of total and counting number of times its greater than 50
k=0
percent=[]
for i in range(0,len(sum2)):
percent.append((sum2[i]/sum_[i])*(100))
if percent[i] > 50:
k=k+1

# calculating final ratio


percent_side1_higher = 100*k / len(sum2)
percent_side2_higher = 100 - percent_side1_higher
def popupmsg(msg):
popup = tk.Tk()
label = tk.Label(popup, text=msg)
label.pack(side="top", fill="x", pady=10)
B1 = tk.Button(popup, text="Okay", command = popup.destroy)
B1.pack()
popup.mainloop()

msg = "The ratio of time where the rider applied higher contact pressure on the left/right
sides is %d / %d ." % (percent_side1_higher, percent_side2_higher)
popupmsg(msg)
# end of ratio calculation function

button1 = tk.Button(self, text="Ratio Calculation", command=lambda: RatioCalc())


button1.pack()

### GRAPHICAL DISPLAY FUNCTION


def GraphDisplay():
global dest
import numpy as np

51
# importing file and extracting data matrix
filename = dest.filename
f = open(filename, 'r')
text = f.read()
text2 = [float(x) for x in text.split(' ') if x != '']
data2=[];
for i in xrange(0, len(text2), 16):
data = text2[i:i+16]
data1 = np.array(data)
data2.append(data1)
data0 = np.array(data2)

# average of first 8 values in each row


data3 = data0[:, 0:8]
sum1 = np.sum(data3, axis = 1).tolist()
average1=[]
for i in range (0, len(sum1)):
average1.append(sum1[i]/8)

# average of last 8 values in each row


data4 = data0[:,9:16]
sum2 = np.sum(data4, axis = 1).tolist()
average2=[]
for i in range (0, len(sum2)):
average2.append(sum2[i]/8)

# timescale of plot
x = range(0, len(sum2))
x2=[]
for i in range (0, len(sum2)):
x2.append(x[i]/4)

# plotting
import matplotlib.pyplot as plt

from IPython import get_ipython


#get_ipython().run_line_magic('matplotlib', 'tk')

plt.plot(x2, average1, color ='g', label = 'Left')


plt.plot(x2, average2, color = 'orange', label ='Right')
plt.legend()
plt.xlabel('Time (s)')
plt.ylabel('Contact Pressure')
plt.title('Rider Gluteal Contact Pressure Over Time (lbs)')
plt.show()

52
button2 = tk.Button(self, text="Graphical Display", command=lambda: GraphDisplay())
button2.pack()

def RawData():
global dest
import subprocess
subprocess.Popen(["notepad",str(dest.filename)])

button3 = tk.Button(self, text="Raw Data", command=lambda: RawData())


button3.pack()

button3 = tk.Button(self, text="RESTART",


command=lambda: controller.show_frame(Screen1))
button3.pack()

class Screen5(tk.Frame):

def __init__(self, parent, controller):


tk.Frame.__init__(self, parent)

button1 = tk.Button(self, text="Upload another file",


command=lambda: controller.show_frame(Screen2))
button1.pack()

button2 = tk.Button(self, text="Continue to data analysis",


command=lambda: controller.show_frame(Screen4))
button2.pack()

app = SeaofBTCapp()
app.mainloop()

53

You might also like