Make a Heartbeat Visualiser with an LED Ring
Share
A pulse sensor watches for the tiny blood-volume swing that happens under your skin with every heartbeat, and a microcontroller reading that signal fires a brief LED flash at the exact instant it detects the peak — turning a signal you can normally only feel as a pulse under your fingertip into something you can actually watch happen, beat by beat, on a ring of lights. That is the entire idea behind a heartbeat visualizer: no diagnosis, no numbers to interpret, just your own heartbeat made visible in real time.
This is a hobby and learning project, not a medical device. Nothing in this build is clinically calibrated, validated, or certified for health use. Do not use it to monitor your health, diagnose a condition, or make any actual medical decision for yourself or anyone else. If you have real concerns about your heart rate, use a certified medical device and talk to a healthcare professional.
How does a pulse sensor detect a heartbeat?
Both common options for this build work on photoplethysmography (PPG): light shone into a fingertip is partly absorbed by blood, and the amount absorbed changes slightly with every heartbeat as blood volume in the capillaries rises and falls. A photodetector reads how much light comes back, and that signal traces out a small periodic wave riding on top of a steady baseline — the peak of each wave is a heartbeat. A simple analog pulse sensor does this with a single LED, a photodiode, and an onboard op-amp, and hands the Arduino one continuously varying voltage to watch on an analog pin. A MAX30100/MAX30102 module does the same job with red and infrared LEDs and digitizes the result itself, handing the microcontroller raw sample data over I²C instead of a raw analog voltage. Either way, the actual beat-finding — picking the peak out of a noisy, slowly drifting waveform — happens in firmware running on the Arduino, not inside the sensor.
What parts does a heartbeat visualizer need?
At minimum: a microcontroller with either an analog input or an I²C bus (an Arduino Uno covers both), a pulse sensor to read the heartbeat, and a strip or ring of addressable LEDs — WS2812B/NeoPixel — that can be told to flash on command from a single data pin. Addressable LEDs matter here specifically because the Arduino needs to command every LED in the ring to change at once, in exact sync with a detected beat, from one digital pin using a single-wire protocol; a plain non-addressable LED strip can't do that kind of instant, uniform flash on command the same way. Everything else — a breadboard, jumper wires, a stable power source — is standard prototyping hardware, not anything specific to this project.
How do you sync an LED flash to a detected pulse?
| Arduino Uno pin | Connects to | Signal |
|---|---|---|
| A4 | MAX30100/30102 SDA | I²C data |
| A5 | MAX30100/30102 SCL | I²C clock |
| D2 | WS2812B ring DIN | NeoPixel data |
| 5V | Sensor VCC & ring VCC | Power |
| GND | Sensor GND & ring GND | Ground |
The firmware watches the sensor's data stream continuously for the characteristic shape of a heartbeat — a sharp rise above a rolling baseline, the same peak-detection logic pulse-oximeter libraries already use to calculate BPM — and the moment it confirms that peak, it writes a color to every pixel on the WS2812B ring over that single NeoPixel data line and calls show() to latch it, then fades or clears the ring before the next beat arrives. The lag between the actual physical pulse and the visible flash is small (bounded by how often the main loop samples the sensor), but it is not zero, and it is not clinically timed — it is timed for a convincing visual effect, which is exactly what this project is for.
Can you use this for anything beyond a visual effect?
Honestly, not much beyond that, and it's worth being direct about it: this is a fun demo and a wearable art piece, not a diagnostic tool. It's a genuinely good way to learn PPG sensing, interrupt-free peak detection, and addressable-LED control on real hardware, and it makes a strong show-and-tell piece or costume prop. What it is not is a way to track your resting heart rate over time, catch an irregular rhythm, or replace an actual fitness or medical wearable — treat every flash as a demonstration of the signal, not a measurement you can rely on.
Watch it built live
We typed this into Compoden's storefront assistant, Soldr, exactly as a customer would:
"I want to build a heartbeat visualizer that pulses an LED ring in time with a heart rate sensor, using an Arduino Uno"

Soldr's first pass matched a general "heart rate sensor" request to "The Pulse Sensor (PPG) Module - Analog Output is how you measure your heart rate. A PPG sensor detects changes in blood volume under your skin, which corresponds to your pulse. This module outputs an analog signal… This sensor is a good fit because the Arduino Uno can directly read its analog output." For the display slot, though, its default pick was a monochrome dot-matrix module, not an addressable ring: "The MAX7219 8x8 Dot Matrix LED Display Module (common cathode) is your visualizer. It's a grid of small lights that can be turned on and off to show patterns." Asking directly for the addressable part this project actually needs — "For the LED display I specifically need an addressable WS2812B/NeoPixel LED ring, not a dot matrix display – do you have that in stock?" — got a straight answer: "Here's the WS2812B 5050 RGB LED Ring Light 241 LEDs 9 Rings Matrix — Rs.3040, in stock." Compoden does stock a genuine WS2812B ring for this build; it just isn't the assistant's first suggestion for a generic "LED ring" request, so naming the part directly is the reliable way to get it. Soldr also flagged a real wiring gotcha on its own, unprompted: "the Arduino Uno R3 CH340G ATmega328P Board accepts 7-12V DC power through its barrel connector, but the 5V 2A Power Adapter (Barrel Connector) outputs 5V. This means the barrel connector on the Arduino will not work with this specific power adapter; you would need to power the Arduino through its USB port…" — worth heeding if you buy that adapter alongside this build; power the Uno over USB instead.
Watch the firmware get generated
We then asked Compoden's code assistant, Soldr's PWA build companion, to write the actual sync firmware, naming both real parts directly:
"I'm building a heartbeat visualizer with an Arduino Uno, a MAX30100 pulse sensor, and a WS2812B LED ring. Write firmware that detects each heartbeat pulse and flashes the LED ring in sync."

Its own summary read: "Flash this sketch to your Arduino Uno using the Arduino IDE. Install via Library Manager: SparkFun MAX3010x Pulse and Proximity Sensor Library, Adafruit NeoPixel." The generated sketch includes #include <MAX30105.h> (the SparkFun library, which explicitly covers the MAX30100/30102/30105 family) with a heartRate.h header for beat detection, and #include <Adafruit_NeoPixel.h> for the ring, with the comment "Adafruit NeoPixel library for WS2812B" right next to it. It wires the sensor over I²C with an inline comment — "SCL to A5, SDA to A4, VCC to 5V, GND to GND" — and the ring on a single digital pin: "Data pin to D2, VCC to 5V, GND to GND", declared as #define LED_PIN 2. It also assumed NUM_LEDS 24 by default, flagging its own assumption inline — "Assuming a 24-LED ring, adjust if yours is different" — which matters in practice, since the WS2812B ring Compoden actually stocks for this build has 241 LEDs across 9 rings, not 24; that constant needs updating to match before flashing. Treat the generated source as a real, editable starting point for this exact wiring, not a guaranteed drop-in compile.
Get everything in this build
These are real, in-stock Compoden parts for this exact build — live prices and direct add-to-cart links, no bundling or assumed extras. The pulse sensor and LED ring below are the ones this article's wiring and firmware actually target; Compoden's storefront assistant defaults a generic "LED ring" request to a cheaper dot-matrix display instead, so the WS2812B ring here was confirmed by asking for it by name, exactly as shown above.
| Part | Price | Add to cart |
|---|---|---|
| Arduino Uno R3 CH340G ATmega328P Board | Rs.230 | Add to cart |
| Pulse Sensor (PPG) Module - Analog Output | Rs.130 | Add to cart |
| WS2812B 5050 RGB LED Ring Light (241 LEDs, 9 Rings) | Rs.3040 | Add to cart |
| Male-to-Male Breadboard Jumper Wires (20 cm, 24 AWG) | Rs.40 | Add to cart |
| SYB-170 Mini Breadboard | Rs.20 | Add to cart |
| 5V 2A Power Adapter (Barrel Connector) | Rs.170 | Add to cart |
| Total | Rs.3630 | Add all 6 to cart |
If you'd rather use the MAX30100/30102 module shown in the firmware demo instead of the analog Pulse Sensor above, Compoden stocks that too; either sensor reads a real PPG waveform and works with this build. As flagged above, power the Arduino Uno over USB rather than that barrel-jack adapter, since the adapter's 5V output doesn't match the Uno's 7–12V barrel-jack input. The 241-LED ring is also far more ring than a handful of heartbeat-flash pixels need — running only a portion of it lit at a time keeps current draw well within what a basic 5V supply can handle.
Built and Backed by Compoden
The parts listed above ship from Compoden's India stock and are checked for compatibility before they're carded together, not sourced individually and hoped to work. Delivery typically takes 3–7 days across India, with Cash on Delivery and UPI both available at checkout. Compoden's support team can help with wiring or firmware issues on this build, including the LED-count constant and power-adapter points raised above.
FAQ
Can this heartbeat visualizer be used to monitor my health?
No. It's a hobby and educational project. Nothing in this build is clinically calibrated or certified, and the flash timing is tuned for a convincing visual effect, not medical accuracy. Never use it to diagnose a condition or make a health decision — see a healthcare professional and use a certified medical device for that.
Do I need a MAX30100 sensor, or will a simple analog pulse sensor work?
Either works. Both read a real PPG (photoplethysmography) waveform from your fingertip; the analog Pulse Sensor hands the Arduino one continuous voltage on an analog pin, while the MAX30100/30102 digitizes the signal itself and talks over I²C. The firmware demo above targets the MAX30100 specifically.
Why does Compoden's assistant suggest a dot-matrix display instead of an LED ring by default?
Its general match for "LED ring" or "LED display" currently defaults to a cheaper MAX7219 dot-matrix module. Compoden does stock a genuine addressable WS2812B ring for exactly this kind of project — asking for "WS2812B" or "NeoPixel" by name, as shown above, gets it correctly.
Do I need to change anything in the generated firmware before it will work with the ring Compoden sells?
Yes, at minimum the LED count. The generated sketch defaults to NUM_LEDS 24 and says so in a comment, but the WS2812B ring in this build has 241 LEDs across 9 rings, so that constant needs to be updated to match before flashing.