I had previously written drivers for the older Interaxon Muse Model. It used a simple Bluetooth socket and the protocol was documented on their homepage.
When one Electrode went dead after a few years, the App refused to accept its signal. So I bought a new Muse, and this time the newer model. Unfortunately there is no information on it and it uses the BLE ATT protocol.
This is my first attempt at reverse engineering any BLE protocol, and I guess this is not the easiest to start with.
I basically have two tasks:
- Find out how to make the Muse start recording and sending the data.
- Find out how the Muse sends data to the App
I used the Android develepment features to spy on the App, receiving a capture of all Bluetooth packets. Wireshark can read these and export them as a JSON file.
I whipped up some Python code in a Jupyter notebook, and decided to first go after parsing the data. Those packets have the opcode "0x1b" which is a notification of an attribute.
There are handles for seven different handles, where each handle refers to one attribute. Each notification has a value with 20 bytes. From the rate of the packets and the size of the value this can't be a single value. After some trial and error I figured out that these are 16 unsigned integers of 10bits each.
Decoding this data for a few minutes of meditation yielded relatively promising graphs.
Now one big question is the sampling frequency. From the timing data of the packets I got about 340 sps. But when I looked at the spectrograms, the most prominent noise signal wasn't at 50hz, where it should be (mains power interference).
Somehow, 256hz is the right frequency to put the dominant signal right on the 50hz mark. I wonder if there is something special about that 256 number? Yes, I'm kidding.
Applying a 50hz notch filter and a 60hz lowpass filter, I get the spectrograms you see in the pictures. This looks relatively plausible.
But there are still issues.
I have too much data for 256hz. I also noticed strange patterns in the plots.
Then I took a closer look at the decoded values and discovered that the first 16 bit of each packet are unsigned integers, incrementing by one for each packet. That somehow leaves 4 bit at the end of the data.
This works out to about 300hz, both from the spectrum and the timing metadata.
Next steps will be to discover what the other channels carry. There is an optical heart rate sensor on the device, also potentially an accelerometer...
And I still need to figure out how to make the device send the data to a PC.
hey, have you worked on this any more? I've been working a little on a python library to stream data from the Muse S, and it seems to be working well. The muse-js project is very helpful. I was wondering if you knew what IMU is inside the muse 2 hardware? I'm not sure where the gyroscope multiplier comes from.
Thanks ... I think it's easier for me to compare the output values with those from one of the closed source apps, or reverse engineer them. The rest of my work is at https://github.com/xloem/pymuse . Work is on hold for me too now but clearly collaboration around this project is needed. The muse is the only comfortable and affordable device for ongoing consumer EEG that I'm aware of.
you are sure the sampling rate is not 250 sps ?