Hackers in Residence - Hacking MindWave Mobile

Pages
Contributors: Sophi Kravitz
Favorited Favorite 8

Gathering Materials

In order to interface with the MindWave, you'll need a few bits of hardware and software.

Hardware

To interface with the MindWave, the RN-42 Bluetooth module was chosen. For this project, I created a custom PCB, however, you could also use a BlueSMiRF or a Bluetooth Mate. The Bluetooth module will be connected to an Arduino Uno to read in the data being transmitted wirelessly.

alt text

The BlueSMiRF Silver module from SparkFun.

Once you've decided on which hardware you'll be using, connect everything. Again, the Bluetooth Basics and BlueSMiRF tutorials should cover how to do this extensively.

Software

You’ll want to get some programs to be able to read data from and configure the RN42 Bluetooth module.

If you are unfamiliar with serial terminal emulators, please check out our tutorial.

Firmware

Here is the firmware for the Arduino side of this project. If you are following along, you'll want to upload this to whichever Arduino board you are using.

language:c
///////////////////////////////////////////////////////////////
// Arduino Bluetooth Interface with Mindwave
// Sophi Kravitz edit 11-4
// Shane Clements edit 11-5
//////////////////////////////////////////////////////////////////////// 
#include <SoftwareSerial.h>     // library for software serial
SoftwareSerial mySerial(5, 6);  // RX, TX
int LED = 8;                    // yellow one
int LED1 = 7;                   //white one
int BAUDRATE = 57600;

// checksum variables
byte payloadChecksum = 0;
byte CalculatedChecksum;
byte checksum = 0;              //data type byte stores an 8-bit unsigned number, from 0 to 255
int payloadLength = 0;
byte payloadData[64] = {0};
byte poorQuality = 0;
byte attention = 0;
byte meditation = 0;

// system variables
long lastReceivedPacket = 0;
boolean bigPacket = false;
boolean brainwave = false;
void setup() {
  pinMode(LED, OUTPUT);
  pinMode(LED1, OUTPUT);
  digitalWrite(LED, HIGH);   // hello sequence
  delay(100);
  digitalWrite(LED, LOW);
  delay(100);
  Serial.begin(57600);       // Bluetooth
  delay(500);
  mySerial.begin(4800);      // software serial
  delay(500);
  mySerial.print("Communicating... ");
  mySerial.println();
}
byte ReadOneByte() {
   int ByteRead;
  // Wait until there is data
  while(!Serial.available());
  //Get the number of bytes (characters) available for reading from the serial port.
  //This is data that's already arrived and stored in the serial receive buffer (which holds 64 bytes)
  ByteRead = Serial.read();
  return ByteRead; // read incoming serial data
  }

unsigned int delta_wave = 0;
unsigned int theta_wave = 0;
unsigned int low_alpha_wave = 0;
unsigned int high_alpha_wave = 0;
unsigned int low_beta_wave = 0;
unsigned int high_beta_wave = 0;
unsigned int low_gamma_wave = 0;
unsigned int mid_gamma_wave = 0;

void read_waves(int i) {
  delta_wave = read_3byte_int(i);
  i+=3;
  theta_wave = read_3byte_int(i);
  i+=3;
  low_alpha_wave = read_3byte_int(i);
  i+=3;
  high_alpha_wave = read_3byte_int(i);
  i+=3;
  low_beta_wave = read_3byte_int(i);
  i+=3;
  high_beta_wave = read_3byte_int(i);
  i+=3;
  low_gamma_wave = read_3byte_int(i);
  i+=3;
  mid_gamma_wave = read_3byte_int(i);
}

int read_3byte_int(int i) {
  return ((payloadData[i] << 16) + (payloadData[i+1] << 8) + payloadData[i+2]);
}

void loop() {
  // Look for sync bytes
  // Byte order: 0xAA, 0xAA, payloadLength, payloadData,
  // Checksum (sum all the bytes of payload, take lowest 8 bits, then bit inverse on lowest
if(ReadOneByte() == 0xAA) {
if(ReadOneByte() == 0xAA) {
payloadLength = ReadOneByte();
if(payloadLength > 169) //Payload length can not be greater than 169
return;
payloadChecksum = 0;
      for(int i = 0; i < payloadLength; i++) {      //loop until payload length is complete
        payloadData[i] = ReadOneByte();             //Read payload
        payloadChecksum += payloadData[i];
      }
      checksum = ReadOneByte();                     //Read checksum byte from stream
      payloadChecksum = 255 - payloadChecksum;      //Take one’s compliment of generated checksum
      if(checksum == payloadChecksum) {
        poorQuality = 200;
        attention = 0;
        meditation = 0;
 }
     brainwave = false;
     for(int i = 0; i < payloadLength; i++) { // Parse the payload
          switch (payloadData[i]) {
          case 02:
            i++;
            poorQuality = payloadData[i];
            bigPacket = true;
            break;
          case 04:
            i++;
            attention = payloadData[i];
            break;
          case 05:
            i++;
            meditation = payloadData[i];
            break;
          case 0x80:
            i = i + 3;
            break;
          case 0x83:                         // ASIC EEG POWER INT
            i++;
            brainwave = true;
            byte vlen = payloadData[i];
            //mySerial.print(vlen, DEC);
            //mySerial.println();
            read_waves(i+1);
            i += vlen; // i = i + vlen
            break;
          }                                 // switch
        }                                   // for loop

        if(bigPacket) {
          if(poorQuality == 0){
          }
          else{                             // do nothing
           }
         }


            if(brainwave && attention > 0 && attention < 100) {
            mySerial.print("Attention value is: ");
            mySerial.print(attention, DEC);
            mySerial.println();
            mySerial.print("Delta value is: ");
            mySerial.print(delta_wave, DEC);
            mySerial.println();
            mySerial.print("Theta value is: ");
            mySerial.print(theta_wave, DEC);
      mySerial.println();
            mySerial.print("Low Alpha value is: ");
            mySerial.print(low_alpha_wave, DEC);
            mySerial.println();
            mySerial.print("High Alpha value is: ");
            mySerial.print(high_alpha_wave, DEC);
            mySerial.println();            
            mySerial.print("Alertness value1 is: ");
            mySerial.print(low_beta_wave, DEC);
            mySerial.println();
            mySerial.print("Alertness value2 is: ");
            mySerial.print(high_beta_wave, DEC);
            mySerial.println();           
            mySerial.print(low_gamma_wave, DEC);
            mySerial.println();
            mySerial.print(mid_gamma_wave, DEC);
            mySerial.println();
         }

          if(attention > 40){
            digitalWrite(LED1, HIGH);
          }
          else
            digitalWrite(LED1, LOW);
        } 
        }
      }

Here is the Processing code, which interprets the data coming from the MindWave to the Arduino, and then gives you a visual representation of that data.

language:java
//Processing code to graph Attention values
//Comment out all of the lines after “if(brainwave && attention > 0 && attention < 100) {“
//Except for   
//mySerial.print(attention, DEC);
// mySerial.println();
//This will print out ONLY an Attention value and a new line afterwards

// Graphing sketch by Tom Igoe
// Sophi Kravitz edit 11/8

 import processing.serial.*; 
 Serial myPort;        // The serial port
 int xPos = 1;         // horizontal position of the graph 
 void setup () {
 // set the window size:
 size(400, 300);   
String portName = Serial.list()[1];         //[1]  println(Serial.list()) to find the ports 
 myPort = new Serial(this, "COM16", 4800);  // make sure the Baud rate matches the Arduino code
 myPort.bufferUntil('\n');                  // Wait for newline character:
 background(0);                             // set inital background color: 0 = black, 255 = white
 }

void draw () {                              // everything happens in the serialEvent()
 }

 void serialEvent (Serial myPort) {
 String inString = myPort.readStringUntil('\n');

   if (inString != null) {                  // trim whitespace:
   inString = trim(inString);               // convert to an int and map to the screen height:
   float inByte = float(inString); 
   inByte = map(inByte, 0, 100, 0, height); // take number from 0 to 100, and map it to 0 to height
   stroke(5,34,255);                        // draw the line:
   line(xPos, height, xPos, height - inByte);

   if (xPos >= width) {                     // at the edge of the screen, go back to the beginning:
   xPos = 0;
   background(0); 
   } 
   else { 
   xPos++;                                  // increment the horizontal position:
   }
 }
 }