Meditating on Matlab/Simulink

In 2011, neuroscientist and best-selling author Sam Harris wrote an article titled How to Meditate in which he cites a host of research on the observed neurological benefits of mindfulness-based meditation techniques. As a life-long skeptic of anything promising enlightenment, or being associated with incense, I've never considered meditation to be a truly constructive way to spend one's time. However, I recall being fairly compelled by Sam's article. Sam dispassionately describes a variety of scientifically demonstrable benefits of meditation. Such as mitigating anxiety and depression, improving cognitive function, and even producing changes in gray matter density in regions of the brain related to learning and memory, emotional regulation, and self awareness. And he does this without giving praise to any cult iconography or incantations. Just science.

About 8 months ago, he wrote a brief follow-up article including two guided meditations, one 9 minutes long and one 26 minutes long. Here's a snippet from the text:

There is nothing spooky or irrational about mindfulness, and the literature on its psychological benefits is now substantial. Mindfulness is simply a state of clear, nonjudgmental, and nondiscursive attention to the contents of consciousness, whether pleasant or unpleasant. [link]

Stumbling across this recently, I decided to give this topic a little more attention. However, being borderline obsessed with data collection/visualization/processing, I couldn't just try it out. I had to figure out a means of quantifying my body's response. So I did what any rational person would do and built a small EKG with Matlab. Recording my heart rate would be an easy way to at least superficially gauge my relaxation level without having to embark on a journey of learning more complex biosignal processing interpretation. The end result of my 9 minute meditation session was this graph. The green plot is the audio from Harris' 9 minute guided meditation, and the red plot is my heart rate as I listened to the audio. 

Figure 1: Audio of a 9-minute guided meditation, by Sam Harris (upper). My average heart rate while following along with the meditation (lower). I continued the heart rate recording for some time after the guided meditation had completed because...well, I was in the zone!

My heart-rate isn't particularly impressive, I know. I was hoping for a downward trend into a seemingly cryogenic state of meditative zen. But instead I got a fairly steady 65'ish BPM, and a random moment of anxiety (can you guess where?). I suppose I need to practice. And although it isn't particularly noticeable from the HR plot, I did have brief moments of feeling a bizarre disconnect between the mechanical rhythms of my body and my conscious awareness of those rhythms. Like my body was going on autopilot, but my brain was still awake. Neat. Anyways, it was a fun experiment. This is how I did it.

The basics

So, before we try to solve any mysteries of science, let's talk briefly about the basic principles of signal acquisition. Since our cardiac signal is already in the form of electrical energy, all we have to do is amplify/clean the signal prior to viewing/analysis. The signal is going to be very small and buried in noise. Keep in mind that our bodies are essentially moving antennas. They pick up a lot of noise from our environment. Here's a high-level view of our game plan: 

Figure 2: The biosignal is acquired from one of the many points of contact on the skin (labelled V1-V6 in the figure), and then amplified. Next, the amplified analog signal is filtered to remove unwanted spectral components (noise), and sent to an A/D converter. The analog filtering also helps to bandlimit the signal prior to sampling to prevent aliasing. The A/D converter then translates the analog signal to a digital signal, which is then fed into some sort of digital architecture to fascilitate further signal processing and visualization. Easy enough, right? Okay, let's get started.

 

Electrode Choice/Placement

The cardiac signal is complex, and is often viewed from many *angles* simultaneously when studied diagnostically. Since we're not doing anything particularly complex here, we'll just pick two reference points. I chose V1 and V6. V1 is located in the 4th intercostal space just right of the lower sternum. V6 is located along the left mid-axilary line. You can google these to get a better description of the locations, if you need to. 

I'm using standard silver/silver-chloride sticky electrodes, like this one from 3M. You can get them for peanuts on Amazon.

Amplification

There are a variety of amplifiers available on the market, and some are specifically designed for physiological signal acquisition. For this experiment, I went with the INA2126P. It's well-known for these types of things, and is super easy to use. It's a dual-supply precision amplifier. The gain is set with a single external resistor and it operates under a wide range of supply voltages. I chose to use two coin-cell batteries for my amplifier supplies. CR2032's to be specific. I found it helpful to solder together a little battery holder with leads that extend out for breadboard connectivity. You'll want to put the batteries in series with a lead that extends from their center. The positive lead will be your amplifiers' positive supply rail, the negative will be your amplifiers' negative supply rail, and the center lead will be your virtual ground. I'm pluralizing "amplifiers" here because, as you'll see in a moment, we'll use a couple op-amps in the filtering stage.

Analog Filtering

The purpose of analog filtering is two-fold. Firstly, our cardiac signal will  be buried in spectral content that is uninteresting to us (noise), which we'd like to remove. Secondly, we need to bandlimit our signal prior to sampling to prevent aliasing. I chose to cascade two 2nd order Sallen-Key filters to create a bandpass filter with lower/upper cutoffs of ~100 mHz and 50 Hz, respectively. I used standard LM741 op-amps and the same coin-cells as mentioned above for the supply rails. Here you can see the two stages labeled, along with the equations used to estimate their spectral properties.

 

A/D Conversion & Microcontroller

Since I was particularly interested in doing my signal processing (the heavy lifting) in Matlab, I kept this stage of the circuit very simple. The goal was to plainly sample the filtered signal, and send it straight to Matlab. I chose to use an Arduino Uno accomplish this. The code I used was a very minor adaptation of the analog sample example that comes with the Arduino IDE. You could likely use any of the Arduino development boards for this, or one of a variety of development boards from other manufacturers. If you're unsure how to proceed with analog sampling, there are tons of tutorials available online.


void setup() {
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  Serial.print("hello!")
}

void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}
 

Finished Circuit

Now, the fun part. To accept the Arduino's incoming signal, I first had to configure Matlab to listen to the correct com-port, and with the correct baudrate. I found that this can be done by creating a serial object in the matlab command window, like so: 



s = serial('/dev/ttyACM0') % linux version
s = serial('COM9') % windows version
fopen(s)
s.BaudRate=115200

Note: You don't need to instantiate s twice. Keep the instantiation that corresponds to your operating system. Your exact com port may differ.

You can test Matlab's connection by typing the *fread(s)* command in Matlab's command window. This should result in a buffer full of values spilling onto the screen. Once I established a good connection, I whipped up a Simulink model to sample the incoming data, perform some more sophisticated filtering, and display the results in real time. Here's my heart beat!

At the bottom of this blog is a link to the model featured above. Keep in mind, this likely won't be a *turn-key* solution for those following at home. You'll probably need to modify the sampling rate and filter parameters to suit your sampling/noise conditions. This model also requires that Matlab is configured with a c-compiler. I don't recall if Matlab has a compiler configured right out of the box or not, but here's where you'll want to look if you get a compiler error. So after tweaking my digital filter parameters until I can cleanly see my heart beat, I positioned myself in a comfortable posture on the couch, turned on Sam's 9 minute guided meditation, and used the Simulink *to workspace* block to save my incoming data to the matlab workspace. After the meditation was over, I began writing the post-processing scripts to do 'peak-tracking' (for heart-rate calculations) and spectral analysis (for...fun, I guess).  Here's the output of my post-processing function (I've slowed it down a bit, so you can follow the waveform).

The first row of plots shows the raw sampled data, and its spectral estimate. You'll see in the second row of plots, the digitally filtered data along with its spectral estimate. You can see the red diamond markers are tracking each QRS-peak, from which an estimation of the heart rate is being averaged and plotted in the third row. In the fourth row, a spectrogram shows the power spectrum falling downwards like a waterfall. It's clear in this colorful display that despite both analog and digital filters, there is still some spectral power in the 60 Hz range (power line interference), as well as its 120 Hz harmonic. 

 

All in all, this was a fun project. And among other things, it taught me that meditation is damn hard. Happy researching,

Will