Basic serial-debug demo of reading and parsing data from Neurosky's Mindwave Mobile EEG headset via BlueSMIRF Silver bluetooth modem.

Dependencies:   mbed

Basic demo of reading data packets from Neurosky's Mindwave Mobile headset via BlueSMIRF Silver bluetooth modem. Adapted from http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino

Connect pin9 to BlueSMIRF's RX and pin10 to BlueSMIRF's TX, also hook up GND to GND and VCC to the mbed's 3V3 supply.

To prepare the BlueSMIRF to auto-connect to the Mindwave Mobile:

First wire it up and power it using the mbed's power pins. Once it's powered, pair your computer to the Mindwave Mobile headset to you can find out its MAC address. Write that down as you will need it.

Next pair your computer to the BlueSMIRF so we can configure it. It will appear as RN-42-5922 or similar (it's a Roving Networks RN-42 unit).

Now we can use a terminal program to connect to the serial modem created on your computer that connects wirelessly to the BlueSMIRF - by default it's at 115200 baud, 8 N 1 - when you're connected the light will go green.

If you've got a successful serial connection, put it into command mode by typing three dollar signs $$$ - if successful you should see a prompt saying 'CMD'. If not, power it down and try again till you get a CMD prompt.

At that prompt we need to change some defaults so that the BlueSMIRF is set to master mode, 57600 baud and sends a pincode of '0000', and seeks to connect to the headset's MAC address. To do this, type:

SP,0000
SM,3
SR,<the 12 digit MAC address of the headset written down earlier>
SU,57.6
D

You should see AOK after each line, and after the D it will print out its settings so you can check it's now AUTO, 57600, using 0000 and the right MAC address. All being well, type three minuses '---' to exit command mode.

To check it's working, close the terminal you've been using, reboot the BlueSMIRF (flashing red light) and switch on the Mindwave Mobile headset - the light on the BlueSMIRF should go green when it connects and the flashing blue light on the Mindwave Mobile headset should go steady blue.

Files at this revision

API Documentation at this revision

Comitter:
RorschachUK
Date:
Sun Jun 02 16:04:19 2013 +0000
Child:
1:fac5c6ba2f07
Commit message:
First commit of basic demo of reading and parsing Mindwave Mobile headset data via BlueSMIRF Silver.

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Jun 02 16:04:19 2013 +0000
@@ -0,0 +1,235 @@
+/* Mindwave Mobile demo - Bob Stone June 2013
+ * Basic demo of reading data packets from Neurosky's Mindwave Mobile headset
+ * via BlueSMIRF Silver bluetooth modem.
+ * Adapted from http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino
+ *
+ * Connect pin9 to BlueSMIRF's RX and pin10 to BlueSMIRF's TX,
+ * also hook up GND to GND and VCC to the mbed's 3V3 supply.
+ *
+ * To prepare the BlueSMIRF to auto-connect to the Mindwave Mobile:
+ *
+ * First wire it up and power it using the mbed's power pins.  Once it's powered,
+ * pair your computer to the Mindwave Mobile headset to you can
+ * find out its MAC address.  Write that down as you will need it.
+ *
+ * Next pair your computer to the BlueSMIRF so we can configure it.  It will
+ * appear as RN-42-5922 or similar (it's a Roving Networks RN-42 unit).
+ *
+ * Now we can use a terminal program to connect to the serial modem created on
+ * your computer that connects wirelessly to the BlueSMIRF - by default it's at
+ * 115200 baud, 8 N 1 - when you're connected the light will go green.
+ *
+ * If you've got a successful serial connection, put it into command mode by
+ * typing three dollar signs $$$ - if successful you should see a prompt saying 
+ * 'CMD'.  If not, power it down and try again till you get a CMD prompt.
+ * 
+ * At that prompt we need to change some defaults so that the BlueSMIRF is set to
+ * master mode, 57600 baud and sends a pincode of '0000', and seeks to connect to
+ * the headset's MAC address.  To do this, type:
+ *  SP,0000
+ *  SM,3
+ *  SR,<the 12 digit MAC address of the headset written down earlier>
+ *  SU,57.6
+ *  D
+ * You should see AOK after each line, and after the D it will print out its 
+ * settings so you can check it's now AUTO, 57600, using 0000 and the right MAC
+ * address.  All being well, type three minuses '---' to exit command mode.
+ * 
+ * To check it's working, close the terminal you've been using, reboot the 
+ * BlueSMIRF (flashing red light) and switch on the Mindwave Mobile headset
+ * - the light on the BlueSMIRF should go green when it connects and the 
+ * flashing blue light on the Mindwave Mobile headset should go steady blue.
+ */
+#include "mbed.h"
+Serial pc(USBTX, USBRX);    //for debug
+Serial blueSmirf(p9, p10);  //for bluetooth comms (TX, RX)
+
+//*****************************
+//User routines to process data
+//*****************************
+
+//This will be called if you blink.
+void blinked(void)
+{
+    printf("\nBlink!\n\n");
+}
+
+//This will be called when processed eSense data comes in, about once a second.  If the
+//connection's good, poorQuality will be zero, if the connection's useless (e.g. ear clip
+//or forehead electrode not connected)it will be 200, and it can be somewhere in between 
+//for varying degrees of confidence in the data.  Values for attention and meditation are 
+//0-100, and the time since last packet is in milliseconds.
+void eSenseData(int poorQuality, int attention, int meditation, int timeSinceLastPacket)
+{
+    if (poorQuality < 200) {
+        printf("PoorQuality: %d", poorQuality);
+    }
+    if (attention > 0) {
+        printf(" Attention: %d", attention);
+    }
+    if (meditation > 0) {
+        printf(" Meditation: %d", meditation);
+    }
+    printf(" Time since last packet: %d", timeSinceLastPacket);
+    printf("\n");
+}
+
+//This will be called when processed meter reading data arrives, about once a second.
+//This is a breakdown of frequencies in the wave data into 8 named bands, these are:
+//  0: Delta        (0.5-2.75 Hz)
+//  1: Theta        (3.5-6.75 Hz)
+//  2: Low-Alpha    (7.5-9.25 Hz)
+//  3: High-Alpha   (10-11.75 Hz)
+//  4: Low-Beta     (13-16.75 Hz)
+//  5: High-Beta    (18-29.75 Hz)
+//  6: Low-Gamma    (31-39.75 Hz)
+//  7: High-Gamma   (41-49.75 Hz)
+void meterData(int meter[8])
+{
+    printf("Meters: ");
+    for (int j=0; j<8; j++) {
+        printf("%d = %d, ", j, meter[j]);
+    }
+    printf("\n");
+}
+
+//This will be called when wave data arrives.  There will be a lot of these,
+//512 a second, so if you're planning to do anything here, don't let it take long.
+//Best not to printf this out as it will just choke.
+void waveData(int wave)
+{
+}
+
+//*****************
+//End User routines
+//*****************
+
+//System routines to obtain and parse data
+//Simplify serial comms
+unsigned char ReadOneByte()
+{
+    int ByteRead;
+
+    while(!blueSmirf.readable());
+    ByteRead = blueSmirf.getc();
+
+    return ByteRead;
+}
+//Main loop, sets up and keeps listening for serial
+int main()
+{
+    Timer t; //packet timer
+    t.start();
+    Timer blinkTimer; //used for detecting blinks
+    int time;
+    int generatedChecksum = 0;
+    int checksum = 0;
+    int payloadLength = 0;
+    int payloadData[64] = {0};
+    int poorQuality = 0;
+    int attention = 0;
+    int meditation = 0;
+    int wave = 0;
+    int meter[8] = {0};
+
+    bool eSensePacket = false;
+    bool meterPacket = false;
+    bool wavePacket = false;
+
+    blueSmirf.baud(57600);
+    pc.baud(115200);
+    printf("\n\nStarted\n\n");
+    blinkTimer.reset();
+
+    while(1) {
+        // Look for sync bytes
+        if(ReadOneByte() == 170) {
+            if(ReadOneByte() == 170) {
+                //Synchronised to start of packet
+                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 & 0xFF);   //Take one's compliment of generated checksum
+
+                if(checksum == generatedChecksum) {
+                    //Packet seems OK
+                    poorQuality = 200;
+                    attention = 0;
+                    meditation = 0;
+                    wave = 0;
+                    for(int i = 0; i < payloadLength; i++) {    // Parse the payload
+                        switch (payloadData[i]) {
+                            case 2: //quality
+                                i++;
+                                poorQuality = payloadData[i];
+                                eSensePacket = true;
+                                break;
+                            case 4: //attention
+                                i++;
+                                attention = payloadData[i];
+                                eSensePacket = true;
+                                break;
+                            case 5: //meditation
+                                i++;
+                                meditation = payloadData[i];
+                                eSensePacket = true;
+                                break;
+                            case 0x80: //wave
+                                wave = payloadData[i+2] * 256 + payloadData[i+3];
+                                //We also want to try to detect blinks via analysing wave data
+                                time = blinkTimer.read_ms();
+                                if (wave > 32767) wave -= 65535; //cope with negatives
+                                if (wave>200 && blinkTimer.read_ms() == 0) {
+                                    blinkTimer.start();
+                                } else if (wave<-90 && time > 10 && time < 100) {
+                                    blinkTimer.stop();
+                                    blinkTimer.reset();
+                                    blinked();
+                                } else if (time>500) {
+                                    blinkTimer.stop();
+                                    blinkTimer.reset();
+                                }
+                                i = i + 3;
+                                wavePacket = true;
+                                break;
+                            case 0x83: //meter readings for different frequency bands
+                                for (int j=0; j<8; j++) {
+                                    meter[j] = payloadData[i+j*3+2] + payloadData[i+j*3+3]*256 + payloadData[i+j*3+4]*65536;
+                                }
+                                meterPacket = true;
+                                i = i + 25;
+                                break;
+                            default:
+                                break;
+                        } // switch
+                    } // for loop
+
+                    //Call routines to process data
+                    if(eSensePacket) {
+                        eSenseData(poorQuality, attention, meditation, t.read_ms());
+                        eSensePacket = false;
+                    }
+                    if (meterPacket) {
+                        meterData(meter);
+                        t.reset();
+                        meterPacket=false;
+                    }
+                    if (wavePacket) {
+                        waveData(wave);
+                        wavePacket=false;
+                    }
+                } else {
+                    // Checksum Error
+                }  // end if else for checksum
+            } // end if read 0xAA byte
+        } // end if read 0xAA byte
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Jun 02 16:04:19 2013 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/b3110cd2dd17
\ No newline at end of file