Prospects for higher sample rates?
I'm interested in any means to increase the sample rate of OBCI. The application is real-time neurofeedback, so I'm unsure that any solution involving an SD-card, e.g.
http://openbci.com/forum/index.php?p=/discussion/546/solution-for-session-freezing-overruns-2khz-sample-rate-with-sd-only
will be useful. Are there any hacks now, or any prospects in the future, for higher sample rates for OBCI? Boosting the 32-bit 16-channel board up from 125 Hz would be particularly awesome.
Comments
There is currently a speed bottleneck in the serial link between the chipKIT and the mainboard RFduino. As well as another speed limit in the RFduino's radio link. There are a number of older threads which discuss the details and possible workarounds, such as: Bluetooth 2 or 3 module, wifi, compression, etc.
http://openbci.com/forum/index.php?p=/discussion/342/adding-wifi-faster-bt-and-other-connections-for-v4
http://openbci.com/forum/index.php?p=/discussion/248/constraints-on-data-rates-thru-dongle
http://openbci.com/forum/index.php?p=/discussion/94/using-dpcm-to-save-bandwith
Possibly one of the 'easier' approaches which has already been done, is to use a tiny external Bluetooth 2 or 3 module, attached to the mainboard. The links below show this being done with an external breadboard, but you could just as easily attach the module to the mainboard with double stick foam tape, then run your jumpers.
Bluetooth v2 or v3 has MUCH higher throughput than the Bluetooth 4 / BLE (or Gazelle on the RFduino) currently used. You would bypass the firmware that is sending to the RFduino, and instead pass the data to the BT 2 module over the SPI pins. This approach would also eliminate the dongle, and you could go direct to devices which support standard Bluetooth. The Bluetooth 4 / Bluetooth Low Energy (BLE) stack was intended for lower speed / low power applications, hence is not as adaptable for higher data rates.
William
---
One disadvantage of the Bluetooth 2 or 3 add on modules, is that most of them use a serial port RX TX pins for connection to the uC. And not SPI. This can impose its own bottleneck on serial port data rates.
Regarding tiny uC breakout modules that allow high speed radio connection, just ran across this new wifi module yesterday, based on the ATWINC1500 module from Atmel,
https://learn.adafruit.com/adafruit-atwinc1500-wifi-module-breakout/overview
This uses SPI so should run blazing fast (uC to ATWINC) and with no radio link bottlenecks.
Only downside is that Adafruit is currently out of stock on these little boards. Must be popular. I'm guessing you could find similar add on tiny board modules containing the same wifi chip from other manufacturers. Or ask Adafruit their estimated time for having more stock.
Actually the only thing the Adafruit board does is 5v to 3.3 v level shifting. And since the 32 bit board is already 3.3 v, you should be able to interface directly to a ATWINC1500, if you can find another PC breakout for the chip.
https://www.google.com/search?q=ATWINC1500+breakout
ATMEL has their own breakout, if you need another supplier,
http://www.atmel.com/Images/Atmel-42388-ATWINC1500-Xplained-Pro_UserGuide.pdf
William
http://atmel.force.com/support/articles/en_US/FAQ/What-is-the-supported-Tx-output-power-for-ATWINC1500
https://en.wikipedia.org/wiki/DBm
The TX_PWR_LOW -> 6 dBm (4 mW) should be plenty. And is close to the 4 dBm (2.5 mW) used by Bluetooth class 2 (10 meter range).
First let me congratulate you for the courage in jumping into this. :-)
I would take as an example the previously mentioned code from Momen. Even though that is using serial port output, the idea is similar to what you'll be doing, as far as pumping out the data on another port. In Momen's case he had BOTH data streams going (one through dongle and one through Bluetooth). Since you want to avoid speed bottlenecks, you might end up just going strictly through the wifi.
So as far as your step #3 above, use Momen's code as an example for diverting the data stream to another device, and add the necessary setup calls to initiate the ATWINC and it's wifi connection.
Wiring: The SPI is a 'bus', meaning multiple devices can share it, including the Daisy and the ATWINC. The shared pins are the MISO, MOSI, and SCK. You'll also take DVDD (+3.3v) and GND from the same daisy header pins. There is also a RST pin, I think your ATWINC supports that as well.
https://www.arduino.cc/en/reference/SPI
You will use one of the unused digital output pins on the main board (header pins) as your "chip select" for the ATWINC. That's up to you which one you use.
As far as the Adafruit library, you'll have the source, so should be able to tweek it if needed. I would take a look at the Adafruit ATWINC example programs. They have several there. With the wifi link up, you'll have the ability to initiate a tcp/ip connection to your laptop. The data will be sent over that.
It's possible by doing some searches on Google, that you could locate a prototype tcp server code that would run on the laptop; that would take an incoming socket connection, and then connect that (route the data streams) into what is called a pseudo-tty, an emulated COM port. On Unix / Linux this doesnt take much code at all. Not sure what is out there for Windows.
OpenBCI_GUI and the existing LSL stuff expects such a serial port. If you can emulate the COM port over tcp, then you could use those without modifications.
https://www.google.com/search?q=emulate+com+port+over+ethernet
https://en.wikipedia.org/wiki/COM_port_redirector
William
Currently the Daisy has pins extending from the bottom that plug into the mainboard. So there are a couple ways you can do this.
(1) The 'hack' way. Just solder tack some wires onto the pins you need on top of the Daisy board. This is a bit ugly, but would work. A downside is that the wires would not be very strain reliefed, so flexing many times could break off.
(2) use one or the other type of 'stacking' header pin. The female type is shown here,
https://www.adafruit.com/products/85
You would just use one of the 8 pin headers, this kit has 2 of those. Removing the existing header would require some unsoldering skills. A "solder sucker" tool helps here in removing most of the solder, then eack individual pin can be eased out. Once the holes are clean, the new header can be soldered in.
Alternately "stacking" male headers are also available, these have long pins on each side.
https://www.adafruit.com/products/400
For connecting to the stacked header, you can use jumper wire plugs,
https://www.adafruit.com/products/1954
One side at the ATWINC would be soldered, and the other plugged into the Daisy header. Same idea for your chip select line to the mainboard.
----
As far as attaching the ATWINC breakout board physically. I'd use a small piece of double stick foam tape. Cut to size, then stick it a few times to your hand / skin to reduce the aggressiveness of the adhesive. This is so you can pull it off in the future from the mainboard when you need to.
You could stick it on the front surface of the mainboard, on the opposite side from where the RFduino is located. This is a bit away from the ADS1299 A/D chip and more sensitive analog sections of the board. An alternate location would be on the Daisy itself, say over the OpenBCI logo area, off the right edge away from the ADS1299. Much less surface area here on the Daisy, so mainboard probably best.
The wiring of the ATWINC vs Bluetooth is not that much more challenging. SPI is way faster than serial ports, and the data rates over the air also much faster.
@Winslow_Strong,
Do you realy need 1kHz to performe neurofeedback?
Which kind of EEG "high frequency" feature dou you want to use/study?
Have you thought about data compression?
Most of the time 16bits are enough, then using 16 instead 24 allows you to access to 16 channels - 250Hz
(if the signal drifts you can implement a high pass filter by mean subtraction.)
Moreover a simple "u-Law" compression might allow you to reach 500Hz...
The current bluetooth frame length being 31 octes , a 15 channels / 500Hz seems accessible by software modification.
Regards,
y.j.
re: 1K sample rates. Others interested in EMG and realtime feedback EMG have requested faster rates. So it's not just EEG applications that could benefit.
EEG Data Compression Techniques (1997)
Abstract
In this paper EEG and Holter EEG data compression techniques which allow perfect reconstruction of the recorded waveform from the compressed one are presented and discussed. Data compression permits one to achieve significant reduction in the space required to store signals and in transmission time. The Huffman coding technique in conjunction with derivative computation reaches high compression ratios (on average 49 % on Holter and 58 % on EEG signals) with low computational complexity. By exploiting this result a simple and fast encoder/decoder scheme capable of real time performance on a PC was implemented. This simple technique is compared with other predictive transformations, vector quantization, discrete cosine transform and repetition count compression methods. Finally, it is shown that the adoption of a collapsed Huffman tree for the encoding/decoding operations allows one to choose the maximum codeword length without significantly affecting the compression ratio. Therefore, low cost commercial microcontrollers and storage devices can be effectively used to store long Holter EEGs in a compressed format. Keywords--- Data Compression, Huffman Code, EEG Signal. I.
----
For comparison, a high compression, high computation cost EEG compression scheme,
http://www.hindawi.com/journals/ijta/2012/302581/
A High-Performance Lossless Compression Scheme for EEG Signals Using Wavelet Transform and Neural Network Predictors
Thank you very much William for these references to papers (not easy to read, at least for me) and discussion which I discover.
The u-Law is not loss less...
When the signal increases small details disappear.
I wonder how it would affect the gamma band which is the small amplitude desynchronized eeg.
May be u-law would be a good filter... (joke)
@Winslow_Strong,
if the pic32 can extract from a 1kHz flux the features you are looking at for the feedback, this could be the best way to compress datas.
Biomurph is working on an "interrupt Version" which will facilitate this computation...
If you want to try u-law the algorithm is rather simple : u-Law
Regards,
y.j.
just a note : averages are sent alternatively ( or successively , sequentially, serially, [1:8,9:16], like any bits...) but the 16 channels have been sampled synchronously @ 250Hz.
y.j.
you make me doubt,
I was thinking that :
at t1= 0mS channels 1-16 are sampled
at t2= 4mS channels 1-16 are sampled again average t1,2 ch 1- 8 are sent in frame 1 (odd ) time stamp = 2mS
at t3= 8mS channels 1-16 are sampled again average t1,2 ch 9-16 are sent in frame 2 (even) " " = 2mS
at t4=12mS channels 1-16 are sampled again average t3,4 ch 1- 8 are sent in frame 3 (odd ) time stamp = 10mS
at t5=16mS channels 1-16 are sampled again average t3,4 ch 9-16 are sent in frame 4 (even) " " = 10mS
...
The critical point is to know if channels 1-16 are sampled by the two ads1299, at the very same time or not.
Biomurph can probably answer.
Regards,
y.j.
Yes, the mainboard ADS1299 and daisy ADS1299 are synchronized and sampling at the same time. The mainboard sends it's ADS1299 CLK output signal to the input CLK pin of the daisy ADS1299. Then they are both started at the same time using the START SPI command, with both chips being simultaneously selected (through their CS chip select pins.)
http://openbci.com/forum/index.php?p=/discussion/161/daisy-and-main-board-sample-synchronization
Sorry , I am afraid that you are probably right ! ! !
The boolean "firstDataPacket" is true at start : line 175 & 590
and after that always false...
Strange affair...
The code seems to do an average at each sampling step and not one over two
To toogle it I expected to find at the end of OpenBCI_32_Daisy::updateDaisyData() something looking like :
firstDataPacket = ! firstDataPacket ;
But nothing...
may be I am tired or too old...
I already found this strange , look in my version on GitHub for example line 744
It is funny, I commented lines using this boolean "always false" or suppressed it from tests...
But since I do not use a daisy card , I did not bothered about adverse consequences...
And as William says, let us wait for Joel's and Conor's explanations.
Winslow , run the card with the squarewave test and look if there is a shift of ADSs at the transition or if they are sync...
Use TEST SIGNAL CONTROL COMMANDS : '='
Anyway if it is really buggy, it is easy to correct.
Regards,
y.j.