For this #MyoCraft, I wanted to take the time to touch on something a bit different than usual. As you know, we published the Bluetooth protocol the Myo armband uses a while ago. A lot of developers have jumped in and started building implementations for new platforms, but a common stumbling block is the EMG data. I thought I'd take the time this week to explain how it actually works, to avoid any further confusion.
The Myo armband has 8 separate electromyography (EMG) sensors, which we use to read your muscles and figure out what your hand is doing. If you want to get the EMG data yourself, you may care about what reading corresponds to which sensor. Here's the order it comes in:
That's also the order if you get the EMG data through the calls in the SDK, incidentally.
EMG data is off by default (since it's quite bandwidth and battery intensive to stream). To turn it on, you have to (like all commands) write to the
CommandCharacteristic, in this case setting the
emg_mode of your
myohw_command_set_mode_t to one of the three supported values:
myohw_emg_mode_send_emg_raw. To enable EMG, you want
myohw_emg_mode_send_emg. It's basically the same as
myohw_emg_mode_send_emg_raw, except we've removed interference from nearby electrical signals, which can otherwise throw your data off quite a bit.
myohw_emg_mode_none will turn EMG streaming back off (which will also happen automatically whenever the Myo armband is disconnected).
You can set the IMU parameter of
myohw_command_set_mode_t to whatever you like, but it's worth nothing that if you've set
myohw_emg_mode_send_emg_raw the classifier will be disabled (meaning no poses), since it depends on powerline interference being filtered out.
Once you have turned on EMG data, you can subscribe to each of the four
EmgDataXCharacteristics. These are
notify characteristics, not
indicate, meaning there is no acknowledgement (in return, we get higher throughput). This means in a noisy environment it's possible to lose packets.
Emg Data Characteristics
Now we get to the meat of this article, and the issue that most people seem to run into: "Given that there are 8 sensor pods, why are there four
EmgDataXCharacteristics that each give two arrays full of 8
int8_ts? That seems like way too much data."
The thing is, you can't send enough data over a single characteristic to get up to 200Hz. So we broke it up into four, and sent two sequential readings in each update. That means the way you interpret the data is like this:
EmgData0Characteristic Sample1 Sample2 EmgData1Characteristic Sample3 Sample4 EmgData2Characteristic Sample5 Sample6 EmgData3Characteristic Sample7 Sample8 EmgData0Characteristic Sample9 Sample10 etc
There is no timestamp included with the data, but you don't really need it. The samples are read at a consistent rate (every 5ms), so you can figure out the time just based on what characteristic and array the data comes from. If a transmission gets lost, you'll just have a gap.
That's it! Let us know if you use the EMG data to make something cool, we're always looking for awesome projects to show off to the community. And if you open source an implementation of our Bluetooth protocol for a new platform, we'd love to feature it in The Lab.
Good luck, and happy coding!