Introduction: Stress Makes Art: Galvanic Skin Response and Visual Generation

I'm a graphic design student and built this project for a beginning electronics class. I'm interested in connecting the signals generated by one's body to the act of visual generation. This piece takes the galvanic skin response value of the user and uses it to fuel the creation of a visual on screen. Galvanic skin response is thought to be correlated to a person's stress level and is used in lie detectors. In this particular work, the GSR value affects the speed at which a black growth is visualized on screen. This represents the idea that the more stressed we are, the faster diseases and other negative consequences can spread.


The hardware part of this project is fairly straightforward and uses an Arduino Uno board and the following other materials:
- Arduino Uno w/usb connector
--Breadboard
- 2 250K resistors, in a series
- Jumper wires
- Stranded wires
- 2 ring terminals (or other metal objects to place fingers on)
- Solder + soldering iron 

The more complicated part of this project was coding in the Processing environment. These instructions will be in two main steps, "Hardware" and "Code" with a brief mention in step three of the construction of the enclosure for the electronics.

Step 1: Hardware

To make the sensors, I soldered the two ring terminals to jumper wires (you can also use stranded wires) and connected the wires to the breadboard as noted in the photograph and schematic. One wire is connected to 5V and the second wire is connected to GND through two 250K resistors in a series. This second sensor's wire is also connected to the A0 terminal on the Arduino. These connections to the Arduino are all made via the breadboard.

Step 2: Code

For the coding part of this project, I referred to the two sources below. You don't need to look at these sources unless you want to understand them in their original form. If you just want to copy/paste code that works, skip to 3) My Code.

1) GSR Source Code
The first was http://cwwang.com/2008/04/13/gsr-reader/ which includes the Arduino code (for Arduino and Processing to communicate) and the Processing code to use the galvanic skin response data from the constructed sensors. Wang's code basically charts a person's galvanic skin response value in a moving line graph, which looks a little like an EKG reading visually. I wanted to have a more abstract visualization of the data so used code from another source to generate the visuals. 

2) Visual Source Code
The code to create the visuals is from: http://www.generative-gestaltung.de/P_2_2_1_01

3) My Code


A) ARDUINO CODE BELOW

void setup(){
  Serial.begin(9600);
}

void loop(){
  int a=analogRead(0);
  if (Serial.available() > 0)
  {

    byte inbyte=Serial.read();
    if(inbyte=='a')
    {
      Serial.write(a);


    }
  }
}

---------------------------------------------
B) PROCESSING CODE BELOW

// you can copy/paste this code into a new Processing sketch
// Visual source code from: http://www.generative-gestaltung.de/P_2_2_1_01
// GSR source code from: http://cwwang.com/2008/04/13/gsr-reader/

import processing.pdf.*;
import java.util.Calendar;

boolean recordPDF = false;

import processing.serial.*;
Serial myPort; 


int hPosition = 1;    
float currentReading;
float lastReading;
int count=0;
int zeroLinePos=0;

float gsrAverage,prevGsrAverage;
float baseLine=0;
long lastFlatLine=0;
int baselineTimer=10000;//10 sec
int gsrValue;
int gsrZeroCount=0;
float gsrRange=0;
int downhillCount=0;
int uphillCount=0;
boolean downhill;
boolean peaked=false;
float peak, valley;
int speed ;
int NORTH = 0;
int NORTHEAST = 1;
int EAST = 2;
int SOUTHEAST = 3;
int SOUTH = 4;
int SOUTHWEST = 5;
int WEST = 6;
int NORTHWEST= 7;

float stepSize = 1;
float diameter = 1;

int direction;
float posX, posY;
int minCurrentReading = 1000;
int maxCurrentReading = 0;

void setup() {
  size(800, 800);//size of window for image
  background(255);
  smooth();
  noStroke();
  posX = width/2;
  posY = height/2;
  println(Serial.list());
  currentReading=0;
  lastReading=0;
  gsrAverage=0;

//find the right serial port for your computer and enter in the number inside []
  myPort = new Serial(this, Serial.list()[8], 9600);
}

void serialEvent (Serial myPort) {
  int inByte=myPort.read();
  //0-255
  gsrValue=inByte;//taking value sent from Arduino
}


void draw() {
 
  calculateGSR();
 
  println("currentReading = " + currentReading);
 
  // map currentReading to speed
  if (currentReading <= 50)
  {
    currentReading = minCurrentReading; 
  } else  if (currentReading > 1000)
  {
    currentReading = maxCurrentReading; 
  }
  else // valid zone
  {
 
  if (currentReading< minCurrentReading)
  {
    minCurrentReading = int( currentReading);
  }
 
   if (currentReading> maxCurrentReading)
  {
    maxCurrentReading = int(currentReading);
  }}
 
println("currentReading = " +  currentReading + " minCurrentReading = " + minCurrentReading + " maxCurrentReading = " + maxCurrentReading);
   currentReading = map (currentReading, minCurrentReading,maxCurrentReading,10,15000);
   speed = int (currentReading);
  
  println("mapped value = "+  speed);
    delay(50);//delay for stability
   
//applying the GSR reading to drive the speed of that the organic drawing "grows"
  for (int i=0; i<=speed; i++) {
    direction = (int) random(0, 8);

    if (direction == NORTH) { 
      posY -= stepSize; 
    }
    else if (direction == NORTHEAST) {
      posX += stepSize;
      posY -= stepSize;
    }
    else if (direction == EAST) {
      posX += stepSize;
    }
    else if (direction == SOUTHEAST) {
      posX += stepSize;
      posY += stepSize;
    }
    else if (direction == SOUTH) {
      posY += stepSize;
    }
    else if (direction == SOUTHWEST) {
      posX -= stepSize;
      posY += stepSize;
    }
    else if (direction == WEST) {
      posX -= stepSize;
    }
    else if (direction == NORTHWEST) {
      posX -= stepSize;
      posY -= stepSize;
    }

    if (posX > width) posX = 0;
    if (posX < 0) posX = width;
    if (posY < 0) posY = height;
    if (posY > height) posY = 0;

    fill(0, 40);
    ellipse(posX+stepSize/2, posY+stepSize/2, diameter, diameter);
     //send 'a' for more bytes
  }
}


void calculateGSR () {
  //best delay setting for gsr readings
  //println(gsrValue);
  delay(50);
  //image(myMovie, 0, 0);

  if (gsrValue<15 &&gsrValue>-15){ // anything between -15 and +15 is considered zero
   //if someone lifts fingers off for 10 seconds resulting in 10 0s, just reset

    if( gsrZeroCount>10){
      currentReading=0;//flatline
      gsrAverage=0;
      baseLine=0;
      lastFlatLine=millis();
      gsrZeroCount=0;
      // println("reset");
    }
   
    gsrZeroCount++;
  } // end of test for close to zero
 
  else{ // ggood reading
    currentReading=gsrValue-baseLine;
    gsrZeroCount=0;
  }

  if(millis()-lastFlatLine>baselineTimer){
    baseLine=gsrAverage;//if we got at least 10 seconds of reading since the last flatline
  }


  gsrRange=peak-valley;



  gsrAverage=smooth(currentReading,.99,gsrAverage);

int thres=7;

  if (currentReading-thres>lastReading && peaked==true){
    downhill=false;
    //println(downhillCount);
    uphillCount++; 
    downhillCount=0;
    point(hPosition-1, height/2.0-lastReading);
    valley=lastReading;
    peaked=false;

  }
  if(currentReading+thres<lastReading && peaked==false){
    //println(uphillCount);
    downhill=true;
    uphillCount=0;
    downhillCount++;
    point(hPosition-1, height/2.0-lastReading);
    peak=lastReading;
    peaked=true;
  }

  prevGsrAverage=gsrAverage;
  lastReading=currentReading;
  //send 'a' for more bytes
  myPort.write('a');
 
}


int smooth(float data, float filterVal, float smoothedVal){
  if (filterVal > 1){      // check to make sure param's are within range
    filterVal = .99;
  }
  else if (filterVal <= 0){
    filterVal = 0;
  }
  smoothedVal = (data * (1 - filterVal)) + (smoothedVal  *  filterVal);
  return (int)smoothedVal;
}


Step 3: External Design/Enclosure (silver Box With Black Hand)

If you want to make a simple paper box enclosure for the electronics, you can look at this box template. I made the box with metallic cardboard and printed a hand mark on top so that people at the exhibition knew to place their hand on the box to start the experience. This is obviously optional and there are many ways to make sturdier enclosures.

Comments

author
Mosam+shah made it!(author)2017-04-11

PLEASE HELP ME. while compiling its shows error which states " 'import' does not name a type".

author
CelestialBeing made it!(author)2017-03-05

Does the electrode material effect the readings(sensitivity) sensor?

author
ShreyasS25 made it!(author)2016-11-06

I tried to make this without the Processing part, and code doesn't work. I have a science project due in a couple of days and I need help quick. Can you help me?

author
anglosaxon252 made it!(author)2016-04-15

It's really strange I have this page bookmarked on another computor which shows part two it now seems the code there for the gsr is no longer valid could you update this and kindly give more detales on how to convert the reading from a wiggally line to the dot pattern shown there and if possable provide some help to acheive Nigmans ability to randomly colour the dots.

author
mshebli made it!(author)2014-03-23

Is it possible to show the changing results on serial monitor for the arduino without refering back to processing ?

author
jocelynzada made it!(author)2014-03-11

The listening component is not essential. My project was set up in a loud gallery space with multiple projects surrounding it, many with audio components. I decided to try to enhance the user's experience a little by having a looping soundtrack of stressful sounds such as car horns and cell phone alarms and calming sounds like rain and classical music so that he/she could see how those sounds changed the reading.

author
saimasaima made it!(author)2014-03-10

What is the listening component of this project?

author
Akash+jaiswal made it!(author)2014-01-09

really thank you sir...its a great instructables...the problem of using "BYTE"for arduino is also solved by replacing it with "WRITE"............but since i m a novice....small question........
Q) HOW WILL PROCESSING AND ARDUINO WILL COMMUNICATE WITH EACH OTHER?????

author
dts2504 made it!(author)2014-01-07

Is it possible to do without soldering the rings on..? I understand why they're soldered on, but I'm a little limited in materials in money to get a soldering iron.

author
jocelynzada made it!(author)2014-01-08

I haven't tried it without soldering, but I would think if you have the metal have good contact somehow without soldering, it could work. You would just need to try it out.

author
kidos100 made it!(author)2013-12-31

Processing or Arduino sketch?

author
kidos100 made it!(author)2014-01-01

Never mind that, but is there a way to speed it up?

author
jocelynzada made it!(author)2014-01-08

what do you mean by speed it up? the processing of the information?

author
Akash+jaiswal made it!(author)2014-01-07

where is the arduino sketch?????

author
jocelynzada made it!(author)2014-01-08

I just added the Arduino sketch above the Processing sketch in the code section.

author
jocelynzada made it!(author)2013-12-29

Nigman - thanks for the add! C. Wheeler - sorry I don't know anything about polaroid.

author
Nigman made it!(author)2013-12-26

interesting project - users who copy your code may run into an out of bound error with this line: myPort = new Serial(this, Serial.list()[8], 9600);

changing the 8 to 0 will fix that.

I added a void on mine to adjust the colour at each serial request to make it a little more arty (and remove some of that stress being mapped :p )

stress art.png
author
wheelbme made it!(author)2013-12-29

Could you help me please? I bought a Polaroid S7 pad. (I'm sort of computer ignorant).
Anyway, I want to use it to download and read books offline. I've got a nook library, didn't like the nook. I can't open up my books with the Polaroid. Do you have any experience with these devices? Thanks

About This Instructable

31,956views

159favorites

License:

More by jocelynzada:Stress Makes Art:  Galvanic Skin Response and Visual Generation
Add instructable to: