Hi There,
I'm working on making advancements to the existing Galvanic Skin Response (GSR) projects currently available. For those who are not familiar, GSR is a method of measuring electrical conductance of the skin, which varies based on the amount of moisture in or on the skin. You might be asking, “What in the devil does sweat have to do with skin conductance and why do we care?”
The sympathetic nervous system affects the sweat glands so psychological or physiological arousal can be measured by skin conductance. This process has been termed the Electordermal Response. People may build GSR circuits for a variety of reasons, some to help control stress, some to detect lies, nonetheless GSR is a very powerful tool and in my opinion way understood and underused by the Arduino Community.
Most designs that I have come across have been based on Wang’s design which has some really cool processing but appears to be fundamentally flawed in the circuit design and methodology. Sorry Wang, no offense, just trying to make it better for everyone!
http://cwwang.com/2008/04/13/gsr-reader/
From the research I have been doing, it appears that a GSR circuits are susceptible to a few shortcomings.
Please, please, please, research, review, comment, and correct me!
-
Noise in the analog input.
a. Take a look at Wang’s video on his website. The graph pulses regularly, looking more like a heartbeat. A clean GSR signal should be relatively linear.
b. This is usual combated with a low or/and high pass filter. Some have been successful using a passive software filter. -
Polarizing of the sensors
a. This happens with the use of Direct Current (D.C.) voltages for measurement and dramatically affects accuracy.
b. Can be combated with using special electrodes and special paste for electrodes or by using Alternating Currents (A.C.). I believe using Pulse Width
Modulation will achieve the same result on Arduino???
A recent message from a contributing member was helpful but still leaves ???'s... how?!
[You need to implement a h-bridge, the sort you use for driving motors. Then applying a PWM signal to it will give you an AC signal.
Alternitavly you can have two outputs and alternate them high and low.]
- Use of non-linear voltage
a. Many existing designs use Arduino’s 5+ volt output directly onto the finger for measurement. This will result in inaccurate measurements. Consider the relationship of skin conductance and voltage output. The values of human skin conductance are supposedly linear only at below 0.5v.
Using this as a guide (if you know of something better, please post!):
http://courses.cit.cornell.edu/ee476/FinalProjects/s2006/hmm32_pjw32/index.html#SHDesign
The Circuit
The circuit should integrate a voltage divider to bring Arduino 5v to 0.5v. A 0.1uF capacitor works well as low pass filter but can we achieve the same affect in software? What should be done on Hardware side for high pass filter, if anything?
The Code
The basics.
int sensorPin = A0; //analog pin to connect sensor pad
void setup (){
pinMode(sensorPin, INPUT);
Serial.begin(9600); //open serial port connection to computer
}
void loop() {
int raw = analogRead(sensorPin); //reads value of sensor pin (value between 0 and 1023)
Serial.println(raw);
delay(250);
}
Next Steps
- A passive low pass filter 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
- Convert to uS (microsiemens)
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
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 )
Use gaussian smoothing filter to smooth the skin conductance values. Is there a better filter to use? To increase speed of execution, implement the filter in fixed point notation.
• [.006 .061 .242 .383 .242 .061 .006]
• sums -> 1
• [2 16 61 97 61 16 2]
• sums -> 256
Can anyone please give some guidance how to implement these concepts on Arduino? Input much appreciated.
More Research
-On Electrodermal Response: 27. The Electrodermal Response
-On AC vs DC and polarization: http://www.jstor.org/discover/10.2307/1418531?uid=3739808&uid=2129&uid=2&uid=70&uid=4&uid=3739256&sid=55879571203