照海倚天 发表于 2016-11-23 14:25:05

[硅谷行报名]“脑电之翼”--牛刀小试(专注度点亮LDE)

本帖最后由 Genius 于 2016-11-30 16:24 编辑

    话说申请了机智云Gokit2开发板,咱就不能闲着啊 ,就要干活 ,就把最近的进度汇报下:lol。    因为项目的需要,就在网上购买了“意念方舟头带”,下面是他的自拍,好家伙小400块,不是特别贵吧,但是还是感觉有点贵,想想是学校给的项目经费,掏的是学校的腰包就不那么心疼了,但是国家支持咱们研究,咱就得好好干活啊,你说对吧,闲话少叙,开工:lol。
                            通过这一段时间的学习与实践,已经可以从“意念方舟头带”上获取数据,并进行处理分析,并在读取数据后做出相应动作,下面是具体说明。    硬件模块:Thinkgear模块机智云GoKit2    蓝牙HC-05模块    软件:MindViewer   XCOM V2.0.exe   Arduino    细节说明:之前一直再采集数据,但是数据一直不能正常读取到,后来通过与卖家的交流与沟通发现可能是头带上蓝牙模块的问题,经过改装最后终于解决了其中的问题,最后能从头带上获取数据了。       数据通过蓝牙传输,其中只要把蓝牙模块配置为主机,波特率设置为57600    接线方式如图
   
         实物图:         
         至于头带吗 当然是要戴在头上的,因为本人忒丑,就让这个歪果仁来展示怎么佩戴吧 。         


    原始数据:
       经过查阅thinkgear数据手册可以知道:TGAM大约每秒钟发送513个包, 发送送的包有小包和大包两种:小包的格式是AA AA 04 80 02 xxHigh xxLow xxCheckSum前面的AA AA 04 80 02 是不变的,后三个字节是一只变化的,xxHigh和xxLow组成了原始数据rawdata,xxCheckSum就是校验和。所以一个小包里面只包含了一个对开发者来 说有用的数据,那就是rawdata,可以说一个小包就是一个原始数据,大约每秒钟会有 512个原始数据。rawdata = (xxHigh << 8) | xxLow; if(rawdata > 32768){      rawdata=65536;
}现在原始数据就这么算出来了,但是在算原始数据之前,我们先应该检查校验和。sum = ((0x80 + 0x02 + xxHigh + xxLow)^ 0xFFFFFFFF) & 0xFF    就是把04后面的四个字节加起来,取反,再取低八位。 如果算出来的sum和xxCheckSum是相等的,那说明这个包是正确的,然后再去计算 rawdata,否则直接忽略这个包。丢包率在10%以下是不会对最后结果造成影响的。大包中是信号强度Signal,专注度Attention,放松度 Meditation,和8个EEG Power的值它们在在第513个这个大包里面,这个大包的格式是固定的。
AA 同步AA 同步20 是十进制的32,即有32个字节的payload,除掉20本身+两个AA同步+最后校验和 02 代表信号值Signal 33信号的值 83 代表EEG Power开始了 18 是十进制的24,说明EEG Power是由24个字节组成的,以下每三个字节为一组 0D Delta 1/3 CC Delta 2/3 64Delta 3/3 01 Theta 1/3 81 Theta 2/3 C5 Theta 3/3 01 LowAlpha 1/3 30 LowAlpha 2/3 36 LowAlpha 3/3 00 HighAlpha 1/3 BD HighAlpha 2/3 E4 HighAlpha 3/3 00 LowBeta 1/3 A9LowBeta 2/3 F0 LowBeta 3/3 00 Hi**eta 1/3 F4 Hi**eta 2/3 66 Hi**eta 3/3 00 LowGamma 1/3 FF LowGamma 2/3 F0 LowGamma 3/3 00 MiddleGamma 1/3 DB MiddleGamma 2/3 FB MiddleGamma 3/3 04 代表专注度Attention 00 Attention的值(0到100之间) 05 代表放松度Meditation 00 Meditation的值(0到100之间) D5 校验和 所得的数据可以在MindViewer中显示出来,其中包括attention,Meditation等数据 及最原始的α,β,γ等波形 。效果如图所示
通过对数据的识别与处理,我使用机智云提够的Gokit2开发板,对数据进行处理,计划做成专注度识别控制的LED显示。下面为arduino源程序 :<em>#define LED 13

#define BAUDRATE 57600

#define DEBUGOUTPUT 0

#define GREENLED1 3

#define GREENLED2 4

#define GREENLED3 5

#define YELLOWLED1 6

#define YELLOWLED2 7

#define YELLOWLED3 8

#define YELLOWLED4 9

#define REDLED1 10

#define REDLED2 11

#define REDLED3 12

#define powercontrol 10

// checksum variables

byte generatedChecksum = 0;

byte checksum = 0;

int payloadLength = 0;

byte payloadData = {0};

byte poorQuality = 0;

byte attention = 0;

byte meditation = 0;

// system variables

long lastReceivedPacket = 0;

boolean bigPacket = false;



void setup()

{

pinMode(GREENLED1, OUTPUT);

pinMode(GREENLED2, OUTPUT);

pinMode(GREENLED3, OUTPUT);

pinMode(YELLOWLED1, OUTPUT);

pinMode(YELLOWLED2, OUTPUT);

pinMode(YELLOWLED3, OUTPUT);

pinMode(YELLOWLED4, OUTPUT);

pinMode(REDLED1, OUTPUT);

pinMode(REDLED2, OUTPUT);

pinMode(REDLED3, OUTPUT);

pinMode(LED, OUTPUT);

Serial.begin(BAUDRATE); // USB

}



byte ReadOneByte()

{

int ByteRead;

while(!Serial.available());

ByteRead = Serial.read();

#if DEBUGOUTPUT

Serial.print((char)ByteRead);

#endif

return ByteRead;

}



void loop()

{

// Look for sync bytes

if(ReadOneByte() == 170)

{

if(ReadOneByte() == 170)

{

payloadLength = ReadOneByte();

if(payloadLength > 169) //Payload lengthcan not be greater than 169

return;

generatedChecksum = 0;

for(int i = 0; i < payloadLength; i++)

{

payloadData = ReadOneByte(); //Readpayload into memory

generatedChecksum += payloadData;

}

checksum = ReadOneByte(); //Read checksumbyte 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)

{

case 2:

i++;

poorQuality = payloadData;

bigPacket = true;

break;

case 4:

i++;

attention = payloadData;

break;

case 5:

i++;

meditation = payloadData;

break;

case 0x80:

i = i + 3;

break;

case 0x83:

i = i + 25;

break;

default:

break;

} // switch

} // for loop

#if !DEBUGOUTPUT

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:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, LOW);

digitalWrite(GREENLED3, LOW);

digitalWrite(YELLOWLED1, LOW);

digitalWrite(YELLOWLED2, LOW);

digitalWrite(YELLOWLED3, LOW);

digitalWrite(YELLOWLED4, LOW);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 1:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, LOW);

digitalWrite(YELLOWLED1, LOW);

digitalWrite(YELLOWLED2, LOW);

digitalWrite(YELLOWLED3, LOW);

digitalWrite(YELLOWLED4, LOW);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 2:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, LOW);

digitalWrite(YELLOWLED2, LOW);

digitalWrite(YELLOWLED3, LOW);

digitalWrite(YELLOWLED4, LOW);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 3:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, LOW);

digitalWrite(YELLOWLED3, LOW);

digitalWrite(YELLOWLED4, LOW);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 4:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, LOW);

digitalWrite(YELLOWLED4, LOW);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 5:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, HIGH);

digitalWrite(YELLOWLED4, LOW);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 6:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, HIGH);

digitalWrite(YELLOWLED4, HIGH);

digitalWrite(REDLED1, LOW);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 7:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, HIGH);

digitalWrite(YELLOWLED4, HIGH);

digitalWrite(REDLED1, HIGH);

digitalWrite(REDLED2, LOW);

digitalWrite(REDLED3, LOW);

break;

case 8:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, HIGH);

digitalWrite(YELLOWLED4, HIGH);

digitalWrite(REDLED1, HIGH);

digitalWrite(REDLED2, HIGH);

digitalWrite(REDLED3, LOW);

break;

case 9:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, HIGH);

digitalWrite(YELLOWLED4, HIGH);

digitalWrite(REDLED1, HIGH);

digitalWrite(REDLED2, HIGH);

digitalWrite(REDLED3, HIGH);

break;

case 10:

digitalWrite(GREENLED1, HIGH);

digitalWrite(GREENLED2, HIGH);

digitalWrite(GREENLED3, HIGH);

digitalWrite(YELLOWLED1, HIGH);

digitalWrite(YELLOWLED2, HIGH);

digitalWrite(YELLOWLED3, HIGH);

digitalWrite(YELLOWLED4, HIGH);

digitalWrite(REDLED1, HIGH);

digitalWrite(REDLED2, HIGH);

digitalWrite(REDLED3, HIGH);

break;

}

}

#endif

bigPacket = false;

}

else {

// Checksum Error

} // end if else for checksum

} // end if read 0xAA byte

} // end if read 0xAA byte

}</em>
程序可实现通过把人的专注度以点亮LED多少展示出来 。

   这个是视频展示的地址 :   http://v.youku.com/v_show/id_XMTgzMTY0NjI2OA==.html    未来计划:    进一步研究数据,对数据进一步分析处理,深入研究thinkgear数据流,分析每一种波形的相应功能作用,提取关于健康方面有用信息,贴近脑点之翼的初衷,自己设计自己的app进行数据分析处理,尽可能的完成最初的设计理念。










bigfanofloT 发表于 2016-11-23 15:11:52

赞一个:lol

Cherry 发表于 2016-11-28 23:44:33

期待楼主佳作
页: [1]
查看完整版本: [硅谷行报名]“脑电之翼”--牛刀小试(专注度点亮LDE)