基于python可以在Mac/linux/windows系统获取BCIduino脑电数据,基于android我们也提供了方案,联系下方管理员可以索取。此处贴出基于python获取BCIduino脑电数据的程序代码,有爱好者实测,可以在同一台电脑获取多个BCIduino模组的数据。
import sys
from pylsl import StreamInfo, StreamOutlet
import argparse
import os
import string
import atexit
import threading
import sys
import random
import serial
import struct
import numpy as np
import time
import timeit
import atexit
import logging
import pdb
import glob
header = {
}
sample_count = 0
dict1 = dict(channal1= 0,channal2= 0,channal3= 0,channal4= 0,channal5= 0,channal6= 0,channal7= 0,ch8= 0,refer1 =0,refer2 = 0)
data_ = []
SAMPLE_RATE = 500.0 # or 250
START_BYTE = 0xA0 # start of data packet
END_BYTE = 0xC0 # end of data packet
ADS1299_Vref = 4.5 #reference voltage for ADC in ADS1299. set by its hardware
ADS1299_gain = 24.0 #assumed gain setting for ADS1299.
scale_fac_uVolts_per_count = ADS1299_Vref/float((pow(2,23)-1))/ADS1299_gain*1000000.
scale_fac_accel_G_per_count = 0.002 /(pow(2,4)) #assume set to +/4G, so 2 mG
c = ''
'''
command_stop = "s";
command_startText = "x";
command_startBinary = "b";
command_startBinary_wAux = "n";
command_startBinary_4chan = "v";
command_activateFilters = "F";
command_deactivateFilters = "g";
command_deactivate_channel = {
"1", "2", "3", "4", "5", "6", "7", "8"};
command_activate_channel = {
"q", "w", "e", "r", "t", "y", "u", "i"};
command_activate_leadoffP_channel = {
"!", "@", "#", "$", "%", "^", "&", "*"}; //shift + 1-8
command_deactivate_leadoffP_channel = {
"Q", "W", "E", "R", "T", "Y", "U", "I"}; //letters (plus shift) right below 1-8
command_activate_leadoffN_channel = {
"A", "S", "D", "F", "G", "H", "J", "K"}; //letters (plus shift) below the letters below 1-8
command_deactivate_leadoffN_channel = {
"Z", "X", "C", "V", "B", "N", "M", "<"}; //letters (plus shift) below the letters below the letters below 1-8
command_biasAuto = "`";
command_biasFixed = "~";
'''
class BCIduinoSample(object):
"""Object encapulsating a single sample from the BCIduino board."""
def __init__(self, packet_id, channel_data, aux_data):
self.id = packet_id
self.channel_data = channel_data
self.aux_data = aux_data
class BCIduinoBoard(object):
"""
Handle a connection to an BCIduino board.
Args:
port: The port to connect to.
baud: The baud of the serial connection.
"""
def __init__(self, port=None, baud=256000, filter_data=True,
scaled_output=True, daisy=False, log=True, timeout=None):
self.log = log
self.streaming = False
self.baudrate = baud
self.timeout = timeout
if not port:
port = 'COM3'
self.port = port
print("Connecting to BCIduino at port %s" %(port))
self.ser = serial.Serial(port= port, baudrate = baud, timeout=timeout)
print("Serial established...")
time.sleep(2)
#Initialize 32-bit board, doesn't affect 8bit board
self.ser.write(b'v')
#wait for device to be ready
time.sleep(1)
self.print_incoming_text()
self.streaming = False
self.filtering_data = filter_data
self.scaling_output = scaled_output
self.eeg_channels_per_sample = 8 # number of EEG channels per sample *from the board*
self.aux_channels_per_sample = 3 # number of AUX channels per sample *from the board*
self.read_state = 0
self.daisy = daisy
self.last_odd_sample = BCIduinoSample(-1, [], []) # used for daisy
self.log_packet_count = 0
self.attempt_reconnect = False
self.last_reconnect = 0
self.reconnect_freq = 5
self.packets_dropped = 0
#Disconnects from board when terminated
atexit.register(self.disconnect)
def getSampleRate(self):
if self.daisy:
return SAMPLE_RATE/2
else:
return SAMPLE_RATE
def getNbEEGChannels(self):
if self.daisy:
return self.eeg_channels_per_sample*2
else:
return self.eeg_channels_per_sample
def getNbAUXChannels(self):
return self.aux_channels_per_sample
def start_streaming(self, callback, lapse=-1):
"""
Start handling streaming data from the board. Call a provided callback
for every single sample that is processed (every two samples with daisy module).
Args:
callback: A callback function -- or a list of functions -- that will receive a single argument of the
BCIduinoSample object captured.
"""
if not self.streaming:
self.ser.write(b'b')
self.streaming = True
start_time = timeit.default_timer()
# Enclose callback funtion in a list if it comes alone
if not isinstance(callback, list):
callback = [callback]
#Initialize check connection
self.check_connection()
while self.streaming:
# read current sample
sample = self._read_serial_binary()
# if a daisy module is attached, wait to concatenate two samples (main board + daisy) before passing it to callback
if self.daisy:
# odd sample: daisy sample, save for later
if ~sample.id % 2:
self.last_odd_sample = sample
# even sample: concatenate and send if last sample was the fist part, otherwise drop the packet
elif sample.id - 1 == self.last_odd_sample.id:
# the aux data will be the average between the two samples, as the channel samples themselves have been averaged by the board
avg_aux_data = list((np.array(sample.aux_data) + np.array(self.last_odd_sample.aux_data))/2)
whole_sample = BCIduinoSample(sample.id, sample.channel_data + self.last_odd_sample.channel_data, avg_aux_data)
for call in callback:
call(whole_sample)
else:
for call in callback:
call(sample)
if(lapse > 0 and timeit.default_timer() - start_time > lapse):
self.stop()
if self.log:
self.log_packet_count = self.log_packet_count
"""
PARSER:
Parses incoming data packet into BCIduinoSample.
Incoming Packet Structure:
Start Byte(1)|Sample ID(1)|Channel Data(24)|Aux Data(6)|End Byte(1)
0xA0|0-255|8, 3-byte signed ints|3