High Level Design
Rationale and Sources
Skin conductance is known to be correlated with an
individual's emotional state. It is often used in psychology for quantifying a person's
reaction to different stimulus. It is also often implemented in a traditional lie detectors.
The current theory is that a person under arousal generates sweat at the skin that
changes the skin's electrical properties. However, this explanation is still debatable,
as some scientists claim that the conductance changes too fast to attribute the cause
Because a change in mental state can be observed by the change in
skin conductance, the arousal level of a person can be
quantified. While one of us is interested in visualizing the meditative experiences, the other
wanted to recreate the lie detector test seen in one too many movies.
We were also intrigued by this project because of the controversial results
found in different studies such as the 'prestimulus' response,
and the characterization of psychotics using skin conductance
patterns. There was also the allure of the use of skin conductance in many
Please read hardware details
We needed to calculate three resistor values and the gain of the differential amplifier depending on the range of skin conductance values we want to measure.
Human skin conductance values are supposedly only linear when voltages applied are below 0.5V. So we used a voltage divider to bring the bridge Vdd voltage to 0.5V.
This ensures that the highest voltage across the user would never exceed 0.5V.
The relationship between skin conductance and output voltage is summed in one equation:
- C1 = cond of resistor in series with finger - placed nearer to Vdd
- C2 = cond of resistor in series with C3 - placed adj to Vdd
- C3 = cond of resistor in series with C2 - placed adj to Gnd
- G = Gain of differential amplifier
- Vo = 0.5V x (C1/(C1+S) - C2/(C2+C3)) x G
At first we met with the problem that the relationship between skin conductance S and output voltage Vo is not linear.
The following graph displays resistor values and gain chosen for a skin conductance range of (2uS - 50uS). One can see that the resolution
for skin conductance is ridiculously good below 5uS but suffers as the skin conductance climbs.
Eventually, we came to realize that we can linearize the
curve by choosing C1 as large as possible. We ended up revising the skin conductance range to (2uS - 25uS) and a C1 value of 500uS (2kOhms). C2, C3, G are all calculated
based on the skin conductance range constraint. This gave us a consistent skin conductance resolution over all voltages.
The matlab script for generating these solutions can be found in the appendix
A passive low pass filter was created to filter the output with cutoff frequency of 0.5 Hz.
- R = 3.3 M
- C = 0.1 u
- f = 1/(pi 2 R C) = .48 Hz
To convert 10-bit ADC value to a high resolution voltage. ADCW contains the 10-bit value
at the most significant end.
- 5V / 1024b = .004V / b
- Therefore, voltage must be measured in centi-volts.
- Ai = ADCW
- Vo = Ain x 500cV / 1024b x 2
- Vo = Ain x 125cV / 128b
To convert Vo to skin conductance value in uS. Skin conductance value will be stored as hundreds
of microsiemens. The reason that the skin conductance values are stored to values beyond their absolute accuracy (.046uS) is because in software we will run a gaussian smoothing filter to interpolate the data.
- (25uS - 2uS) x 100 / 500cV = 4.6 cuS / cV
- S = 2500 cuS - ( 4.6 cus/cV x Vo )
We used a gaussian smoothing filter to smooth the skin conductance values. To increase speed of execution, we implemented the filter in fixed point notation.
- [.006 .061 .242 .383 .242 .061 .006]
- sums -> 1
- [2 16 61 97 61 16 2]
- sums -> 256
Our GSR design is based around the Mega32 microcontroller. Skin
conductance readings are taken from a test subject and are
amplified and filtered using our hardware design seen in the
hardware section of the lab. We send the signal to the Mega32 through PortA0, the
input to the ADC. We programmed the Mega32 for 10-bit ADC to increase the resolution of the data.
The pushbuttons allows the user to select and interact with different softwares: detect events, waveform
capture, stimulus comparison, and a biofeedback game. The data collected
under the different modes are processed and output to the LCD. We
also have a serial connection that can be connected to a
computer. A java program reads from the serial port using a freeware communications package. It then collects the
skin conductance values and outputs to a graph generated by a freeware charting package.
Because our hardware is not as technically rigorous as some other
projects, we spent much time to enhance the software elements. By adding many
interesting features to the software, we feel that we compensated
for the lack of difficulty in our hardware with the blood and sweat we put into hours of debugging.
Relationship of design to existing standards
Since this device is connected to a human, we had to comply to
the class safety standard that there should never be a connection
from the human to the 120 V power grid. Furthermore, we made sure
that the electrode placement would never be on opposite sides of
the body given that even small currents can cause fibrillation in
Existing patents, copyrights, and trademarks
There should be no patent, copyright or trademark infringement
issues in our project as all work is our own and we did not
modify preexisting design. Sources of inspiration and help are
listed in the references section.
Skin conductance circuit
A wheatstone bridge is implemented to measure skin conductance.
The voltage across the bridge can be used to extrapolate the skin conductance.
We feed the voltage at both ends of the bridge to a voltage follower and then
into a differential amplifier. The output of the differential amplifier is fed into a
low pass filter of cutoff frequency 0.5Hz, and then into PortA0, where ADC takes place.
We built the hardware during one lab period. It would undercome many revisions down the road, but at the time, we
were uncertain of whether the hardware was working at all. It was then that we realized that simply acquiring
the skin conductance value is not enough; we needed to graph the skin conductance over a range of time. Without visualization,
we will never be certain of the data. A week later, we had coded out a java program to collect and display the data.
But even then we were still not sure what we were looking at. Two amazing things happened to us. First we decided to scratch
the aluminum electrodes we had been working on. Second, we found a video on the internet that is guaranteed to scare whoever
watches it. The graph worked wonderfully. The increase in skin conductance caused by the video
also gave us new confidence in the data we were collecting. Below are two examples to establish the genuine nature of the data we were collecting.
Left shows a graph of 5 minutes of activity. Another 5 minutes devoted to meditation shows a radically cleaner graph, free from waveforms.
We fabricated our own electrodes using o-rings and wire from lab.
Although not ideal, we found that our design gave superb readings
for our purposes. We have 2 electrodes that are placed at the
distal phalanges of the index and middle finger. The electrodes
are then connected to the ends of the wheatstone bridge.
The LCD is connected to the Mega32 through the PortC pins as was
done in Lab 1. The pin connections are shown in Lab 1 which can
be reached through the reference section. The LCD is the
interface between the user and the various skin conductance
programs within the MCU.
The pushbuttons are connected to PortA of the Mega32. They allow
the user to control the different settings of our design. If
pressed, the pushbutton is shorted to a ground connection and an
output low signal is seen by the Mega32.
We used the Mega32 for analog-digital conversion, reading inputs
from pushbuttons, and outputting to the LCD.
We powered our design using a 9V battery that was regulated down
to 5V for the purposed of the Mega32. We did not use power from a
wall socket, as any path connecting a human being to the power
grid was an unacceptable safety hazard for this lab.
We had considered cramming as many skin conductance values into SRAM as we possible can, and then display it graphically on the portable black and white TV.
However, when a Java serials communication and charting package got into our hands, we realized we could take the alternative approach of simply sending all data to the pc for processing and display.
This gave us the opportunity to focus on more rewarding software implementations.
The difficulty in doing the software is the inability to visualize the skin conductance values in real time.
If building a robot, and the robot stops moving, it is obvious a bug exists in the program. When measuring skin conductance, we were never
really certain if the data we collected was correct unless it was radically off mark. Debugging became a nightmare, as the skin conductance
charts became our only window for looking into our mistakes.
Event detection (Java)
We built our event detection algorithm into Java first before implementing it in C.
There are four steps in event detection. All conductance values have already been collected and UART transmission has halted.
- Gaussian smooth conductance values
- Forward difference of smoothed conductance
- Gaussian smooth slope values
- Detect events
Gaussian smoothing is achieved by convoluting the conductance values with an array of seven values
Forward difference is simply taking the difference between consecutive points. The smoothing is necessary because while the data has been hardware low pass filtered, there are still many artifacts. It also
acts to break up the discretized data due to the insufficient skin conductance resolution. Smoothing the forward difference acts
to prevent glitches where two consecutive discretized skin conductance values register a zero slope. Finally, a detection algorithm
finds the number of times the slope breaks a set threshold level. We ended up classifying each wave by the maximum slope it achieves during its ascent. We hypothesized that the faster waves indicate
a more intense emotional response. From this assumption, we classified each event into five categories (excited, aroused, alerted, normal, relaxed).
Event detection (C)
After the java event detection algorithm was complete, we proceeded to translate the algorithm onto the MCU. We realized we could not collect
data in the MCU without overflowing the SRAM. Data collection is conducted at a rate of 8Hz. Even 5 minutes would translate to 2400 8-bit ints, more than
what the Mega32 chip can handle. So we decided we would process and collect all events within 15 seconds of data.The plan worked beautifully, and we capped the time at 30 minutes only because we were afraid the number of events might exceed what can be displayed by the LCD!
In actuality, we can run the event detection algorithm indefinitely. However, we then compared the events collected by java with the events collected by the MCU;
they were different.
This was a big mystery, as we implemented the exact same code into the MCU as we did Java. After some nights of headache, we came to realize the problem.
We took data every fifteen seconds, smoothed it, forward differenced it, then smoothed the forward difference, where it is then fed into the event detection algorithm.
It turns out that for every gaussian smoothing, we were ignoring the first and last three points! Almost a second of data is not being smoothed every 15 seconds, and it turned out to make
a huge difference. So for every 15 seconds round of collection, we had to save the last six data points and carry it to the next round so that all points are convoluted over the
entire duration of event detection. This solved the problem, and the java and MCU yielded the same results.
When measuring skin conductance, there is the skin conductance level (SCL) and skin conductance response (SCR). SCL
is the slow varying skin conductance value, changing over the course of minutes. SCR is the fast varying skin conductance value,
changing over the course of seconds. The SCR that rides on top of the SCL reflects a person's mental response to various stimulus.
SCR has several statistics that are useful for psychologists. First is latency, which is the amount of time between the stimulus and
the rise of the wave. Next is the rise time, how long it takes for the skin conductance to shoot up to it's peak. Amplitude is the height of the SCR.
Half recovery time is the amount of time it takes for the wave to fall back to half it's amplitude.
We decide it would be useful if we were able to capture these four statistics whenever a wave is detectable. However, this
would require that the program read and analyze the data in real-time! So we decided we would store 7 data points of skin conductance values, enough
to gaussian smooth just one point. We would then save two of the smoothed conductance points, enough so we can forward difference them. We would then
store 7 data points of the forward difference, enough so we can gaussian smooth that. Finally, we store 2 data points of the smoothed slope points to drive the state machine.
The operations of the state machine is listed below.
- Initializing: wait for slope to stay below threshold for 1 sec
- Waiting for wave: wait for slope to break threshold value
- Analyzing wave:
- If slope is increasing, keep recording maximum slope value.
- If slope starts decreasing, check to make certain slope does not start increasing again.
- If slope increases, -> Wave Deformed state
- if slope decreases, keep current state
- If slope is equal or less than zero, we have reached peak of wave
- record amplitude
- record rise time
- record maximum slope
- Wait for wave to fall to half of amplitude.
- if conductance value starts increasing before falling back to half amp -> Wave Deformed
- if conductance value steadily decreases, keep current state
- if conductance value at half amp, record half recovery time -> Wave Complete
- Wave Completed: message shows for 1 sec before -> Waiting for Wave
- Wave Deformed: message shows for 1 sec before -> Initializing
At first we encountered huge problems. Whenever we tried to verify the statistics we obtained, it turned out to be wildly different
than what we observed on the Java graphs. Waves were not being captured and statistics were fishy. After much confusion, we realized the problem.
It turns out that the smoothed slope value we fed into the state machine actual corresponds to data taken 8 points before! In other words,
the state machine is being driven by data 1 second in the past! Therefore, what we see on the state machine is not actually real-time, but
1 second into the past. We quickly adjusted our software for this error, and the waveform capture now works like a charm.
To capture latency, we allow the user to press a button to indicate a stimulus during the Waiting for wave
state. It would then record
the time between the press of the button and the start of the rising of the wave. A second is subtracted off to keep consistent with the fact
that the state machine is a second behind reality. If latency is ever less than zero or greater than eight seconds, the program will indicate
to the user of the possible incorrect nature of the wave. The purpose of measuring latency is to see the reaction of a person to a stimulus.
If the person had not reacted to the stimulus in the appropriate amount of time (1-4 sec), then it can be assumed that the wave probably does not
reflect the stimulus.
At first we attempted to write a lie detection program. However, after extensive testing, we realized that we could not generate an algorithm to
determine decption without resorting to a lot of standardized procedures, much of which cannot be handled by software. So we decided that we would
create a handy software where the interrogator, or any psychologist, can record statistics of different stimulus. The program will then compare the
stimulus with each other so that the psychologist can measure the differences in statistical results among events.
As the wave capture is already working, the stimulus comparison was quite easy to implement. When the program is activated,
we turn on the real-time waveform analyzer. We then added some modifications so that the user can store up to 20 different events.
The main statistical variables in the spotlight are latency, amplitude, and half recovery time. Latency is thought to reflect
the amount of attention placed on the stimulus by the individual. Amplitude reflects the strength of the reaction of the user to the stimulus.
Half recovery time reflects how fast the individual recovers from the stimulus. All three holds
potential information for deception detection.
The program stores the statistics into an array, where it then finds the maximum value of each variable. A percentage is then given
for the statistics of each stimulus in respect to that maximum. Therefore, the relative
strengths of the stimulus is accessible and intuitive.
We ran into little trouble programming the biofeedback game. The game simply toggles between two different states depending on the user's
skin conductance. If the user is calm, indicated by an extended period of lack of SCRs, the game slows down, and the race track has less obstacles.
However, if the user is agitated, indicated by SCRs with sufficient slope at rise time, the game speeds up, and the race track has more obstacles.
If the person relaxes more, the likelihood of getting a higher score increases. This feedback ensures that the person is working toward a
more tranquil state of mind.
Things tried which did not work
While testing our design, we implemented several different
electrode designs to find the one that would give us the cleanest
signal. We found that several things did not work. First, a
simple wire pressed against the skin was flimsy and provided too
small a surface contact. Then, per the suggestion of a website,
we built electrodes out of aluminum and velcro wrapped around the
fingers. This design caused the skin to perspire independent of
emotional stimulation. We finally settled on o-ring connectors
which provided good surface contact and some amazing
A semi-goal that we entertained ourselves with, but which we did not
ultimately implement, was the lie detector. Although we were able to accurately show emotional response to
stimulus from questions and visuals, we had trouble coming up
with an algorithm to detect lies from the data collected.
One problem may be that we simulated the lie detection in a very
informal atmosphere. When we lied about trivial facts, we did not
fear the other knowing the deception, and the response detected
was low and often insignificant. Yet when we decided to change
the topic to more sensitive questions, the meter detected a
response everytime regardless of truth and lies. We then noticed
that we get the best results when we ask questions that the user
does not expect. Yet, to simulate this proved to be both
embarrassing and difficult, as the user does not have time to
prepare for a lie. And we both preferred to know what we were
going to be asked before the question arose.
Thus, we revised our software so it compares the emotional
responses among many stimulus. From the continual experimentation we
learned a lot about each other that we did and did not wanted to