alexandrebarachant / muse-lsl

Python script to stream EEG data from the muse 2016 headset
BSD 3-Clause "New" or "Revised" License
614 stars 181 forks source link

Running on Raspberry Pi #55

Open Gilgahex opened 6 years ago

Gilgahex commented 6 years ago

I've been working through all the errors trying to get the project working on a raspberry Pi B+.

So far so good, I found a PyLSL shared library (liblsl32.so) that was compiled for ARM so that's working. Link here

Now I receive the following printout.

2018-07-02-100443_615x132_scrot

The problem is that the stream only stays open for a few seconds.

I've narrowed it down to the following line in stream.py

"while time() - muse.last_timestamp < AUTO_DISCONNECT_DELAY:"

I tried changing that delay constant from 3 to 5 and then to 60, but no avail.

Now physically I see the light on the Muse itself go from the poling search pattern to a solid light after the "Connected." print statement in stream.py, but returns to the poling search a few seconds after "Stream has ended".

I also noticed that when I added debug statements to stream.py nothing happened. 2018-07-02-103055_1115x307_scrot

This makes me think that the main script is doing something strange with the stream script, not sure what gives.

Any ideas why the Stream would immediately timeout?

My guess is that the "time() - muse.last_timestamp < AUTO_DISCONNECT_DELAY" is always defaulting to "False" for some reason.

jdpigeon commented 6 years ago

Hey Gilgahex,

Thanks for the well-written issue. I've got a couple ideas for you.

First, how are you running the copy of the code you are modifying? The fact that those debug statements aren't printing is very weird and makes me think your computer is still running the version of muselsl from pypi. I recommend creating a clean new python environment (conda or virtualenv) and then running pip install -e path/to/your/version/of/muselsl to make sure that it relies on the version you are working on.

As for the disconnect issue, I've seen something like this before on a few computers, but not Linux yet, though. The important thing to find out is whether the Muse is actually sending data at all. Once you've established that you can get debug statements printing, try putting a print statement in the push_eeg function in stream.py and see how much data actually gets received from the Muse. My guess is that data just isn't getting sent and the autodisconnect is working as intended. If this is the case, then the issue is probably lower level and related to pygatt and bluetooth adapter stuff.

Gilgahex commented 6 years ago

I was indeed editing the wrong file, I had a snafu with pip the other day and its default install directory was changed.

Now, with the debug you recommended I get about 3 seconds of push_eeg calls which is about 100 debug statements and then it still disconnects.

I made sure that I installed pygatt 3.1.1. The time delta between the received chunks is not what I expected. I expected them to be about (1/256) seconds the inverse of the sampling frequency, but what I see is about 0.07sec on average, which is almost 18 times slower than the sampling time.

2018-07-10-180504_1966x572_scrot

For a sanity check when I printout "muse.last_timestamp" from within push_eeg it is being updated every 12 chunks which is right.

So turns out the stream will be open for as long as whatever the AUTO_DISCONNECT_DELAY const is set to.

When I remove the evaluation and simply write "while 1" the stream is open indefinitely as expected.

muse.last_timestamp is not being updated properly Here's the running delta. It's some kind of weird timing issue.

2018-07-10-185846_1883x428_scrot

Now what dictates the update for muse.last_timestamp?

Must be something in the muse class,

self.last_timestamp = self.time_func() Or self.last_timestamp = timestamps[-1] in _handle_eeg

Maybe " _handle_eeg" isn't updating properly?

I have no idea at this point, this is as far as I've gotten. I'll keep trying to get the timestamp to update properly.

jdpigeon commented 6 years ago

Damn,

Good work looking into this. Your screenshots have been helpful trying to figure out what the problem is.

I think it's just the Pi.

I think there's a bottleneck somewhere on the Pi that's causing bluetooth packets to build up faster than they can be processed into EEG and sent to the push_eeg function.

Here's what your debugging code looks like on my machine, the delta between current time and last_timestamp, which represents the cumulative amount of time involved in parsing BLE data and turning it into an array of EEG values, always stays below 100ms

screenshot from 2018-07-10 22-30-58

My best guess is that this is partly a bluetooth hardware issue. I wouldn't be surprised if the built-in bluetooth adapters that come with those Pis just aren't very good and can't handle the speed at which pygatt is trying to read packets.

That said, people have done Muse projects with Raspberry Pis before, so it's possible that there's something we could do in muse-lsl to cut the bluetooth hardware some slack; maybe by reading larger chunks of data a time

jdpigeon commented 6 years ago

If I'm reading this right, I think you could be having the same issue as this guy: https://github.com/peplin/pygatt/issues/187

Try using a BLE dongle with the BGAPI backend

Gilgahex commented 6 years ago

Strange, it makes sense that you should use the BGAPI backend for a BlueGiga BLE Dongle, but why would the generic GATT-Tool Backend run any slower for any other BLE Chipset.

I'll report what happens when I try another GATT BLE and BG BLE Dongle. I'm currently using an ASUS BlueTooth 4.0 Dongle, FCC ID: MSQ-USBBT400

dxjones commented 6 years ago

Hi ... I am trying to grab EEG data from a Muse, but I cannot seem to get "pylsl" working properly on a Raspberry Pi 3 B+.

Since the default "pylsl" does not support ARM and Raspberry Pi, I copied this file:

https://github.com/micuat/pylsl/blob/arm/pylsl/liblsl32armv7l.so

into this directory:

/usr/local/lib/python2.7/dist-packages/pylsl/

but when I try to run a simple example, I get an error message:

/usr/local/lib/python2.7/dist-packages/pylsl/examples# python ReceiveData.py
...
AttributeError: /usr/local/lib/python2.7/dist-packages/pylsl/liblsl32.so: undefined symbol: lsl_library_info

Does anybody know why this symbol is undefined? ... or how to resolve this issue?

We are doing a research project and capturing raw EEG data from the Muse is an essential part.

I would very much appreciate any kind of help or advice.

jdpigeon commented 6 years ago

Did you copy over liblsl32armv7l.so or liblsl32.so? That error message could be because it didn't find liblsl32.so

dxjones commented 6 years ago

Yes, I renamed the ARM-compiled version of the library to “liblsl32.so”.

I also looked at all the symbols in the “.so” file and all the “lsl_...” symbols were there, EXCEPT “lsl_library_info”, which makes me think that symbol was maybe added in the past 12-14 months, so that is why it is missing in the “.so” that was compiled for ARM just over 1 year ago.

jdpigeon commented 6 years ago

Looks like you're on your way to a solution here: https://github.com/sccn/labstreaminglayer/issues/336

Keep this thread updated! I know several developers are doing Muse-Rasperry pi apps.

cboulay commented 6 years ago

Just FYI, @tstenner has a pending pull request that fixes a bug that was preventing lbilsl from compiling on ARM. I tried cross-compiling from Ubuntu 18.04 using raspberrypi/tools. I have no way of testing this. Please let me know if it works for you and if it does then I'll try to put it on pypi. https://github.com/labstreaminglayer/liblsl/pull/2

swld commented 6 years ago

Hi i've copied the files pylsl.py liblsl32armv7l.so and setup.py from micuat folder and now i have this:

------------user.py------------- Board type: OpenBCI Cyton (v3 API) Traceback (most recent call last): File "user.py", line 62, in from openbci import cyton as bci File "/home/pi/OpenBCI_Python/openbci/init.py", line 4, in from .plugins import File "/home/pi/OpenBCI_Python/openbci/plugins/init.py", line 4, in from .streamer_lsl import File "/home/pi/OpenBCI_Python/openbci/plugins/streamer_lsl.py", line 6, in from pylsl import StreamInfo, StreamOutlet File "/usr/local/lib/python2.7/dist-packages/pylsl/init.py", line 2, in from .pylsl import IRREGULAR_RATE, DEDUCED_TIMESTAMP, FOREVER, cf_float32,\ ImportError: cannot import name proc_ALL

nuKs commented 5 years ago

On raspbian stretch apt-get install lsl-liblsl seems to work (but tbh I did wget https://github.com/labstreaminglayer/liblsl/releases/download/1.12/liblsl-1.12.0-Linux-ARM7.deb; apt-get install ./liblsl-1.12.0-Linux-ARM7.deb).

For people passing by, I strongly recommand listing muse-lsl dependencies first using pip download muselsl -d /tmp --no-binary :all: and then install them manually using apt-get install python-xxx to avoid very slow source compilation time while doing the ultimate pip install muselsl. Especially on rpi zero.

Thanks a lot cboulay !

raymondhocc commented 5 years ago

I am new to Muse 2 and would like to build muselsl on Raspberry Pi Zero. I would like to example for this command "apt-get install python-xxx". Thanks in advance.

syami commented 4 years ago

Hi All, I am trying to connect to Muse 2 on Raspberry Pi Zero W. Installed all the libraries as recommended above including building some of them from source. I am still unable to connect to Muse. Tried using muselsl list. Also then wrote a simple program to connect using pygatt directly (since muselsl uses that library). That also does not work. However I can easily connect to my iPhone and other devices using bluetoothctl on raspberry pi. Is there any alternative for pygatt for Muselsl?

thanks