Since 2014 I have recorded hundreds of data-rich heartbeat recordings with low-cost software and hardware for a long-term heart rate variability biofeedback project. Originally I wanted to pursue neurofeedback (and still do) but in 2012 I got a tip from the biohacker community that the heart provided a dense but hackable biosignal with comparable personal value.

Heart rate variability (HRV) is the physiological phenomenon of variation in the time interval between heartbeats [1]. The heart rate changes from moment to moment and provides a rich signal that integrates local emotional arrousal and broad physiological activity. More below

Biofeedback is the process of gaining greater awareness and influence of physiological functions by using electrical sensors to connect us to the activity of those systems. Here I outline my data set analysis and demo real-time visual feedback. More below

Collecting HRV with Arduino

The hardware stack to get the heart beat signal to the computer is simple:

  • Microcontroller/Arduino with firmware
  • 5V Pulse Sensor Amped analog sensor
  • Pulse Sensor clipped to ear lobe
  • USB cord to computer for serial output
hrv training

Arduino Duemilanove with pulse sensor connected to analog pin

hrv training

Prototype 2: Pulse Sensor with Pro Micro incased in silicone

Since 2014 heart rate monitoring devices have become more popular but I still can't find many options to satisfy my use case:

  • RR interval data is not collected
  • Raw data is not easily viewable if at all
  • Private health data is shared
  • Heart beat events arn't able to be transmitted live

The Pulse Sensor Amped is an photoplethysmogram [1] made for the Arduino. The Pulse Sensor site has well-documented and concise firmware [1] that will allow you to extract live heart beat signal. I simply modified the code to send the interbeat interval, IBI variable, in milliseconds over the USB serial port:

Reading Arduino Serial with Python

Every time a pulse is detected the time delay from the last beat is pushed through a serial device like /dev/ttyUSB0:

joe@joegle $ stty -F /dev/ttyUSB0 cs7 cstopb -ixon raw speed 115200
joe@joegle $ cat /dev/ttyUSB0
648 ...

My first biofeedback server was written in Python as a module with an extendenble class 'Heart_Monitor' and used pySerial python module to read the serial device. The class has the following usual methods that can be reimplemented:

  • __ini___ constructor
  • start to begin scanning the device
  • listen_for_beat for waiting for next heart beat
  • on_beat for handling each heart beat events
  • on_quit for stopping the monitor

The feedback server built with a Python HTTPServer and extending Heart_Monitor class to send data to a website rendering a live updating graph using D3.js.

The Python server was a great "minimum viable product" that I mostly used to passively archive my data to disk. I have rewritten the server in Go and have gained nanosecond resolution on event times which should increase the signal-to-noise ratio. I will continue to enjoy Python for informatics and prototyping but after you learn exactly what you want and demand speed I have found Go to be phenomenally productive.

Datamining and Feedback

After collecting a large sample of heart beat signals I can start to do some sensemaking. I primarily use Python for the data processing environment; NumPy handles the statistics and the graphs are generated with matplotlib.

For a quick overview of the data I plot the mean and variances of each session (without taking into acount the session length).

HRV data timeline
2013 Recording Activity

Sample count in terms of number of files; Script here

BPM scatter plot
2013 BPM

BPM in 70-100 range; Script here

Standard Deviations scatter plot
2013 Interval Deviation

Standard deviation of intervals plot indicating a slight increase in hear rate variability Script here

FFT for Heart Rate Variability

To inspect deeper into each session we can use the Fourier transform which SciPy provides. Running a time series session through the Fast Fourier Transform (FFT) will return an interesting graph of its frequency domain. The peaks show us where "energy" is located. Most of the heart beat is generated by a regular ticking from the sinoatrial node but it also appears to have a secondary rhythms from other influences.

hrv training hrv training hrv training

FFT graphs might show us activities in the parasympathetic nervous system, "rest-and-digest" and the sympathetic nervous system, "Fight-or-flight". For example, in a relaxed state your heartbeat will slow down during inhalation and speed up durring exhalation. Durring a stressor, such as excersize, the heartrate will be strong and steady.

Here are 2 different sessions to show how specgram qualities and features can be seen (click to enlarge):

Day 1
hrv training
Day 2
hrv training


Video of first prototype

After getting a big picture of the data you can streamline the processing to display metrics to the user in near real-time. When the delay is short and the representation is intuitive the user can begin understanding the signal as an experience and not as numbers.

The first proof of concept was this simple D3.js plot of rolling standard deviation and averages.

The current iteration is a React app that interacts with a historical data API and live data WebSocket. React is a refreshing web framework for composing responsive and reusable web components. A demo is available here.

hrv training

Draft design of HRV dashbord

hrv training

Screenshot of React implementation of biofeedback dashboard. Demo here.

The main modal of the HRV dashboard is a set of horizon graphs [3] that I implemented in D3 inside the React components. The horizon graphs (or charts) have a high return on investment because they are easy to code and can be stacked to compare any number of metrics over time.

hrv training

Mapping an information dense signal into another modality is a wonderfully intimidating, open-ended and multidisciplinary art. The RR interval sequence may have a relatively small dimensionality but still demands quite a bit of engineering overhead. To increase development speed I have been studying OpenGL Shader Language as a powerful medium to iterate through high fidelity mappings of the live signal.

Experimental biofeedback system using WebGL Shading Language

Improvements / Ideas / Todo

  • Portable monitoring
  • Passively recording breathing and heart through video
  • Adding blood O2 measurements
  • Recording the raw arduino diode signal
  • Measure noise and latency
  • On-board FFT
  • More accurate clock


1. The Pulse Sensor Amped works by photoplethysmography where it shines a light into thin body tissue to illuminate the blood flowing through capillaries and the Pulse Sensor Amped firmware finds spikes in the photodiode samples to derive heart beat events. More specifications found on their store page.

2. The Arduino project has a beginner-friendly IDE for developing and uploading firmware. The arduino/ folder of my repo has more information with Ardiuno code and self-contained c++ code with a Makefile for compiling and uploading the code to your board.

3. Sizing the Horizon: The Effects of Chart Size and Layering on the Graphical Perception of Time Series Visualizations - Jeffrey Heer, Nicholas Kong, Maneesh Agrawala