Pulse Oximeter DIY






Create a Simple Pulse Oximeter with EFM32 Tiny Gecko

Hack-a-Gecko project by Pål Øyvind

Explore the capabilities of the EFM32 Tiny Gecko by creating the beginnings of a DIY pulse oximeter.

The theory behind

A pulse oximeter is based around a simple principle: Shine red light and an infrared light through a blood-rich part of the body and measure the difference in absorbed light with a photo sensor (Figure 1). Hemoglobin absorbs red and infrared light differently depending on the oxygen saturation level (Figure 2). Based on this, it is possible to calculate the ratio of oxygenated vs. deoxygenated hemoglobin (Equation 1). For a more in-depth description of the measurement principle and issues, this page on equipmentexplained.com explains it very thoroughly.

Figure 1 Pulse oximeter sensor principle 

Figure 2 Light absorption rates differ between oxygenated and deoxygenated blood 

Equation 1 Oxygenation ratio calculation 

Hardware Implementation

First, I made a very simple LED/sensor harness by wiring up the LEDs and the sensor and putting it all into some leftover black Velcro I had lying around (Figure 3). The Velcro was very helpful in being able to adjust the alignment of the sensor and LEDs and making a good fit for a human finger. In addition, it worked well to block out match of the ambient light.

Figure 3 Velcro based Hack-a-Pulse oximeter sensor harness

I wired up the sensor to a prototyping board containing interfacing the STK (Figure 4).

Figure 4 Interface to STK

The prototype PCB contained only simple external components:

  • RI, R2, Q0, Q1: Drivers for the red and infrared LEDs. (Figure 5)
  • R4, Q2, R3: Constant current drive circuitry. When it is working, OPA0 and Q2 will make sure the voltage across R3 is constant (and thereby the current flowing in the LEDs). The level can also be programmed by the DAC. As I did not have enough time to program the control of the LED current, it is currently limited by the bypass resistor R5 that is hacked in. (Figure 5)
  • R0, C0: Together with OPA2 on the EFM32 Tiny Gecko, this creates a transimpedance amplifier/high-pass filter with a cut-off set by R0*C0 and again set by R0. This converts the photodiode current into a voltage suitable for readout by ADC0. (Figure 6)

Figure 5 LED drive and constant current schematic 

Figure 6 Photo sensor schematic 

In order to read the data from the ADC back to a computer, I used a FTDI USB device connected to USART1 TX on PD0.

Software Implementation

The software tools by Energy Micro made this implementation very simple. It is loosely based on the opamp_to_ADC example from the app note “AN0038 Operational Amplifiers” and USART from “AN008 USART Synchronous Mode.”
The software data allowed me to:

  • Initialize the chip and clocks
  • Configure the hardware and I/O as shown in Figure 4 and Figure 5
  • Set up the USART communication
  • Turn on the red LED
  • Go into an infinite loop
  1. Sampling the ADC
  2. Displaying the readout voltage on the LCD
  3. Sending it via the USART

The PC-side software is based on a stripped-down version of a Patient Monitor demo from Qt to display the results on a graph. I compiled the incoming data in a version of QextSerialPort to grab the data from the COM port that I got when the FTDI driver was installed.

A simple band-pass data filter was also implemented to filter out the DC from the signal and removing high-frequency noise. The results were quite satisfying. (It’s always good to get confirmation that I’m alive :)). This is a screenshot of the PC application output when I wore the sensor on my finger:

Figure 7 Screenshot of PC application displaying a live pulse graph 

Suggested steps to complete the pulse oximeter function:

For those who want to try this project, here are my suggestions for you:

  • Finish the software for the control of the LED current and remove the bypass hack.
  • Add duty cycling between red and infrared LEDs. For now, this has not been implemented, so the oxygenation levels can’t be calculated quite yet. Part of the reason was that the IR LED I used turned out to be a lot brighter than the red LED, and blinded the sensor. I expect that current control should deal with this and make duty-cycling possible.
  • Move the data filtering and interpretation to the Tiny Gecko and display pulse and oxygenation levels on the STK LCD.

Materials Used

  • EFM32 Tiny Gecko STK
  • FTDI 3.3V breakout module from Sparkfun
  • Everlight 383SDRC/S530-A3/H2 red LED
  • Everlight IR383 IR LED
  • Osram BPW34 photodiode 850nm
  • Q0, Q1: BC557 PNP transistors
  • Q2: BC547 NPN transistor
  • R0: 2Mohm
  • C0: 10nF
  • R1, R2, R4: 1kohm
  • R5: 42ohm
  • R3: 6.8ohm
  • cables, prototyping PCB etc
  • Source Files

Source Files

Source code for both the PC application and the EFM32 Tiny Gecko are found here:


This Hack a Gecko project is a result of a “fun hacking session” and are provided as is, free of charge with no guarantees or support from Energy Micro, to partially or fully show and demonstrate EFM32 Gecko microcontroller capabilities. Get inspired, use at own risk, and build some awesome and cool applications.


For technical questions about this project, please use our support forum. The Hack-a-Gecko team will answer your questions directly.