HackEEG

8-32 channel TI ADS1299 Arduino shield for EEG, EMG, and EKG bio-signals acquisition

Available for pre-order

View Purchasing Options
Jan 22, 2020

Project update 9 of 15

16,000 Samples Per Second on a Raspberry Pi 4

In a previous update, I went over how to stream data from a Raspberry Pi 4. That demo used the HackEEG Python client, which could only stream data over WiFi at 1,000 samples per second on the Pi. In this update, I’ll show you how to stream 16,000 samples per second on a Raspberry Pi 4.

Why is the Python client slower on the Pi? I’m not totally sure, but it’s probably because it was using too many resources. Python is an interpreted language and while it’s great to program in on a computer with lots of resources like my laptop, it often has difficulty on smaller embedded computers.

But one of HackEEG’s super powers is speed. So how to unlock this on embedded Linux?

Rust

Rust is a new compiled systems programming language. It’s open source too like many languages. And it’s awesome. It’s used to implement the Servo rendering engine for the Firefox web browser, and it has a lot of technical benefits (which you can read about here, here, here, and other places). But the main advantages for HackEEG users is that it has a great community; it has a lot of good software available for it via its Cargo package manager; and it’s blindingly fast.

The fact that it has a great community means that there’s a lot of good help. The fact that it has a great package manager (cargo) means that it’s easy to implement an open-protocol client that can do the wifi streaming. And the fact that it’s blindingly fast… well I did start this out saying it can do 16,000 samples per second on a Raspberry Pi 4!

hackeeg-client-rust

Introducing hackeeg-client-rust. This was developed by my friend and colleague Andrew Moffat. It works like the hackeeg-client-python. But it’s much, much faster. 16x faster. (Of course it can only read data as fast as the driver running on the Arduino Due can send it.)

Here’s how to start it (doing the internal test):

hackeeg-stream rust command line client starting
[pi@raspberrypi]$ ./target/release/hackeeg-stream /dev/ttyACM0 2000000 --lsl-stream-name EEG --sps 16000 --lsl --samples 200000 --channel-test --messagepack --quiet

And here’s the results:

hackeeg-stream rust command line client results
[pi@raspberrypi]$ ./target/release/hackeeg-stream /dev/ttyACM0 2000000 --lsl-stream-name EEG --sps 16000 --lsl --samples 200000 --channel-test --messagepack --quiet
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][INFO] Creating client connection to /dev/ttyACM0
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][INFO] Ensuring we're in mode JsonLines
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][INFO] stop
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][INFO] sdatac
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][WARN] Timed out draining, but that's ok
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][INFO] Blinking board LED
[2020-01-22][02:33:57][Thread: ThreadId(1)][hackeeg_client][INFO] Turning board LED on
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Turning board LED off
[2020-01-22][02:33:58][Thread: ThreadId(1)][main][INFO] Disabling all channels
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling all channels
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 1
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 2
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 3
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 4
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 5
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 6
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 7
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 8
[2020-01-22][02:33:58][Thread: ThreadId(1)][main][INFO] Enabling channel config test
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Disabling channel 8
[2020-01-22][02:33:58][Thread: ThreadId(1)][main][INFO] Enabling reference electrode SRB1
[2020-01-22][02:33:58][Thread: ThreadId(1)][main][INFO] Setting dual-ended mode
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] Ensuring we're in mode MsgPack
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] start
[2020-01-22][02:33:58][Thread: ThreadId(1)][hackeeg_client][INFO] rdatac
[2020-01-22][02:34:10][Thread: ThreadId(1)][main][INFO] Reached 200000 samples, breaking
[2020-01-22][02:34:10][Thread: ThreadId(1)][main][INFO] 200000 samples (0 errors) in 12.566575 seconds, or 15915.235/s
 (feature/message-pack) [~/src/hackeeg-client-rust-amoffat]
[pi@raspberrypi]$

15,915.235 samples per second – pretty close to 16,000. Like the Python client, it doesn’t quite reach 16,384 because of problems measuring the start and stop of the streaming exactly.

So if you want to build a portable embedded system with HackEEG, this will do it. Or just stream from your laptop and use very few CPU resources.

Thanks

Thanks to Andrew Moffat for being an amazing programmer and rust enthusiast. And thanks to the great rust team and community. The rust client uses a large amount of open source software to make it go– it wouldn’t be possible without the contributions of many people. Thank you.

Software

The program used above is available here:

Note that it’s only available right now for Linux; it doesn’t yet build on macOS or Linux.


Sign up to receive future updates for HackEEG.

Subscribe to the Crowd Supply newsletter, highlighting the latest creators and projects