direct MATLAB serial interface vs LSL ?
Hello all,
--------------------------------------------------------------
I'm currently developing a Matlab interface to operate with my openBCI. I use openBCI in the context of a EEG-based brain-machine interface. I created this thread because I thought it would be nice to share my progress with the openBCI community and maybe find some help whenever I get stuck. I will be publishing my code once it works.
So far, things have been progressing well. I found most of the information I needed here: http://docs.openbci.com/software/02-OpenBCI_Streaming_Data_Format
Very quickly, I was able to reset the device and read the returning status packet.
--------------------------------------------------------------
% constants I'm using
OPENBCI_PORT = 'COM8';
OPENBCI_BAUDRATE = 115200;
START_STREAMING_MSG = char('b');
STOP_STREAMING_MSG = char('s');
RESET_MSG = char('v');
% init the port
s_bci = serial(OPENBCI_PORT,'BaudRate',OPENBCI_BAUDRATE);
fopen(s_bci);
% write a reset
fwrite(s_bci,RESET_MSG,'uchar');
% read the status data
status_chunk = fread(s_bci,STATUS_PACKET_LENGTH);
--------------------------------------------------------------
Then, I was able to put the device in streaming mode and capture a certain number of packets.
--------------------------------------------------------------
% go in streaming mode
fwrite(s_bci,START_STREAMING_MSG,'uchar');
% read 100x33 bytes packets and pack them in an array
nb_samples = 100;
eeg_data = zeros(nb_samples,8);
for ii=1:nb_samples
temp = fread(s_bci,DATA_PACKET_LENGTH);
eeg_data(ii,:) = unpack_openbci_eeg(temp);
end
% stop streaming
fwrite(s_bci,STOP_STREAMING_MSG,'uchar');
--------------------------------------------------------------
What, I'm currently struggling with. however, is that I would like to be able to go back in streaming mode and capture another series of packets. On paper, it's not a problem, but it appears that Matlab serial buffer is filled with samples that came in after the last fread and before the fwrite was effective. I thought I could simply empty the buffer using the line:
fread(s_bci,s_bci.BytesAvailable);
but that doesn't do it. In fact, I got my best result using:
--------------------------------------------------------------
while s_bci.BytesAvailable>0
fread(s_bci,s_bci.BytesAvailable);
pause(0.1)
end
And then, I was able to do a second run. This method, however, is not very stable and because I read fixed packet length, whenever the buffer wraps around, my program lose track of packet beginning.
Also, even though the code above work fairly correctly, whenever I try to do something with the packets, such as displaying them, my interface begins too slow and the buffer gets overrun.
I don't have a precise question, but I'm thinking of ways to improve the reliability of my program, by investigating the following possibilities, feel free to suggest other ideas or comment on these:
- Read more than one packet at a time from the buffer. Right now, I read only one packet, but maybe reading an integer number of packets at a time would optimize the time spent at extracting the packets.
- Dynamically find the beginning of the packets and then extract the data. Right now, I can't miss any packet, I'm depending on their alignment in the buffer.
Fred
PS: I built a function to extract eeg samples from packets, it includes a function to translate from 24bits to 32bits. It took me an afternoon to get it to work, but let me know if you need it and l'll give it to you.
Comments
A direct serial port MATLAB interface might be helpful. And... The LSL interface via @jfrey 's Python plugin may also be another route you may want to consider. LSL can bridge between many different packages.
http://openbci.com/forum/index.php?p=/discussion/334/labstreaminglayer-into-bcilab-eeglab-matlab
William
By the way, I now have a better way to flush the buffer.
Complete BrainBay tree is here.