The personal website of Scott W Harden
May 8th, 2013

Realtime Data Plotting in Python

WARNING: this project is largely outdated, and some of the modules are no longer supported by modern distributions of Python.For a more modern, cleaner, and more complete GUI-based viewer of realtime audio data (and the FFT frequency data), check out my Python Real-time Audio Frequency Monitor project. I love using python for handing data. Displaying it isn't always as easy. Python fast to write, and numpy, scipy, and matplotlib are an incredible combination. I love matplotlib for displaying data and use it all the time, but when it comes to realtime data visualization, matplotlib (admittedly) falls behind. Imagine trying to plot sound waves in real time. Matplotlib simply can't handle it. I've recently been making progress toward this end with PyQwt with the Python X,Y distribution. It is a cross-platform solution which should perform identically on Windows, Linux, and MacOS. Here's an example of what it looks like plotting some dummy data (a sine wave) being transformed with numpy.roll().

How did I do it? Easy. First, I made the GUI with QtDesigner (which comes with Python x,y). I saved the GUI as a .ui file. I then used the pyuic4 command to generate a python script from the .ui file. In reality, I use a little helper script I wrote designed to build .py files from .ui files and start a little "ui.py" file which imports all of the ui classes. It's overkill for this, but I'll put it in the ZIP anyway. Here's what the GUI looks like in QtDesigner:

After that, I tie everything together in a little script which updates the plot in real time. It takes inputs from button click events and tells a clock (QTimer) how often to update/replot the data. Replotting it involves just rolling it with numpy.roll(). Check it out:

import ui_plot #this was generated by pyuic4 command
import sys
import numpy
from PyQt4 import QtCore, QtGui
import PyQt4.Qwt5 as Qwt

numPoints=1000
xs=numpy.arange(numPoints)
ys=numpy.sin(3.14159*xs*10/numPoints) #this is our data

def plotSomething():
    global ys
    ys=numpy.roll(ys,-1)
    c.setData(xs, ys)
    uiplot.qwtPlot.replot()

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    win_plot = ui_plot.QtGui.QMainWindow()
    uiplot = ui_plot.Ui_win_plot()
    uiplot.setupUi(win_plot)

    # tell buttons what to do when clicked
    uiplot.btnA.clicked.connect(plotSomething)
    uiplot.btnB.clicked.connect(lambda: uiplot.timer.setInterval(100.0))
    uiplot.btnC.clicked.connect(lambda: uiplot.timer.setInterval(10.0))
    uiplot.btnD.clicked.connect(lambda: uiplot.timer.setInterval(1.0))

    # set up the QwtPlot (pay attention!)
    c=Qwt.QwtPlotCurve()  #make a curve
    c.attach(uiplot.qwtPlot) #attach it to the qwtPlot object
    uiplot.timer = QtCore.QTimer() #start a timer (to call replot events)
    uiplot.timer.start(100.0) #set the interval (in ms)
    win_plot.connect(uiplot.timer, QtCore.SIGNAL('timeout()'), plotSomething)

    # show the main window
    win_plot.show()
    sys.exit(app.exec_())
Markdown source code last modified on January 18th, 2021
---
title: Realtime Data Plotting in Python
date: 2013-05-08 16:34:27
tags: python, old
---

# Realtime Data Plotting in Python

>  WARNING: this project is largely outdated, and some of the modules are no longer supported by modern distributions of Python.For a more modern, cleaner, and more complete GUI-based viewer of realtime audio data (and the FFT frequency data), check out my [Python Real-time Audio Frequency Monitor](https://www.swharden.com/wp/2016-07-31-real-time-audio-monitor-with-pyqt/) project.
__I love using python for handing data. Displaying it isn't always as easy.__ Python fast to write, and numpy, scipy, and matplotlib are an incredible combination. I love matplotlib for displaying data and [use it all the time](http://swharden.com/blog/matplotlib), but when it comes to realtime data visualization, matplotlib (admittedly) falls behind. Imagine trying to plot sound waves in real time. Matplotlib simply can't handle it. I've recently been making progress toward this end with PyQwt with the [Python X,Y](https://code.google.com/p/pythonxy/) distribution. It is a cross-platform solution which should perform identically on Windows, Linux, and MacOS. Here's an example of what it looks like plotting some dummy data (a sine wave) being transformed with numpy.roll().

<div class="text-center img-border">

![](f.gif)

</div>

__How did I do it?__ Easy. First, I made the GUI with [QtDesigner](http://qt-project.org/doc/qt-4.8/designer-manual.html) (which comes with Python x,y). I saved the GUI as a .ui file. I then used the pyuic4 command to generate a python script from the .ui file. In reality, I use a little helper script I wrote designed to build .py files from .ui files and start a little "ui.py" file which imports all of the ui classes. It's overkill for this, but I'll put it in the ZIP anyway.  Here's what the GUI looks like in QtDesigner:

<div class="text-center img-border">

[![](qtdesigner-python-windows-qwtplot_thumb.jpg)](qtdesigner-python-windows-qwtplot.png)

</div>

__After that, I tie everything together in a little script which updates the plot in real time.__ It takes inputs from button click events and tells a clock (QTimer) how often to update/replot the data. Replotting it involves just rolling it with [numpy.roll()](http://docs.scipy.org/doc/numpy/reference/generated/numpy.roll.html).  Check it out:

```python
import ui_plot #this was generated by pyuic4 command
import sys
import numpy
from PyQt4 import QtCore, QtGui
import PyQt4.Qwt5 as Qwt

numPoints=1000
xs=numpy.arange(numPoints)
ys=numpy.sin(3.14159*xs*10/numPoints) #this is our data

def plotSomething():
    global ys
    ys=numpy.roll(ys,-1)
    c.setData(xs, ys)
    uiplot.qwtPlot.replot()

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    win_plot = ui_plot.QtGui.QMainWindow()
    uiplot = ui_plot.Ui_win_plot()
    uiplot.setupUi(win_plot)

    # tell buttons what to do when clicked
    uiplot.btnA.clicked.connect(plotSomething)
    uiplot.btnB.clicked.connect(lambda: uiplot.timer.setInterval(100.0))
    uiplot.btnC.clicked.connect(lambda: uiplot.timer.setInterval(10.0))
    uiplot.btnD.clicked.connect(lambda: uiplot.timer.setInterval(1.0))

    # set up the QwtPlot (pay attention!)
    c=Qwt.QwtPlotCurve()  #make a curve
    c.attach(uiplot.qwtPlot) #attach it to the qwtPlot object
    uiplot.timer = QtCore.QTimer() #start a timer (to call replot events)
    uiplot.timer.start(100.0) #set the interval (in ms)
    win_plot.connect(uiplot.timer, QtCore.SIGNAL('timeout()'), plotSomething)

    # show the main window
    win_plot.show()
    sys.exit(app.exec_())
```
May 7th, 2013

AVR Programming in 64-bit Windows 7

A majority of the microcontroller programming I do these days involves writing C for the ATMEL AVR series of microcontrollers. I respect PIC, but I find the open/free atmosphere around AVR to be a little more supportive to individual, non-commercial cross-platform programmers like myself. With that being said, I've had a few bumps along the way getting unofficial AVR programmers to work in Windows 7. Previously, I had great success with a $11 (shipped) clone AVRISP-mkII programmer from fun4diy.com. It was the heart of a little AVR development board I made and grew to love (which had a drop-in chip slot and also a little breadboard all in one) seen in a few random blog posts over the years. Recently it began giving me trouble because, despite downloading and installing various drivers and packages, I couldn't get it to work with Windows Vista or windows 7. I needed to find another option. I decided against the official programmer/software because the programmer is expensive (for a college student) and the software (AVR studio 6) is terribly bloated for LED-blink type applications. "AStudio61.exe" is 582.17 Mb. Are you kidding me? Half a gig to program a microchip with 2kb of memory? Rediculous. I don't use arduino because I'm comfortable working in C and happy reading datasheets. Furthermore, I like programming chips hot off the press, without requiring a special boot loader.

I got everything running on Windows 7 x64 with the following:

Here's the "hello world" of microchip programs (it simply blinks an LED). I'll assume the audience of this page knows the basics of microcontroller programming, so I won't go into the details. Just note that I'm using an ATMega48 and the LED is on pin 9 (PB6). This file is named "blink.c".

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
    DDRB = 255;
    while(1)
    {
        PORTB ^= 255;
        _delay_ms(500);
    }
}

Here's how I compiled the code:

avr-gcc -mmcu=atmega48 -Wall -Os -o blink.elf blink.c
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex

In reality, it is useful to put these commands in a text file and call them "compile.bat" Here's how I program the AVR. I used AVRDudess! I've been using raw AVRDude for years. It's a little rough around the edges, but this GUI interface is pretty convenient. I don't even feel the need to include the command to program it from the command line! If I encourage nothing else by this post, I encourage (a) people to use and support AVRDudess, and (b) AVRDudess to continue developing itself as a product nearly all hobby AVR programmers will use. Thank you 21-year-old Zak Kemble.

And finally, the result. A blinking LED. Up and running programming AVR microcontrollers in 64-bit Windows 7 with an unofficial programmer, and never needing to install bloated AVR Studio software.

Markdown source code last modified on January 18th, 2021
---
title: AVR Programming in 64-bit Windows 7
date: 2013-05-07 18:14:58
tags: microcontroller, old
---

# AVR Programming in 64-bit Windows 7

__A majority of the microcontroller programming I do these days involves writing C for the ATMEL AVR series of microcontrollers.__ I respect PIC, but I find the open/free atmosphere around AVR to be a little more supportive to individual, non-commercial cross-platform programmers like myself. With that being said, I've had a few bumps along the way getting unofficial AVR programmers to work in Windows 7. Previously, I had great success with a $11 (shipped) [clone AVRISP-mkII programmer](http://fun4diy.com/AVRISP_mkII.htm)  from fun4diy.com. It was the heart of a little AVR development board I made and grew to love (which had a drop-in chip slot and also a little breadboard all in one) seen in a [few](http://www.swharden.com/blog/2010-12-28-full-auto-rapidfire-mouse-modification/) random blog [posts](http://www.swharden.com/blog/2010-05-24-solar-powered-qrss-beacon/) over the years. Recently it began giving me trouble because, despite downloading and installing various drivers and packages, I couldn't get it to work with Windows Vista or windows 7. I needed to find another option. I decided against the official programmer/software because the programmer is expensive (for a college student) and the software (AVR studio 6) is terribly bloated for LED-blink type applications. "AStudio61.exe" is 582.17 Mb. Are you kidding me? Half a gig to program a microchip with 2kb of memory? Rediculous.  I don't use [arduino](http://en.wikipedia.org/wiki/Arduino) because I'm comfortable working in C and happy reading datasheets. Furthermore, I like programming chips hot off the press, without requiring a special boot loader.

<div class="text-center img-border">

[![](2013-05-05-22.57.01_thumb.jpg)](2013-05-05-22.57.01.jpg)

</div>

I got everything running on Windows 7 x64 with the following:

* **Programmer:** USBTinyISP (eBay, $8.50 free shipping)___It's a branch of an unofficial AvrISP-mkII project. [Ladyada.net provides](http://www.ladyada.net/make/usbtinyisp/) code, [schematics](http://www.ladyada.net/make/usbtinyisp/make.html), and even an option to buy a [built-it-yourself kit](http://www.adafruit.com/category/16) for $~22 (+shipping) through adafruit. However I found them [pre-assembled with SMT components for $8.48 shipped on eBay](http://www.ebay.com/sch/usbtiny). _

* **Drivers:** Find them on the[ Ladyada page](http://www.ladyada.net/make/usbtinyisp/download.html). (Free)___There are links at the top for 32-bit and 64-bit windows._

* **Compiler Software:** [WinAvr](http://winavr.sourceforge.net/index.html) (Free)___This is windows software. Linux users want a different flavor of AVR-GCC and should see my previous post on [programming AVR in Ubuntu Linux](http://www.swharden.com/blog/2013-01-06-avr-programming-in-linux/)_

* **Programming Software:** [AVRDudess](http://blog.zakkemble.co.uk/avrdudess-a-gui-for-avrdude/) (Free)___This is actually a GUI for [AVRDude](http://www.ladyada.net/make/usbtinyisp/avrdude.html), a command line driven programmer. It has a [great tutorial](http://www.ladyada.net/learn/avr/avrdude.html) though. I accidentally keep thinking (and searching) for this program by the incorrect title AVRDudette._


__Here's the "hello world" of microchip programs (it simply blinks an LED).__ I'll assume the audience of this page knows the basics of microcontroller programming, so I won't go into the details. Just note that I'm using an ATMega48 and the LED is on pin 9 (PB6). This file is named "blink.c".

```c
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
    DDRB = 255;
    while(1)
    {
        PORTB ^= 255;
        _delay_ms(500);
    }
}
```

__Here's how I compiled the code:__

```bash
avr-gcc -mmcu=atmega48 -Wall -Os -o blink.elf blink.c
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex
```

_In reality, it is useful to put these commands in a text file and call them "compile.bat"_
__Here's how I program the AVR.__ I used [AVRDudess](http://blog.zakkemble.co.uk/avrdudess-a-gui-for-avrdude/)! I've been using raw AVRDude for years. It's a little rough around the edges, but this GUI interface is pretty convenient. I don't even feel the need to include the command to program it from the command line! If I encourage nothing else by this post, I encourage (a) people to use and support AVRDudess, and (b) AVRDudess to continue developing itself as a product nearly all hobby AVR programmers will use. Thank you 21-year-old Zak Kemble.

<div class="text-center img-border">

[![](2013-05-05-22.56.20_thumb.jpg)](2013-05-05-22.56.20.jpg)

</div>

__And finally, the result.__ A blinking LED. Up and running programming AVR microcontrollers in 64-bit Windows 7 with an unofficial programmer, and never needing to install bloated AVR Studio software.

<div class="text-center img-border">

[![](2013-05-05-23.05.53_thumb.jpg)](2013-05-05-23.05.53.jpg)

</div>
April 17th, 2013

Tenma 72-7750 Multimeter for RF Engineering

Update: This page reviews my initial impressions of the Tenma 72-7750. In a later article (TENMA Multimeter Serial Hack) I use Python to interface this multimeter to make it easier to log data and create plots of measurements without using the official (Windows-only) software.

I recently got my hands on a Tenma 72-7750 multimeter. Tenma has a pretty large collection of test equipment and measurement products, including several varieties of hand-held multimeters. The 72-7750 multimeter has the standard measurement modes you'd expect (voltage, current capacitance, resistance, conductivity), but stood out to me because it also measures frequency, temperature, and has RS232 PC connectivity. Currently it's sale from Newark for under fifty bucks! This is what mine arrived with:

The obvious stuff worked as expected. Auto ranging, (5 ranges of voltage and resistance, 3 of current, 7 of capacitance), accurate measurement, etc. I was, however, impressed with the extra set of test leads they provided - little short ones with gator clips! These are perfect for measuring capacitance, or for clipping onto wires coming out of a breadboard. So many times with my current multimeters I end-up gator-clipping wires to my probes and taking them to what I'm measuring. I'm already in love with the gator clip leads, and know I'll have a set of these at my bench for the rest of my life.

I was impressed by the frequency measuring ability of this little multimeter! When I read that it could measure up to 60MHz, I was impressed, but also suspected it might be a little flakey. This was not at all the case - the frequency measurement was dead-on at several ranges! With so many of the projects I work on being RF-involved (radio transmitters, radio receivers, modulators, mixers, you name it), I sided with this meter because unlike some of its siblings this one is rated beyond 50Mz. I hooked it up to the frequency synthesizer I built based around an ad9850 direct digital synthesizer and played around. When the synthesizer was set to various frequencies, the multimeter followed it to the digit! Check out the pics of it in action, comparing the LCD screen frequency with that being displayed on the meter:

I also took a closer look at the PC interface. When I looked closely, I noticed it wasn't an electrical connection - it was an optical one! It has a phototransistor on one end, and a serial connection on the other. I'm no stranger to tossing data around with light (I made something that did this here, which was later featured on Hack-A-Day here). I wondered what the format of the data was, when to my surprise I saw it spelled out in the product manual! (Go Tenma!) It specifically says "Baud Rate 19230, Start Bit 1 (always 0), Stop bit 1 (always 1), Data bits (7), Parity 1 (odd)". Although they have their own windows-only software to display/graph readings over time, I'd consider writing Python-based logging software. It should be trivial with python, pySerial, numpy, and matplotlib. Clearly I'm no stranger to graphing things in python :)

How does the photo-transistor work without power? I attached my o-scope to the pins and saw nothing when RS232 mode was activated on the multimeter. Presumably, the phototransistor requires a voltage source (albeit low current) to operate. With a little digging on the internet, I realized that the serial port can source power. I probably previously overlooked this because serial devices were a little before my time, but consider serial mice: they must have been supplied power! Joseph Sullivan has a cool write-up on a project which allowed him to achieve bidirectional optical (laser) communication over (and completely powered by) a serial port. With a little testing, I applied 0V to pin 5 (GND), +5V to pin 6 (DSR, data set ready), and looked at the output on pin 3 (PC RX). Sure enough, there were bursts of easy-to-decode RS232 data. Here's the scheme Joseph came up with to power his laser communication system, which presumably is similar to the one in the multi-meter. (Note, that the cable is missing its "TX" light, but the meter has an "RX" phototransistor. I wonder if this would allow optically-loaded firmware?)

There were a couple other things I found useful. Although I didn't appreciate it at first, after a few days the backlight grew on me. I've been doing experiments with photosensors which require me to turn out the lights in the room, and the backlight saved the day! Also, the meter came with a thermocouple for temperature measurement. It has it's own "ºC" setting on the dial, and displays human-readable temperature right on the screen. I used to do this with LM334-type thermosensitive current sources but it was always a pain (especially if I had one which output temperature in Kelvin!) I'm not sure exactly what's inside the one that came with this meter, but the datasheet suggests it can measure -40 through 1,000 C, which certainly will do for my experiments!

All in all, I'm happy with this little guy, and am looking forward to hacking into it a little bit. There may be enough room in the case to add a hacked-together high frequency divider (a decade counter would be fantastic, divided by ten would allow measurement through 500MHz), but I might be over-reaching a bit. Alternatively, a high gain preamplifier would be a neat way to allow the sort probe to serve as an antenna to measure frequency wirelessly, rater than requiring contact. Finally, I'm looking forward to writing software to interface the RS232 output. The ability to measure, record, and display changes in voltage or temperature over time is an important part of designing controller systems. For example, an improved crystal oven is on my list of projects to make. What a perfect way to monitor the temperature and stability of the completed project! Straight out of the box, this multimeter is an excellent tool.

Markdown source code last modified on January 18th, 2021
---
title: Tenma 72-7750 Multimeter for RF Engineering
date: 2013-04-17 22:20:55
tags: old
---

# Tenma 72-7750 Multimeter for RF Engineering

> **Update:** This page reviews my initial impressions of the Tenma 72-7750. In a later article ([TENMA Multimeter Serial Hack](https://swharden.com/blog/2016-08-24-tenma-multimeter-serial-hack/)) I use Python to interface this multimeter to make it easier to log data and create plots of measurements without using the official (Windows-only) software.

__I recently got my hands on a Tenma 72-7750 multimeter.__ Tenma has a [pretty large collection of test equipment and measurement products](http://www.newark.com/jsp/search/results.jsp?N=422+2203+200023&Ntk=gensearch&Ntt=tenma&Ntx=mode+matchallpartial&isNotify=true), including [several varieties of hand-held multimeters](http://www.newark.com/jsp/search/productListing.jsp?SKUS=02J5540,02J5541,02J5542,02J5543,02J5546). The 72-7750 multimeter has the standard measurement modes you'd expect (voltage, current capacitance, resistance, conductivity), but stood out to me because it also measures frequency, temperature, and has RS232 PC connectivity. Currently it's [sale from Newark for under fifty bucks](http://www.newark.com/tenma/72-7750/multimeter-digital-handheld-3-3/dp/02J5543)! This is what mine arrived with:

<div class="text-center img-small">

[![](2013-04-06-11.09.44_thumb.jpg)](2013-04-06-11.09.44.jpg)
[![](2013-04-06-11.11.35_thumb.jpg)](2013-04-06-11.11.35.jpg)

</div>

__The obvious stuff worked as expected.__ Auto ranging, (5 ranges of voltage and resistance, 3 of current, 7 of capacitance), accurate measurement, etc. I was, however, impressed with the extra set of test leads they provided - little short ones with gator clips! These are perfect for measuring capacitance, or for clipping onto wires coming out of a breadboard. So many times with my current multimeters I end-up gator-clipping wires to my probes and taking them to what I'm measuring. I'm already in love with the gator clip leads, and know I'll have a set of these at my bench for the rest of my life.

__I was impressed by the frequency measuring ability of this little multimeter!__ When I read that it could measure up to 60MHz, I was impressed, but also suspected it might be a little flakey. This was not at all the case - the frequency measurement was dead-on at several ranges! With so many of the projects I work on being RF-involved (radio transmitters, radio receivers, modulators, mixers, you name it), I sided with this meter because unlike some of its siblings this one is rated beyond 50Mz. I hooked it up to the frequency synthesizer I built based around an [ad9850](http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf) direct digital synthesizer and played around. When the synthesizer was set to various frequencies, the multimeter followed it to the digit! Check out the pics of it in action, comparing the LCD screen frequency with that being displayed on the meter:

<div class="text-center img-small img-border">

[![](2013-04-17-21.01.57_thumb.jpg)](2013-04-17-21.01.57.jpg)
[![](2013-04-17-21.02.50_thumb.jpg)](2013-04-17-21.02.50.jpg)

</div>

<div class="text-center img-border">

[![](2013-04-17-20.58.47_thumb.jpg)](2013-04-17-20.58.47.jpg)

</div>


__I also took a closer look at the PC interface.__ When I looked closely, I noticed it wasn't an electrical connection - it was an optical one! It has a phototransistor on one end, and a serial connection on the other. I'm no stranger to tossing data around with light (I made something that did this [here](http://www.swharden.com/blog/2011-07-26-pcmicrocontroller-wireless-data-transfer/), which was later featured on Hack-A-Day [here](http://hackaday.com/2011/07/28/microcontroller-communications-using-flashing-lights/)). I wondered what the format of the data was, when to my surprise I saw it spelled out in the product manual! (Go Tenma!)  It specifically says "Baud Rate 19230, Start Bit 1 (always 0), Stop bit 1 (always 1), Data bits (7), Parity 1 (odd)". Although they have their own windows-only software to display/graph readings over time, I'd consider writing Python-based logging software. It should be trivial with python, pySerial, numpy, and matplotlib. Clearly [I'm no stranger to graphing things in python](http://www.swharden.com/blog/category/python/) :)

<div class="text-center img-small">

[![](2013-04-17-21.04.28_thumb.jpg)](2013-04-17-21.04.28.jpg)
[![](2013-04-17-21.04.46_thumb.jpg)](2013-04-17-21.04.46.jpg)

</div>

__How does the photo-transistor work without power?__ I attached my o-scope to the pins and saw nothing when RS232 mode was activated on the multimeter. Presumably, the phototransistor requires a voltage source (albeit low current) to operate. With a little digging on the internet, I realized that the serial port can source power. I probably previously overlooked this because serial devices were a little before my time, but consider serial mice: they must have been supplied power! [Joseph Sullivan](http://www.clansullivan.com/joseph/index.html) has a [cool write-up](http://www.clansullivan.com/joseph/projects/laser.htm) on a project which allowed him to achieve bidirectional optical (laser) communication over (and completely powered by) a serial port. With a little testing, I applied 0V to pin 5 (GND), +5V to pin 6 (DSR, data set ready), and looked at the output on pin 3 (PC RX). Sure enough, there were bursts of easy-to-decode RS232 data. Here's the scheme Joseph came up with to power his laser communication system, which presumably is similar to the one in the multi-meter. (Note, that the cable is missing its "TX" light, but the meter has an "RX" phototransistor. I wonder if this would allow optically-loaded firmware?)

<div class="text-center img-border">

![](rs232-phototransistor-communication.jpg)

</div>

__There were a couple other things I found useful.__ Although I didn't appreciate it at first, after a few days the backlight grew on me. I've been doing experiments with photosensors which require me to turn out the lights in the room, and the backlight saved the day! Also, the meter came with a thermocouple for temperature measurement. It has it's own "ºC" setting on the dial, and displays human-readable temperature right on the screen. I used to do this with LM334-type thermosensitive current sources but it was always a pain (especially if I had one which output temperature in Kelvin!) I'm not sure exactly what's inside the one that came with this meter, but the datasheet suggests it can measure -40 through 1,000 C, which certainly will do for my experiments!

__All in all, I'm happy with this little guy,__ and am looking forward to hacking into it a little bit. There may be enough room in the case to add a hacked-together high frequency divider (a decade counter would be fantastic, divided by ten would allow measurement through 500MHz), but I might be over-reaching a bit. Alternatively, a high gain preamplifier would be a neat way to allow the sort probe to serve as an antenna to measure frequency wirelessly, rater than requiring contact. Finally, I'm looking forward to writing software to interface the RS232 output. The ability to measure, record, and display changes in voltage or temperature over time is an important part of designing controller systems. For example, an improved crystal oven is on my list of projects to make. What a perfect way to monitor the temperature and stability of the completed project! Straight out of the box, this multimeter is an excellent tool.
April 15th, 2013

Fixing Slow Matplotlib in Python(x,y)

I recently migrated to Python(x,y) and noticed my matplotlib graphs are resizing unacceptably slowly when I use the pan/zoom button. I'm quite a fan of numpy, scipy, matplotlib, the python imaging library (PIL), and GUI platforms like Tk/TkInter, pyGTK, and pyQT, but getting them all to play nicely is a sometimes pain. I'm considering migrating entirely to Python(x,y) because, as a single distribution, it's designed to install all these libraries (and many more) in a compatible way out of the box. However, when I did, I noticed matplotlib graphs would resize, rescale, and drag around the axes very slowly. After a lot of digging on the interweb, I figured out what was going wrong. I'll show you by plotting 20 random data points the slow way (left) then the fast way (right).

THE PROBLEM: See the difference between the two plots? The one on the left (SLOW!) uses the Qt4Agg backend, which renders the matplotlib plot on a QT4 canvas. This is slower than the one on the right, which uses the more traditional TkAgg backend to draw the plot on a Tk canvas with tkinter (FASTER!). Check out matplotlib's official description of what a backend is and which ones you can use. When you just install Python and matplotlib, Tk is used by default.

import numpy
import matplotlib
matplotlib.use('TkAgg') # <-- THIS MAKES IT FAST!
import pylab
pylab.plot(numpy.random.random_integers(0,100,20))
pylab.title("USING: "+matplotlib.get_backend())
pylab.show()

THE FIX: Tell matplotlib to stop using QT to draw the plot, and let it plot with Tk. This can be done immediately after importing matplotlib, but must be done before importing pylab using the line matplotlib.use('TkAgg'). Here's the full example I used to generate the demonstration plots above. Change TkAgg to Qt4Agg (or comment-out the 'use' line if you're using PythonXY) and you will see performance go down the tube. Alternatively, make a change to the matplotlib rc file to customize default behavior when the package is loaded.

Markdown source code last modified on January 18th, 2021
---
title: Fixing Slow Matplotlib in Python(x,y)
date: 2013-04-15 11:55:27
tags: python, old
---

# Fixing Slow Matplotlib in Python(x,y)

__I recently migrated to [Python(x,y)](https://code.google.com/p/pythonxy/) and noticed my matplotlib graphs are resizing unacceptably slowly when I use the pan/zoom button.__ I'm quite a fan of [numpy](http://www.scipy.org/Download), [scipy](http://www.scipy.org/Download), [matplotlib](http://matplotlib.org), the [python imaging library (PIL)](http://www.pythonware.com/products/pil/), and GUI platforms like [Tk/TkInter](http://wiki.python.org/moin/TkInter), [pyGTK](http://www.pygtk.org/), and [pyQT](http://www.riverbankcomputing.com/software/pyqt/intro), but getting them all to play nicely is a sometimes pain. I'm considering migrating entirely to [Python(x,y)](https://code.google.com/p/pythonxy/) because, as a single distribution, it's designed to install all [these libraries (and many more)](https://code.google.com/p/pythonxy/wiki/StandardPlugins) in a compatible way out of the box. However, when I did, I noticed matplotlib graphs would resize, rescale, and drag around the axes very slowly. After a lot of digging on the interweb, I figured out what was going wrong. I'll show you by plotting 20 random data points the slow way (left) then the fast way (right).

<div class="text-center img-small">

[![](matplotlib-qt4agg_thumb.jpg)](matplotlib-qt4agg.jpg)
[![](matplotlib-tkagg_thumb.jpg)](matplotlib-tkagg.jpg)

</div>

__THE PROBLEM:__ See the difference between the two plots? The one on the left (SLOW!) uses the Qt4Agg backend, which renders the matplotlib plot on a QT4 canvas. This is slower than the one on the right, which uses the more traditional TkAgg backend to draw the plot on a Tk canvas with tkinter (FASTER!).  Check out [matplotlib's official description of what a backend is](http://matplotlib.org/faq/usage_faq.html#what-is-a-backend) and which ones you can use. When you just install Python and matplotlib, Tk is used by default.

```python
import numpy
import matplotlib
matplotlib.use('TkAgg') # <-- THIS MAKES IT FAST!
import pylab
pylab.plot(numpy.random.random_integers(0,100,20))
pylab.title("USING: "+matplotlib.get_backend())
pylab.show()
```

__THE FIX:__ Tell matplotlib to stop using QT to draw the plot, and let it plot with Tk. This can be done immediately after importing matplotlib, but must be done before importing pylab using the line `` matplotlib.use('TkAgg') ``. Here's the full example I used to generate the demonstration plots above. Change TkAgg to Qt4Agg (or comment-out the 'use' line if you're using PythonXY) and you will see performance go down the tube. Alternatively, [make a change to the matplotlib rc file](http://matplotlib.org/users/customizing.html) to customize default behavior when the package is loaded.
April 14th, 2013

Simple DIY ECG + Pulse Oximeter (version 2)

⚠️ Check out my newer ECG designs:

Of the hundreds of projects I've shared over the years, none has attracted more attention than my DIY ECG machine on the cheap posted almost 4 years ago. This weekend I re-visited the project and made something I'm excited to share! The original project was immensely popular, my first featured article on Hack-A-Day, and today "ECG" still represents the second most searched term by people who land on my site. My gmail account also has had 194 incoming emails from people asking details about the project. A lot of it was by frustrated students trying to recreate the project running into trouble because it was somewhat poorly documented. Clearly, it's a project that a wide range of people are interested in, and I'm happy to revisit it bringing new knowledge and insight to the project. I will do my best to document it thoroughly so anyone can recreate it!

The goal of this project is to collect heartbeat information on a computer with minimal cost and minimal complexity. I accomplished this with fewer than a dozen components (all of which can be purchased at RadioShack). It serves both as a light-based heartbeat monitor (similar to a pulse oximeter, though it's not designed to quantitatively measure blood oxygen saturation), and an electrocardiogram (ECG) to visualize electrical activity generated by heart while it contracts. Let's jump right to the good part - this is what comes out of the machine:

That's my actual heartbeat. Cool, right? Before I go into how the circuit works, let's touch on how we measure heartbeat with ECG vs. light (like a pulse oximeter). To form a heartbeat, the pacemaker region of the heart (called the SA node, which is near the upper right of the heart) begins to fire and the atria (the two top chambers of the heart) contract. The SA node generates a little electrical shock which stimulated a synchronized contraction. This is exactly what defibrillators do when a heart has stopped beating. When a heart attack is occurring and a patient is undergoing ventricular fibrillation, it means that heart muscle cells are contracting randomly and not in unison, so the heart quivers instead of pumping as an organ. Defibrillators synchronize the heart beat with a sudden rush of current over the heart to reset all of the cells to begin firing at the same time (thanks Ron for requesting a more technical description). If a current is run over the muscle, the cells (cardiomyocytes) all contract at the same time, and blood moves. The AV node (closer to the center of the heart) in combination with a slow conducting pathway (called the bundle of His) control contraction of the ventricles (the really large chambers at the bottom of the heart), which produce the really large spikes we see on an ECG. To measure ECG, optimally we'd place electrodes on the surface of the heart. Since that would be painful, we do the best we can by measuring voltage changes (often in the mV range) on the surface of the skin. If we amplify it enough, we can visualize it. Depending on where the pads are placed, we can see different regions of the heart contract by their unique electrophysiological signature. ECG requires sticky pads on your chest and is extremely sensitive to small fluctuations in voltage. Alternatively, a pulse oximeter measures blood oxygenation and can monitor heartbeat by clipping onto a finger tip. It does this by shining light through your finger and measuring how much light is absorbed. This goes up and down as blood is pumped through your finger. If you look at the relationship between absorbency in the red vs. infrared wavelengths, you can infer the oxygenation state of the blood. I'm not doing that today because I'm mostly interested in detecting heart beats.

For operation as a pulse oximeter-type optical heartbeat detector (a photoplethysmograph which produces a photoplethysmogram), I use a bright red LED to shine light through my finger and be detected by a phototransistor (bottom left of the diagram). I talk about how this works in more detail in a previous post. Basically the phototransistor acts like a variable resistor which conducts different amounts of current depending on how much light it sees. This changes the voltage above it in a way that changes with heartbeats. If this small signal is used as the input, this device acts like a pulse oximeter.

For operation as an electrocardiograph (ECG), I attach the (in) directly to a lead on my chest. One of them is grounded (it doesn't matter which for this circuit - if they're switched the ECG just looks upside down), and the other is recording. In my original article, I used pennies with wires soldered to them taped to my chest as leads. Today, I'm using fancier sticky pads which are a little more conductive. In either case, one lead goes in the center of your chest, and the other goes to your left side under your arm pit. I like these sticky pads because they stick to my skin better than pennies taped on with electrical tape. I got 100 Nikomed Nikotabs EKG Electrodes 0315 on eBay for $5.51 with free shipping (score!). Just gator clip to them and you're good to go!

In both cases, I need to build a device to amplify small signals. This is accomplished with the following circuit. The core of the circuit is an LM324 quad operational amplifier. These chips are everywhere, and extremely cheap. It looks like Thai Shine sells 10 for $2.86 (with free shipping). That's about a quarter each. Nice! A lot of ECG projects use instrumentation amplifiers like the AD620 (which I have used with fantastic results), but these are expensive (about $5.00 each). The main difference is that instrumentation amplifiers amplify the difference between two points (which reduces noise and probably makes for a better ECG machine), but for today an operational amplifier will do a good enough job amplifying a small signal with respect to ground. I get around the noise issue by some simple filtering techniques. Let's take a look at the circuit.

This project utilizes one of the op-amps as a virtual ground. One complaint of using op-amps in simple projects is that they often need + and - voltages. Yeah, this could be done with two 9V batteries to generate +9V and -9V, but I think it's easier to use a single power source (+ and GND). A way to get around that is to use one of the op-amps as a current source and feed it half of the power supply voltage (VCC), and use the output as a virtual ground (allowing VCC to be your + and 0V GND to be your -). For a good description of how to do this intelligently, read the single supply op amps web page. The caveat is that your signals should remain around VCC/2, which can be done if it is decoupled by feeding it through a series capacitor. The project works at 12V or 5V, but was designed for (and has much better output) at 12V. The remaining 3 op-amps of the LM324 serve three unique functions:

STAGE 1: High gain amplifier. The input signals from either the ECG or pulse oximeter are fed into a chain of 3 opamp stages. The first is a preamplifier. The output is decoupled through a series capacitor to place it near VCC/2, and amplified greatly thanks to the 1.8Mohm negative feedback resistor. Changing this value changes initial gain.

STAGE 2: active low-pass filter. The 10kOhm variable resistor lets you adjust the frequency cutoff. The opamp serves as a unity gain current source / voltage follower that has high input impedance when measuring the output f the low-pass filter and reproduces its voltage with a low impedance output. There's some more information about active filtering on this page. It's best to look at the output of this stage and adjust the potentiometer until the 60Hz noise (caused by the AC wiring in the walls) is most reduced while the lower-frequency component of your heartbeat is retained. With the oximeter, virtually no noise gets through. Because the ECG signal is much smaller, this filter has to be less aggressive, and this noise is filtered-out by software (more on this later).

STAGE 3: final amplifier with low-pass filter. It has a gain of ~20 (determined by the ratio of the 1.8kOhm to 100Ohm resistors) and lowpass filtering components are provided by the 22uF capacitor across the negative feedback resistor. If you try to run this circuit at 5V and want more gain (more voltage swing), consider increasing the value of the 1.8kOhm resistor (wit the capacitor removed). Once you have a good gain, add different capacitor values until your signal is left but the noise reduced. For 12V, these values work fine. Let's see it in action!

Now for the second half - getting it into the computer. The cheapest and easiest way to do this is to simply feed the output into a sound card! A sound card is an analog-to-digital converter (ADC) that everybody has and can sample up to 48 thousand samples a second! (overkill for this application) The first thing you should do is add an output potentiometer to allow you to drop the voltage down if it's too big for the sound card (in the case of the oximeter) but but also allow full-volume in the case of sensitive measurements (like ECG). Then open-up sound editing software (I like GoldWave for Windows or Audacity for Linux, both of which are free) and record the input. You can do filtering (low-pass filter at 40Hz with a sharp cutoff) to further eliminate any noise that may have sneaked through. Re-sample at 1,000 Hz (1kHz) and save the output as a text file and you're ready to graph it! Check it out.

Here are the results of some actual data recorded and processed with the method shown in the video. let's look at the pulse oximeter first.

That looks pretty good, certainly enough for heartbeat detection. There's obvious room for improvement, but as a proof of concept it's clearly working. Let's switch gears and look at the ECG. It's much more challenging because it's signal is a couple orders of magnitude smaller than the pulse oximeter, so a lot more noise gets through. Filtering it out offers dramatic improvements!

Here's the code I used to generate the graphs from the text files that GoldWave saves. It requires Python, Matplotlib (pylab), and Numpy. In my case, I'm using 32-bit 2.6 versions of everything.

# DIY Sound Card ECG/Pulse Oximeter
# by Scott Harden (2013) http://www.SWHarden.com

import pylab
import numpy

f=open("light.txt")
raw=f.readlines()[1:]
f.close()

data = numpy.array(raw,dtype=float)
data = data-min(data) #make all points positive
data = data/max(data)*100.0 #normalize
times = numpy.array(range(len(data)))/1000.0
pylab.figure(figsize=(15,5))
pylab.plot(times,data)
pylab.xlabel("Time Elapsed (seconds)")
pylab.ylabel("Amplitude (% max)")
pylab.title("Pulse Oximeter - filtered")
pylab.subplots_adjust(left=.05,right=.98)
pylab.show()

Future directions involve several projects I hope to work on soon. First, it would be cool to miniaturize everything with surface mount technology (SMT) to bring these things down to the size of a postage stamp. Second, improved finger, toe, or ear clips (or even taped-on sensors) over long duration would provide a pretty interesting way to analyze heart rate variability or modulation in response to stress, sleep apnea, etc. Instead of feeding the signal into a computer, one could send it to a micro-controller for processing. I've made some darn-good progress making multi-channel cross-platform USB option for getting physiology data into a computer, but have some work still to do. Alternatively, this data could be graphed on a graphical LCD for an all-in-one little device that doesn't require a computer. Yep, lots of possible projects can use this as a starting point.

Notes about safety: If you're worried about electrical shock, or unsure of your ability to make a safe device, don't attempt to build an ECG machine. For an ECG to work, you have to make good electrical contact with your skin near your heart, and some people feel this is potentially dangerous. Actually, some people like to argue about how dangerous it actually is, as seen on Hack-A-Day comments and my previous post comments. Some people have suggested the danger is negligible and pointed-out that it's similar to inserting ear-bud headphones into your ears. Others have suggested that it's dangerous and pointed-out that milliamps can kill a person. Others contest that pulses of current are far more dangerous than a continuous applied current. Realists speculate that virtually no current would be delivered by this circuit if it is wired properly. Rational, cautionary people worried about it reduce risk of accidental current by applying bidirectional diodes at the level of the chest leads, which short any current (above 0.7V) similar to that shown here. Electrically-savvy folks would design an optically decoupled solution. Intelligent folks who abstain from arguing on the internet would probably consult the datasheets regarding ECG input protection. In all cases, don't attach electrical devices to your body unless you are confident in their safety. As a catch-all, I present the ECG circuit for educational purposes only, and state that it may not be safe and should not be replicated There, will that cover me in court in case someone tapes wires to their chest and plugs them in the wall socket?

LET ME KNOW WHAT YOU THINK! If you make this, I'm especially interested to see how it came out. Take pictures of your projects and send them my way! If you make improvements, or take this project further, I'd be happy to link to it on this page. I hope this page describes the project well enough that anyone can recreate it, regardless of electronics experience. Finally, I hope that people are inspired by the cool things that can be done with surprisingly simple electronics. Get out there, be creative, and go build something cool!

Markdown source code last modified on January 18th, 2021
---
title: Simple DIY ECG + Pulse Oximeter (version 2)
date: 2013-04-14 16:00:14
tags: diyECG, microcontroller, old
---

# Simple DIY ECG + Pulse Oximeter (version 2)

> **⚠️ Check out my newer ECG designs:** 
* [**Sound Card ECG with AD8232**](https://swharden.com/blog/2019-03-15-sound-card-ecg-with-ad8232/)
* [**Single op-amp ECG**](https://swharden.com/blog/2016-08-08-diy-ecg-with-1-op-amp/)

__Of the hundreds of projects I've shared over the years, none has attracted more attention than my [DIY ECG machine on the cheap](http://www.swharden.com/blog/2009-08-14-diy-ecg-machine-on-the-cheap/) posted almost 4 years ago. This weekend I re-visited the project and made something I'm excited to share!__  The original project was immensely popular, my [first featured article on Hack-A-Day](http://hackaday.com/2009/08/22/collect-and-analyze-ecg-data/), and today "ECG" still represents the second most searched term by people who land on my site. My gmail account also has had 194 incoming emails from people asking details about the project. A lot of it was by frustrated students trying to recreate the project running into trouble because it was somewhat poorly documented. Clearly, it's a project that a wide range of people are interested in, and I'm happy to revisit it bringing new knowledge and insight to the project. I will do my best to document it thoroughly so anyone can recreate it!

<div class="text-center img-border">

[![](diy-ecg-pulse-oximeter-lm324-opamp-sound-card_thumb.jpg)](diy-ecg-pulse-oximeter-lm324-opamp-sound-card.jpg)

</div>

__The goal of this project is to collect heartbeat information on a computer with minimal cost and minimal complexity.__  I accomplished this with fewer than a dozen components (all of which can be purchased at RadioShack). It serves both as a light-based heartbeat monitor (similar to a pulse oximeter, though it's not designed to quantitatively measure blood oxygen saturation), and an electrocardiogram (ECG) to visualize electrical activity generated by heart while it contracts. Let's jump right to the good part - this is what comes out of the machine:

<div class="text-center">

[![](pulse-ecg-filtered-a_thumb.jpg)](pulse-ecg-filtered-a.png)

</div>

<strong>That's <em>my</em> actual heartbeat. Cool, right? Before I go into how the circuit works, let's touch on how we measure heartbeat with ECG vs. light (like a pulse oximeter).</strong>  To form a heartbeat, the pacemaker region of the heart (called the SA node, which is near the upper right of the heart) begins to fire and the atria (the two top chambers of the heart) contract. The SA node generates a little electrical shock which stimulated a synchronized contraction. <span style="text-decoration: line-through;">This is exactly what defibrillators do when a heart has stopped beating.</span> When a heart attack is occurring and a patient is undergoing ventricular fibrillation, it means that heart muscle cells are contracting randomly and not in unison, so the heart quivers instead of pumping as an organ. Defibrillators synchronize the heart beat with a sudden rush of current over the heart to reset all of the cells to begin firing at the same time (thanks Ron for requesting a more technical description).  If a current is run over the muscle, the cells (cardiomyocytes) all contract at the same time, and blood moves. The AV node (closer to the center of the heart) in combination with a slow conducting pathway (called the bundle of His) control contraction of the ventricles (the really large chambers at the bottom of the heart), which produce the really large spikes we see on an ECG.  <strong>To measure ECG</strong>, optimally we'd place electrodes on the surface of the heart. Since that would be painful, we do the best we can by measuring voltage changes (often in the mV range) on the surface of the skin. If we amplify it enough, we can visualize it. Depending on where the pads are placed, we can see different regions of the heart contract by their unique electrophysiological signature. ECG requires sticky pads on your chest and is extremely sensitive to small fluctuations in voltage. Alternatively, <strong>a pulse oximeter measures blood oxygenation and can monitor heartbeat by clipping onto a finger tip</strong>. It does this by shining light through your finger and measuring how much light is absorbed. This goes up and down as blood is pumped through your finger. If you look at the relationship between absorbency in the red vs. infrared wavelengths, you can infer the oxygenation state of the blood. I'm not doing that today because I'm mostly interested in detecting heart beats.

<strong>For operation as a pulse oximeter-type optical heartbeat detector (a <em>photoplethysmograph</em> which produces a <a href="http://en.wikipedia.org/wiki/Photoplethysmogram"><em>photoplethysmogram</em></a>),</strong> I use a bright red LED to shine light through my finger and be detected by a phototransistor (bottom left of the diagram). I talk about how this works in more detail <a href="http://www.swharden.com/blog/2012-12-06-single-wavelength-pulse-oximeter/">in a previous post</a>. Basically the phototransistor acts like a variable resistor which conducts different amounts of current depending on how much light it sees. This changes the voltage above it in a way that changes with heartbeats. If this small signal is used as the input, this device acts like a pulse oximeter.

<div class="text-center img-border">

[![](2013-04-14-11.36.39_thumb.jpg)](2013-04-14-11.36.39.jpg)

</div>

<strong>For operation as an electrocardiograph (ECG)</strong>, I attach the (in) directly to a lead on my chest. One of them is grounded (it doesn't matter which for this circuit - if they're switched the ECG just looks upside down), and the other is recording. In my <a href="http://www.swharden.com/blog/2009-08-14-diy-ecg-machine-on-the-cheap/">original article</a>, I used pennies with wires soldered to them taped to my chest as leads. Today, I'm using fancier sticky pads which are a little more conductive. In either case, one lead goes in the center of your chest, and the other goes to your left side under your arm pit. I like these sticky pads because they stick to my skin better than pennies taped on with electrical tape. I got <a href="http://www.ebay.com/sch/i.html?_trksid=m570.l3201&_nkw=100+NIKOMED+NIKOTABS+EKG+ELECTRODES+0315&_sacat=0">100 Nikomed Nikotabs EKG Electrodes 0315</a> on eBay for $5.51 with free shipping (score!). Just gator clip to them and you're good to go!

<div class="text-center img-border">

[![](2013-04-14-15.06.20_thumb.jpg)](2013-04-14-15.06.20.jpg)

</div>

__In both cases, I need to build a device to amplify small signals__. This is accomplished with the following circuit. The core of the circuit is an [LM324 quad operational amplifier](http://www.ti.com/lit/ds/symlink/lm124-n.pdf).  These chips are everywhere, and extremely cheap. It looks like [Thai Shine sells 10 for $2.86](http://www.thaishine.com/servlet/the-910/10-x-LM324N-LM324/Detail) (with free shipping). That's about a quarter each. Nice!  A lot of ECG projects use instrumentation amplifiers like the AD620 (which I have used with [fantastic results](http://www.swharden.com/blog/2012-06-14-multichannel-usb-analog-sensor-with-atmega48/)), but these are expensive (about $5.00 each). The main difference is that instrumentation amplifiers amplify the difference between two points (which reduces noise and probably makes for a better ECG machine), but for today an operational amplifier will do a good enough job amplifying a small signal with respect to ground. I get around the noise issue by some simple filtering techniques. Let's take a look at the circuit.

<div class="text-center img-border">

[![](lm324-opamp-pulse-oximeter-ecg-schematic_thumb.jpg)](lm324-opamp-pulse-oximeter-ecg-schematic.jpg)

</div>

<strong>This project utilizes one of the op-amps as a <a href="http://en.wikipedia.org/wiki/Virtual_ground">virtual ground</a>.</strong> One complaint of using op-amps in simple projects is that they often need + and - voltages. Yeah, this <a href="http://cdn.head-fi.org/8/80/801b6a4a_principle.gif">could be done with two 9V batteries</a> to generate +9V and -9V, but I think it's easier to use a single power source (+ and GND). A way to get around that is to use one of the op-amps as a current source and feed it half of the power supply voltage (VCC), and use the output as a virtual ground (allowing VCC to be your + and 0V GND to be your -). For a good description of how to do this intelligently, read the <a href="http://www.swarthmore.edu/NatSci/echeeve1/Ref/SingleSupply/SingleSupply.html">single supply op amps web page</a>. The caveat is that your signals should remain around VCC/2, which can be done if it is decoupled by feeding it through a series capacitor. The project works at 12V or 5V, but was designed for (and has much better output) at 12V. The remaining 3 op-amps of the LM324 serve three unique functions:

<strong>STAGE 1: High gain amplifier.</strong> The input signals from either the ECG or pulse oximeter are fed into a chain of 3 opamp stages. The first is a preamplifier. The output is decoupled through a series capacitor to place it near VCC/2, and amplified greatly thanks to the 1.8Mohm negative feedback resistor. Changing this value changes initial gain.

<strong>STAGE 2: active low-pass filter.</strong> The 10kOhm variable resistor lets you adjust the frequency cutoff. The opamp serves as a unity gain current source / voltage follower that has high input impedance when measuring the output f the low-pass filter and reproduces its voltage with a low impedance output. There's some <a href="http://www.electronics-tutorials.ws/filter/filter_5.html">more information about active filtering on this page</a>. It's best to look at the output of this stage and adjust the potentiometer until the 60Hz noise (caused by the AC wiring in the walls) is most reduced while the lower-frequency component of your heartbeat is retained. With the oximeter, virtually no noise gets through. Because the ECG signal is much smaller, this filter has to be less aggressive, and this noise is filtered-out by software (more on this later).

<strong>STAGE 3: final amplifier with low-pass filter.</strong> It has a gain of ~20 (determined by the ratio of the 1.8kOhm to 100Ohm resistors) and lowpass filtering components are provided by the 22uF capacitor across the negative feedback resistor. If you try to run this circuit at 5V and want more gain (more voltage swing), consider increasing the value of the 1.8kOhm resistor (wit the capacitor removed). Once you have a good gain, add different capacitor values until your signal is left but the noise reduced. For 12V, these values work fine. Let's see it in action!

<iframe frameborder="0" height="360" src="http://www.youtube.com/embed/bKAJsZJvMI0?list=UUs3-qUELPY-2AOHa7Q_db5w" width="640"></iframe>

<strong>Now for the second half - getting it into the computer.</strong> The cheapest and easiest way to do this is to simply feed the output into a sound card! A sound card is an analog-to-digital converter (ADC) that <em>everybody</em> has and can sample up to 48 thousand samples a second! (overkill for this application) The first thing you should do is add an output potentiometer to allow you to drop the voltage down if it's too big for the sound card (in the case of the oximeter) but but also allow full-volume in the case of sensitive measurements (like ECG). Then open-up sound editing software (I like <a href="http://www.goldwave.com/">GoldWave</a> for Windows or <a href="http://audacity.sourceforge.net/">Audacity</a> for Linux, both of which are free) and record the input. You can do filtering (low-pass filter at 40Hz with a sharp cutoff) to further eliminate any noise that may have sneaked through. Re-sample at 1,000 Hz (1kHz) and save the output as a text file and you're ready to graph it! Check it out.

<iframe frameborder="0" height="360" src="http://www.youtube.com/embed/9BFS9D3x_sY?list=UUs3-qUELPY-2AOHa7Q_db5w" width="640"></iframe>

__Here are the results__ of some actual data recorded and processed with the method shown in the video. let's look at the pulse oximeter first.

<div class="text-center">

[![](pulse-ecg-filtered-a_thumb.jpg)](pulse-ecg-filtered-a.png)

</div>

<strong>That looks pretty good, certainly enough for heartbeat detection.</strong> There's obvious room for improvement, but as a proof of concept it's clearly working. Let's switch gears and look at the ECG. It's much more challenging because it's signal is a couple orders of magnitude smaller than the pulse oximeter, so a lot more noise gets through. Filtering it out offers dramatic improvements!

<div class="text-center">

[![](pulse-oximeter-a_thumb.jpg)](pulse-oximeter-a.png)
[![](pulse-oximeter-b_thumb.jpg)](pulse-oximeter-b.png)

</div>

<strong>Here's the code</strong> I used to generate the graphs from the text files that GoldWave saves. It requires <a href="http://www.Python.org">Python</a>, <a href="http://matplotlib.org/">Matplotlib (pylab)</a>, and <a href="http://www.scipy.org/Download">Numpy</a>. In my case, I'm using 32-bit 2.6 versions of everything.

```python
# DIY Sound Card ECG/Pulse Oximeter
# by Scott Harden (2013) http://www.SWHarden.com

import pylab
import numpy

f=open("light.txt")
raw=f.readlines()[1:]
f.close()

data = numpy.array(raw,dtype=float)
data = data-min(data) #make all points positive
data = data/max(data)*100.0 #normalize
times = numpy.array(range(len(data)))/1000.0
pylab.figure(figsize=(15,5))
pylab.plot(times,data)
pylab.xlabel("Time Elapsed (seconds)")
pylab.ylabel("Amplitude (% max)")
pylab.title("Pulse Oximeter - filtered")
pylab.subplots_adjust(left=.05,right=.98)
pylab.show()
```

<strong>Future directions involve several projects</strong> I hope to work on soon. First, it would be cool to miniaturize everything with surface mount technology (SMT) to bring these things down to the size of a postage stamp. Second, improved finger, toe, or ear clips (or even taped-on sensors) over long duration would provide a pretty interesting way to analyze heart rate variability or modulation in response to stress, sleep apnea, etc. Instead of feeding the signal into a computer, one could send it to a micro-controller for processing. I've made some <a href="http://www.swharden.com/blog/2012-06-14-multichannel-usb-analog-sensor-with-atmega48/">darn-good progress making multi-channel cross-platform USB option for getting physiology data into a computer</a>, but have some work still to do. Alternatively, this data could be graphed on a <a href="http://learn.adafruit.com/system/assets/assets/000/000/899/medium800/graphiclcd.jpg?1342115751">graphical LCD</a> for an all-in-one little device that doesn't require a computer. Yep, lots of possible projects can use this as a starting point.

<strong>Notes about safety:</strong> If you're worried about electrical shock, or unsure of your ability to make a safe device, don't attempt to build an ECG machine. For an ECG to work, you have to make good electrical contact with your skin near your heart, and some people feel this is potentially dangerous. Actually, some people like to argue about how dangerous it actually is, as seen on <a href="http://hackaday.com/2009/08/22/collect-and-analyze-ecg-data/#comments">Hack-A-Day comments</a> and my <a href="http://www.swharden.com/blog/2009-08-14-diy-ecg-machine-on-the-cheap/#comments">previous post comments</a>. Some people have suggested the danger is negligible and pointed-out that it's similar to inserting ear-bud headphones into your ears. Others have suggested that it's dangerous and pointed-out that <a href="http://hypertextbook.com/facts/2000/JackHsu.shtml">milliamps can kill a person</a>. Others contest that pulses of current are far more dangerous than a continuous applied current. Realists speculate that virtually no current would be delivered by this circuit if it is wired properly. Rational, cautionary people worried about it reduce risk of accidental current by applying bidirectional diodes at the level of the chest leads, which short any current (above 0.7V) similar to <a href="http://www.extremecircuits.net/2010/07/ecg-amplifier-by-tlc274.html">that shown here</a>. Electrically-savvy folks would design an optically decoupled solution. Intelligent folks who abstain from arguing on the internet would probably consult the <a href="http://www.analog.com/static/imported-files/tech_articles/MS-2160.pdf">datasheets regarding ECG input protection</a>. In all cases, don't attach electrical devices to your body unless you are confident in their safety. As a catch-all, I present the ECG circuit for educational purposes only, and state that it may not be safe and should not be replicated  There, will that cover me in court in case someone tapes wires to their chest and plugs them in the wall socket?

<strong>LET ME KNOW WHAT YOU THINK!</strong> If you make this, I'm especially interested to see how it came out. Take pictures of your projects and send them my way! If you make improvements, or take this project further, I'd be happy to link to it on this page. I hope this page describes the project well enough that anyone can recreate it, regardless of electronics experience. Finally, I hope that people are inspired by the cool things that can be done with surprisingly simple electronics. Get out there, be creative, and go build something cool!
Pages