Tuesday, May 26, 2015

Lab 7.1 - Realtime Visualisation of Data - GSR and lie detectors

In the last lab we used a Python program that receives data from an XBee to visualize heart beats in close-to-real time. It was close to real time due to several factors:

  • big sampling rate of the pulse sensor
  • processing, queuing, transmission and propagation delay due to using 2 XBees
  • inefficient Python code that drew the graph containing all the values ever received
This time, we decided to focus on solving some of these issues in order to achieve a more accurate visualizing application.


The idea
By using 2 XBees, an Arduino and a Galvanic Skin Response Sensor, we are able to monitor the conductance of an individual's skin and send it wirelessly to a computer that plots the data in real time with the use of Python. Indirectly, this shows the stress the individual currently faces and could serve as a helping tool in finding if someone is lying.
By adding a buzzer we can get audio feedback when a threshold is reached.

How to do it? 
The GSR sensor measures electrodermal activity and it works by sensing the conductance of one's skin and sending analog values to its controller when this happens. The GSR sensor is connected to an Arduino, and the Arduino sends an encapsulated message containing the sensor reading to a connected XBee. The Arduino is also connected to a buzzer that beeps whenever a threshold crossed.

We decreased the sampling rate to 100 samples/second (in Arduino, delay(100) after sampling) as there is no need for a very high sampling rate. This solves one of the latency issues.

On the other wireless side, an XBee is connected to the computer and a Python application listens for new serial data. As soon as it receives a new message, it decapsulates it and adds the values to an array. It also calculates the time it received it at and adds that to another array. It then removes the first elements of the arrays so that the arrays always have a fixed number of elements. This helps decrease the latency of the application. It then plots them, displaying the graph in real time.

At the same time, because the data is not always received correctly and in the right order, possible errors must be checked for in the Python application.

Image of real time data





Video


https://www.youtube.com/watch?v=6YvWhxkTbZU&feature=youtu.be


Schematics

                                    

Materials used

  • 1 Arduino Uno
  • 2 XBees Explorer
  • 2 XBee
  • 1 Breadboards
  • 1 Galvanic Skin Response sensor (we used http://www.seeedstudio.com/depot/Grove-GSR-p-1614.html )

Software needed

  • XCTU - here
  • Python - here.
  • XBee library for Python here.
  • Pyserial library for Python - here.
  • XBee library for Arduino - here.
  • Matplotlib library for Python - here

Steps

  1. Set one XBee to Coordinator AT mode
    1. In XCTU - Set PAN ID to BBBB
    2. Connect this Xbee to Computer
  2. Set one XBee to Router AT mode
    1. In XTCU - Set PAN ID to BBBB
    2. Connect this Xbee to Arduino (Rx to Tx and Tx to Rx)
  3. Connect GSR to Arduino as shown in schematics
  4. Connect Buzzer to Arduino
  5. Upload Arduino code on Arduino
  6. Run Python code on computer

Code:


Arduino:
const int BUZZER = 3;
const int GSR = A2;
int threshold = 0;
int sensorValue;
long counter = 0;
void setup() {
  long sum = 0;
  Serial.begin(9600);
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, LOW);
  delay(1000);

  for (int i = 0; i < 500; i++)
  {
    sensorValue = analogRead(GSR);
    sum += sensorValue;
    delay(5);
  }
  threshold = sum / 500;
  Serial.print("threshold =");
  Serial.println(threshold);
}

void loop() {
  int temp;
  sensorValue = analogRead(GSR);
  //Serial.print("sensorValue=");
  Serial.println(sensorValue);
  temp = threshold - sensorValue;
  if (abs(temp) > 50)
  {
    sensorValue = analogRead(GSR);
    temp = threshold - sensorValue;
    if (abs(temp) > 50) {
      tone(BUZZER, 300);
      //Serial.println("YES!");
    }
  }
  else noTone(BUZZER);
  delay(50);
  //Serial.print(counter);

}

Python

import time
import serial
import numpy as np
from matplotlib import pyplot as plt


ser = serial.Serial('COM20', 9600) #on linux it's a different port, do LSUSB to find the various usbports used
#example on linux: ser = serial.Serial('dev/tty.usbserial', 9600)
y = [0] * 200 # values you can mess with depending on your sampling rate
x = [0] * 200 # it only shows the maximum number of values you can see on your plot
# make the plot
line, = plt.plot(y)
plt.xlabel("Time in miliseconds")
plt.ylabel("Value of sensor data")
plt.ylim([0,1000]) #limit the y axis, change this if your values are higher than 1000

# start data collection
while True:  
    data = ser.readline() # read data from serial port
    print "Time:" , time.clock()
    data=data.split()[0]
    print "Data received is", data
    ####Check if received Y is a correct value
    if (type(data) is not str and (data < 1023 and data > 0)):
        y.append(data)
        x.append(time.clock() * 1000)
        del y[0] #delete first element
        del x[0] #delete first element
        line.set_xdata(x)
        line.set_ydata(y)
        plt.xlim([int(x[len(x) - 1]) - 10000, int(x[len(x) - 1])])  # make x and y axis stable
        plt.draw()
        plt.pause(0.00001)

    else:
        if data.isdigit():
            y.append(int(data))
            x.append(time.clock() * 1000)
            del y[0]
            del x[0]
            line.set_xdata(x)
            line.set_ydata(y)
            plt.xlim([int(x[len(x) - 1]) - 10000, int(x[len(x) - 1])])  # make x and y axis stable
            plt.draw()
            plt.pause(0.00001)
            

No comments:

Post a Comment