TAD2011.01 Emotiv EPOC Data Logger

My first TAD project is a Processing sketch to log data from the Emotiv EPOC via OSC messages, to a tab-delimited text file.

import oscP5.*;

// declare objects
OscP5 oscP5;
PrintWriter output;
Format formatter;

void setup() {
  // listen for OSC messages on port 7400
  oscP5 = new OscP5(this, 7400);
  
  // create a file to log data to
  output = createWriter("epoc_log.txt");
  
  // format timestamp for the log entries
  formatter = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss.SSS");
}

void draw() {
  // this sketch does not draw anything specific
}

// receive, parse, and write OSC data to the log file
void oscEvent(OscMessage theOscMessage) {
  Date date = new Date(); // get the current timestamp
  String dateTime = formatter.format(date); // format the timestamp
  String event = theOscMessage.addrPattern(); // get the message's address pattern
  float value = theOscMessage.get(0).floatValue(); // get the message's value
  output.println(dateTime+"\t"+event+"\t"+value); // write it all to the log file
}

// press any key to save the data
void keyPressed() {
  output.flush(); // write the remaining data
  output.close(); // finish the file
  exit(); // stop the program
}

This variation inserts the date into the file name, and only the time (instead of the date and time) into the log file.

/**
 * EPOC Logger 2
 * by Joshua Madara, hyperRitual.com
 * This sketch logs data from the Emotiv EPOC via
 * OSC messages, to a tab-delimited text file.
 */

import oscP5.*;

// declare objects
OscP5 oscP5;
PrintWriter output;
Format dateForm;
Format timeForm;

void setup() {
  // listen for OSC messages on port 7400
  oscP5 = new OscP5(this, 7400);
  
  // format datestamp for the file name
  dateForm = new SimpleDateFormat("yyyy_MM_dd");
  
  // format timestamp for the the log entries
  timeForm = new SimpleDateFormat("HH.mm.ss.SSS");
  
  // create a file to log data to
  Date date = new Date(); // get the current date
  String dateS = dateForm.format(date); // format the date
  output = createWriter("epoc_log_"+dateS+".txt"); // include the date in the file name
}

void draw() {
  // this sketch does not draw anything specific
}

// receive, parse, and write OSC data to the log file
void oscEvent(OscMessage theOscMessage) {
  Date time = new Date(); // get the current time
  String timeS = timeForm.format(time); // format the time
  String event = theOscMessage.addrPattern(); // get the message's address pattern
  float value = theOscMessage.get(0).floatValue(); // get the message's value
  output.println(timeS+"\t"+event+"\t"+value); // write it all to the log file
}

// press any key to save the data
void keyPressed() {
  output.flush(); // write the remaining data
  output.close(); // finish the file
  exit(); // stop the program
}

Evocation and Invocation with EPOC

Related articles: FBLR Mind-Controlled Robot | Ideas for Experimenting with EPOC + Meta-Magick

Here are synopses for two exhibitions I am developing, that experiment with the Emotiv EPOC‘s ability to recognize state transitions corresponding to occult activity.

Evocation

A human actor evokes (i.e. draws out) an entity and projects it into a defined space such as the Triangle of Art in Solomonic evocation (see below). The actor wears an EPOC headset that, having been previously trained, recognizes her intention to project the entity, and signals the activation of a robot occupying the same space. The overall effect is of having magically evoked the spirit into the robot body. (I am not presently concerned with the robot’s subsequent behavior, but will elsewhere address magical behavior in robots, perhaps as addendum to this project.)

Triangle of Art
(thanks to Osiris for the image)

Invocation

This project was inspired by a scene from Ghostbusters: Louis Tully (played by Rick Moranis) has been possessed by Vinz Clortho, arrested by the New York City police, and delivered into the hands of Egon Spengler (played by Harold Ramis) who connects Louis-Vinz to an EEG-looking device capable of showing the demon within him on a sort of spectral (pun intended) analysis monitor. The project plays with the idea that who we are on the “inside” — our so-called spirit or soul — may appear differently to an observer than our “outside”/physical appearance to the same or other observers.

Vinz Clortho

A human actor wearing an EPOC headset is observed by a video camera that transmits a moving image of her profile to a viewing screen. She invokes (i.e. draws in) an entity, and her invocation is detected by the EPOC which alters the signal between the video camera and monitor, in a manner corresponding to the nature of the entity invoked. Alternatively, a still image of the actor’s face is projected and then switched to or morphed into the face of the entity during the invocation.

EPOC-to-Arduino “Goodbye, World”

Related articles: FBLR Mind-Controlled Robot | Processing + EPOC via OSC

This Processing sketch demonstrates a simple interface between the Emotiv EPOC and Arduino via Processing and OSC. When the operator wearing the EPOC thinks “disappear,” the LED connected to the Arduino turns off; when the operator ceases thinking “disappear,” the LED turns back on. The sketch requires the arduino and oscP5 libraries for Processing, and the Mind Your OSCs application for EPOC.

(There exists one OSC library for Arduino, that I know of, that has been reportedly updated for build 0021, but I have not used it. I typically use Processing in conjunction with Arduino, for developing graphical interfaces such as the one shown here.)

Here is the Processing code:

/**
 * EPOC-to-Arduino "Goodbye, World"
 * by Joshua Madara, hyperRitual.com
 * 
 * This sketch demonstrates a simple interface between
 * Emotiv EPOC and Arduino via Processing and OSC. When the
 * operator wearing the EPOC thinks "disappear," 
 * the LED connected to the Arduino turns off;
 * when the operator ceases thinking "disappear,"
 * the LED turns back on.
 * 
 * The sketch requires the arduino and oscP5 libraries
 * for Processing, and the Mind Your OSCs application for EPOC.
 */

// import libraries needed for Arduino and OSC
import processing.serial.*;
import cc.arduino.*;
import oscP5.*;

Arduino arduino; // declare object
OscP5 oscP5; // declare object

float disappear = 0; // holds the value incoming from EPOC
int LED = 13; // LED connected to Arduino pin 13

void setup() {
  println(Arduino.list()); // look for available Arduino boards
  // start Arduino communication at 57,600 baud
  arduino = new Arduino(this, Arduino.list()[1], 57600);
  
  // set LED as output pin
  arduino.pinMode(LED, arduino.OUTPUT);
  
  // start oscP5, listening for incoming messages on port 7400
  // make sure this matches the port in Mind Your OSCs
  oscP5 = new OscP5(this, 7400);
  
  /* plug automatically forwards OSC messages having
  address pattern /COG/DISAPPEAR to getDisappear()
  which updates the disappear variable with the value
  of the OSC message */
  oscP5.plug(this,"getDisappear","/COG/DISAPPEAR");
}

void draw() {
  /* the following block evaluates disappear and if it is 
  greater than or equal to .5, turns LED off, otherwise it 
  turns/keeps LED on */
  if(disappear >= 0.5) {
    arduino.digitalWrite(LED, arduino.LOW);
  } else {
    arduino.digitalWrite(LED, arduino.HIGH);
  }
}

/* the following function updates disappear with the value
of any incoming OSC messages for /COG/DISAPPEAR/, plugged
in setup() */
void getDisappear (float theValue) {
  disappear = theValue;
  println("OSC message received; new disappear value: "+disappear);
}

Arduino LED setup

FBLR Mind-Controlled Robot

Related articles: Processing + EPOC via OSC | EPOC-to-Arduino “Goodbye, World” | Arduino + fischertechnik | BYTR Virtual Servitor

FBLR (“Fibbler”) is a robot that moves forward and backward, and turns left and right, in response to its operator’s thoughts. The signal flow is brain → Emotiv EPOCMind Your OSCsProcessingArduinofischertechnik robot. I wrote a Processing sketch (zipped with data files) that converts the EPOC signals via OSC messages, to Arduino signals that move the robot. The sketch uses the arduino, controlP5, and oscP5 libraries. The Arduino uses Firmata (standard with the Arduino software) and a motor shield from Rugged Circuits (see this article for more info).

FBLR Processing Interface

There are four knobs for adjusting the actuator thresholds. The EPOC’s Cognitiv values are compared to said thresholds to determine whether to enable the robot’s motors and which directions to turn them in:

Cognitiv Action Motor 1 Direction Motor 2 Direction
PUSH 0 0
PULL 1 1
LEFT 1 0
RIGHT 0 1

Setting a knob to 0 (all the way to the left) will enable its associated motors regardless of the Cognitiv value. Four bars display the levels of the incoming Cognitiv values; if a value is greater than or equal to its threshold, the bar displays green, otherwise it displays red.

The slider can be used to change the delay from 0 to 200 milliseconds. The shorter the delay, the more frequently OSC messages are evaluated, but the robot may also “stutter” for trying to retrieve messages faster than they are delivered. There are a variety of ways to handle this; I chose one that was simple and effective but not the most elegant. I found that 100ms makes for smooth operation most of the time. Note also that push, pull, left, and right are evaluated in that order by the draw() loop, so if, e.g., push and left both exceed their threshold values, only moveForward() will fire.

Here is an EmoScript for EmoComposer, to test the interaction without needing the headset. See the Emotiv EPOC SDK guide for more about that.

Occult Applications

Mankind’s oldest fantasy is to move something with the power of thought. // Tan Le, co-founder of Emotiv

Any use of the EPOC seems to be magical in a folk sense, but I am interested in new-media interactions that respond to explicitly magical intentions or commands (e.g. sigil concentration), ecstatic or gnostic states of consciousness, state entity projections, etc. I expect the EPOC to feature in some of the robomancy projects I will be developing in the near future.

FBLR mind-Controlled Robot

AffectCircles

This Processing sketch demonstrates interaction with the Emotiv EPOC‘s Affectiv™ data. The five circles grow or shrink and brighten or dim according to the values (between 0 and 1) of “Engaged/Bored,” “Excitement,” Excitement Long Term,” “Meditation,” and “Frustration.” Below is a video showing the circles changing over time (sped up 3×). See the article, “Processing + EPOC via OSC,” for more general information about interfacing the EPOC and Processing.

Here is an EmoScript for EmoComposer, to test the interaction without needing the headset. See the Emotiv EPOC SDK guide for more about that.

Here is the code (looking at it a year later, it could stand to be refactored):

/**
 * AffectCircles
 * by Joshua Madara, hyperRitual.com
 * demonstrates Processing + Emotiv EPOC via OSC
 * five circles grow and shrink in response to five
 * Affectiv values from EPOC: engagement/boredom; excitement; 
 * long-term excitement; meditation; frustration.
 */
 
import oscP5.*;
import netP5.*;

public float engBor = 0; // Engaged/Bored
public float exc = 0; // Excitement
public float excLon = 0; // Excitement Long Term
public float med = 0; // Meditation
public float fru = 0; // Frustration

OscP5 oscP5;

void setup() {
  size(480, 360);
  frameRate(30);
  smooth();
  
  /* start oscP5, listening for incoming messages on port 7400
  make sure this matches the port in Mind Your OSCs */
  oscP5 = new OscP5(this, 7400);
  
  // plug the OSC messages for the Affectiv values
  oscP5.plug(this,"updateEngBor","/AFF/Engaged/Bored");
  oscP5.plug(this,"updateExc","/AFF/Excitement");
  oscP5.plug(this,"updateExcLon","/AFF/Excitement Long Term");
  oscP5.plug(this,"updateMed","/AFF/Meditation");
  oscP5.plug(this,"updateFru","/AFF/Frustration");
}

void draw() {
  // draw fading background
  fill(0, 10);
  rectMode(CORNER);
  rect(0, 0, width, height);
  
  // draw circles
  drawCircle(engBor, 1); // circle 1: Engaged/Bored
  drawCircle(exc, 2); // circle 2: Excitement
  drawCircle(excLon, 3); // circle 3: Excitement Long Term
  drawCircle(med, 4); // circle 4: Meditation
  drawCircle(fru, 5); // circle 5: Frustration
}

void drawCircle(float affVal, int circleNo) {
  noFill();
  strokeWeight(3);
  ellipseMode(CENTER);
  stroke(color(round(map(affVal, 0, 1, 0, 255))), 10);
  float diam = map(affVal, 0, 1, 1, width/5);
  ellipse((width/6)*circleNo, height/2, diam, diam);
}

public void updateEngBor(float theValue) {
  engBor = theValue;
}

public void updateExc(float theValue) {
  exc = theValue;
}

public void updateExcLon(float theValue) {
  excLon = theValue;
}

public void updateMed(float theValue) {
  med = theValue;
}

public void updateFru(float theValue) {
  fru = theValue;
}