The personal website of Scott W Harden

Breadboard Line Driver Module

Sometimes I rapidly want to amplify a signal, but building amplifiers, buffers, and line drivers can be a hassle, especially on a breadboard! It's important to know how to carefully design build tuned and untuned amplifier circuits, but sometimes you just want to analyze or work with a signal without modifying it by sinking too much current, so being able to rapidly drop in a buffer stage would be a great help. Sometimes I want to buffer a signal so I can analyze it (with an oscilloscope or frequency counter) or use use it (perhaps to drive or gate something), but the signal source is across the room, so I need a beefy amplifier to drive it into coax as I run it across my ceiling while I'm experimenting. A MOSFET voltage follower or a Darlington transistor may do the job, but I have to worry about input conditioning, biasing, output voltage limiting, class A, B, C, D, etc., RF vs DC, copying this circuit multiple times for multiple signals, and before you know it I'm sinking more time into my task than I need to.

Line driver chips are one of my go-tos for quickly amplifying digital signals because they're so fast to drop in a breadboard and they provide a strong output with very high impedance inputs and need no external components. Individual buffer of the integrated chip can be paralleled to multiply their current handling capabilities too. One of the common variants is the 74HC240. I don't know why it's so popular (I still find its pinout odd), but because it is popular it is cheap. They're $0.50 on Mouser.com (perhaps cheaper on ebay) and according to their datasheet they can be run up to 7V to deliver or sink 20mA/pin with a maximum dissipation of 500mW. With propagation, enable, and disable times of tens of nanoseconds, they're not awful for lower-range radio frequencies (HF RF). This specific chip (somewhat comically at the exclusion of almost all others) has been latched onto by amateur radio operators who use it as an amplifier stage of low power (QRP) Morse code radio transmitters often pushing it to achieve ~1 watt of power output. A quick google reveals thousands of web pages discussing this! This Portuguese site is one of the most thorough. Even if not used as the final amplifier, they're a convenient intermediate stage along an amplifier chain as they can directly drive FET final stages very well (probably best for class C operation). If you're interested, definitely check out The Handiman's Guide to MOSFET "Switched Mode" Amplifiers guide by Paul Harden (no relation). Also his part 2.

This is the circuit I commonly build. I have one variant on hand for RF (extremely fast oscillations which are continuously fed into the device and often decoupled through a series capacitor), and one for TTL signals (extremely fast). I find myself paralleling line driver outputs all the time. On a breadboard, this means tons of wires! It becomes repetitive and a pain. I've started pre-packaging highly parallel line drivers into little modules which I find really convenient. I have a half dozen of these soldered and ready to go, and I can use them by simply dropping them into a breadboard and applying ground, power (+5V), and input signal, and it amplifies it and returns an output signal. Note that in the "Case 2: RF input" example, the inverted output of the first stage is continuously fed back into the input. This will result in continuous oscillation and undesired output if no input is supplied. In case 2, RF must be continuously applied. The advantage is that the feedback network holds the input near the threshold voltage, so very little voltage swing through the decoupling capacitor is required to generate strong output.

Although I have made this entirely floating, I prefer using copper-clad board. Not only does it aid heat dissipation and provide better mechanical structure, but it also serves as a partial RF shield to minimize noise in the input and output signals. A Dremel with a diamond wheel does a good job at cutting out notches in the copper-clad board.

The best way to replicate this is to look at the picture. It's surprisingly difficult to get it right just by looking at the datasheet, because when it's upside down it's mirror-imaged and very easy to make mistakes. I just connect all inputs and all outputs in parallel, for 7 of 8 gates. For one gate, I connect its output to the parallel inputs. I added some passives (including a ferrite bead and decoupling capacitor on the VCC pin) and it's good to go. With only 4 pins (GND, +5V, IN, and OUT) this amplifier is easy to drop in a breadboard:

Although I often use it in a breadboard, it's easy to stick in a project. Since the back side is unpopulated, you can use a dot of super glue and stick it anywhere you want. In this example, I had a GPS receiver module which blinked a LED at exactly one pulse per second (1PPS) [check out why] and I wanted to do some measurements on its output. I couldn't send this line signal out a coax line because it was so low current (in reality, I didn't know what it could deliver). This is a perfect use for a buffer / line driver.

I glued this board inside my temporary project enclosure (which admittedly looks nicer and more permanent than it's actually intended to be) and set the output to deliver through 50 Ohm coax. It works beautifully!

Markdown source code last modified on January 18th, 2021
---
title: Breadboard Line Driver Module
date: 2016-08-20 19:16:27
tags: circuit, old
---

# Breadboard Line Driver Module

__Sometimes I rapidly want to amplify a signal, but building amplifiers, buffers, and line drivers can be a hassle, especially on a breadboard!__ It's important to know how to carefully design build [tuned and untuned amplifier circuits](https://en.wikibooks.org/wiki/Practical_Electronics/Amplifiers#Type_of_load), but sometimes you just want to analyze or work with a signal without modifying it by sinking too much current, so being able to rapidly drop in a buffer stage would be a great help. Sometimes I want to buffer a signal so I can analyze it (with an oscilloscope or frequency counter) or use use it (perhaps to drive or gate something), but the signal source is across the room, so I need a beefy amplifier to drive it into coax as I run it across my ceiling while I'm experimenting. A [MOSFET voltage follower](https://en.wikipedia.org/wiki/Buffer_amplifier#Impedance_transformation_using_the_MOSFET_voltage_follower) or a [Darlington transistor](https://en.wikipedia.org/wiki/Darlington_transistor) may do the job, but I have to worry about input conditioning, biasing, output voltage limiting, class A, B, C, D, etc., RF vs DC, copying this circuit multiple times for multiple signals, and before you know it I'm sinking more time into my task than I need to. 

__Line driver chips are one of my go-tos for quickly amplifying digital signals because they're so fast to drop in a breadboard and they provide a strong output with very high impedance inputs and need no external components.__ Individual buffer of the integrated chip can be paralleled to multiply their current handling capabilities too. One of the common variants is the 74HC240. I don't know why it's so popular (I still find its pinout odd), but because it is popular it is cheap. They're [$0.50 on Mouser.com](http://www.mouser.com/Semiconductors/Integrated-Circuits-ICs/Logic-ICs/Buffers-Line-Drivers/_/N-6j78c?P=1z0z63x&Keyword=74hc240&FS=True) (perhaps cheaper on ebay) and [according to their datasheet](http://www.nxp.com/documents/data_sheet/74HC_HCT240.pdf) they can be run up to 7V to deliver or sink 20mA/pin with a maximum dissipation of 500mW. With propagation, enable, and disable times of tens of nanoseconds, they're not awful for lower-range radio frequencies (HF RF). This specific chip (somewhat comically at the exclusion of almost all others) has been latched onto by amateur radio operators who use it as an amplifier stage of low power (QRP) Morse code radio transmitters often pushing it to achieve ~1 watt of power output. A quick google [reveals](https://www.google.com/search?q=74hc240+transmitter) thousands of web pages discussing this! This [Portuguese site](http://py2ohh.w2c.com.br/trx/digital/rfdigital.htm) is one of the most thorough. Even if not used as the final amplifier, they're a convenient intermediate stage along an amplifier chain as they can directly drive FET final stages very well (probably best for class C operation). If you're interested, definitely check out [The Handiman's Guide to MOSFET "Switched Mode" Amplifiers guide by Paul Harden](http://www.aoc.nrao.edu/~pharden/hobby/_ClassDEF1.pdf) (no relation). Also his [part 2](http://www.aoc.nrao.edu/~pharden/hobby/_ClassDEF2.pdf).

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

[![](schematic_thumb.jpg)](schematic.jpg)

</div>

This is the circuit I commonly build. I have one variant on hand for RF (extremely fast oscillations which are continuously fed into the device and often decoupled through a series capacitor), and one for TTL signals (extremely fast). __I find myself paralleling line driver outputs all the time. On a breadboard, this means tons of wires!__ __It becomes repetitive and a pain. I've started pre-packaging highly parallel line drivers into little modules which I find really convenient.__ I have a half dozen of these soldered and ready to go, and I can use them by simply dropping them into a breadboard and applying ground, power (+5V), and input signal, and it amplifies it and returns an output signal. Note that in the "Case 2: RF input" example, the inverted output of the first stage is continuously fed back into the input. This will result in continuous oscillation and undesired output if no input is supplied. In case 2, RF must be continuously applied. The advantage is that the feedback network holds the input near the threshold voltage, so very little voltage swing through the decoupling capacitor is required to generate strong output.

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

[![](IMG_7890_thumb.jpg)](IMG_7890.jpg)
[![](IMG_7894_thumb.jpg)](IMG_7894.jpg)
[![](IMG_7897_thumb.jpg)](IMG_7897.jpg)

</div>

__Although I have made this entirely floating, I prefer using copper-clad board.__ Not only does it aid heat dissipation and provide better mechanical structure, but it also serves as a partial RF shield to minimize noise in the input and output signals. A Dremel with a diamond wheel does a good job at cutting out notches in the copper-clad board.

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

[![](IMG_7898_thumb.jpg)](IMG_7898.jpg)
[![](IMG_7900_thumb.jpg)](IMG_7900.jpg)
[![](IMG_7909_thumb.jpg)](IMG_7909.jpg)

</div>

__The best way to replicate this is to look at the picture.__ It's surprisingly difficult to get it right just by looking at the datasheet, because when it's upside down it's mirror-imaged and very easy to make mistakes. I just connect all inputs and all outputs in parallel, for 7 of 8 gates. For one gate, I connect its output to the parallel inputs. I added some passives (including a [ferrite bead](https://en.wikipedia.org/wiki/Ferrite_bead) and decoupling capacitor on the VCC pin) and it's good to go. With only 4 pins (GND, +5V, IN, and OUT) this amplifier is easy to drop in a breadboard:

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

[![](IMG_7904_thumb.jpg)](IMG_7904.jpg)

</div>

__Although I often use it in a breadboard, it's easy to stick in a project.__ Since the back side is unpopulated, you can use a dot of super glue and stick it anywhere you want. In this example, I had a GPS receiver module which blinked a LED at exactly one pulse per second (1PPS) [[check out why](http://electronics.stackexchange.com/questions/30750/why-do-gps-receivers-have-a-1-pps-output)] and I wanted to do some measurements on its output. I couldn't send this line signal out a coax line because it was so low current (in reality, I didn't know what it could deliver). This is a perfect use for a buffer / line driver. 

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

[![](IMG_7912_thumb.jpg)](IMG_7912.jpg)

</div>

I glued this board inside my temporary project enclosure (which admittedly looks nicer and more permanent than it's actually intended to be) and set the output to deliver through 50 Ohm coax. It works beautifully!

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

[![](IMG_7943_thumb.jpg)](IMG_7943.jpg)
[![](IMG_7948_thumb.jpg)](IMG_7948.jpg)

</div>

DIY ECG with 1 op-amp

⚠️ Check out my newer ECG design:

I made surprisingly good ECG from a single op-amp and 5 resistors! An ECG (electrocardiograph, sometimes called EKG) is a graph of the electrical potential your heart produces as it beats. Seven years ago I posted DIY ECG Machine on the Cheap which showed a discernible ECG I obtained using an op-amp, two resistors, and a capacitor outputting to a PC sound card's microphone input. It didn't work well, but the fact that it worked at all was impressive! It has been one of the most popular posts of my website ever since, and I get 1-2 emails a month from people trying to recreate these results (some of them are during the last week of a college design course and sound pretty desperate). Sometimes people get good results with that old circuit, but more often than not the output isn't what people expected. I decided to revisit this project (with more patience and experience under my belt) and see if I could improve it. My goal was not to create the highest quality ECG machine I could, but rather to create the simplest one I could with emphasis on predictable and reproducible results. The finished project is a blend of improved hardware and custom cross-platform open-source software (which runs on Windows, Linux, and MacOS), and an impressively good ECG considering the circuit is so simple and runs on a breadboard! Furthermore, the schematics and custom software are all open-sourced on my github!

Here's a video demonstrating how the output is shown in real time with custom Python software. The video is quite long, but you can see the device in action immediately, so even if you only watch the first few seconds you will see this circuit in action with the custom software. In short, the amplifier circuit (described in detail below) outputs to the computer's microphone and a Python script I wrote analyzes the audio data, performs low-pass filtering, and graphs the output in real time. The result is a live electrocardiograph!

ECG Circuit

The circuit is simple, but a lot of time and thought and experimentation went into it. I settled on this design because it produced the best and most reliable results, and it has a few nuances which might not be obvious at first. Although I discuss it in detail in the video, here are the highlights:

  • The output goes to the microphone jack of your computer.

  • There's nothing special about the op-amp I used (LM741). A single unit of an LM324 (or any general purpose op-amp) should work just as well.

  • Resistor values were chosen because I had them on hand. You can probably change them a lot as long as they're in the same ballpark of the values shown here. Just make sure R1 and R2 are matched, and R3 should be at least 10MOhm.

  • Do not use a bench power supply! "BAT+" and "BAT-" are the leads of a single 9V battery.

  • Note that the leg electrode is ground (same ground as the computer's microphone ground)

  • R5 and R4 form a traditional voltage divider like you'd expect for an op-amp with a gain of about 50.

    • You'd expect R4 to connect to ground, but since your body is grounded, chest 2 is essentially the same

    • R3 must be extremely high value, but it pulls your body potential near the optimal input voltage for amplification by the op-amp.

    • R1 and R2 split the 9V battery's voltage in half and center it at ground, creating -4.5V and +4.5V.

  • altogether, your body stays grounded, and the op-amp becomes powered by -4.5V and +4.5V, and your body is conveniently near the middle and ready to have small signals from CHEST1 amplified. Amplification is with respect to CHEST2 (roughly ground), rather than actual ground, so that a lot of noise (with respect to ground) is eliminated.

For those of you who would rather see a picture than a schematic, here's a diagram of how to assemble it graphically. This should be very easy to reproduce. Although breadboards are typically not recommended for small signal amplification projects, there is so much noise already in these signals that it doesn't really matter much either way. Check out how good the signals look in my video, and consider that I use a breadboard the entire time.

The most comfortable electrodes I used were made for muscle simulators. A friend of mine showed me some muscle stimulator pads he got for a back pain relief device he uses. As soon as I saw those pads, I immediately thought they would be perfect for building an ECG! They're a little bit expensive, but very comfortable, reusable, last a long time, and produce brilliant results. They also have 3.5 mm (headphone jack) connectors which is perfect for DIY projects. On Amazon.com you can get 16 pads for $11 with free shipping. I decided not to include links, because sometimes the pads and cords are sold separately, and sometimes they have barrel connectors and sometimes they have snap connectors. Just get any adhesive reusable electrodes intended for transcutaneous electrical nerve stimulation (TENS) that you can find! They should all work fine.

Pennies as Electrodes

You can make your own electrodes for $0.03! Okay that's a terrible joke, but it's true. I made not-awful electrodes by soldering wires to copper pennies, adding strength by super-gluing the wire to the penny, and using electrical tape to attach them to my chest. Unless you want a tattoo of an old guy's face on your torso, wait until they cool sufficiently after soldering before proceeding to the adhesion step. I suspect that super gluing the penny to your chest would also work, but please do not do this. Ironically, because the adhesive pads of the TENS electrodes wear away over time, the penny solution is probably "more reusable" than the commercial electrode option.

This ECG was recorded using pennies as electrodes:

Notes on filtering: Why didn't I just use a hardware low-pass filter?

  1. It would have required extra components, which goes against the theme of this project
  2. It would require specific value components, which is also undesirable for a junkbox project
  3. I'm partial to the Chebyshev filter, but getting an extremely sharp roll-off a few Hz shy of 50Hz would take multiple poles (of closely matched passive components) and not be as trivial as it sounds.

Notes on software: This a really cool use of Python! I lean on some of my favorite packages numpy, scipy, matplotlib, pyqrgraph, and PyQt4. I've recently made posts describing how to perform real-time data graphing in Python using these libraries, so I won't go into that here. If you're interested, check out my real-time audio monitor, notes on using PlotWidget, and notes on using MatPlotLib widget. I tried using PyInstaller to package this project into a single .EXE for all my windows readers who might want to recreate this project, but the resulting EXE was over 160MB! That's crazy! It makes sense considering packagers like PyInstaller and Py2EXE work by building your entire python interpreter and all imported libraries. With all those fun libraries I listed above, it's no wonder it came out so huge. It may be convenient for local quick-fixes, but not a good way to distribute code over the internet. To use this software, just run it in Python. It was tested to work with out-of-the-box WinPython-64bit-3.5.2.1 (not the Qt5 version), so if you want to run it yourself start there.

Notes on safety. How safe is this project? I'm conflicted on this subject. I want to be as conservative as I can (leaning on the side of caution), but I also want to be as realistic as possible. I'm going to play it safe and say "this may not be safe, so don't build or use it". As an exercise, let's consider the pros and cons:

  • PROS:

    • It's powered from a 9V battery which is safer than a bench power supply (but see the matching con).

    • The only connections to your body are:

      • leg - ground. you ground yourself all the time. using a wrist grounding strap is the same thing.
      • chest 1 - extremely high impedance. You're attaching your chest to the high impedance input of an op-amp (which I feel fine with), and also to a floating battery through a 10MOhm resistor (which also I feel fine with)
      • chest 2 - raises an eyebrow. In addition to a high impedance input, you're connected to an op-amp through a 100k resistor. Even if the op-amp were putting out a full 4.5V, that's 0.045mA (which doesn't concern me a whole lot).
    • I don't know where to stick this, but I wonder what type of voltages / currents TENS actually provide.

  • CONS / WARNINGS:

    • It's powered from a 9V battery. So are many stun guns.
    • If the op-amp oscillates, oscillations may enter your body. Personally I feel this may be the most concerning issue.
    • Small currents can kill. I found a curiously colored website that describes this. It seems like the most dangerous potential effect is induction of cardiac fibrillation, which can occur around 100mA.

Improving safety through optical isolation: The safety of this device may be improved (albeit with increased complexity) through the implementation of opto-isolators. I may consider a follow-up post demonstrating how I do this. Unlike digital signals which I've optically isolated before, I've never personally isolated analog signals. Although I'm sure there are fully analog means to do this, I suspect I'd accomplish it by turning it into a digital signal (with a voltage-to-frequency converter), pulsing the output across the optoisolator, and turning it back into voltage with a frequency-to-voltage converter or perhaps even a passive low-pass filter. Analog Devices has a good write-up about optical isolation techniques.

Do you have comments regarding the safety of this device? Write your thoughts concisely and send them to me in an email! I'd be happy to share your knowledge with everyone by posting it here.

Did you build this or a device similar to it? Send me some pictures! I'll post them here.

Source code and project files: https://github.com/swharden/diyECG-1opAmp/

LEGAL: This website is for educational purposes only. Do not build or use any electrical devices shown. Attaching non-compliant electronic devices to your body may be dangerous. Consult a physician regarding proper usage of medical equipment.

Markdown source code last modified on January 18th, 2021
---
title: DIY ECG with 1 op-amp
date: 2016-08-08 01:49:24
tags: diyECG, python, circuit
---

# DIY ECG with 1 op-amp

> **⚠️ Check out my newer ECG design:** 
* [**Sound Card ECG with AD8232**](https://swharden.com/blog/2019-03-15-sound-card-ecg-with-ad8232/)

__I made surprisingly good ECG from a single op-amp and 5 resistors! __An ECG (electrocardiograph, sometimes called EKG) is a graph of the electrical potential your heart produces as it beats. Seven years ago I posted _[DIY ECG Machine on the Cheap](https://www.swharden.com/wp/2009-08-14-diy-ecg-machine-on-the-cheap/)_ which showed a discernible ECG I obtained using an op-amp, two resistors, and a capacitor outputting to a PC sound card's microphone input. It didn't work well, but the fact that it worked at all was impressive! It has been one of the most popular posts of my website ever since, and I get 1-2 emails a month from people trying to recreate these results (some of them are during the last week of a college design course and sound pretty desperate). Sometimes people get good results with that old circuit, but more often than not the output isn't what people expected. I decided to revisit this project (with more patience and experience under my belt) and see if I could improve it. My goal was not to create the highest quality ECG machine I could, but rather to create the _simplest_ one I could with emphasis on predictable and reproducible results. The finished project is a blend of improved hardware and custom cross-platform open-source software (which runs on Windows, Linux, and MacOS), and an impressively good ECG considering the circuit is so simple and runs on a breadboard! Furthermore, the schematics and custom software are all [open-sourced on my github](https://github.com/swharden/diyECG-1opAmp/)!

![](https://www.youtube.com/embed/AfirWls9Sys)

__Here's a video demonstrating how the output is shown in real time with custom Python software.__ The video is quite long, but you can see the device in action immediately, so even if you only watch the first few seconds you will see this circuit in action with the custom software. In short, the amplifier circuit (described in detail below) outputs to the computer's microphone and a Python script I wrote analyzes the audio data, performs low-pass filtering, and graphs the output in real time. The result is a live electrocardiograph!

<div class="text-center">

[![](ECG_1470609065_thumb.jpg)](ECG_1470609065.png)

</div>

### ECG Circuit

<div class="text-center">

[![](circuit_thumb.jpg)](circuit.jpg)

</div>

__The circuit is simple, but a lot of time and thought and experimentation went into it.__ I settled on this design because it produced the best and most reliable results, and it has a few nuances which might not be obvious at first. Although I discuss it in detail in the video, here are the highlights:

*   The output goes to the microphone jack of your computer.
*   There's nothing special about the op-amp I used ([LM741](http://www.ti.com/lit/ds/symlink/lm741.pdf)). A single unit of an [LM324](http://www.ti.com.cn/cn/lit/ds/symlink/lm2902-n.pdf) (or any general purpose op-amp) should work just as well.
*   Resistor values were chosen because I had them on hand. You can probably change them a lot as long as they're in the same ballpark of the values shown here. Just make sure R1 and R2 are matched, and R3 should be at least 10MOhm.
*   <span style="color: #ff0000;">Do not use a bench power supply!</span> "BAT+" and "BAT-" are the leads of a single 9V battery.
*   Note that the leg electrode is ground (same ground as the computer's microphone ground)
*   R5 and R4 form a traditional voltage divider like you'd expect for an op-amp with a gain of about 50.

    *   You'd expect R4 to connect to ground, but since your body is grounded, chest 2 is essentially the same

    *   R3 must be extremely high value, but it pulls your body potential near the optimal input voltage for amplification by the op-amp.

    *   R1 and R2 split the 9V battery's voltage in half and center it at ground, creating -4.5V and +4.5V.

*   altogether, your body stays grounded, and the op-amp becomes powered by -4.5V and +4.5V, and your body is conveniently near the middle and ready to have small signals from CHEST1 amplified. Amplification is with respect to CHEST2 (roughly ground), rather than actual ground, so that a lot of noise (with respect to ground) is eliminated.

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

[![](IMG_7574_thumb.jpg)](IMG_7574.jpg)

</div>

__For those of you who would rather see a picture than a schematic__, here's a diagram of how to assemble it graphically. This should be very easy to reproduce. Although breadboards are typically not recommended for small signal amplification projects, there is so much noise already in these signals that it doesn't really matter much either way. Check out how good the signals look in my video, and consider that I use a breadboard the entire time.

<div class="text-center">

[![](design_thumb.jpg)](design.jpg)

</div>

__The most comfortable electrodes I used were made for muscle simulators.__ A friend of mine showed me some muscle stimulator pads he got for a back pain relief device he uses. As soon as I saw those pads, I immediately thought they would be perfect for building an ECG! They're a little bit expensive, but very comfortable, reusable, last a long time, and produce brilliant results. They also have 3.5 mm (headphone jack) connectors which is perfect for DIY projects. On Amazon.com you can get 16 pads for $11 with free shipping. I decided not to include links, because sometimes the pads and cords are sold separately, and sometimes they have barrel connectors and sometimes they have snap connectors. Just get any adhesive reusable electrodes intended for [transcutaneous electrical nerve stimulation (TENS)](https://en.wikipedia.org/wiki/Transcutaneous_electrical_nerve_stimulation) that you can find! They should all work fine.

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

[![](IMG_7576_thumb.jpg)](IMG_7576.jpg)

</div>

### Pennies as Electrodes

__You can make your own electrodes for $0.03!__ Okay that's a terrible joke, but it's true. I made not-awful electrodes by soldering wires to copper pennies, adding strength by super-gluing the wire to the penny, and using electrical tape to attach them to my chest. Unless you want a tattoo of an old guy's face on your torso, wait until they cool sufficiently after soldering before proceeding to the adhesion step. I suspect that super gluing the penny to your chest would also work, but please do not do this. Ironically, because the adhesive pads of the TENS electrodes wear away over time, the penny solution is probably "more reusable" than the commercial electrode option.

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

[![](IMG_7527_thumb.jpg)](IMG_7527.jpg)
[![](IMG_7570-1_thumb.jpg)](IMG_7570-1.jpg)

</div>

This ECG was recorded using pennies as electrodes:

<div class="text-center">

[![](ECG_1470611901_thumb.jpg)](ECG_1470611901.png)

</div>

__Notes on filtering:__ Why didn't I just use a [hardware low-pass filter](https://en.wikipedia.org/wiki/Low-pass_filter)?

1.   It would have required extra components, which goes against the theme of this project
2.   It would require _specific value_ components, which is also undesirable for a junkbox project
3.   I'm partial to the [Chebyshev filter](https://en.wikipedia.org/wiki/Chebyshev_filter), but getting an extremely sharp roll-off a few Hz shy of 50Hz would take multiple poles (of closely matched passive components) and [not be as trivial as it sounds](http://www.analog.com/library/analogDialogue/archives/43-09/EDCh%208%20filter.pdf?doc=ADA4661-2.pdf).

__Notes on software:__ This a really cool use of Python! I lean on some of my favorite packages [numpy](http://www.numpy.org/), [scipy](https://www.scipy.org/), [matplotlib](http://matplotlib.org/), [pyqrgraph](http://www.pyqtgraph.org/), and [PyQt4](https://wiki.python.org/moin/PyQt4). I've recently made posts describing how to perform real-time data graphing in Python using these libraries, so I won't go into that here. If you're interested, check out my [real-time audio monitor](https://www.swharden.com/wp/2016-07-31-real-time-audio-monitor-with-pyqt/), notes on using [PlotWidget](https://www.swharden.com/wp/2016-07-31-live-data-in-pyqt4-with-plotwidget/), and notes on using [MatPlotLib widget](https://www.swharden.com/wp/2016-07-30-live-data-in-pyqt4-with-matplotlibwidget/). I tried using [PyInstaller](http://www.pyinstaller.org/) to package this project into a single .EXE for all my windows readers who might want to recreate this project, but the resulting EXE was over 160MB! That's crazy! It makes sense considering packagers like PyInstaller and Py2EXE work by building your entire python interpreter and all imported libraries. With all those fun libraries I listed above, it's no wonder it came out so huge. It may be convenient for local quick-fixes, but not a good way to distribute code over the internet. To use this software, just run it in Python. It was tested to work with out-of-the-box [WinPython-64bit-3.5.2.1](https://sourceforge.net/projects/winpython/files/) (not the Qt5 version), so if you want to run it yourself start there.

__Notes on safety.__ How safe is this project? I'm conflicted on this subject. I want to be as conservative as I can (leaning on the side of caution), but I also want to be as realistic as possible. I'm going to play it safe and say "this may not be safe, so don't build or use it". As an exercise, let's consider the pros and cons:

*   __PROS:__

    *   It's powered from a 9V battery which is safer than a bench power supply (but see the matching con).
    *   The only connections to your body are:

        *   leg - ground. you ground yourself all the time. using a wrist grounding strap is the same thing.
        *   chest 1 - extremely high impedance. You're attaching your chest to the high impedance input of an op-amp (which I feel fine with), and also to a floating battery through a 10MOhm resistor (which also I feel fine with)
        *   chest 2 - raises an eyebrow. In addition to a high impedance input, you're connected to an op-amp through a 100k resistor. Even if the op-amp were putting out a full 4.5V, that's 0.045mA (which doesn't concern me a whole lot).

    *   I don't know where to stick this, but I wonder what type of voltages / currents [TENS](https://en.wikipedia.org/wiki/Transcutaneous_electrical_nerve_stimulation) actually provide.

*   __CONS / WARNINGS:__

    *   It's powered from a 9V battery. So are many stun guns.
    *   If the op-amp oscillates, oscillations may enter your body. Personally I feel this may be the most concerning issue.
    *   Small currents can kill. I found a [curiously colored website](https://www.physics.ohio-state.edu/~p616/safety/fatal_current.html) that describes this. It seems like the most dangerous potential effect is induction of cardiac fibrillation, which can occur around 100mA.

__Improving safety through optical isolation:__ The safety of this device may be improved (albeit with increased complexity) through the implementation of [opto-isolators](https://en.wikipedia.org/wiki/Opto-isolator). I may consider a follow-up post demonstrating how I do this. Unlike digital signals which I've [optically isolated before](https://www.swharden.com/wp/2016-07-28-opto-isolated-laser-controller-build/), I've never personally isolated analog signals. Although I'm sure there are fully analog means to do this, I suspect I'd accomplish it by turning it into a digital signal (with a voltage-to-frequency converter), pulsing the output across the optoisolator, and turning it back into voltage with a frequency-to-voltage converter or perhaps even a passive low-pass filter. Analog Devices has a good write-up about [optical isolation techniques](http://www.analog.com/media/en/training-seminars/tutorials/MT-071.pdf).

__Do you have comments regarding the safety of this device?__ Write your thoughts concisely and send them to me in an email! I'd be happy to share your knowledge with everyone by posting it here.

__Did you build this or a device similar to it?__ Send me some pictures! I'll post them here.

__Source code and project files:__ <https://github.com/swharden/diyECG-1opAmp/>

___LEGAL__: This website is for educational purposes only. Do not build or use any electrical devices shown. Attaching non-compliant electronic devices to your body may be dangerous. Consult a physician regarding proper usage of medical equipment._

Python Real-time Audio Frequency Monitor

A new project I'm working on requires real-time analysis of soundcard input data, and I made a minimal case example of how to do this in a cross-platform way using python 3, numpy, and PyQt. Previous posts compared performance of the matplotlib widget vs PyQtGraph plotwidget and I've been working with PyQtGraph ever since. For static figures matplotlib is wonderful, but for fast responsive applications I'm leaning toward PyQtGraph. The full source for this project is on a github page, but here's a summary of the project.

I made the UI with QT Designer. The graphs are QGraphicsView widgets promoted to a pyqtgraph PlotWidget. I describe how to do this in my previous post. Here's the content of the primary program:

from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pyqtgraph
import SWHear

class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        pyqtgraph.setConfigOption('background', 'w') #before loading widget
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.grFFT.plotItem.showGrid(True, True, 0.7)
        self.grPCM.plotItem.showGrid(True, True, 0.7)
        self.maxFFT=0
        self.maxPCM=0
        self.ear = SWHear.SWHear()
        self.ear.stream_start()

    def update(self):
        if not self.ear.data is None and not self.ear.fft is None:
            pcmMax=np.max(np.abs(self.ear.data))
            if pcmMax>self.maxPCM:
                self.maxPCM=pcmMax
                self.grPCM.plotItem.setRange(yRange=[-pcmMax,pcmMax])
            if np.max(self.ear.fft)>self.maxFFT:
                self.maxFFT=np.max(np.abs(self.ear.fft))
                self.grFFT.plotItem.setRange(yRange=[0,self.maxFFT])
            self.pbLevel.setValue(1000*pcmMax/self.maxPCM)
            pen=pyqtgraph.mkPen(color='b')
            self.grPCM.plot(self.ear.datax,self.ear.data,
                            pen=pen,clear=True)
            pen=pyqtgraph.mkPen(color='r')
            self.grFFT.plot(self.ear.fftx[:500],self.ear.fft[:500],
                            pen=pen,clear=True)
        QtCore.QTimer.singleShot(1, self.update) # QUICKLY repeat

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    form.update() #start with something
    app.exec_()
    print("DONE")

This project uses a gutted version of the SWHEar class which I still haven't released on githib yet. It will likely have its own project folder. For now, take this project with a grain of salt. The primary advantage of this class is that it makes it easy to use PyAudio to automatically detect input sound cards, channels, and sample rates which are likely to succeed without requiring the user to enter any information.

All files used for this project are in a GitHub folder

Audio Visualizer Screenlet

2016-09-05: Okko adapted this project into a screenlet (cross platform) which also includes an installer for Windows: https://github.com/ninlith/audio-visualizer-screenlet

Markdown source code last modified on January 18th, 2021
---
title: Python Real-time Audio Frequency Monitor
date: 2016-07-31 15:21:11
tags: python, old
---

# Python Real-time Audio Frequency Monitor

__A new project I'm working on requires real-time analysis of soundcard input data, and I made a minimal case example of how to do this in a cross-platform way using python 3, numpy, and PyQt.__ Previous posts compared performance of the [matplotlib widget](https://www.swharden.com/wp/2016-07-30-live-data-in-pyqt4-with-matplotlibwidget/) vs [PyQtGraph plotwidget](https://www.swharden.com/wp/2016-07-31-live-data-in-pyqt4-with-plotwidget/) and I've been working with [PyQtGraph](http://www.pyqtgraph.org/) ever since. For static figures matplotlib is wonderful, but for fast responsive applications I'm leaning toward PyQtGraph. The [full source for this project is on a github page](https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-37_qt_audio_monitor), but here's a summary of the project.

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

![](demo-1.gif)

</div>

![](https://www.youtube.com/embed/lDS9rI0o6mM)

__I made the UI with QT Designer.__ The graphs are _QGraphicsView_ widgets promoted to a pyqtgraph_ PlotWidget_. I describe how to do this [in my previous post](https://www.swharden.com/wp/2016-07-31-live-data-in-pyqt4-with-plotwidget/). Here's the content of the primary program:

```python
from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pyqtgraph
import SWHear

class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        pyqtgraph.setConfigOption('background', 'w') #before loading widget
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.grFFT.plotItem.showGrid(True, True, 0.7)
        self.grPCM.plotItem.showGrid(True, True, 0.7)
        self.maxFFT=0
        self.maxPCM=0
        self.ear = SWHear.SWHear()
        self.ear.stream_start()

    def update(self):
        if not self.ear.data is None and not self.ear.fft is None:
            pcmMax=np.max(np.abs(self.ear.data))
            if pcmMax>self.maxPCM:
                self.maxPCM=pcmMax
                self.grPCM.plotItem.setRange(yRange=[-pcmMax,pcmMax])
            if np.max(self.ear.fft)>self.maxFFT:
                self.maxFFT=np.max(np.abs(self.ear.fft))
                self.grFFT.plotItem.setRange(yRange=[0,self.maxFFT])
            self.pbLevel.setValue(1000*pcmMax/self.maxPCM)
            pen=pyqtgraph.mkPen(color='b')
            self.grPCM.plot(self.ear.datax,self.ear.data,
                            pen=pen,clear=True)
            pen=pyqtgraph.mkPen(color='r')
            self.grFFT.plot(self.ear.fftx[:500],self.ear.fft[:500],
                            pen=pen,clear=True)
        QtCore.QTimer.singleShot(1, self.update) # QUICKLY repeat

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    form.update() #start with something
    app.exec_()
    print("DONE")

```

This project uses a gutted version of the SWHEar class which I still haven't released on githib yet. It will likely have its own project folder. For now, take this project with a grain of salt. The primary advantage of this class is that it makes it easy to use PyAudio to automatically detect input sound cards, channels, and sample rates which are likely to succeed without requiring the user to enter any information.

All files used for this project are [in a GitHub folder](https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-37_qt_audio_monitor)

### Audio Visualizer Screenlet

2016-09-05: Okko adapted this project into a screenlet (cross platform) which also includes an installer for Windows: https://github.com/ninlith/audio-visualizer-screenlet

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

[![](widget_thumb.jpg)](widget.png)

</div>

Live Data in PyQt4 with PlotWidget

After spending a day comparing performance of MatplotlibWidget with PlotWidget, when it comes to speed PlotWidget wins by a mile! Glance over my last post where I describe how to set up the window with QT Designer and convert the .ui file to a .py file. With only a few changes to the code, I swapped the matplotlib _MatplotlibWidget _with the pyqtgraph PlotWidget. I easily got a 20x increase in speed (frame rate), and I'm likely to favor PyQtGraph over matpltolib for python applications involving realtime display of data. Just like the previous example using matplotlib, this one uses the system time to control the phase and color of a sine wave in real time. You can grab the full code from my github folder.

When designing the GUI with QT Designer, add a QGraphicsView widget then assign it to become a PyQtGraph object. To do this, follow the steps found on the pyqtgraph docs page:

  • In Designer, create a QGraphicsView widget
  • Right-click on the QGraphicsView and select “Promote To...”
  • Set “Promoted class name” to “PlotWidget”
  • Under “Header file”, enter “pyqtgraph”
  • Click “Add”, then click “Promote”
  • apparently this only needs to be done once per project

In addition to faster frame rate, the PyQtGraph method is easy to interact with. Clicking and dragging scrolls the data, and right-clicking and dragging zooms on each axis. Here's the program code:

from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pylab
import time
import pyqtgraph

class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        pyqtgraph.setConfigOption('background', 'w') #before loading widget
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.btnAdd.clicked.connect(self.update)
        self.grPlot.plotItem.showGrid(True, True, 0.7)

    def update(self):
        t1=time.clock()
        points=100 #number of data points
        X=np.arange(points)
        Y=np.sin(np.arange(points)/points*3*np.pi+time.time())
        C=pyqtgraph.hsvColor(time.time()/5%1,alpha=.5)
        pen=pyqtgraph.mkPen(color=C,width=10)
        self.grPlot.plot(X,Y,pen=pen,clear=True)
        print("update took %.02f ms"%((time.clock()-t1)*1000))
        if self.chkMore.isChecked():
            QtCore.QTimer.singleShot(1, self.update) # QUICKLY repeat

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    form.update() #start with something
    app.exec_()
    print("DONE")

This project is available on GitHub: https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-31_qt_PyQtGraph_sine_scroll

Markdown source code last modified on January 18th, 2021
---
title: Live Data in PyQt4 with PlotWidget
date: 2016-07-31 07:28:28
tags: python, old
---

# Live Data in PyQt4 with PlotWidget

__After spending a day comparing performance of MatplotlibWidget with PlotWidget, when it comes to speed PlotWidget wins by a mile!__ Glance over my [last post](https://www.swharden.com/wp/2016-07-30-live-data-in-pyqt4-with-matplotlibwidget/) where I describe how to set up the window with QT Designer and convert the .ui file to a .py file. With only a few changes to the code, I swapped the matplotlib _MatplotlibWidget _with the pyqtgraph _PlotWidget_. I easily got a 20x increase in speed (frame rate), and I'm likely to favor [PyQtGraph](http://www.pyqtgraph.org/) over matpltolib for python applications involving realtime display of data. Just like the [previous example using matplotlib](https://www.swharden.com/wp/2016-07-30-live-data-in-pyqt4-with-matplotlibwidget/), this one uses the system time to control the phase and color of a sine wave in real time. You can grab the full code from [my github folder](https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-31_qt_PyQtGraph_sine_scroll).

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

![](demo2.gif)
[![](demo2cmd_thumb.jpg)](demo2cmd.png)

</div>

__When designing the GUI with QT Designer, add a QGraphicsView widget then assign it to become a PyQtGraph object.__ To do this, follow the steps found on the [pyqtgraph docs page](http://www.pyqtgraph.org/documentation/how_to_use.html#embedding-widgets-inside-pyqt-applications):

* In Designer, create a QGraphicsView widget
* Right-click on the QGraphicsView and select “Promote To...”
* Set “Promoted class name” to “PlotWidget”
* Under “Header file”, enter “pyqtgraph”
* Click “Add”, then click “Promote”
* _apparently this only needs to be done once per project_

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

[![](promoted_thumb.jpg)](promoted.png)

</div>

__In addition to faster frame rate, the PyQtGraph method is easy to interact with.__ Clicking and dragging scrolls the data, and right-clicking and dragging zooms on each axis. Here's the program code:

```python
from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pylab
import time
import pyqtgraph

class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        pyqtgraph.setConfigOption('background', 'w') #before loading widget
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.btnAdd.clicked.connect(self.update)
        self.grPlot.plotItem.showGrid(True, True, 0.7)

    def update(self):
        t1=time.clock()
        points=100 #number of data points
        X=np.arange(points)
        Y=np.sin(np.arange(points)/points*3*np.pi+time.time())
        C=pyqtgraph.hsvColor(time.time()/5%1,alpha=.5)
        pen=pyqtgraph.mkPen(color=C,width=10)
        self.grPlot.plot(X,Y,pen=pen,clear=True)
        print("update took %.02f ms"%((time.clock()-t1)*1000))
        if self.chkMore.isChecked():
            QtCore.QTimer.singleShot(1, self.update) # QUICKLY repeat

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    form.update() #start with something
    app.exec_()
    print("DONE")
```

This project is available on GitHub: https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-31_qt_PyQtGraph_sine_scroll

Live Data in PyQt4 with MatplotlibWidget

I keep getting involved in projects which require live data to be graphed in real time. Since most of my back-end is written in Python, it makes sense to have a Pythonic front-end. Cross-platform GUI programming in Python is frustratingly non-trivial, as there multiple window frameworks available (TK, GTK, and QT) and their respective graphical designers (torture, Glade, and QT Designer) and each has its own way of doing things. Add different ways to plot data in the mix (gnuplot, matplotlib, and custom widgets) and it can become a complicated mess. Different framework combinations favor different features (with unique speed / simplicity / elegance), so my goal is to slowly test out a few combinations most likely to work for my needs, and add my findings to a growing github repository. The first stab is using PyQt4 and matplotlib's widget (MatplotlibWidget). Rather than capture data from the sound card (my ultimate goal), I'm going to generate a sine wave whose phase and color is related to the system time. Matplotlib plotting is a bit slow, but the output is beautiful, and their framework is so robust. Here's the output of my first test showing the sine wave generated as well as the console output (showing that each call to the plotting function takes about 40 ms. At this rate, I can expect a maximum update rate of ~25 Hz.

Designing this project was easy, but it was surprisingly hard to figure out how to do this based on examples I found on the internet. This is part of why I wanted to place this example here. The downside of many internet examples is that they did not use Qt Designer to make the window, so their code to create a window and insert the MatplotlibWidget wasn't copy/paste compatible with my goals, and often more complex than I needed. Some internet examples did use Qt Designer to make the window, but left a frame empty which they later manually filled with a widget and attached to a matplotlib canvas. This is fine, but more complex than I need to get started.

First, I designed a GUI with Qt Designer. I dropped a MatplotlibWidget somewhere, and used its default name. I saved this file as ui_main.ui (which is an XML file, ready to be used for multiple programming languages).

Next, I converted the UI file into a .py file with a standalone python script that's an alternative to using pyuic from the command line. The script to do this is ui_convert.py and it calls PyQt4.uic.compileUi():

from PyQt4 import uic
fin = open('ui_main.ui','r')
fout = open('ui_main.py','w')
uic.compileUi(fin,fout,execute=False)
fin.close()
fout.close()

I then created my main program file which populates the matplotlib widget with data. I called it go.py and running it will launch the app. The code explains it all, and there's not much more to say! It produces the output at the top of this post.

from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pylab
import time

class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.btnAdd.clicked.connect(self.update)
        self.matplotlibwidget.axes.hold(False) #clear on plot()

    def update(self):
        t1=time.time()
        points=100 #number of data points
        X=np.arange(points)
        Y=np.sin(np.arange(points)/points*3*np.pi+time.time())
        C=pylab.cm.jet(time.time()%10/10) # random color
        self.matplotlibwidget.axes.plot(X,Y,ms=100,color=C,lw=10,alpha=.8)
        self.matplotlibwidget.axes.grid()
        self.matplotlibwidget.axes.get_figure().tight_layout() # fill space
        self.matplotlibwidget.draw() # required to update the window
        print("update took %.02f ms"%((time.time()-t1)*1000))
        if self.chkMore.isChecked():
            QtCore.QTimer.singleShot(10, self.update) # QUICKLY repeat

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    form.update() #start with something
    app.exec_()
    print("DONE")

This project is on GitHub: https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-30_qt_matplotlib_sine_scroll

Markdown source code last modified on January 18th, 2021
---
title: Live Data in PyQt4 with MatplotlibWidget
date: 2016-07-30 23:15:23
tags: python, old
---

# Live Data in PyQt4 with MatplotlibWidget

__I keep getting involved in projects which require live data to be graphed in real time.__ Since most of my back-end is written in Python, it makes sense to have a Pythonic front-end. Cross-platform GUI programming in Python is frustratingly non-trivial, as there multiple window frameworks available (TK, GTK, and QT) and their respective graphical designers ([torture](https://wiki.python.org/moin/Intro%20to%20programming%20with%20Python%20and%20Tkinter), [Glade](https://glade.gnome.org/), and [QT Designer](http://doc.qt.io/qt-4.8/designer-manual.html)) and each has its own way of doing things. Add different ways to plot data in the mix ([gnuplot](http://www.gnuplot.info/), [matplotlib](http://matplotlib.org/), and [custom widgets](http://qcustomplot.com/)) and it can become a complicated mess. Different framework combinations favor different features (with unique speed / simplicity / elegance), so my goal is to slowly test out a few combinations most likely to work for my needs, and add my findings to a [growing github repository](https://github.com/swharden/Python-GUI-examples). The first stab is using PyQt4 and matplotlib's widget (MatplotlibWidget). Rather than capture data from the sound card (my ultimate goal), I'm going to generate a sine wave whose phase and color is related to the system time. Matplotlib plotting is a bit slow, but the output is beautiful, and their framework is so robust. Here's the output of my first test showing the sine wave generated as well as the console output (showing that each call to the plotting function takes about 40 ms. At this rate, I can expect a maximum update rate of ~25 Hz.

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

![](demo.gif)
[![](qt4_thumb.jpg)](qt4.png)

</div>

__Designing this project was easy, but it was surprisingly hard to figure out how to do this based on examples I found on the internet.__ This is part of why I wanted to place this example here. The downside of many internet examples is that they did not use Qt Designer to make the window, so their code to create a window and insert the MatplotlibWidget wasn't copy/paste compatible with my goals, and often more complex than I needed. Some internet examples _did_ use Qt Designer to make the window, but left a frame empty which they later manually filled with a widget and attached to a matplotlib canvas. This is fine, but more complex than I need to get started.

__First, I designed a GUI with Qt Designer__. I dropped a MatplotlibWidget somewhere, and used its default name. I saved this file as [ui\_main.ui](https://github.com/swharden/Python-GUI-examples/blob/master/2016-07-30_qt_matplotlib_sine_scroll/ui_main.ui) (which is an XML file, ready to be used for [multiple programming languages](http://doc.qt.io/qt-4.8/designer-using-a-ui-file.html)).

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

[![](pyqt4-designer_thumb.jpg)](pyqt4-designer.png)

</div>

__Next, I converted the UI file into a .py file__ with a standalone python script that's an alternative to using pyuic from the command line. The script to do this is [ui\_convert.py](https://github.com/swharden/Python-GUI-examples/blob/master/2016-07-30_qt_matplotlib_sine_scroll/ui_convert.py) and it calls PyQt4.uic.compileUi():

```python
from PyQt4 import uic
fin = open('ui_main.ui','r')
fout = open('ui_main.py','w')
uic.compileUi(fin,fout,execute=False)
fin.close()
fout.close()
```

__I then created my main program file which populates the matplotlib widget with data.__ I called it [go.py](https://github.com/swharden/Python-GUI-examples/blob/master/2016-07-30_qt_matplotlib_sine_scroll/go.py) and running it will launch the app. The code explains it all, and there's not much more to say! It produces the output at the top of this post.

```python
from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pylab
import time

class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.btnAdd.clicked.connect(self.update)
        self.matplotlibwidget.axes.hold(False) #clear on plot()

    def update(self):
        t1=time.time()
        points=100 #number of data points
        X=np.arange(points)
        Y=np.sin(np.arange(points)/points*3*np.pi+time.time())
        C=pylab.cm.jet(time.time()%10/10) # random color
        self.matplotlibwidget.axes.plot(X,Y,ms=100,color=C,lw=10,alpha=.8)
        self.matplotlibwidget.axes.grid()
        self.matplotlibwidget.axes.get_figure().tight_layout() # fill space
        self.matplotlibwidget.draw() # required to update the window
        print("update took %.02f ms"%((time.time()-t1)*1000))
        if self.chkMore.isChecked():
            QtCore.QTimer.singleShot(10, self.update) # QUICKLY repeat

if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    form.update() #start with something
    app.exec_()
    print("DONE")
```

This project is on GitHub: https://github.com/swharden/Python-GUI-examples/tree/master/2016-07-30_qt_matplotlib_sine_scroll
Pages