1. GHOST RUNNER
By
Byers, Kelsey H.
Dreebin, Charles W.
Perbohner, Ethan R.
Final Report for ECE 445, Senior Design, Fall 2015
TA: Jacob Bryan
9th December 2015
Project No. 34
2. ii
Abstract
A system was designed that allows for the tracking of a competitive runner around a 400m track (40m
demo track). This system utilized RGB LEDs to visually replay a runner’s best lap pace on their next
training lap. The system was segmented into 10m increments that allowed for the propagation speed of
the LEDs within each 10m to vary compared to neighboring 10m segments. This allowed for the runner
to observe where in their lap they slowed down, sped up, or maintained a constant pace. As a result, the
runner would be able to make conscience decision mid-run in order to obtain a better time and have a
more effective training session. The tracking of the runner was accomplished using passive RFID readers
and tags. The demonstrated system was comprised of two microcontrollers that work with four RFID
readers and 40 LEDs. A runner was tracked through a passive RFID tag which was very lightweight and
was worn on their shoe. After an initial lap’s data had been collected it would then be processed and
displayed on the LEDs during the runner’s next lap.
3. iii
Contents
1. Introduction ..............................................................................................................................................5
1.1 Statement of Purpose.........................................................................................................................5
1.2 Objectives............................................................................................................................................5
1.3 Block Diagram .....................................................................................................................................6
1.4 Block Descriptions...............................................................................................................................6
2. Design........................................................................................................................................................8
2.1 Power Supply ......................................................................................................................................8
2.2 RFID Microcontroller...........................................................................................................................8
2.2.1 Hardware Component .................................................................................................................8
2.2.2 Software Component...................................................................................................................9
2.3 LED Microcontroller..........................................................................................................................10
2.3.1 Hardware Component ...............................................................................................................10
2.3.2 Software Component.................................................................................................................10
2.4 LED Strip............................................................................................................................................11
2.5 RFID Reader/Tag ...............................................................................................................................12
3. Design Verification..................................................................................................................................14
3.1 Power Supply ....................................................................................................................................14
3.2 RFID Microcontroller.........................................................................................................................14
3.2.1 Hardware Component ...............................................................................................................14
3.2.2 Software Component.................................................................................................................14
3.3 LED Microcontroller..........................................................................................................................15
3.3.1 Hardware Component ...............................................................................................................15
3.3.2 Software Component.................................................................................................................15
3.4 LED Strip............................................................................................................................................16
3.5 RFID Reader/Tag ...............................................................................................................................16
4. Costs........................................................................................................................................................19
4.1 Parts ..................................................................................................................................................19
4.2 Labor .................................................................................................................................................19
4.3 Grand Total .......................................................................................................................................19
5. Conclusion...............................................................................................................................................20
5.1 Accomplishments..............................................................................................................................20
4. iv
5.2 Uncertainties.....................................................................................................................................20
5.3 Ethical Considerations.......................................................................................................................21
5.4 Future Work......................................................................................................................................22
6. References ..............................................................................................................................................24
Appendix A: Final Full Circuit Schematic.....................................................................................................25
Appendix B: PCB Design..............................................................................................................................26
Appendix C: RFID Microcontroller Source Code .........................................................................................30
Appendix D: LED Microcontroller Source Code ..........................................................................................34
5. 5
1. Introduction
1.1 Statement of Purpose
The goal of the Ghost Runner project was to provide competitive runners with a visual motivator to beat
their best time and pace themselves to set records. With this goal in mind the project was designed to
be a modular system that can be installed on any running track. This design was comprised of an RFID
tracking system and an LED display system. This design had to consider several components: interface
control between the RFIDs and LEDs, power management, accuracy of sensing RFID tags, and storage
and retrieval of data. It allows runners to record their lap times, accounting for change of pace within a
lap, and displays this data during a later run to serve as a motivator.
1.2 Objectives
Goals
Deliver a visual real-time LED display of a runner’s best time (single user) or the overall best
runner’s time (multiple users) on a track to aid in training.
Effectively use RFID readers/tags to create the best possible timing feedback for a given runner.
Provide reliable and quick interface relationship between the RFID and the LED microcontrollers.
Functions
Monitor the runner’s location on the track using RFID readers/tags. Each runner (up to five) will
have a lightweight RFID tag on their shoe and there will be an RFID reader every 10m.
Store the best time for a given runner that can be used for future training exercises.
Control the speed at which the LEDs between two sequential RFID readers illuminate based on
the timing data received from the RFID readers.
Benefits
The ghost of a runner’s best time (single user) or overall best runner’s time (multiple users) will
provide the runners with extra motivation with the hopes of beating their ghost.
Designing the system into modules will allow for it to be sized to different lengths of 10m
intervals.
The ability to program other people’s ghosts in order to provide additional motivation.
Features
Strand of LED lights on the side of the track (on the lane line)
Energy efficient since only 1m of track will be powered at any given time (except during start up
sequence)
Ability to identify different runners on the track through different active RFID tags
6. 6
Convenient start up procedure for a user. There is an LED start up sequence. The LEDs will flash
red three times followed by a green LED flash. The user is to begin their lap once the LEDs flash
green.
1.3 Block Diagram
1.4 Block Descriptions
Power Supply
The function of this block will be to provide power to: RFID microcontroller, LED microcontroller, and
RFID Reader. All of these blocks will receive approximately 5V (closer to 6V for the RFID Readers). A wall
outlet will be used to power the two microcontrollers. Four AA batteries will be connected in series to
provide power to the four RFID Readers.
RFID Microcontroller
The input to this block comes from the Power Supply and the RFID Reader; the output from this block
goes to the LED microcontroller. The function of this block is threefold. Firstly, this device transmits a
read ready signal to each RFID Reader block and also receives the data from those RFID Reader blocks.
Secondly, this block interprets the data from the RFID Readers and determines the best time for a given
Figure 1: Block Diagram of Design
7. 7
lap. In the case where the new total time is less than the time stored in memory, then this new total
time is kept and written to memory. Thirdly, this block transmits the timing data obtained from either
memory or the previous lap (depending which was faster) to the LED microcontroller.
LED Microcontroller
The device receives input from the RFID microcontroller and the Power Supply. The output from this
block goes to the LED Strip. There are two functions for this particular block. First, the data received
from the RFID microcontroller is read and used to determine the timing sequence for each 10m segment
of the track. Second, this block is responsible for providing the necessary power and input data to
achieve the correct propagation speeds of the LEDS for each 10m segment to the LED Strip.
LED Strip
The input to this block will come from the LED microcontroller, and the output will be the visual display
of the LED lights. The function of this block is to display the ghost of the user’s best time. This block will
be the face of the project since the correct propagation of the LED lights to mimic the user’s best time is
the net end goal. There will be one LED per meter.
RFID Reader
This block will receive input from the RFID tags and RFID microcontroller; the output will go to the RFID
microcontroller. The function of this block will be to generate a serial signal (RFID tag specific) when the
runner comes in range of the RFID reader. The RFID reader/tag will both be passive with a read range of
approximately 4 inches. This block will be critical in determining the location of the runner on the track.
RFID Tag
This output of the block will go to the RFID reader. This device will be attached on the ankle or shoe of
the runner. The function of this block will be to communicate with the RFID reader the location of the
runner. This block is tied very closely with the RFID reader block, and is also critical in determining the
location of the runner on the track.
8. 8
2. Design
The final full circuit schematic can be seen in Figure 7 found in Appendix A. The PCB designs can be seen
in Figure 8, Figure 9, Figure 10, and Figure 11 found in Appendix B. The tests and calculations that led to
this design are discussed below.
2.1 Power Supply
To power both of the microcontroller PCBs a DC socket was attached to the RFID microcontroller PCB.
The RFID microcontroller PCB was then wire connected to the LED microcontroller PCB to ensure that it
too received sufficient power. The power supply that was attached to the DC socket was 5V with the
capability to deliver current between 0.2-2A. The decision to use this type of power supply for these
microcontrollers was based on the datasheets [1]. To provide power to the four RFID reader PCBs a
single group of four AA batteries were connected in series. The voltage provided by these four AA
batteries is slightly greater than the desired 5V, but still fell within the given specifications provided in
the datasheet [2].
2.2 RFID Microcontroller
2.2.1 Hardware Component
This microcontroller was designed using the microprocessor of the Arduino Uno (ATmega328P-PU). The
microprocessor would be programmed on the Arduino Uno using the Arduino software and then the
ATmega328P-PU would be popped off and placed on a PCB. This PCB was designed to provide the
necessary power and clock to the microprocessor. In Figure 2, the circuit diagram shows all the
components which are used to correctly give the microprocessor both the required power and clock to
ensure full functionality [3]. The schematic and layout for this PCB can be found in Appendix B. The
physical PCB used in the design can be seen below in Figure 3.
Figure 2: Circuit Schematic for Microcontroller
9. 9
2.2.2 Software Component
This microcontroller was responsible for collecting and relaying data about when a user passes each
RFID reader on the track. First it recorded the start time of the program. All of the data obtained was
stored in an 𝑁 by 𝑀 array, with 𝑁 users and 𝑀 RFID readers in the track. Due to the limitations of the
ATmega328P-PU and its ability to only interface with one serial device at a time, the RFID readers had to
be read sequentially. This was accomplished by setting the first reader to active and relaying a
read/write command to it, along with an address at which it can store data captured by a passing RFID
tag. If a tag was scanned while the reader was active, the serial number would be passed on to the
microcontroller. The tag is then associated with a user number (0,1, … , 𝑁), and the time would also be
Figure 3: Physical PCB Design for Both Microcontrollers
Figure 4: RFID Software Flowchart
10. 10
stored in the corresponding element of the array. Time was calculated by taking the system time when
the RFID tag was scanned and subtracting from it system time of when the tag was previously read at
the last RFID reader. This time represented how long a user spent in that respective interval of the track.
From this point, the remaining RFID readers are set to active in succession until all tags have been read.
Once all tags have been read, which signifies a complete lap, the array would be sent over to the LED
microcontroller. Similar to the other operations, this transfer is done via serial communication. The data
is held in a buffer, and a start signal is sent over to the receiving microcontroller along with the length of
the data. Next, the desired data is sent over in a stream. Once this transaction is complete, the RFID
microcontroller is free to read tags and re-build the data array. This entire process repeats once per lap,
and begins with the data being sent over by serial transfer before looping to the next lap.
2.3 LED Microcontroller
2.3.1 Hardware Component
Exactly as the previous microcontroller, this microcontroller was designed using the microprocessor of
the Arduino Uno (ATmega328P-PU). The microprocessor would be programmed on the Arduino Uno
using the Arduino software and then the ATmega328P-PU would be popped off and placed on a PCB.
This PCB was designed to provide the necessary power and clock to the microprocessor. In Figure 2, the
circuit diagram shows all the components which are used to correctly give the microprocessor both the
required power and clock to ensure full functionality. The schematic and layout for this PCB can be
found in Appendix B. The physical PCB used in the design can be seen above in Figure 3.
2.3.2 Software Component
This microcontroller’s task was to take the data collected by the RFID microcontroller and display it on
the LED segments in the track as a visual for the user. The data was received via the aforementioned
serial transfer after each complete lap performed by the user. The code then calculates the overall
average pace for the lap for all users. In any situation where the new average pace for given user is
faster than their previous pace stored in the array, the new average pace is kept for future laps. The
data used for display in the next lap executed by the user(s) comes from the user with the fastest overall
pace. The index associated with that user in the array of data is used to access the data and the color for
that user. The desired row of the array will have 𝑀 items, corresponding to each RFID reader in the
track. Conveniently, there are also 𝑀 segments of ten LEDs. Each element contributing to the time can
be divided by ten to determine the duration of time each LED should be illuminated for in the display
sequence.
Figure 5: LED Software Flowchart
11. 11
𝑡𝑙𝑖𝑔ℎ𝑡 𝑜𝑛 =
𝑐𝑢𝑟𝑟𝑇𝑖𝑚𝑒𝑠[𝑢𝑠𝑒𝑟][𝑠𝑒𝑔𝑚𝑒𝑛𝑡]
# 𝑙𝑖𝑔ℎ𝑡𝑠 𝑖𝑛 𝑠𝑒𝑔𝑚𝑒𝑛𝑡
Once the display data has been determined, a start sequence is then initiated. This sequence consists of
three flashes of red throughout the entire track followed by one flash of green. This allows the users to
match the start of their next lap with the start of the data being displayed. A delay of length 𝑡𝑙𝑖𝑔ℎ𝑡 𝑜𝑛
was inserted each time before updating the LED module to activate the next light in the sequence. From
there, the entire process repeats for each lap completed. As new data arrives, it is compared with
existing data to see if best times have been beat. Then the pace is calculated again, and the fastest
user’s lap is displayed.
Timing Calculation for Each 10m Segment
There is 10m of LED strip in between two RFID readers. As a result, the 10 LEDs in this region need to
propagate in a manner that accurately displays the user’s pace in this region. Therefore, a mock example
was calculated to show how the software will compute this time data.
Problem:
1. Average time between RFID readers over 10m
Recorded time
10 m
= number of seconds for each LED segment to remain on
Example:
A runner’s pace is 10 min/mile on one of the 10 meter segments
This translates to
15 seconds
10 meters
, so each LED in that will be on for 1.5 seconds before the next one
lights up.
2.4 LED Strip
LED Density
LEDs need to be frequent enough that an average runner can consciously make decisions based on the
information they obtain from the moving light segments. If the LEDs are too far apart, the idea of a
“Ghost Runner” will not be apparent to the runner. They can theoretically be very close together.
However, for budgeting and practicality, they will be placed intermittently.
According to data obtained from Livestrong [4], the average worst-case stride length for a marathon
runner is approximately 4 feet 10 inches. To have a visual indicator positioned at least as frequently as
every two steps, LEDs must be placed accordingly.
Problem:
1. Determine average stride length for two steps
Solution:
1. 2 × (4 𝑓𝑒𝑒𝑡 10 𝑖𝑛𝑐ℎ𝑒𝑠) = (9 𝑓𝑒𝑒𝑡 8 𝑖𝑛𝑐ℎ𝑒𝑠) = 9.67 𝑓𝑒𝑒𝑡
9.67 𝑓𝑒𝑒𝑡 =
0.3048 𝑚𝑒𝑡𝑒𝑟𝑠
1 𝑓𝑜𝑜𝑡
= 2.95 𝑚𝑒𝑡𝑒𝑟𝑠 ≈ 3 𝑚𝑒𝑡𝑒𝑟𝑠
12. 12
LED segments will be placed every 3 meters in the design. LED segments consist of 1 LED per
meter.
The human brain can process an image at 13ms [5], and the fastest runner in the world can run 28
mph [6].
28 𝑚𝑝ℎ = 12.5171 𝑚𝑒𝑡𝑒𝑟𝑠/𝑠𝑒𝑐𝑜𝑛𝑑
Spacing LED segments every 3 meters, (
3
12.5171
) = 0.239 𝑠𝑒𝑐𝑜𝑛𝑑𝑠, which is eighteen times greater
than the 13 ms it takes a human brain to process an image confirms that the 3 meter spacing will
allow enough time for the runner to consciously process the light.
Design Decision:
From the above calculations it was determined that 1 LED placed at every 3 meter interval would work.
However, to make the design have a more complete and continuous look it was decided to place 1 LED
every meter.
The purchased LED strip contained all 40 LEDs connected together. Fortunately, the select strip had a
nice feature where each LED could easily be cut off from the strip. Therefore, each of the 40 LEDs were
taken off of the strip and then connected together with 1m of wire in-between each LED. Each LED had
three wire connections on each side; one for power, ground, and data. For safety reasons, black
electrical tape was used to cover the soldered connections on either side of all the LEDs. A picture of a
single LED used in the design is shown in Figure 6.
2.5 RFID Reader/Tag
The RFID system used in the project was a passive system. In a passive RFID system the RFID tags use the
RFID reader as their power source [7]. In this design, the Parallax #28440 RFID Readers were used with a
read range of approximately 4±0.5in. In order to work, both serial input and serial output of the RFID
Figure 6: Single LED
13. 13
reader must be connected to the microcontroller. The microcontroller sends a “ready to read” signal to
the RFID reader which activates the reader. When the RFID reader picks up a RFID tag, it then sends the
tag’s data back to the microcontroller. A PCB was designed to provide a convenient way to power the
RFID reader and allow it to connect with the RFID microcontroller. The schematic and layout for this PCB
can be found in Appendix B.
RFID Placement
Since the read range of the RFIDs is not very large the placement of these components is important.
These devices need to be placed in a position that has the greatest probability of correctly reading a
runner. If the RFID readers are not placed in a good spot then these readers will most likely not pick up
the RFID tag.
According to the data obtained from Livestrong [4], the average stride length of an individual is
approximately 1.14 to 1.17 times their height. Additionally, the average height of a USA male is 1.763m
and a female is 1.626m [4].
Problem:
1. Determine the ideal placement for a RFID reader to have a successful RFID tag read
Solution:
1.
Male Female
Avg. USA Height 1.763m 1.626m
Avg. stride range
X1.14 2.012m 1.853m
X1.17 2.065m 1.902m
Avg. of stride range 2.040m 9.387m
Avg. of stride range X5 10.195m 9.387m
Avg. combination of male
and female
9.79±0.404m
RFID readers placed at every 9.79m would be an ideal position to successfully read a RFID tag worn by
either a male or female.
Design Decision:
From the above calculations, it was determined that placing the RFID readers at every 9.79m would
work, but in order to make the design modular, it was decided to place the RFID readers at every 10m
interval. With the decision to place an RFID reader at 10m increments, this would guarantee that a
reader would be at the end of the 40m module to give an accurate time when the runner ended each
40m.
14. 14
3. Design Verification
A summary of all the tests conducted and results are given below.
3.1 Power Supply
To satisfy power requirements for the design, two separate tests were conducted. First the
microcontroller PCBs were given full power through the DC power supply/socket on the board. Both of
these devices were powered from one DC power supply. Additionally, all 40 of the LEDs were able to
light up from the power given to them from the LED microcontroller. A mulitimeter was used to
measure the voltage and current coming from the DC power supply. The voltage was found to be 5.13V,
and the current was found to be 0.5A. The second test conducted was for the RFID reader PCBs, which
were given full batteries. Again a mulitimeter was used to measure the voltage and current coming from
the battery holder. The voltage was found to be 5.64V and the current was found to be 0.556A. From
these two tests, it was concluded that this component met the design requirements for this section.
3.2 RFID Microcontroller
3.2.1 Hardware Component
To test the RFID microcontroller PCB, the transceiver software code was loaded onto the Arduino Uno
which determined whether or not a RFID tag had been read by the RFID reader. Initially, the Arduino
Uno was used as the microcontroller and then the RFID microcontroller PCB was exchanged in the
design. The net goal of this test was to have the same results independent of which microcontroller was
used in the design. The microprocessor (ATmega328P-PU) always received its program from the Arduino
Uno board before it was transferred over to the PCB design. The results for this test were the same for
when either the Arduino Uno or the PCB design was used as the microcontroller.
3.2.2 Software Component
In order to create a successful software package for the RFID module, it was broken down into three
segments. The first segment entailed connecting a single RFID reader to the microprocessor with a serial
monitor open a PC. RFID tags were used to determine, in real-time, if the serial numbers on each tag
were successfully read by the readers using a sample code from the manufacturer [9]. This initial phase
simply set one active serial port and sent a read/write signal to the RFID reader while continuously
listening for data.
The second segment looked to include a total of 4 RFID readers while constantly listening/reading for
data at each reader. Once all 4 RFID readers were correctly coded into the software, it was discovered
that the microprocessor used in the design was only capable of handling one active serial port at a time.
In other words, only 1 RFID reader could be active and listening at any given time. This issue was
discovered by observing that the red LED on the 4 RFID readers, which indicates the reader is
active/listening for data, was cycling between the 4 readers.
Therefore, in the final design of this project the RFID readers are read in sequential order. This severely
limited the ability of the system to detect all runners at all times. A runner would have to be passing the
RFID reader at the same time that reader was active in order for their time to be successfully recorded.
15. 15
In an effective implementation, either a powerful microcontroller with the ability to read from multiple
serial ports simultaneously would be used, or each RFID reader would have its own microcontroller that
is constantly collecting data and reporting back via serial connection to a more powerful main
microcontroller. The result of this change had an impact on the system’s ability to complete objectives
as originally intended. However, the system was still able to recognize tags and associate them with a
user as well as record the time at which tags were read.
The third segment involved the serial communication between this microcontroller and the LED
microcontroller. Initially, sample code from the manufacturer for a simple serial data transfer was used
to transfer an int from the RFID microcontroller to the LED microcontroller [10]. The next task was
changing the type of data transferred into a struct. In the code, the data to be transferred (the array of
times) was contained within a struct. At the conclusion of each lap (once the array has been populated
with data), the contents of the struct were placed into a buffer where they waited to be sent over via
serial transfer. The address of the buffer in memory were stored, and a stream was initialized on the
transceiver serial port. The start signal x06 was sent, followed by x85, which indicated that the size of
the data being transferred was being sent. Following this, the contents of each item in memory in the
struct were sent on the stream. Upon completion, the program entered a 200 ms delay so that the
receiving microcontroller could receive the data before the serial port was closed.
3.3 LED Microcontroller
3.3.1 Hardware Component
The LED Microcontroller PCB was tested in a similar way that the RFID microcontroller was tested. The
difference for this test was that the software loaded onto the microprocessors was the receiver
software code. This code was used to test the interface communication between the RFID and LED
microcontrollers. Initially, the Arduino Uno was used as the microcontroller and then the LED
microcontroller PCB was exchanged in the design. The net goal of this test was to have the same results
independent of which microcontroller was used in the design. The results for this test were the same for
when either the Arduino Uno or the PCB design was used as the microcontroller.
3.3.2 Software Component
In order to create a successful software package for the LED module, it was broken down into four
segments. The first segment involved connecting the LED strip to the microprocessor and illuminating
each LED sequentially with various pacing using a sample code from the manufacturer [11]. This initial
phase was used to ensure that the microcontroller could successfully control and power the LED strip.
The second segment entailed setting up different user’s timing data to be displayed in the LED strip. At
first, all of the timing data was attempted to be displayed at once. However, it was determined that it
would be too complicated for the user if more than one user was displayed in the same lane, given that
the users are close to each other. Instead, it was decided that the microprocessor controlling the LED
strip would calculate which user in the array of data had the best overall pace (defined by the total time
taken on one entire lap) and only display that user’s lap. Nonetheless, each user still was assigned their
own color to allow all of the users to know who had the best lap time. Several tests were conducted
16. 16
with fake data to confirm the functionality of this part. The fake data was loaded onto the
microprocessor at the completion of each lap. This test confirmed that when a different user obtained a
new, overall best lap time, the color of the LEDs in the strip would change. The new color corresponded
correctly to the user with the new, overall best lap time.
The third segment introduced a visual start sequence for the user. In this sequence, all lights in the track
flashed red for 500 ms three times followed by a 1000 ms green flash to indicate the start of the lap. At
the time that the green light was flashed, the start time was recorded so that future readings were
recorded relative to the start of the current lap. This start sequence correctly displayed on the LED strip
at the start of each lap.
The fourth segment looked at the serial communication between this microcontroller and the RFID
microcontroller. To start this process, sample code from the manufacturer for a simple serial data
transfer was used to transfer an int from the RFID microcontroller to the LED microcontroller [10]. In
order to receive data from the other microcontroller, the receiving serial port was opened, and once the
start signal x06 was received, it waited for the size to be received. Upon receipt of the size, the
microcontroller received data on the stream sent over and stored it in a struct similar to the one it is
sent from on the other microcontroller. This data was then used to update the array on the local
microcontroller used for displaying best times. This was initially tested by transferring small amounts of
data and confirming receipt, followed by incrementally transferring more data up to the full size array.
3.4 LED Strip
The LED Strip was comprised of 40 LEDs that were each 1 meter away from one another connected with
three wires. The total distance that this LED Strip covered was 40 meter. There were two main tests
conducted on the LED Strip. The first test was simply illuminate all 40 LEDs in the strip to ensure that all
LEDs were functioning and receiving data. The LED Strip passed this test and the brightness of 40 LEDs
was constant and strong. The second test had the LED microcontroller send timing data through the
strip that had difference times for each 10 meter segment. For this second test all 40 LEDs worked and
were correctly on at their designated times. Both of these tests were conducted with the LEDs
prepackaged from the manufacturer. The next step involved cutting the strip up such that each LED was
separated by 1 meter of wire. The two tests were again performed on the LED strip and both worked as
expected to ensure that this component met the requirements for this design.
3.5 RFID Reader/Tag
The PCB for the RFID reader was tested by first connecting the RFID reader on a breadboard to an
Arduino and power. The transceiver software code was loaded onto the Arduino Uno which determined
whether or not a RFID tag had been read by the RFID reader. This initial setup was tested several times
with different RFID tags and correctly read each of the tags. Next the RFID Reader PCB was used, instead
of the breadboard, in the design. This setup was again tested with the same procedure as the
breadboard setup. The results were the same for the PCB design and the breadboard design, which was
the original goal of this test.
17. 17
Several tests were conducted to determine the read reliability of the RFID component between the
different readers and tags. First, the experimental range was determined by moving a tag past the
reader. Both the reader and tag were aligned as they would be when used in the actual functioning
system. The reader was upright and parallel (flat) with respect to the track, and the tag was passed at a
perpendicular angle to the reader (as if it were attached to a user’s shoe) at a constant horizontal
distance of 1.5 inches. This range is within reason for actual use. The distance along the track, in which
the tag was identified by the reader and lost from the reader, was recorded. The results are as follows:
Trial Enter Distance (inches) Exit Distance (inches) Total Distance (inches)
1 1.6 0.9 2.5
2 2.2 1.0 3.2
3 1.5 0.9 2.4
4 1.6 1.0 2.6
5 0.9 0.6 1.5
6 1.3 1.0 2.3
7 1.1 0.3 1.4
8 2.5 2.0 4.5
9 1.7 1.6 3.3
10 0.8 1.3 2.1
Graph of results:
With the average total distance being 2.58 inches, this can provide some information about how long a
user will be in read range of the RFID reader when running past. For this calculation, an average pace of
7 minutes/mile is used.
18. 18
7 𝑚𝑖𝑛
1 𝑚𝑖𝑙𝑒
×
60 𝑠𝑒𝑐
1 𝑚𝑖𝑛
×
1 𝑚𝑖𝑙𝑒
5280 𝑓𝑡
×
1 𝑓𝑡
12 𝑖𝑛
× 2.58 𝑖𝑛 = 0.017 𝑠𝑒𝑐𝑜𝑛𝑑𝑠
So, the average user’s tag will be inside the read range of the reader for 0.017 seconds as they are
passing by. This begs the question of how reliably an RFID tag is read.
Another test is conducted to determine RFID tag read reliability. This test is designed to determine how
often a tag is successfully read when passed by the RFID reader. Each tag is passed by the reader twenty
times at running pace, and it is recorded whether or not the tag was successfully read. Successful read is
defined as recognition of the tag and its serial number. The results are as follows:
Tag Number Number of Successful Reads
1 13
2 14
3 14
4 16
5 15
Graph of results:
Overall, this shows a 72% successful read rate, which falls below the 97% successful read rate
requirement. The successful read rate would likely increase by using a RFID reader with a larger read
range. Another way this shortfall can be overcome is in the software portion of the design. These
improvements are further described in Section 5.4.
19. 19
4. Costs
4.1 Parts
4.2 Labor
Name Hourly Rate Total Hours Total = Hourly Rate x 2.5 x
Total Hours
Charlie Dreebin $35 150 $13,125
Ethan Perbohner $35 150 $13,125
Kelsey Byers $35 150 $13,125
Total 450 $39,375
4.3 Grand Total
Labor Parts Grand Total
$39,375 $413.19 $39,788.20
.
Part Part Number Unit Cost Quantity Total
LED Strip Adafruit NeoPixel 1460 $16.95 3 $50.85
Microcontroller ATmega328P-PU $6.28 2 $12.56
RFID Reader Parallax #28440 $49.95 4 $199.80
RFID Tag World Tag $2.50 5 $12.50
RFID Reader PCB Service Shop $15 4 $60.00
Microcontroller PCB Service Shop $35 2 $70.00
Battery Holder Radio Shack #2700409 $2.49 1 $2.49
4 AA Batteries Radio Shack #230213 $4.99 1 $4.99
Total $413.19
20. 20
5. Conclusion
5.1 Accomplishments
At the end of the project there were many aspects of the project that worked extremely well. The
following section will highlight these aforementioned successes from the design.
The design was able to differentiate and store multiple user’s tags in an array. Each user’s data would be
stored in its own designated row of the array with the correct corresponding time. Every RFID reader
was successfully able to read each user within a 5in. perpendicular read range. This perpendicular read
range exceeded the original goal of 40.5in.
Additionally, once the timing data was obtained by the RFID microcontroller the system was successfully
able to transfer this data over to the LED microcontroller. This was a serial data transfer operation that
occurred after each lap completed by the user. All of the timing data stored in the array in the RFID
microcontroller was transferred and then stored into another data array in the LED microcontroller. This
serial data transfer worked perfectly when implemented on the Arduino Uno microcontrollers, but was
less effective on the PCB microcontrollers.
The computations performed on the timing data stored in the array in the LED microcontroller were
accurately able to display the user’s pace in each 10m segment. For instance, if the user went very slow
in the first 10m segment and then increased their pace in the next 10m segment the LEDs correctly
displayed this change of pace.
Due to the use of two microcontrollers in the design it was possible to have continuous updating after
each lap completed by the user. This means that as soon as there was a complete lap of data stored in
the RFID microcontroller’s data array for a given user that data would be available for LED display on the
very next lap. There must be a complete laps worth of data for at least one user in order for the LED
strip to display data. Overall, this project worked very well given its limitations.
5.2 Uncertainties
There were a couple areas in the design which proved to be challenging tasks to tackle as the project
progressed through the semester. The following sections will take a look into these problematic areas.
The RFID readers used in the project were selected because one was already owned by the ECE
Department. The availability of this one RFID reader helped with budget constraints for the project, and
also serviced the needs of the design. However, it was originally believed that the serial input for these
readers was a floating pin that could be ignored. The first RFID reader PCBs were designed with the
serial input set to ground, and did not function. These PCBs were redesigned to include a pad for the
serial input and these inputs were connected to the RFID microcontroller.
Another area of concern was related to the microcontroller PCBs. To clarify, the RFID microcontroller
PCB worked as desired when it was only connected to the RFID reader component. Also, the LED
microcontroller PCB worked as expected when it was only connected to the LED strip. However, when
the two microcontroller PCBs were connected in an effort to transfer the data between the two did not
21. 21
work. All of the connections were tested for continuity. The RFID microcontroller PCB was able to collect
and process the data but was not then able to transfer this data to the LED microcontroller LED. This
issue remains to have an unknown solution.
Furthermore, as the project progressed it became apparent that the microprocessor (ATmega328P-PU)
was not powerful enough to meet the requirements. This microprocessor is only able to have one serial
read/write signal at any given time. This discovery lead to the development of the mutual relationship
between the RFID and LED microcontrollers compared to the original design which had a master-slave
relationship between the microcontrollers. Unfortunately, this did not completely eliminate the issue
because the RFID microcontroller could only have one RFID reader active/listening at one time. Each
RFID reader required a serial input of a “ready to read” signal in order to detect a tag.
Lastly, the project was not able to display all of the users on the track at the same time due to the
density of the LEDs. There were 40 LEDs on the track and to show multiple users there could potentially
be two sets of data trying to control the same LED at the same time. A potential fix to this issue would
be to increase the number of LEDs used, but the tradeoff would be a much high cost to purchase all of
those LEDs.
5.3 Ethical Considerations
5.3.1 Safety Statement
This project has two main areas for safety concerns: electrical and radio frequency safety.
The electrical safety portion of this project pertains to the use of electrical circuits. There is an inherent
risk of electrical shock when dealing with any electrical circuit. This design uses several electrical
components but none of these components require a large voltage/power value. The minimum value in
each component range is satisfied and the maximum value in each component range is not exceeded in
an effort to minimize all safety risks. The design decision to use a maximum of 5V DC electricity to power
the LEDs ensures that the minimum value in the range is satisfied while also keeping the risk of an
electrical shock to a minimum.
The customers who use this product will never be exposed to any of the circuity used in the design. The
user will only wear an enclosed RFID tag and use that to activate the system. From that point, the
remainder of the system is automated as long as the user remains within the range of the system’s RFID
readers. For this reason, it is highly unlikely that the user will receive an electrical shock. As an added
precaution, the circuity of the LED strips and their respective connectors will be enclosed in a rubber
casing.
The radio frequency safe of this project pertains to the use of RFID components of the design. There
exists a general concern for humans being exposed to radio frequencies. However, this applies mostly to
extremely high-frequency signals with long ranges. This project uses only the 125 kHz frequency and the
range of the signal is limited to approximately three inches. For this reason, there is not a concern of
damaging any human tissue or interfering with medical devices (give that the medical devices do not
22. 22
operate at the 125 kHz frequency). Additionally, there is no sensitive data being transmitted via the
RFIDs (only time data). As a result, there is no concern for the stealing of personal information.
5.3.2 Ethics Statement
In accordance with the IEEE Codes of Ethics, the members of this team commit themselves to the
highest ethical and professional conduct in the completion of this project. In particular, the team will
adhere to Sections 7.8.1 and 7.8.9 in the creation of this project. Consideration will be given to ensuring
that the system does not interfere with a runner in any way that could bring harm to the individual while
training or competing. The team will aim to minimize the system’s presence in a way that very little to
no impact is made on how a user runs. To comply with Sections 7.8.6 and 7.8.10, the team will
guarantee that every task is taken as an opportunity to learn and utilize the members of the team in the
most efficient way possible. This means that those team members with the best skillset are either
assigned to relevant tasks or they are used as references for that task.
5.4 Future Work
There are three key areas that would be of immediate interest to improve upon going forward with this
project. These three areas are: microprocessor capability, wireless communication feature, and RFID
read range.
The current microprocessor (ATmega328P-PU) only allows for one serial read/write function at a time.
This limited the design such that only one RFID reader would be active and listening for a tag. In the
future, a more capable and powerful microprocessor would need to be used to obtain optimal
functionality for the project. Ideally, the new microprocessor would be capable of performing multiple
serial functions at once.
As of right now, there are lots of long wires used to connect the RFID readers to the RFID
microcontroller. These wires would only get longer as the track is increased to its full length of 400m. It
would be more practical to remove these excessive wires and place a wireless communication device on
each RFID reader. The addition of these wireless communication devices would make the overall design
of the project more aesthetically pleasing and more practical.
Another area to improve upon is the read range of the RFID readers. Currently, the read range used in
this design is approximately 4±0.5inches. In the future, the read range should be increased to at least 21
inches to cover half the width of a track lane [8]. By increasing the read range, there is a greater
likelihood that the runner’s tag will be correctly captured/read by the RFID reader.
To further improve the RFID reader segment, it would be useful to modify the software to account for a
missed read. From Section 3.5 it was found that the RFID reader and tags only achieved a 72% successful
read rate in testing. This could be done by checking each time a tag is read, whether or not a tag was
registered with the previous RFID reader. If there was not a successful read from the previous reader,
then the entire segment encompassing two (or more) RFID readers would be represented as one
segment. The time registered on this segment would then be divided by two and stored as the time in
each of the segments being represented. This would allow the system to overcome some of the
23. 23
shortcomings of the RFID readers. The only information that would be lost in this scenario would be the
detail of the user’s location within a lap, but the overall lap pace would not be lost.
24. 24
6. References
[1] Parallax, 'RFID Read/Write Module, Serial (#28440)', 2015. [Online]. Available:
https://www.parallax.com/sites/default/files/downloads/28440-RFID-Read-Write-Documentation-
v1.0.pdf. [Accessed: 17- Nov- 2015].
[2] Atmel, 'ATmega48A/PA/88A/PA/168A/PA/328/P', 2014. [Online]. Available:
http://www.atmel.com/images/atmel-8271-8-bit-avr-microcontroller-atmega48a-48pa-88a-88pa-168a-
168pa-328-328p_datasheet_complete.pdf. [Accessed: 17- Nov- 2015].
[3] J. Burkett, 'Tinker City | Making an Arduino on a Breadboard', Tinkercity.com, 2015. [Online].
Available: http://tinkercity.com/2014/05/01/making-an-arduino-on-a-breadboard/. [Accessed: 20- Sep-
2015].
[4] C. Cespedes, 'The Average Stride Length in Running | LIVESTRONG.COM', LIVESTRONG.COM, 2015.
[Online]. Available: http://www.livestrong.com/article/438560-the-average-stride-length-in-running/.
[Accessed: 07- Oct- 2015].
[5] A. Trafton, 'In the blink of an eye', MIT News, 2015. [Online]. Available: http://news.mit.edu/2014/in-
the-blink-of-an-eye-0116. [Accessed: 07- Oct- 2015].
[6] LiveScience.com, 'Humans Could Run 40 mph, in Theory', 2015. [Online]. Available:
http://www.livescience.com/8039-humans-run-40-mph-theory.html. [Accessed: 07- Oct- 2015].
[7] K. Bonsor and W. Fenlon, 'How RFID Works', HowStuffWorks, 2007. [Online]. Available:
http://electronics.howstuffworks.com/gadgets/high-tech-gadgets/rfid3.htm. [Accessed: 18- Oct- 2015].
[8] P. Steinbach, 'Exacting Design Standards Spur Quality Track Construction - Athletic Business',
Athleticbusiness.com, 2015. [Online]. Available: http://www.athleticbusiness.com/exacting-design-
standards-spur-quality-track-construction.html. [Accessed: 05- Dec- 2015].
[9] Parallax, Inc. ‘RFID Read/Write Module’, 2012. [Online].
Available: https://www.parallax.com/downloads/rfid-readwrite-module-arduino-code-example.
[Accessed: 19-Oct-2015].
[10] Billporter.info, 'The Mind of Bill Porter', 2015. [Online]. Available:
http://www.billporter.info/2011/05/30/easytransfer-arduino-library/. [Accessed: 29- Oct- 2015].
[11] Learn.adafruit.com, 'Arduino Library | Adafruit NeoPixel Überguide | Adafruit Learning System',
2015. [Online]. Available: https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library.
[Accessed: 30- Sep- 2015].
25. 25
Appendix A: Final Full Circuit Schematic
Figure 7: Schematic for Full Circuit
26. 26
Appendix B: PCB Design
RFID PCB
RFID Schematic
Figure 8: Schematic for RFID PCB
30. 30
Appendix C: RFID Microcontroller Source Code
1. #include <EasyTransfer.h>
2. #include <SoftwareSerial.h>
3.
4. EasyTransfer ET;
5.
6. #define rxPin1 3 // Serial input (connec
ts to the RFID's SOUT pin)
7. #define txPin1 2 // Serial output (conne
cts to the RFID's SIN pin)
8. #define rxPin2 6 // Serial input (connec
ts to SOUT)
9. #define txPin2 5 // Serial output (conne
cts to SIN)
10. #define rxPin3 10 // Serial input (conne
cts to SOUT)
11. #define txPin3 8 // Serial output (conne
cts to SIN)
12. #define rxPin4 12 // Serial input (connec
ts to SOUT)
13. #define txPin4 11 // Serial output (conne
cts to SIN)
14.
15. #define BUFSIZE 8 // Size of receive buffe
r (in bytes) for incoming data from the RFID R
/W Module (this should be adjusted to be large
r than the expected response)
16. #define RFID_Read 0x01 // Read data
from specified address, valid locations 1 to
33 (5)
17. #define RFID_Write 0x02 // Write dat
a to specified address, valid locations 3 to 3
1 (1)
18. #define RFID_Reset 0x06 // Reset tag
(1)
19. // Memory map/address locations for EM4x50 tag
20. // Each address holds/returns a 32-
bit (4 byte) value
21. // ADDR 3-31 are User EEPROM area
22. #define ADDR_Serial 32 // Device Serial N
umber
23. #define ADDR_DeviceID 33 // Device Identi
fication
24. // Status/error return codes
25. #define ERR_OK 0x01 // No errors
26. #define ERR_LIW 0x02 // Did not find a
listen window
27. #define ERR_NAK 0x03 // Received a NAK,
could be invalid command
28. #define ERR_NAK_OLDPW 0x04 // Received a
NAK sending old password (RFID_SetPass), could
be incorrect password
29. #define ERR_NAK_NEWPW 0x05 // Received a
NAK sending new password (RFID_SetPass)
30. #define ERR_LIW_NEWPW 0x06 // Did not fin
d a listen window after setting new password (
RFID_SetPass)
31. #define ERR_PARITY 0x07 // Parity error
when reading data
32.
33. // set up a new serial port
34. SoftwareSerial rfidSerial1 = SoftwareSerial(rx
Pin1,txPin1); //2 is SIN, 3 is SOUT
35. SoftwareSerial rfidSerial2 = SoftwareSerial(rx
Pin2,txPin2); //5 is SIN, 6 is SOUT
36. SoftwareSerial rfidSerial3 = SoftwareSerial(rx
Pin3,txPin3); //8 is SIN, 9 is SOUT
37. SoftwareSerial rfidSerial4 = SoftwareSerial(rx
Pin4,txPin4); //11 is SIN, 12 is SOUT
38.
39. unsigned long timeprev = 0;
40. unsigned long timecurr = 0;
41. unsigned long timestart = 0;
42.
43. #define N 5
44. #define M 4
45. uint32_t currTimes[N][M]; //main array of data
46.
47. struct SEND_DATA_STRUCTURE{ //contains data to
be sent to LED microprocessor
48. uint32_t currTimes00;
49. uint32_t currTimes01;
50. uint32_t currTimes02;
51. uint32_t currTimes03;
52. uint32_t currTimes10;
53. uint32_t currTimes11;
54. uint32_t currTimes12;
55. uint32_t currTimes13;
56. uint32_t currTimes20;
57. uint32_t currTimes21;
58. uint32_t currTimes22;
59. uint32_t currTimes23;
60. uint32_t currTimes30;
61. uint32_t currTimes31;
62. uint32_t currTimes32;
63. uint32_t currTimes33;
64. uint32_t currTimes40;
65. uint32_t currTimes41;
66. uint32_t currTimes42;
67. uint32_t currTimes43;
68. };
69.
70. SEND_DATA_STRUCTURE mydata; //initialize struc
ture to send
71.
72. void setup(){
73. pinMode(rxPin1, INPUT);
74. pinMode(txPin1, OUTPUT);
75. pinMode(rxPin2, INPUT);
76. pinMode(txPin2, OUTPUT);
77. pinMode(rxPin3, INPUT);
78. pinMode(txPin3, OUTPUT);
79. pinMode(rxPin4, INPUT);
80. pinMode(txPin4, OUTPUT);
81. Serial.begin(9600);
82. rfidSerial1.begin(9600);
83. rfidSerial2.begin(9600);
84. rfidSerial3.begin(9600);
85. rfidSerial4.begin(9600);
86. Serial.flush();
87. Serial.println("nnParallax RFID Read/Write
Module");
88. ET.begin(details(mydata), &Serial);
89.
90. for (int i=0;i<N;i++){ //initialize currTime
s to some arbitrary value
91. for (int j=0;j<M;j++){
92. currTimes[i][j] = 99;
93. }
94. }
95.
96. }
97.
98. void loop(){
99. uint8_t rfidData[BUFSIZE]; // Buffer for
incoming data for each RFID reader
100. uint8_t rfidData2[BUFSIZE];
101. uint8_t rfidData3[BUFSIZE];
102. uint8_t rfidData4[BUFSIZE];
103.
104. //Serial.print("Reading tag's unique seria
l number...");
105.
106. rfidSerial1.listen(); //Reader 1 active
107. if (rfidRead1(rfidData, ADDR_Serial) == 0)
{
108. timecurr = millis();
109. if (timecurr - timeprev > 1000){
110. Serial.print("Time: ");
111. Serial.print(timecurr);
112.
31. 31
113. uint8_t length = 4;
114. char tmp[length*2+1];
115. byte first;
116. int j=0;
117. for (uint8_t i=0; i<length; i++)
118. {
119. first = (rfidData[i] >> 4) | 48;
120. if (first > 57) tmp[j] = first + (by
te)39;
121. else tmp[j] = first ;
122. j++;
123.
124. first = (rfidData[i] & 0x0F) | 48;
125. if (first > 57) tmp[j] = first + (by
te)39;
126. else tmp[j] = first;
127. j++;
128. }
129. tmp[length*2] = 0;
130. //Serial.print(hashMap.getValueOf(Stri
ng(tmp).substring(0,8)));
131. //Serial.print(tmp);
132. //Serial.print(hashMap.getValueOf(Stri
ng(tmp).substring(0,8)));
133.
134. Serial.print("tSerial number: ");
135. Serial.print(String(tmp).substring(0,8
));
136. int idx;
137. if (String(tmp).substring(0,8) == "026
0bbd8"){ Serial.print("tUser 1");idx = 0;}
138. else if (String(tmp).substring(0,8) ==
"0260e813"){ Serial.print("tUser 2");idx = 1
;}
139. else if (String(tmp).substring(0,8) ==
"0260bdc4"){ Serial.print("tUser 3");idx = 2
;}
140. else if (String(tmp).substring(0,8) ==
"0260e812"){ Serial.print("tUser 4");idx = 3
;}
141. else if (String(tmp).substring(0,8) ==
"0260e7df"){ Serial.print("tUser 5");idx = 4
;}
142.
143. timeStamps[idx][0] = timecurr-
timestart;
144. currTimes[idx][0] = timeStamps[idx][0]
- timeStamps[idx][M-1];
145.
146. //PrintHex(rfidData, 4); // The rfid
Data string should now contain the tag's seria
l number, so display it on the Serial Monitor
147. Serial.println();
148. Serial.flush();
149.
150. for (int i=0;i<N;i++){
151. for (int j=0;j<M;j++){
152. Serial.print(currTimes[i][j]);
153. Serial.print(" ");
154. }
155. Serial.print("n");
156. }
157. }
158. timeprev = timecurr;
159. }
160.
161. rfidSerial2.listen(); //Reader 2 active
162. if (rfidRead2(rfidData2, ADDR_Serial) == 0
){
163. timecurr = millis();
164. if (timecurr - timeprev > 1000){
165. Serial.print("Time: ");
166. Serial.print(timecurr);
167.
168. uint8_t length = 4;
169. char tmp[length*2+1];
170. byte first;
171. int j=0;
172. for (uint8_t i=0; i<length; i++)
173. {
174. first = (rfidData2[i] >> 4) | 48;
175. if (first > 57) tmp[j] = first + (by
te)39;
176. else tmp[j] = first ;
177. j++;
178.
179. first = (rfidData2[i] & 0x0F) | 48;
180. if (first > 57) tmp[j] = first + (by
te)39;
181. else tmp[j] = first;
182. j++;
183. }
184. tmp[length*2] = 0;
185.
186. Serial.print("tSerial number: ");
187. Serial.print(String(tmp).substring(0,8
));
188. int idx;
189. if (String(tmp).substring(0,8) == "026
0bbd8"){ Serial.print("tUser 1");idx = 0;}
190. else if (String(tmp).substring(0,8) ==
"0260e813"){ Serial.print("tUser 2");idx = 1
;}
191. else if (String(tmp).substring(0,8) ==
"0260bdc4"){ Serial.print("tUser 3");idx = 2
;}
192. else if (String(tmp).substring(0,8) ==
"0260e812"){ Serial.print("tUser 4");idx = 3
;}
193. else if (String(tmp).substring(0,8) ==
"0260e7df"){ Serial.print("tUser 5");idx = 4
;}
194.
195. timeStamps[idx][1] = timecurr-
timestart;
196. currTimes[idx][1] = timeStamps[idx][1]
- timeStamps[idx][0];
197.
198. //PrintHex(rfidData, 4); // The rfid
Data string should now contain the tag's seria
l number, so display it on the Serial Monitor
199. Serial.println();
200. Serial.flush();
201.
202. for (int i=0;i<N;i++){
203. for (int j=0;j<M;j++){
204. Serial.print(currTimes[i][j]);
205. Serial.print(" ");
206. }
207. Serial.print("n");
208. }
209. }
210. timeprev = timecurr;
211. }
212.
213. rfidSerial3.listen(); //Reader 3 active
214. if (rfidRead3(rfidData3, ADDR_Serial) == 0
){
215. timecurr = millis();
216. if (timecurr - timeprev > 1000){
217. Serial.print("Time: ");
218. Serial.print(timecurr);
219.
220. uint8_t length = 4;
221. char tmp[length*2+1];
222. byte first;
223. int j=0;
224. for (uint8_t i=0; i<length; i++)
225. {
226. first = (rfidData3[i] >> 4) | 48;
227. if (first > 57) tmp[j] = first + (by
te)39;
228. else tmp[j] = first ;
229. j++;
230.
32. 32
231. first = (rfidData3[i] & 0x0F) | 48;
232. if (first > 57) tmp[j] = first + (by
te)39;
233. else tmp[j] = first;
234. j++;
235. }
236. tmp[length*2] = 0;
237.
238. Serial.print("tSerial number: ");
239. Serial.print(String(tmp).substring(0,8
));
240. int idx;
241. if (String(tmp).substring(0,8) == "026
0bbd8"){ Serial.print("tUser 1");idx = 0;}
242. else if (String(tmp).substring(0,8) ==
"0260e813"){ Serial.print("tUser 2");idx = 1
;}
243. else if (String(tmp).substring(0,8) ==
"0260bdc4"){ Serial.print("tUser 3");idx = 2
;}
244. else if (String(tmp).substring(0,8) ==
"0260e812"){ Serial.print("tUser 4");idx = 3
;}
245. else if (String(tmp).substring(0,8) ==
"0260e7df"){ Serial.print("tUser 5");idx = 4
;}
246.
247. timeStamps[idx][2] = timecurr-
timestart;
248. currTimes[idx][2] = timeStamps[idx][2]
- timeStamps[idx][1];
249.
250. //PrintHex(rfidData, 4); // The rfid
Data string should now contain the tag's seria
l number, so display it on the Serial Monitor
251. Serial.println();
252. Serial.flush();
253.
254. for (int i=0;i<N;i++){
255. for (int j=0;j<M;j++){
256. Serial.print(currTimes[i][j]);
257. Serial.print(" ");
258. }
259. Serial.print("n");
260. }
261. }
262. timeprev = timecurr;
263. }
264.
265. rfidSerial4.listen(); //Reader 4 active
266. if (rfidRead4(rfidData4, ADDR_Serial) == 0
){
267. timecurr = millis();
268. if (timecurr - timeprev > 1000){
269. Serial.print("Time: ");
270. Serial.print(timecurr);
271.
272. uint8_t length = 4;
273. char tmp[length*2+1];
274. byte first;
275. int j=0;
276. for (uint8_t i=0; i<length; i++)
277. {
278. first = (rfidData4[i] >> 4) | 48;
279. if (first > 57) tmp[j] = first + (by
te)39;
280. else tmp[j] = first ;
281. j++;
282.
283. first = (rfidData4[i] & 0x0F) | 48;
284. if (first > 57) tmp[j] = first + (by
te)39;
285. else tmp[j] = first;
286. j++;
287. }
288. tmp[length*2] = 0;
289.
290. Serial.print("tSerial number: ");
291. Serial.print(String(tmp).substring(0,8
));
292. int idx;
293. if (String(tmp).substring(0,8) == "026
0bbd8"){ Serial.print("tUser 1");idx = 0;}
294. else if (String(tmp).substring(0,8) ==
"0260e813"){ Serial.print("tUser 2");idx = 1
;}
295. else if (String(tmp).substring(0,8) ==
"0260bdc4"){ Serial.print("tUser 3");idx = 2
;}
296. else if (String(tmp).substring(0,8) ==
"0260e812"){ Serial.print("tUser 4");idx = 3
;}
297. else if (String(tmp).substring(0,8) ==
"0260e7df"){ Serial.print("tUser 5");idx = 4
;}
298.
299. timeStamps[idx][3] = timecurr-
timestart;
300. currTimes[idx][3] = timeStamps[idx][3]
- timeStamps[idx][2];
301.
302. //PrintHex(rfidData, 4); // The rfid
Data string should now contain the tag's seria
l number, so display it on the Serial Monitor
303. Serial.println();
304. Serial.flush();
305.
306. for (int i=0;i<N;i++){
307. for (int j=0;j<M;j++){
308. Serial.print(currTimes[i][j]);
309. Serial.print(" ");
310. }
311. Serial.print("n");
312. }
313. }
314. timeprev = timecurr;
315. }
316.
317. //update data in struct to be sent
318. mydata.currTimes00 = currTimes[0][0];
319. mydata.currTimes01 = currTimes[0][1];
320. mydata.currTimes02 = currTimes[0][2];
321. mydata.currTimes03 = currTimes[0][3];
322. mydata.currTimes10 = currTimes[1][0];
323. mydata.currTimes11 = currTimes[1][1];
324. mydata.currTimes12 = currTimes[1][2];
325. mydata.currTimes13 = currTimes[1][3];
326. mydata.currTimes20 = currTimes[2][0];
327. mydata.currTimes21 = currTimes[2][1];
328. mydata.currTimes22 = currTimes[2][2];
329. mydata.currTimes23 = currTimes[2][3];
330. mydata.currTimes30 = currTimes[3][0];
331. mydata.currTimes31 = currTimes[3][1];
332. mydata.currTimes32 = currTimes[3][2];
333. mydata.currTimes33 = currTimes[3][3];
334. mydata.currTimes40 = currTimes[4][0];
335. mydata.currTimes41 = currTimes[4][1];
336. mydata.currTimes42 = currTimes[4][2];
337. mydata.currTimes43 = currTimes[4][3];
338.
339. ET.sendData(); //calls function to transfer
data to LED microcontroller
340. Serial.print("Data sentn");
341. //delay before allowing data to be sent agai
n, while waiting for receiving module to copy
data
342. delay(200);
343. }
344.
345. char rfidRead1(uint8_t *data, uint8_t address)
346. {
347. char offset; // offset into buffer
348.
33. 33
349. rfidFlush1(); // empties any buffered incom
ing serial data
350.
351. rfidSerial1.print("!RW"); // header
352. rfidSerial1.write(RFID_Read); // command
353. rfidSerial1.write(address); // address
354.
355. while (rfidSerial1.available() != 5); // wa
it until data is received from RFID module
356.
357. if (rfidSerial1.read() == ERR_OK) // if our
status byte is OK
358. {
359. for (offset = 0; offset < 4; offset++)
360. data[offset] = rfidSerial1.read(); // g
et the remaining data
361.
362. return 0; // return good
363. }
364.
365. return -1; // return error
366. }
367.
368. char rfidRead2(uint8_t *data, uint8_t address)
369. {
370. char offset; // offset into buffer
371.
372. rfidFlush2(); // empties any buffered incom
ing serial data
373.
374. rfidSerial2.print("!RW"); // header
375. rfidSerial2.write(RFID_Read); // command
376. rfidSerial2.write(address); // address
377.
378. while (rfidSerial2.available() != 5); // wa
it until data is received from RFID module
379.
380. if (rfidSerial2.read() == ERR_OK) // if our
status byte is OK
381. {
382. for (offset = 0; offset < 4; offset++)
383. data[offset] = rfidSerial2.read(); // g
et the remaining data
384.
385. return 0; // return good
386. }
387.
388. return -1; // return error
389. }
390.
391. char rfidRead3(uint8_t *data, uint8_t address)
392. {
393. char offset; // offset into buffer
394.
395. rfidFlush3(); // empties any buffered incom
ing serial data
396.
397. rfidSerial3.print("!RW"); // header
398. rfidSerial3.write(RFID_Read); // command
399. rfidSerial3.write(address); // address
400.
401. while (rfidSerial3.available() != 5); // wa
it until data is received from RFID module
402.
403. if (rfidSerial3.read() == ERR_OK) // if our
status byte is OK
404. {
405. for (offset = 0; offset < 4; offset++)
406. data[offset] = rfidSerial3.read(); // g
et the remaining data
407.
408. return 0; // return good
409. }
410.
411. return -1; // return error
412. }
413.
414. char rfidRead4(uint8_t *data, uint8_t address)
415. {
416. char offset; // offset into buffer
417.
418. rfidFlush4(); // empties any buffered incom
ing serial data
419.
420. rfidSerial4.print("!RW"); // header
421. rfidSerial4.write(RFID_Read); // command
422. rfidSerial4.write(address); // address
423.
424. while (rfidSerial4.available() != 5); // wa
it until data is received from RFID module
425.
426. if (rfidSerial4.read() == ERR_OK) // if our
status byte is OK
427. {
428. for (offset = 0; offset < 4; offset++)
429. data[offset] = rfidSerial4.read(); // g
et the remaining data
430.
431. return 0; // return good
432. }
433.
434. return -1; // return error
435. }
436.
437. void rfidFlush1() // Empties any buffered inc
oming serial data
438. {
439. while (rfidSerial1.available() > 0)
440. rfidSerial1.read();
441. }
442.
443. void rfidFlush2() // Empties any buffered inc
oming serial data
444. {
445. while (rfidSerial2.available() > 0)
446. rfidSerial2.read();
447. }
448.
449. void rfidFlush3() // Empties any buffered inc
oming serial data
450. {
451. while (rfidSerial3.available() > 0)
452. rfidSerial3.read();
453. }
454.
455. void rfidFlush4() // Empties any buffered inc
oming serial data
456. {
457. while (rfidSerial4.available() > 0)
458. rfidSerial4.read();
459. }
34. 34
Appendix D: LED Microcontroller Source Code
1. #include <EasyTransfer.h>
2. #include <Adafruit_NeoPixel.h>
3. #ifdef __AVR__
4. #include <avr/power.h>
5. #endif
6.
7. #define PIN 7
8. #define NUM_LEDS 40
9. //preset display colors
10. #define RED 255,0,0
11. #define ORANGE 255,165,0
12. #define YELLOW 255,255,0
13. #define GREEN 0,255,0
14. #define BLUE 0,0,255
15. #define OFF 0,0,0
16.
17. Adafruit_NeoPixel strip = Adafruit_NeoPixel(NU
M_LEDS, PIN, NEO_GRB + NEO_KHZ800);
18. EasyTransfer ET;
19.
20. unsigned long timestart = 0;
21. unsigned long timeprev = 0;
22. unsigned long timecurr = 0;
23.
24. #define N 5
25. #define M 4
26. uint32_t currTimes[N][M]; //main array of data
27. uint32_t pace[N]; //array to keep track of bes
t pace for each user
28.
29. /* Test Data for mock demo */
30. uint32_t lapone[5][4] = {{1500,4000,2000,3000}
,{2000,3000,2000,5000},{2500,7000,2000,2000},{
5000,6000,5000,1000},{3000,3000,3000,3500}};
31. uint32_t laptwo[5][4] = {{2500,2500,2500,5000}
,{2000,3000,2000,5000},{2500,7000,2000,2000},{
1500,4000,2000,3000},{3000,3000,3000,3500}};
32. uint32_t lapthree[5][4] = {{2000,3000,3000,500
0},{1500,4000,2000,3000},{2500,7000,2000,2000}
,{5000,6000,5000,1000},{3000,3000,3000,3500}};
33.
34. struct RECEIVE_DATA_STRUCTURE{ //contains data
to be received from RFID microprocessor
35. uint32_t currTimes00;
36. uint32_t currTimes01;
37. uint32_t currTimes02;
38. uint32_t currTimes03;
39. uint32_t currTimes10;
40. uint32_t currTimes11;
41. uint32_t currTimes12;
42. uint32_t currTimes13;
43. uint32_t currTimes20;
44. uint32_t currTimes21;
45. uint32_t currTimes22;
46. uint32_t currTimes23;
47. uint32_t currTimes30;
48. uint32_t currTimes31;
49. uint32_t currTimes32;
50. uint32_t currTimes33;
51. uint32_t currTimes40;
52. uint32_t currTimes41;
53. uint32_t currTimes42;
54. uint32_t currTimes43;
55. };
56.
57. RECEIVE_DATA_STRUCTURE mydata; //initialize st
ructure to receive
58.
59. uint16_t lap = 0;
60. uint16_t fastestIdx;
61.
62. void setup(){
63. Serial.begin(9600);
64. ET.begin(details(mydata), &Serial);
65. strip.begin();
66. strip.show(); // Initialize all pixels to 'o
ff'
67. Serial.flush(); // wait for all bytes to b
e transmitted to the Serial Monitor
68. for (int i=0;i<N;i++){
69. for (int j=0;j<M;j++){
70. currTimes[i][j] = 0;
71. }
72. }
73. Serial.print("LED module setup complete.n")
;
74. }
75.
76. void loop(){
77.
78. if (lap == 0){
79. for (uint16_t i=0;i<5;i++){
80. for (uint16_t j=0;j<4;j++){
81. currTimes[i][j] = lapone[i][j];
82. }
83. }
84. Serial.print("lap zeron");
85. }
86.
87. else if (lap == 1){
88. for (uint16_t i=0;i<5;i++){
89. for (uint16_t j=0;j<4;j++){
90. currTimes[i][j] = laptwo[i][j];
91. }
92. }
93. Serial.print("lap onen");
94. }
95. else if (lap == 2){
96. for (uint16_t i=0;i<5;i++){
97. for (uint16_t j=0;j<4;j++){
98. currTimes[i][j] = lapthree[i][j];
99. }
100. }
101. Serial.print("lap twon");
102. }
103.
104. fastestIdx = updatePace();
105. //if (lap == 0){
106. startSequence();
107. //}
108.
109. if (currTimes[0][0] != 99 && currTimes[0][1]
!= 99 && currTimes[0][2] != 99 && currTimes[0
][3] != 99){
110. displaySegment(1,currTimes[fastestIdx][0],
fastestIdx);
111. displaySegment(2,currTimes[fastestIdx][1],
fastestIdx);
112. displaySegment(3,currTimes[fastestIdx][2],
fastestIdx);
113. displaySegment(4,currTimes[fastestIdx][3],
fastestIdx);
114. //lap = -1;
115. }
116.
117. //check and see if a data packet has come in
.
118. if(ET.receiveData()){
119. //this is how you access the variables. [n
ame of the group].[variable name]
120. //since we have data, we will blink it out
.
121. Serial.print("DATA RECEIVED:n");
122. currTimes[0][0] = mydata.currTimes00;
123. currTimes[0][1] = mydata.currTimes01;
124. currTimes[0][2] = mydata.currTimes02;
125. currTimes[0][3] = mydata.currTimes03;
126. currTimes[1][0] = mydata.currTimes10;
127. currTimes[1][1] = mydata.currTimes11;
128. currTimes[1][2] = mydata.currTimes12;
35. 35
129. currTimes[1][3] = mydata.currTimes13;
130. currTimes[2][0] = mydata.currTimes20;
131. currTimes[2][1] = mydata.currTimes21;
132. currTimes[2][2] = mydata.currTimes22;
133. currTimes[2][3] = mydata.currTimes23;
134. currTimes[3][0] = mydata.currTimes30;
135. currTimes[3][1] = mydata.currTimes31;
136. currTimes[3][2] = mydata.currTimes32;
137. currTimes[3][3] = mydata.currTimes33;
138. currTimes[4][0] = mydata.currTimes40;
139. currTimes[4][1] = mydata.currTimes41;
140. currTimes[4][2] = mydata.currTimes42;
141. currTimes[4][3] = mydata.currTimes43;
142. for (uint16_t i=0;i<N;i++){
143. for (uint16_t j=0;j<M;j++){
144. Serial.print(currTimes[i][j]);
145. Serial.print(" ");
146. }
147. Serial.print("n");
148. }
149. }
150. //delay to receive data - must be shorter th
an sending delay to ensure data is not lost
151. delay(100);
152. lap++;
153. }
154.
155. void startSequence(){ //flash red, red, red, g
reen
156. uint32_t wait = 500;
157. uint16_t i,j;
158. for (j=0;j<3;j++){
159. for (i=0;i<strip.numPixels();i++){
160. strip.setPixelColor(i,RED);
161. }
162. strip.show();
163. delay(wait);
164. for (i=0;i<strip.numPixels();i++){
165. strip.setPixelColor(i,OFF);
166. }
167. strip.show();
168. delay(wait);
169. }
170. for (i=0;i<strip.numPixels();i++){
171. strip.setPixelColor(i,GREEN);
172. }
173. strip.show();
174. timestart = millis(); // timestart occurs wh
en green starts***
175. delay(2*wait);
176. for (i=0;i<strip.numPixels();i++){
177. strip.setPixelColor(i,OFF);
178. }
179. strip.show();
180. }
181.
182. void displaySegment(uint16_t segment, uint32_t
curr, uint16_t color){
183. uint16_t startLED = 10*(segment - 1);
184. uint16_t endLED = startLED + 9;
185. uint16_t i;
186.
187. for (i=startLED;i<=endLED;i++){
188. if (color==0)
189. strip.setPixelColor(i,RED);
190. else if (color==1)
191. strip.setPixelColor(i,ORANGE);
192. else if (color==2)
193. strip.setPixelColor(i,YELLOW);
194. else if (color==3)
195. strip.setPixelColor(i,GREEN);
196. else if (color==4)
197. strip.setPixelColor(i,BLUE);
198. strip.show();
199. delay(curr/10); //amount of time for each
individual LED to be on in sequence
200. strip.setPixelColor(i,OFF);
201. strip.show();
202. }
203. }
204.
205. uint16_t updatePace(){
206. uint32_t sum;
207. for (uint16_t i=0;i<N;i++){
208. sum = 0;
209. for (uint16_t j=0;j<M;j++){
210. sum += currTimes[i][j];
211. }
212. pace[i] = sum;
213. Serial.print("Pace for user ");
214. Serial.print(i+1);
215. Serial.print(" is ");
216. Serial.print(sum);
217. Serial.print("n");
218. }
219. uint32_t best = pace[0];
220. uint16_t bestIdx = 0;
221. for (uint16_t i=0;i<N;i++){
222. if (pace[i] < best){
223. best = pace[i];
224. bestIdx = i;
225. }
226. }
227. Serial.print("Best user is user ");
228. Serial.print(bestIdx+1);
229. Serial.print("n");
230. return bestIdx;
231. }