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.

Committer:
RorschachUK
Date:
Sun Jun 02 16:04:19 2013 +0000
Revision:
0:7a3f4ba1851c
Child:
1:fac5c6ba2f07
First commit of basic demo of reading and parsing Mindwave Mobile headset data via BlueSMIRF Silver.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RorschachUK 0:7a3f4ba1851c 1 /* Mindwave Mobile demo - Bob Stone June 2013
RorschachUK 0:7a3f4ba1851c 2 * Basic demo of reading data packets from Neurosky's Mindwave Mobile headset
RorschachUK 0:7a3f4ba1851c 3 * via BlueSMIRF Silver bluetooth modem.
RorschachUK 0:7a3f4ba1851c 4 * Adapted from http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino
RorschachUK 0:7a3f4ba1851c 5 *
RorschachUK 0:7a3f4ba1851c 6 * Connect pin9 to BlueSMIRF's RX and pin10 to BlueSMIRF's TX,
RorschachUK 0:7a3f4ba1851c 7 * also hook up GND to GND and VCC to the mbed's 3V3 supply.
RorschachUK 0:7a3f4ba1851c 8 *
RorschachUK 0:7a3f4ba1851c 9 * To prepare the BlueSMIRF to auto-connect to the Mindwave Mobile:
RorschachUK 0:7a3f4ba1851c 10 *
RorschachUK 0:7a3f4ba1851c 11 * First wire it up and power it using the mbed's power pins. Once it's powered,
RorschachUK 0:7a3f4ba1851c 12 * pair your computer to the Mindwave Mobile headset to you can
RorschachUK 0:7a3f4ba1851c 13 * find out its MAC address. Write that down as you will need it.
RorschachUK 0:7a3f4ba1851c 14 *
RorschachUK 0:7a3f4ba1851c 15 * Next pair your computer to the BlueSMIRF so we can configure it. It will
RorschachUK 0:7a3f4ba1851c 16 * appear as RN-42-5922 or similar (it's a Roving Networks RN-42 unit).
RorschachUK 0:7a3f4ba1851c 17 *
RorschachUK 0:7a3f4ba1851c 18 * Now we can use a terminal program to connect to the serial modem created on
RorschachUK 0:7a3f4ba1851c 19 * your computer that connects wirelessly to the BlueSMIRF - by default it's at
RorschachUK 0:7a3f4ba1851c 20 * 115200 baud, 8 N 1 - when you're connected the light will go green.
RorschachUK 0:7a3f4ba1851c 21 *
RorschachUK 0:7a3f4ba1851c 22 * If you've got a successful serial connection, put it into command mode by
RorschachUK 0:7a3f4ba1851c 23 * typing three dollar signs $$$ - if successful you should see a prompt saying
RorschachUK 0:7a3f4ba1851c 24 * 'CMD'. If not, power it down and try again till you get a CMD prompt.
RorschachUK 0:7a3f4ba1851c 25 *
RorschachUK 0:7a3f4ba1851c 26 * At that prompt we need to change some defaults so that the BlueSMIRF is set to
RorschachUK 0:7a3f4ba1851c 27 * master mode, 57600 baud and sends a pincode of '0000', and seeks to connect to
RorschachUK 0:7a3f4ba1851c 28 * the headset's MAC address. To do this, type:
RorschachUK 0:7a3f4ba1851c 29 * SP,0000
RorschachUK 0:7a3f4ba1851c 30 * SM,3
RorschachUK 0:7a3f4ba1851c 31 * SR,<the 12 digit MAC address of the headset written down earlier>
RorschachUK 0:7a3f4ba1851c 32 * SU,57.6
RorschachUK 0:7a3f4ba1851c 33 * D
RorschachUK 0:7a3f4ba1851c 34 * You should see AOK after each line, and after the D it will print out its
RorschachUK 0:7a3f4ba1851c 35 * settings so you can check it's now AUTO, 57600, using 0000 and the right MAC
RorschachUK 0:7a3f4ba1851c 36 * address. All being well, type three minuses '---' to exit command mode.
RorschachUK 0:7a3f4ba1851c 37 *
RorschachUK 0:7a3f4ba1851c 38 * To check it's working, close the terminal you've been using, reboot the
RorschachUK 0:7a3f4ba1851c 39 * BlueSMIRF (flashing red light) and switch on the Mindwave Mobile headset
RorschachUK 0:7a3f4ba1851c 40 * - the light on the BlueSMIRF should go green when it connects and the
RorschachUK 0:7a3f4ba1851c 41 * flashing blue light on the Mindwave Mobile headset should go steady blue.
RorschachUK 0:7a3f4ba1851c 42 */
RorschachUK 0:7a3f4ba1851c 43 #include "mbed.h"
RorschachUK 0:7a3f4ba1851c 44 Serial pc(USBTX, USBRX); //for debug
RorschachUK 0:7a3f4ba1851c 45 Serial blueSmirf(p9, p10); //for bluetooth comms (TX, RX)
RorschachUK 0:7a3f4ba1851c 46
RorschachUK 0:7a3f4ba1851c 47 //*****************************
RorschachUK 0:7a3f4ba1851c 48 //User routines to process data
RorschachUK 0:7a3f4ba1851c 49 //*****************************
RorschachUK 0:7a3f4ba1851c 50
RorschachUK 0:7a3f4ba1851c 51 //This will be called if you blink.
RorschachUK 0:7a3f4ba1851c 52 void blinked(void)
RorschachUK 0:7a3f4ba1851c 53 {
RorschachUK 0:7a3f4ba1851c 54 printf("\nBlink!\n\n");
RorschachUK 0:7a3f4ba1851c 55 }
RorschachUK 0:7a3f4ba1851c 56
RorschachUK 0:7a3f4ba1851c 57 //This will be called when processed eSense data comes in, about once a second. If the
RorschachUK 0:7a3f4ba1851c 58 //connection's good, poorQuality will be zero, if the connection's useless (e.g. ear clip
RorschachUK 0:7a3f4ba1851c 59 //or forehead electrode not connected)it will be 200, and it can be somewhere in between
RorschachUK 0:7a3f4ba1851c 60 //for varying degrees of confidence in the data. Values for attention and meditation are
RorschachUK 0:7a3f4ba1851c 61 //0-100, and the time since last packet is in milliseconds.
RorschachUK 0:7a3f4ba1851c 62 void eSenseData(int poorQuality, int attention, int meditation, int timeSinceLastPacket)
RorschachUK 0:7a3f4ba1851c 63 {
RorschachUK 0:7a3f4ba1851c 64 if (poorQuality < 200) {
RorschachUK 0:7a3f4ba1851c 65 printf("PoorQuality: %d", poorQuality);
RorschachUK 0:7a3f4ba1851c 66 }
RorschachUK 0:7a3f4ba1851c 67 if (attention > 0) {
RorschachUK 0:7a3f4ba1851c 68 printf(" Attention: %d", attention);
RorschachUK 0:7a3f4ba1851c 69 }
RorschachUK 0:7a3f4ba1851c 70 if (meditation > 0) {
RorschachUK 0:7a3f4ba1851c 71 printf(" Meditation: %d", meditation);
RorschachUK 0:7a3f4ba1851c 72 }
RorschachUK 0:7a3f4ba1851c 73 printf(" Time since last packet: %d", timeSinceLastPacket);
RorschachUK 0:7a3f4ba1851c 74 printf("\n");
RorschachUK 0:7a3f4ba1851c 75 }
RorschachUK 0:7a3f4ba1851c 76
RorschachUK 0:7a3f4ba1851c 77 //This will be called when processed meter reading data arrives, about once a second.
RorschachUK 0:7a3f4ba1851c 78 //This is a breakdown of frequencies in the wave data into 8 named bands, these are:
RorschachUK 0:7a3f4ba1851c 79 // 0: Delta (0.5-2.75 Hz)
RorschachUK 0:7a3f4ba1851c 80 // 1: Theta (3.5-6.75 Hz)
RorschachUK 0:7a3f4ba1851c 81 // 2: Low-Alpha (7.5-9.25 Hz)
RorschachUK 0:7a3f4ba1851c 82 // 3: High-Alpha (10-11.75 Hz)
RorschachUK 0:7a3f4ba1851c 83 // 4: Low-Beta (13-16.75 Hz)
RorschachUK 0:7a3f4ba1851c 84 // 5: High-Beta (18-29.75 Hz)
RorschachUK 0:7a3f4ba1851c 85 // 6: Low-Gamma (31-39.75 Hz)
RorschachUK 0:7a3f4ba1851c 86 // 7: High-Gamma (41-49.75 Hz)
RorschachUK 0:7a3f4ba1851c 87 void meterData(int meter[8])
RorschachUK 0:7a3f4ba1851c 88 {
RorschachUK 0:7a3f4ba1851c 89 printf("Meters: ");
RorschachUK 0:7a3f4ba1851c 90 for (int j=0; j<8; j++) {
RorschachUK 0:7a3f4ba1851c 91 printf("%d = %d, ", j, meter[j]);
RorschachUK 0:7a3f4ba1851c 92 }
RorschachUK 0:7a3f4ba1851c 93 printf("\n");
RorschachUK 0:7a3f4ba1851c 94 }
RorschachUK 0:7a3f4ba1851c 95
RorschachUK 0:7a3f4ba1851c 96 //This will be called when wave data arrives. There will be a lot of these,
RorschachUK 0:7a3f4ba1851c 97 //512 a second, so if you're planning to do anything here, don't let it take long.
RorschachUK 0:7a3f4ba1851c 98 //Best not to printf this out as it will just choke.
RorschachUK 0:7a3f4ba1851c 99 void waveData(int wave)
RorschachUK 0:7a3f4ba1851c 100 {
RorschachUK 0:7a3f4ba1851c 101 }
RorschachUK 0:7a3f4ba1851c 102
RorschachUK 0:7a3f4ba1851c 103 //*****************
RorschachUK 0:7a3f4ba1851c 104 //End User routines
RorschachUK 0:7a3f4ba1851c 105 //*****************
RorschachUK 0:7a3f4ba1851c 106
RorschachUK 0:7a3f4ba1851c 107 //System routines to obtain and parse data
RorschachUK 0:7a3f4ba1851c 108 //Simplify serial comms
RorschachUK 0:7a3f4ba1851c 109 unsigned char ReadOneByte()
RorschachUK 0:7a3f4ba1851c 110 {
RorschachUK 0:7a3f4ba1851c 111 int ByteRead;
RorschachUK 0:7a3f4ba1851c 112
RorschachUK 0:7a3f4ba1851c 113 while(!blueSmirf.readable());
RorschachUK 0:7a3f4ba1851c 114 ByteRead = blueSmirf.getc();
RorschachUK 0:7a3f4ba1851c 115
RorschachUK 0:7a3f4ba1851c 116 return ByteRead;
RorschachUK 0:7a3f4ba1851c 117 }
RorschachUK 0:7a3f4ba1851c 118 //Main loop, sets up and keeps listening for serial
RorschachUK 0:7a3f4ba1851c 119 int main()
RorschachUK 0:7a3f4ba1851c 120 {
RorschachUK 0:7a3f4ba1851c 121 Timer t; //packet timer
RorschachUK 0:7a3f4ba1851c 122 t.start();
RorschachUK 0:7a3f4ba1851c 123 Timer blinkTimer; //used for detecting blinks
RorschachUK 0:7a3f4ba1851c 124 int time;
RorschachUK 0:7a3f4ba1851c 125 int generatedChecksum = 0;
RorschachUK 0:7a3f4ba1851c 126 int checksum = 0;
RorschachUK 0:7a3f4ba1851c 127 int payloadLength = 0;
RorschachUK 0:7a3f4ba1851c 128 int payloadData[64] = {0};
RorschachUK 0:7a3f4ba1851c 129 int poorQuality = 0;
RorschachUK 0:7a3f4ba1851c 130 int attention = 0;
RorschachUK 0:7a3f4ba1851c 131 int meditation = 0;
RorschachUK 0:7a3f4ba1851c 132 int wave = 0;
RorschachUK 0:7a3f4ba1851c 133 int meter[8] = {0};
RorschachUK 0:7a3f4ba1851c 134
RorschachUK 0:7a3f4ba1851c 135 bool eSensePacket = false;
RorschachUK 0:7a3f4ba1851c 136 bool meterPacket = false;
RorschachUK 0:7a3f4ba1851c 137 bool wavePacket = false;
RorschachUK 0:7a3f4ba1851c 138
RorschachUK 0:7a3f4ba1851c 139 blueSmirf.baud(57600);
RorschachUK 0:7a3f4ba1851c 140 pc.baud(115200);
RorschachUK 0:7a3f4ba1851c 141 printf("\n\nStarted\n\n");
RorschachUK 0:7a3f4ba1851c 142 blinkTimer.reset();
RorschachUK 0:7a3f4ba1851c 143
RorschachUK 0:7a3f4ba1851c 144 while(1) {
RorschachUK 0:7a3f4ba1851c 145 // Look for sync bytes
RorschachUK 0:7a3f4ba1851c 146 if(ReadOneByte() == 170) {
RorschachUK 0:7a3f4ba1851c 147 if(ReadOneByte() == 170) {
RorschachUK 0:7a3f4ba1851c 148 //Synchronised to start of packet
RorschachUK 0:7a3f4ba1851c 149 payloadLength = ReadOneByte();
RorschachUK 0:7a3f4ba1851c 150 if(payloadLength > 169) //Payload length can not be greater than 169
RorschachUK 0:7a3f4ba1851c 151 return;
RorschachUK 0:7a3f4ba1851c 152
RorschachUK 0:7a3f4ba1851c 153 generatedChecksum = 0;
RorschachUK 0:7a3f4ba1851c 154 for(int i = 0; i < payloadLength; i++) {
RorschachUK 0:7a3f4ba1851c 155 payloadData[i] = ReadOneByte(); //Read payload into memory
RorschachUK 0:7a3f4ba1851c 156 generatedChecksum += payloadData[i];
RorschachUK 0:7a3f4ba1851c 157 }
RorschachUK 0:7a3f4ba1851c 158
RorschachUK 0:7a3f4ba1851c 159 checksum = ReadOneByte(); //Read checksum byte from stream
RorschachUK 0:7a3f4ba1851c 160 generatedChecksum = 255 - (generatedChecksum & 0xFF); //Take one's compliment of generated checksum
RorschachUK 0:7a3f4ba1851c 161
RorschachUK 0:7a3f4ba1851c 162 if(checksum == generatedChecksum) {
RorschachUK 0:7a3f4ba1851c 163 //Packet seems OK
RorschachUK 0:7a3f4ba1851c 164 poorQuality = 200;
RorschachUK 0:7a3f4ba1851c 165 attention = 0;
RorschachUK 0:7a3f4ba1851c 166 meditation = 0;
RorschachUK 0:7a3f4ba1851c 167 wave = 0;
RorschachUK 0:7a3f4ba1851c 168 for(int i = 0; i < payloadLength; i++) { // Parse the payload
RorschachUK 0:7a3f4ba1851c 169 switch (payloadData[i]) {
RorschachUK 0:7a3f4ba1851c 170 case 2: //quality
RorschachUK 0:7a3f4ba1851c 171 i++;
RorschachUK 0:7a3f4ba1851c 172 poorQuality = payloadData[i];
RorschachUK 0:7a3f4ba1851c 173 eSensePacket = true;
RorschachUK 0:7a3f4ba1851c 174 break;
RorschachUK 0:7a3f4ba1851c 175 case 4: //attention
RorschachUK 0:7a3f4ba1851c 176 i++;
RorschachUK 0:7a3f4ba1851c 177 attention = payloadData[i];
RorschachUK 0:7a3f4ba1851c 178 eSensePacket = true;
RorschachUK 0:7a3f4ba1851c 179 break;
RorschachUK 0:7a3f4ba1851c 180 case 5: //meditation
RorschachUK 0:7a3f4ba1851c 181 i++;
RorschachUK 0:7a3f4ba1851c 182 meditation = payloadData[i];
RorschachUK 0:7a3f4ba1851c 183 eSensePacket = true;
RorschachUK 0:7a3f4ba1851c 184 break;
RorschachUK 0:7a3f4ba1851c 185 case 0x80: //wave
RorschachUK 0:7a3f4ba1851c 186 wave = payloadData[i+2] * 256 + payloadData[i+3];
RorschachUK 0:7a3f4ba1851c 187 //We also want to try to detect blinks via analysing wave data
RorschachUK 0:7a3f4ba1851c 188 time = blinkTimer.read_ms();
RorschachUK 0:7a3f4ba1851c 189 if (wave > 32767) wave -= 65535; //cope with negatives
RorschachUK 0:7a3f4ba1851c 190 if (wave>200 && blinkTimer.read_ms() == 0) {
RorschachUK 0:7a3f4ba1851c 191 blinkTimer.start();
RorschachUK 0:7a3f4ba1851c 192 } else if (wave<-90 && time > 10 && time < 100) {
RorschachUK 0:7a3f4ba1851c 193 blinkTimer.stop();
RorschachUK 0:7a3f4ba1851c 194 blinkTimer.reset();
RorschachUK 0:7a3f4ba1851c 195 blinked();
RorschachUK 0:7a3f4ba1851c 196 } else if (time>500) {
RorschachUK 0:7a3f4ba1851c 197 blinkTimer.stop();
RorschachUK 0:7a3f4ba1851c 198 blinkTimer.reset();
RorschachUK 0:7a3f4ba1851c 199 }
RorschachUK 0:7a3f4ba1851c 200 i = i + 3;
RorschachUK 0:7a3f4ba1851c 201 wavePacket = true;
RorschachUK 0:7a3f4ba1851c 202 break;
RorschachUK 0:7a3f4ba1851c 203 case 0x83: //meter readings for different frequency bands
RorschachUK 0:7a3f4ba1851c 204 for (int j=0; j<8; j++) {
RorschachUK 0:7a3f4ba1851c 205 meter[j] = payloadData[i+j*3+2] + payloadData[i+j*3+3]*256 + payloadData[i+j*3+4]*65536;
RorschachUK 0:7a3f4ba1851c 206 }
RorschachUK 0:7a3f4ba1851c 207 meterPacket = true;
RorschachUK 0:7a3f4ba1851c 208 i = i + 25;
RorschachUK 0:7a3f4ba1851c 209 break;
RorschachUK 0:7a3f4ba1851c 210 default:
RorschachUK 0:7a3f4ba1851c 211 break;
RorschachUK 0:7a3f4ba1851c 212 } // switch
RorschachUK 0:7a3f4ba1851c 213 } // for loop
RorschachUK 0:7a3f4ba1851c 214
RorschachUK 0:7a3f4ba1851c 215 //Call routines to process data
RorschachUK 0:7a3f4ba1851c 216 if(eSensePacket) {
RorschachUK 0:7a3f4ba1851c 217 eSenseData(poorQuality, attention, meditation, t.read_ms());
RorschachUK 0:7a3f4ba1851c 218 eSensePacket = false;
RorschachUK 0:7a3f4ba1851c 219 }
RorschachUK 0:7a3f4ba1851c 220 if (meterPacket) {
RorschachUK 0:7a3f4ba1851c 221 meterData(meter);
RorschachUK 0:7a3f4ba1851c 222 t.reset();
RorschachUK 0:7a3f4ba1851c 223 meterPacket=false;
RorschachUK 0:7a3f4ba1851c 224 }
RorschachUK 0:7a3f4ba1851c 225 if (wavePacket) {
RorschachUK 0:7a3f4ba1851c 226 waveData(wave);
RorschachUK 0:7a3f4ba1851c 227 wavePacket=false;
RorschachUK 0:7a3f4ba1851c 228 }
RorschachUK 0:7a3f4ba1851c 229 } else {
RorschachUK 0:7a3f4ba1851c 230 // Checksum Error
RorschachUK 0:7a3f4ba1851c 231 } // end if else for checksum
RorschachUK 0:7a3f4ba1851c 232 } // end if read 0xAA byte
RorschachUK 0:7a3f4ba1851c 233 } // end if read 0xAA byte
RorschachUK 0:7a3f4ba1851c 234 }
RorschachUK 0:7a3f4ba1851c 235 }