├── Mindwave.cpp ├── Mindwave.h ├── README.md ├── examples ├── AltSoftSerial │ └── AltSoftSerial.ino ├── EEG │ └── EEG.ino ├── Serial │ └── Serial.ino └── TwoHeadsets │ └── TwoHeadsets.ino └── keywords.txt /Mindwave.cpp: -------------------------------------------------------------------------------- 1 | #include "Mindwave.h" 2 | 3 | Mindwave::Mindwave(){} 4 | 5 | void Mindwave::update(Stream &stream,MindwaveDataCallback onData){ 6 | if(stream.available() > 0){ 7 | switch(_state){ 8 | case MINDWAVE_WAIT_FOR_FIRST_A: 9 | if(stream.read() == 0xAA) _state = MINDWAVE_WAIT_FOR_SECOND_A; 10 | break; 11 | case MINDWAVE_WAIT_FOR_SECOND_A: 12 | if(stream.read() == 0xAA) _state = MINDWAVE_WAIT_FOR_PAYLOAD_LENGTH; 13 | break; 14 | case MINDWAVE_WAIT_FOR_PAYLOAD_LENGTH: 15 | _payloadLength = stream.read(); 16 | if(_payloadLength > MINDWAVE_PAYLOAD_MAX_SIZE){ 17 | _state = MINDWAVE_WAIT_FOR_FIRST_A; 18 | return; 19 | } 20 | _generatedChecksum = _payloadIndex = 0; 21 | _state = MINDWAVE_WAIT_FOR_PAYLOAD; 22 | break; 23 | case MINDWAVE_WAIT_FOR_PAYLOAD: 24 | if(_payloadIndex < _payloadLength){ 25 | _payloadData[_payloadIndex] = stream.read(); 26 | _generatedChecksum += _payloadData[_payloadIndex]; 27 | _payloadIndex++; 28 | }else{ 29 | _state = MINDWAVE_WAIT_FOR_CHECKSUM; 30 | } 31 | break; 32 | case MINDWAVE_WAIT_FOR_CHECKSUM: 33 | _checksum = stream.read(); 34 | _generatedChecksum = 255 - _generatedChecksum; 35 | if(_checksum == _generatedChecksum) { 36 | parsePayload(onData); 37 | _state = MINDWAVE_WAIT_FOR_FIRST_A; 38 | }else{ 39 | _state = MINDWAVE_WAIT_FOR_FIRST_A; 40 | } 41 | break; 42 | } 43 | } 44 | } 45 | void Mindwave::parsePayload(MindwaveDataCallback onData){ 46 | _poorQuality = 200; 47 | _attention = 0; 48 | _meditation = 0; 49 | for (int j = 0; j < MINDWAVE_EEG_SIZE; j++) _eeg[j] = 0; 50 | for(int i = 0; i < _payloadLength; i++) { // Parse the payload 51 | switch (_payloadData[i]) { 52 | case 2: 53 | i++; 54 | _poorQuality = _payloadData[i]; 55 | _bigPacket = true; 56 | break; 57 | case 4: 58 | i++; 59 | _attention = _payloadData[i]; 60 | break; 61 | case 5: 62 | i++; 63 | _meditation = _payloadData[i]; 64 | break; 65 | case 0x80: 66 | i = i + 3; 67 | break; 68 | case 0x83: 69 | i++; 70 | for (int j = 0; j < MINDWAVE_EEG_SIZE; j++) { 71 | _eeg[j] = ((int)_payloadData[++i] << 16) | ((int)_payloadData[++i] << 8) | (int)_payloadData[++i]; 72 | } 73 | break; 74 | default: 75 | break; 76 | } // switch 77 | } // for loop 78 | if(_bigPacket) { 79 | _lastUpdate = millis() - _lastReceivedPacket; 80 | _lastReceivedPacket = millis(); 81 | onData(); 82 | } 83 | _bigPacket = false; 84 | } 85 | int Mindwave::attention(){ 86 | return _attention; 87 | } 88 | int Mindwave::meditation(){ 89 | return _meditation; 90 | } 91 | int Mindwave::quality(){ 92 | return (100-(_poorQuality/2)); 93 | } 94 | long Mindwave::lastUpdate(){ 95 | return _lastUpdate; 96 | } 97 | int* Mindwave::eeg(){ 98 | return _eeg; 99 | } 100 | int Mindwave::delta(){ 101 | return _eeg[0]; 102 | } 103 | int Mindwave::theta(){ 104 | return _eeg[1]; 105 | } 106 | int Mindwave::lowAlpha(){ 107 | return _eeg[2]; 108 | } 109 | int Mindwave::highAlpha(){ 110 | return _eeg[3]; 111 | } 112 | int Mindwave::lowBeta(){ 113 | return _eeg[4]; 114 | } 115 | int Mindwave::highBeta(){ 116 | return _eeg[5]; 117 | } 118 | int Mindwave::lowGamma(){ 119 | return _eeg[6]; 120 | } 121 | int Mindwave::midGamma(){ 122 | return _eeg[7]; 123 | } -------------------------------------------------------------------------------- /Mindwave.h: -------------------------------------------------------------------------------- 1 | // 2 | // Mindwave Mobile parser 3 | // Based on the Mindwave Arduino sample: http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino 4 | // and the ThinkGear Protocol specs: http://developer.neurosky.com/docs/doku.php?id=thinkgear_communications_protocol 5 | // Created by George Profenza on 03/04/2015. 6 | // 7 | 8 | #ifndef Mindwave_h 9 | #define Mindwave_h 10 | 11 | #include 12 | #if defined(ARDUINO) && ARDUINO >= 100 13 | #include "Arduino.h" 14 | #else 15 | #include "WProgram.h" 16 | #include 17 | #endif 18 | 19 | //baud rate 20 | #define MINDWAVE_BAUDRATE 57600 21 | //states 22 | #define MINDWAVE_WAIT_FOR_FIRST_A 0 23 | #define MINDWAVE_WAIT_FOR_SECOND_A 1 24 | #define MINDWAVE_WAIT_FOR_PAYLOAD_LENGTH 2 25 | #define MINDWAVE_WAIT_FOR_PAYLOAD 3 26 | #define MINDWAVE_WAIT_FOR_CHECKSUM 4 27 | //EEG 28 | #define MINDWAVE_EEG_SIZE 8 29 | #define MINDWAVE_PACKET_MAX_SIZE 173 30 | #define MINDWAVE_PAYLOAD_MAX_SIZE 169 31 | 32 | typedef void (*MindwaveDataCallback) (); 33 | 34 | class Mindwave 35 | { 36 | 37 | 38 | public: 39 | 40 | Mindwave(); 41 | void update(Stream &stream,MindwaveDataCallback onData); 42 | int attention(); 43 | int meditation(); 44 | int quality(); 45 | long lastUpdate(); 46 | int* eeg(); 47 | int delta(); 48 | int theta(); 49 | int lowAlpha(); 50 | int highAlpha(); 51 | int lowBeta(); 52 | int highBeta(); 53 | int lowGamma(); 54 | int midGamma(); 55 | private: 56 | // checksum variables 57 | byte _generatedChecksum = 0; 58 | byte _checksum = 0; 59 | int _payloadLength = 0; 60 | int _payloadIndex; 61 | byte _payloadData[MINDWAVE_PACKET_MAX_SIZE] = {0}; 62 | 63 | byte _poorQuality = 0; 64 | byte _attention; 65 | byte _meditation; 66 | int _eeg[MINDWAVE_EEG_SIZE]; 67 | // system variables 68 | long _lastReceivedPacket = 0, _lastUpdate = 0; 69 | boolean _bigPacket = false; 70 | int _state = 0; 71 | 72 | void parsePayload(MindwaveDataCallback onData); 73 | 74 | }; 75 | 76 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mindwave Mobile Parser 2 | ====================== 3 | 4 | Simple parser for Mindwave Mobile EEG headsets. 5 | 6 | How to install the library 7 | ========================== 8 | 9 | 1. [Download the library](https://github.com/orgicus/Mindwave/archive/master.zip) 10 | 2. Unzip **Mindwave-master.zip** and rename the **Mindwave-master** folder to the **Mindwave** 11 | 4. Move the freshly rename **Mindwave** folder into the **Documents/Arduino/libraries** and restart Arduino 12 | 13 | 14 | How to use the library 15 | ========================== 16 | If you're using the Serial class and simply want to get the attention value, 17 | it's as simple as this 18 | ``` cpp 19 | #include //import the library 20 | Mindwave mindwave; //start using it 21 | 22 | void setup() { 23 | Serial.begin(MINDWAVE_BAUDRATE); //setup serial communication (MindWave mobile is set to 57600 baud rate) 24 | } 25 | //create a function to received new values as soon as they're avaialble 26 | void onMindwaveData(){ 27 | Serial.print("attention: "); 28 | Serial.println(mindwave.attention()); //access attention value 29 | } 30 | void loop() { 31 | mindwave.update(Serial,onMindwaveData);//update using the data input(Serial in this case) and the function to call when data is ready 32 | } 33 | ``` 34 | 35 | For more examples go to **Arduino > File > Examples > Mindwave** 36 | 37 | Notes 38 | ===== 39 | 40 | Be aware, this is my first Arduino library, so things might not be 100% top-notch. 41 | The code is mostly based on the [official NeuroSky wiki article](http://developer.neurosky.com/docs/doku.php?id=mindwave_mobile_and_arduino) and the [ThinkGear protocol specs](http://developer.neurosky.com/docs/doku.php?id=thinkgear_communications_protocol#bit_raw_wave_value) 42 | 43 | However, it was developed for the **Focus** project. 44 | This is is covered on the following websites: 45 | * [Ditte Blohm](http://ditteblohm.com/FOCUS) 46 | * [Hirsch & Mann](http://www.hirschandmann.com/walking-in-comfort-at-milan-furniture-fair/) 47 | * [Hackaday.io](https://hackaday.io/project/5969-focus) 48 | 49 | ![Walk With Me](https://cdn.hackaday.io/images/2043671432588591267.jpg) 50 | ![Walk With Me](https://cdn.hackaday.io/images/8390241432588613274.jpg) 51 | ![Arduino Shield for DMX and (Mindwave Mobile) Bluetooth](https://cdn.hackaday.io/images/1718121432604763894.jpg) 52 | 53 | -------------------------------------------------------------------------------- /examples/AltSoftSerial/AltSoftSerial.ino: -------------------------------------------------------------------------------- 1 | /** 2 | I found AltSoftSerial more reliable than SoftwareSerial (depends on the version). 3 | https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html 4 | 5 | AltSoftSerial pins 6 | 7 | Board Transmit Pin Receive Pin Unusable PWM 8 | Teensy 3.0 & 3.1 21 20 22 9 | Teensy 2.0 9 10 (none) 10 | Teensy++ 2.0 25 4 26, 27 11 | Arduino Uno 9 8 10 12 | Arduino Leonardo 5 13 (none) 13 | Arduino Mega 46 48 44, 45 14 | Wiring-S 5 6 4 15 | Sanguino 13 14 12 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | AltSoftSerial bluetooth; 22 | Mindwave mindwave; 23 | 24 | void setup() { 25 | bluetooth.begin(MINDWAVE_BAUDRATE); 26 | } 27 | void onMindwaveData(){ 28 | Serial.print("\tquality: "); 29 | Serial.print(mindwave.quality()); 30 | Serial.print("\tattention: "); 31 | Serial.print(mindwave.attention()); 32 | Serial.print("\tmeditation: "); 33 | Serial.print(mindwave.meditation()); 34 | Serial.print("\tlast update: "); 35 | Serial.print(mindwave.lastUpdate()); 36 | Serial.print("ms ago"); 37 | Serial.println(); 38 | } 39 | void loop() { 40 | mindwave.update(bluetooth,onMindwaveData); 41 | } -------------------------------------------------------------------------------- /examples/EEG/EEG.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | Mindwave mindwave; 4 | int* eeg; 5 | 6 | void setup() { 7 | Serial.begin(MINDWAVE_BAUDRATE); 8 | Serial.println("delta\ttheta\tlowAlpha\thighAlpha\tlowBeta\thightBeta\tlowGamma\thighGamma"); 9 | } 10 | void onMindwaveData(){ 11 | eeg = mindwave.eeg(); 12 | for(int i = 0 ; i < MINDWAVE_EEG_SIZE; i++){ 13 | Serial.print(eeg[i]); 14 | if(i < MINDWAVE_EEG_SIZE) Serial.print('\t'); 15 | } 16 | Serial.println(); 17 | //alternatively get individual value via delta(),theta() ,lowAlpha() ,highAlpha() ,lowBeta() ,highBeta() ,lowGamma() ,midGamma() functions 18 | } 19 | void loop() { 20 | mindwave.update(Serial,onMindwaveData); 21 | } 22 | -------------------------------------------------------------------------------- /examples/Serial/Serial.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | Mindwave mindwave; 4 | 5 | void setup() { 6 | Serial.begin(MINDWAVE_BAUDRATE); 7 | } 8 | void onMindwaveData(){ 9 | Serial.print("\tquality: "); 10 | Serial.print(mindwave.quality()); 11 | Serial.print("\tattention: "); 12 | Serial.print(mindwave.attention()); 13 | Serial.print("\tmeditation: "); 14 | Serial.print(mindwave.meditation()); 15 | Serial.print("\tlast update: "); 16 | Serial.print(mindwave.lastUpdate()); 17 | Serial.print("ms ago"); 18 | Serial.println(); 19 | } 20 | void loop() { 21 | mindwave.update(Serial,onMindwaveData); 22 | } 23 | -------------------------------------------------------------------------------- /examples/TwoHeadsets/TwoHeadsets.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | AltSoftSerial bluetooth; 5 | Mindwave mindwave; 6 | 7 | void setup() { 8 | bluetooth.begin(MINDWAVE_BAUDRATE); 9 | Serial.begin(MINDWAVE_BAUDRATE); 10 | } 11 | void headset1Event(){ 12 | Serial.print("headset 1"); 13 | Serial.print("\tquality: "); 14 | Serial.print(mindwave.quality()); 15 | Serial.print("\tattention: "); 16 | Serial.print(mindwave.attention()); 17 | Serial.print("\tmeditation: "); 18 | Serial.print(mindwave.meditation()); 19 | Serial.print("\tlast update: "); 20 | Serial.print(mindwave.lastUpdate()); 21 | Serial.print("ms ago"); 22 | Serial.println(); 23 | } 24 | void headset2Event(){ 25 | Serial.print("headset 2"); 26 | Serial.print("\tquality: "); 27 | Serial.print(mindwave.quality()); 28 | Serial.print("\tattention: "); 29 | Serial.print(mindwave.attention()); 30 | Serial.print("\tmeditation: "); 31 | Serial.print(mindwave.meditation()); 32 | Serial.print("\tlast update: "); 33 | Serial.print(mindwave.lastUpdate()); 34 | Serial.print("ms ago"); 35 | Serial.println(); 36 | } 37 | void loop() { 38 | mindwave.update(bluetooth,headset1Event); 39 | mindwave.update(Serial,headset2Event); 40 | } 41 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | Mindwave KEYWORD1 2 | MINDWAVE_BAUDRATE KEYWORD1 3 | #define MINDWAVE_EEG_SIZE KEYWORD1 4 | update(Stream &stream,MindwaveDataCallback onData) 5 | attention KEYWORD2 6 | meditation KEYWORD2 7 | quality KEYWORD2 8 | lastUpdate KEYWORD2 9 | eeg KEYWORD2 10 | delta KEYWORD2 11 | theta KEYWORD2 12 | lowAlpha KEYWORD2 13 | highAlpha KEYWORD2 14 | lowBeta KEYWORD2 15 | highBeta KEYWORD2 16 | lowGamma KEYWORD2 17 | midGamma KEYWORD2 --------------------------------------------------------------------------------