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;
}