Arduino + BlueSmirf + EEG headset (Mindwave Mobile2)

Hello there,

I want to read data from my Bluetooth EEG headset Mindwave Mobile 2 with Arduino. Now, their website mentioned it was possible to connect the headset to a bluesmirf silver and Arduino (http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino ).

I have set up the BlueSmirf (through the terminal) and set the baudrate to 57600, and it seems to connect to my headset properly, the green LED on the BlueSmirf is on.

The example code that is given on the website, uses an LED bar to show the data from the headset, but I don’t have that and I would just like to read the data coming from the headset directly through the serial monitor in Arduino. This way I can later on send the data to a Processing sketch.

How would this be possible?

This is the code I have tried for now; to be honest, I don’t fully understand all of it. It is the example code, but I removed the parts that use the LED bar they used.

#define LED 13
#define BAUDRATE 57600
#define DEBUGOUTPUT 0

#define powercontrol 10

// checksum variables
byte generatedChecksum = 0;
byte checksum = 0;
int payloadLength = 0;
byte payloadData[64] = {
  0
};
byte poorQuality = 0;
byte attention = 0;
byte meditation = 0;

// system variables
long lastReceivedPacket = 0;
boolean bigPacket = false;

//////////////////////////
// Microprocessor Setup //
//////////////////////////
void setup() {

  pinMode(LED, OUTPUT);
  Serial.begin(BAUDRATE);           // USB

}

////////////////////////////////
// Read data from Serial UART //
////////////////////////////////
byte ReadOneByte() {
  int ByteRead;

  while (!Serial.available());
  ByteRead = Serial.read();

#if DEBUGOUTPUT
  Serial.print((char)ByteRead);   // echo the same byte out the USB serial (for debug purposes)
#endif

  return ByteRead;
}

/////////////
//MAIN LOOP//
/////////////
void loop() {
   Serial.println("hello world!"); 

  // Look for sync bytes
  if (ReadOneByte() == 170) {
    if (ReadOneByte() == 170) {

      payloadLength = ReadOneByte();
      if (payloadLength > 169)                     //Payload length can not be greater than 169
        return;

      generatedChecksum = 0;
      for (int i = 0; i < payloadLength; i++) {
        payloadData[i] = ReadOneByte();            //Read payload into memory
        generatedChecksum += payloadData[i];
      }

      checksum = ReadOneByte();                      //Read checksum byte from stream
      generatedChecksum = 255 - generatedChecksum;   //Take one's compliment of generated checksum

      if (checksum == generatedChecksum) {

        poorQuality = 200;
        attention = 0;
        meditation = 0;

        for (int i = 0; i < payloadLength; i++) {   // Parse the payload
          switch (payloadData[i]) {
            case 2:
              i++;
              poorQuality = payloadData[i];
              bigPacket = true;
              break;
            case 4:
              i++;
              attention = payloadData[i];
              break;
            case 5:
              i++;
              meditation = payloadData[i];
              break;
            case 0x80:
              i = i + 3;
              break;
            case 0x83:
              i = i + 25;
              break;
            default:
              break;
          } // switch
        } // for loop

#if !DEBUGOUTPUT

        // *** Add your code here ***

        if (bigPacket) {
          if (poorQuality == 0)
            digitalWrite(LED, HIGH);
          else
            digitalWrite(LED, LOW);
          Serial.print("PoorQuality: ");
          Serial.print(poorQuality, DEC);
          Serial.print(" Attention: ");
          Serial.print(attention, DEC);
          Serial.print(" Time since last packet: ");
          Serial.print(millis() - lastReceivedPacket, DEC);
          lastReceivedPacket = millis();
          Serial.print("\n");

          switch (attention / 10) {
            case 0:
              Serial.println("case 0"); 
              break;
            case 1:
              Serial.println("case 1");
              break;
            case 2:
              Serial.println("case 2");
              break;
            case 3:
              Serial.println("case 3");
              break;
            case 4:
              Serial.println("case 4");
              break;
            case 5:
              Serial.println("case 5");
              break;
            case 6:
              Serial.println("case 6");
              break;
            case 7:
              Serial.println("case 7");
              break;
            case 8:
              Serial.println("case 8");
              break;
            case 9:
              Serial.println("case 9");
              break;
            case 10:
              Serial.println("case 10");
              break;
          }
        }
#endif
        bigPacket = false;
      }
      else {
        // Checksum Error
      }  // end if else for checksum
    } // end if read 0xAA byte
  } // end if read 0xAA byte
}

The serial monitor does give me the “hello world” which I added in the loop part, but nothing else. What could be going wrong?
I hope I’ve explained it clearly, please let me know. Thanks in advance!

Also, I have wired the BlueSmirf to the Arduino like this:

BlueSmirf Arduino
GND GND
VCC 5V
TX-0 digital pin 2
RX-1 digital pin 3

As they mentioned in the tutorial, I made a connection between the CTS-1 and the RTS-0 of the BlueSmirf.

The sketch is reading from Serial, not pins 2 and 3 where you say the bluetooth interface is attached. I think that for bluetooth you would typically use SoftwareSerial.h to talk to bluetooth and Serial to talk to Serial Monitor.

The code allows for a payload length of up to 169 bytes but the buffer only has room for 64 bytes.

Thank you! Yes, I was wondering where the reference to the pins 2 and 3 was.

I have looked for a simpler example using the SoftwareSerial.h indeed, I found this, which seems to be getting some data from the Bluetooth headset definitely.

#include <SoftwareSerial.h>  

int bluetoothTx = 2;  // TX-O pin of bluetooth mate, Arduino D2
int bluetoothRx = 3;  // RX-I pin of bluetooth mate, Arduino D3

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);

void setup()
{
  Serial.begin(9600);  // Begin the serial monitor at 9600bps

  bluetooth.begin(115200);  // The Bluetooth Mate defaults to 115200bps
  bluetooth.print("$");  // Print three times individually
  bluetooth.print("$");
  bluetooth.print("$");  // Enter command mode
  delay(100);  // Short delay, wait for the Mate to send back CMD
  bluetooth.println("U,9600,N");  // Temporarily Change the baudrate to 9600, no parity
  // 115200 can be too fast at times for NewSoftSerial to relay the data reliably
  bluetooth.begin(9600);  // Start bluetooth serial at 9600
}

void loop()
{
  if(bluetooth.available())  // If the bluetooth sent any characters
  {
    Serial.println((char)bluetooth.read());  
  }
  if(Serial.available())  // If stuff was typed in the serial monitor
  {
    bluetooth.print((char)Serial.read());
  }
}

However, for now all I get is unreadable signs. I have tried to change the baudrate to 57600 (gives only ???) and 9600 and 115200 (no output at serial monitor), but got no readable output in the Serial Monitor yet.

This is what i see at baudrate 9600:







&


T


S



9


(



a


@



<






I believe the headset sends a string of around 8 to 10 numbers every time (alpha low, alpha high, beta low, beta high, et cetera…). So, how can I interpret the data in a more readable way? Do I need to use a piece of the code I first posted here? Because I don’t understand that code :slight_smile:

Since the original program interpreted the arriving bytes as decimal numbers you should probably print out the value rather than a character:

    Serial.println((int)bluetooth.read());

Then you can see if the messages starts with two values of 170, then a packet length, then that number of bytes, then a checksum.

Great, that helps! Now I see a whole lot of numbers!

However, I don't see it starting with two times 170, it's just many different numbers ranging from 0 to 200-ish. Perhaps that's also why the original code didn't give output?

I was wondering if you could perhaps give me some clarity on what happens in the first piece of code? Because I think I will need (part of) that in order to make sense of the string of numbers that the headset sends.
How does that code break down all the numbers?
What I need in the end is the "attention" value, which is somewhere defined in the first sketch;

case 4:
              i++;
              attention = payloadData[i];
              break;

It's just a bit unclear to me which part of that code I'd need and which I could discard :slight_smile:

If you are not seeing pairs of 170’s anywhere in your data stream you may just have the wrong baud rate.

LotusElise:
I was wondering if you could perhaps give me some clarity on what happens in the first piece of code?

OK

  if (ReadOneByte() == 170)
  {
    if (ReadOneByte() == 170)
    {

That ignores everything until you read the 0xAA,0xAA header.

     payloadLength = ReadOneByte();
      if (payloadLength > 169)                     //Payload length can not be greater than 169
        return;

The next byte is the payload length. If that value is greater than 169, go back to looking for a new header.

      generatedChecksum = 0;
      for (int i = 0; i < payloadLength; i++)
      {
        payloadData[i] = ReadOneByte();            //Read payload into memory
        generatedChecksum += payloadData[i];
      }

Read the payload bytes into a buffer as you sum all of the payload bytes.

      checksum = ReadOneByte();                      //Read checksum byte from stream
      generatedChecksum = 255 - generatedChecksum;   //Take one's compliment of generated checksum


      if (checksum == generatedChecksum)
      {

The next (and final) byte is the checksum. If it doesn’t match the generated checksum, don’t process the message and go back to looking for the 170,170 header.

The payload consists of sub-messages. Each starts with a ‘type’ byte:
2, one byte of ‘Quality’
4, one byte of ‘Attention’
5, one byte of ‘Meditation’
0x80, skip 3 bytes
0x83, skip 25 bytes
Any other ‘type’ is ignored. Those match with this table from the Neurosky java parser:

	/* Parser CODE definitions */
	/* Not actually used by this class.  Included for reference purposes
	* only.
	*/
	public static final int PARSER_CODE_BATTERY     = 0x01;
	public static final int PARSER_CODE_POOR_SIGNAL = 0x02;
	public static final int PARSER_CODE_ATTENTION   = 0x04;
	public static final int PARSER_CODE_MEDITATION  = 0x05;
	public static final int PARSER_CODE_8BIT_RAW    = 0x06;
	public static final int PARSER_CODE_RAW_MARKER  = 0x07;
	public static final int PARSER_CODE_RAW         = 0x80;
	public static final int PARSER_CODE_EEG_POWERS  = 0x81;

Thanks a lot for this explanation!! This helps me a lot to understand it! :smiley: