Skip to content

ADD: Support for aux data packets #50 #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 47 additions & 37 deletions open_bci_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ def handle_sample(sample):

SAMPLE_RATE = 250.0 # Hz
START_BYTE = 0xA0 # start of data packet
END_BYTE = 0xC0 # end of data packet
END_BYTE_ACCEL = 0xC0 # end of data packet with accel data
END_BYTE_AUX = 0xC1 # end of data packet with aux data
ADS1299_Vref = 4.5 #reference voltage for ADC in ADS1299. set by its hardware
ADS1299_gain = 24.0 #assumed gain setting for ADS1299. set by its Arduino code
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
scale_fac_accel_G_per_count = 0.002 /(pow(2,4)) #assume set to +/4G, so 2 mG
'''
#Commands for in SDK http://docs.openbci.com/software/01-Open BCI_SDK:

Expand Down Expand Up @@ -68,7 +69,7 @@ class OpenBCIBoard(object):
"""

def __init__(self, port=None, baud=115200, filter_data=True,
scaled_output=True, daisy=False, aux=False, impedance=False, log=True, timeout=None):
scaled_output=True, scaled_accel=True, daisy=False, aux=False, impedance=False, log=True, timeout=None):
self.log = log # print_incoming_text needs log
self.streaming = False
self.baudrate = baud
Expand All @@ -94,6 +95,7 @@ def __init__(self, port=None, baud=115200, filter_data=True,
self.streaming = False
self.filtering_data = filter_data
self.scaling_output = scaled_output
self.scaling_aux = scaled_accel
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.imp_channels_per_sample = 0 # impedance check not supported at the moment
Expand All @@ -112,35 +114,35 @@ def __init__(self, port=None, baud=115200, filter_data=True,
def getBoardType(self):
""" Returns the version of the board """
return self.board_type

def setImpedance(self, flag):
""" Enable/disable impedance measure. Not implemented at the moment on Cyton. """
return

def ser_write(self, b):
"""Access serial port object for write"""
"""Access serial port object for write"""
self.ser.write(b)

def ser_read(self):
"""Access serial port object for read"""
"""Access serial port object for read"""
return self.ser.read()

def ser_inWaiting(self):
"""Access serial port object for inWaiting"""
"""Access serial port object for inWaiting"""
return self.ser.inWaiting();

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

Expand All @@ -165,7 +167,7 @@ def start_streaming(self, callback, lapse=-1):
# Enclose callback funtion in a list if it comes alone
if not isinstance(callback, list):
callback = [callback]


#Initialize check connection
self.check_connection()
Expand All @@ -189,13 +191,13 @@ def start_streaming(self, callback, lapse=-1):
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 + 1;


"""
PARSER:
Parses incoming data packet into OpenBCISample.
Expand All @@ -220,9 +222,9 @@ def read(n):

#---------Start Byte & ID---------
if self.read_state == 0:

b = read(1)

if struct.unpack('B', b)[0] == START_BYTE:
if(rep != 0):
self.warn('Skipped %d bytes before start found' %(rep))
Expand All @@ -245,7 +247,7 @@ def read(n):

#3byte int in 2s compliment
if (unpacked[0] > 127):
pre_fix = bytes(bytearray.fromhex('FF'))
pre_fix = bytes(bytearray.fromhex('FF'))
else:
pre_fix = bytes(bytearray.fromhex('00'))

Expand All @@ -271,27 +273,35 @@ def read(n):
acc = struct.unpack('>h', read(2))[0]
log_bytes_in = log_bytes_in + '|' + str(acc);

if self.scaling_output:
if self.scaling_aux:
aux_data.append(acc*scale_fac_accel_G_per_count)
else:
aux_data.append(acc)
aux_data.append(acc)

self.read_state = 3;
#---------End Byte---------
elif self.read_state == 3:
val = struct.unpack('B', read(1))[0]
log_bytes_in = log_bytes_in + '|' + str(val);
self.read_state = 0 #read next packet
if (val == END_BYTE):
if (val == END_BYTE_ACCEL):
if not self.scaling_aux:
self.scaling_aux = True
sample = OpenBCISample(packet_id, channel_data, aux_data)
self.packets_dropped = 0
return sample
elif (val == END_BYTE_AUX):
if self.scaling_aux:
self.scaling_aux = False
sample = OpenBCISample(packet_id, channel_data, aux_data)
self.packets_dropped = 0
return sample
else:
self.warn("ID:<%d> <Unexpected END_BYTE found <%s> instead of <%s>"
%(packet_id, val, END_BYTE))
self.warn("ID:<%d> <Unexpected END_BYTE found <%s> instead of <%s> or <%s>"
%(packet_id, val, END_BYTE_ACCEL, END_BYTE_AUX))
logging.debug(log_bytes_in);
self.packets_dropped = self.packets_dropped + 1

"""

Clean Up (atexit)
Expand All @@ -311,7 +321,7 @@ def disconnect(self):
print("Closing Serial...")
self.ser.close()
logging.warning('serial closed')


"""

Expand All @@ -338,7 +348,7 @@ def print_incoming_text(self):
line = ''
#Wait for device to send data
time.sleep(1)

if self.ser.inWaiting():
line = ''
c = ''
Expand All @@ -359,7 +369,7 @@ def openbci_id(self, serial):
line = ''
#Wait for device to send data
time.sleep(2)

if serial.inWaiting():
line = ''
c = ''
Expand Down Expand Up @@ -390,7 +400,7 @@ def print_bytes_in(self):
def print_packets_in(self):
while self.streaming:
b = struct.unpack('B', self.ser.read())[0];

if b == START_BYTE:
self.attempt_reconnect = False
if skipped_str:
Expand All @@ -400,7 +410,7 @@ def print_packets_in(self):
packet_str = "%03d"%(b) + '|';
b = struct.unpack('B', self.ser.read())[0];
packet_str = packet_str + "%03d"%(b) + '|';

#data channels
for i in range(24-1):
b = struct.unpack('B', self.ser.read())[0];
Expand All @@ -413,29 +423,29 @@ def print_packets_in(self):
for i in range(6-1):
b = struct.unpack('B', self.ser.read())[0];
packet_str = packet_str + '.' + "%03d"%(b);

b = struct.unpack('B', self.ser.read())[0];
packet_str = packet_str + '.' + "%03d"%(b) + '|';

#end byte
b = struct.unpack('B', self.ser.read())[0];

#Valid Packet
if b == END_BYTE:
if b == END_BYTE_ACCEL or b == END_BYTE_AUX:
packet_str = packet_str + '.' + "%03d"%(b) + '|VAL';
print(packet_str)
#logging.debug(packet_str)

#Invalid Packet
else:
packet_str = packet_str + '.' + "%03d"%(b) + '|INV';
#Reset
self.attempt_reconnect = True


else:
print(b)
if b == END_BYTE:
if b == END_BYTE_ACCEL or b == END_BYTE_AUX:
skipped_str = skipped_str + '|END|'
else:
skipped_str = skipped_str + "%03d"%(b) + '.'
Expand All @@ -444,7 +454,7 @@ def print_packets_in(self):
self.last_reconnect = timeit.default_timer()
self.warn('Reconnecting')
self.reconnect()



def check_connection(self, interval = 2, max_packets_to_skip=10):
Expand Down