Hidden Signals · Companion site ← All activities DE·EN
Chapter 5 · The Chemistry of Teams · Activity 5.1

Heartbeat and Stress

Not how fast your heart beats, but how irregularly — heart-rate variability reveals tension long before you notice it.

Duration 90 min Difficulty medium Group in pairs Fully digital possible H/S

In a nutshell

What: You measure your own heartbeat at rest and under stress and work out how much the gap between two beats varies — the heart-rate variability (HRV). You will see that under stress the heart becomes more regular and the HRV drops. This is one of the most honest signals the body sends.

You need: either a chest strap (e.g. Polar H10) for clean data or just a webcam for the contactless version. The analysis runs in Python straight in your browser.

What it's about

Your pulse is never a metronome. Even when it reads "70 a minute", the gap from beat to beat is sometimes a little longer, sometimes shorter. This fine flutter is not a fault — it is a sign of health. A relaxed heart is tuned by two nervous systems at once (accelerator and brake), and their interplay keeps the intervals varied. Under stress the "accelerator" takes over alone: the heart beats faster and more uniformly, and the variability shrinks.

That makes HRV an honest signal in the sense of this chapter: hard to fake, coupled directly to the state of the body. These are exactly the signals the Happimeter research uses to gauge mood and stress in teams — not from what people say, but from what their bodies do.

Heartbeat trace with the beat-to-beat intervals marked
From beat to beat. What is measured is not the heart rate itself, but the gap between two beats (the RR interval). How much these gaps vary is the HRV.

A little background

What exactly is HRV? You measure the time between successive heartbeats — the RR intervals, in milliseconds. A common measure is RMSSD: you look at how much each pair of neighbouring intervals differs, and average that. High RMSSD = lots of variety = relaxed. Low RMSSD = uniform = tense.

Two routes to the pulse. The chest strap works like an ECG and measures the heart's electrical activity directly — precise, and the best choice for HRV. The webcam version exploits the fact that your face goes minutely redder with every beat (the blood pulses) — this is called rPPG. It is impressive, but more sensitive to movement and light. For a first look it is enough; for clean HRV the strap is better.

Measuring

  1. Baseline at rest. Sit comfortably, breathe calmly for two minutes, then measure for 3 minutes. Move as little as possible — movement is the main enemy of clean data.
  2. Create stress. Now the contrast: 2 minutes of mental arithmetic under time pressure (count backwards from 1000 in steps of 7) or some other unpleasant but harmless task. Keep measuring for 3 minutes.
  3. Recovery. Measure for another 3 minutes at rest and watch whether the HRV climbs back up. How fast it recovers is itself an interesting signal.
  4. Save the data. Export the RR intervals (strap app) or save the values estimated by the webcam. You need one list each for rest, stress and recovery.

Fairness and consent

Body measurements are personal. No one has to be measured, and no one shares their values unasked. Compare within one person (rest vs. stress), not people against each other — HRV depends heavily on age and fitness, so a ranking would be unfair and meaningless.

Analysing with Python

The code takes your RR intervals and computes the HRV (RMSSD) for each phase, showing how it falls under stress. It runs in the browser (Pyodide); the full code is on GitHub.

import numpy as np

def rmssd(rr):
    """rr = list of beat-to-beat intervals in milliseconds."""
    rr = np.asarray(rr, dtype=float)
    diff = np.diff(rr)                 # difference of neighbouring intervals
    return np.sqrt(np.mean(diff**2))   # RMSSD in ms

def heart_rate(rr):
    return 60000.0 / np.mean(rr)       # beats per minute

# ---- paste in your three measurement series (from strap app or webcam) ----
rest     = [812, 845, 798, 861, 833, 807, 850, 795]   # example values
stress   = [612, 620, 605, 618, 609, 615, 611, 607]
recovery = [740, 792, 733, 805, 758, 781, 726, 799]

for name, rr in [("Rest", rest), ("Stress", stress), ("Recovery", recovery)]:
    print(f"{name:9s}  Pulse {heart_rate(rr):4.0f}/min   HRV(RMSSD) {rmssd(rr):5.1f} ms")

# Expectation: under stress the pulse rises AND the HRV falls clearly.

What you should see

At rest a higher HRV (more variety in the intervals), under stress a clearly lower one — often halved — together with a higher pulse. During recovery the HRV climbs again, usually more slowly than it fell. If your HRV does not fall, the stress task was perhaps too easy — or the measurement too noisy.

Worksheet

Reading your honest signal

  1. Enter pulse and HRV for rest, stress and recovery. By what percentage did the HRV fall from rest to stress?
  2. Why is HRV a better stress measure than heart rate alone? (Hint: climbing stairs also raises the pulse.)
  3. Why do we compare a person with themselves and not several people with each other?
  4. RMSSD looks at the difference between neighbouring beats. Why is that more robust against slow trends (e.g. the pulse drifting up over the minute) than "just the spread of all the intervals"?
  5. Where is the limit: what can HRV show — and what can it not (e.g. "why" someone is stressed)?
Show solution

1. Individual; typically the HRV falls by 30–60 % under acute stress. Percent = (HRV_rest − HRV_stress) / HRV_rest × 100.

2. The pulse rises for many reasons (movement, caffeine, standing up). HRV measures more specifically the balance of "accelerator and brake" in the nervous system and responds more selectively to mental tension — even while sitting still.

3. HRV depends heavily on age, fitness and daily form. A comparison between people would be unfair and would say nothing about stress. Only comparing the same person over time is meaningful.

4. Because RMSSD compares only neighbours, a slow rise in the baseline pulse largely cancels out — each step is compared only with the one immediately before it. A measure taken over all the intervals at once would wrongly count the slow trend as "variability".

5. HRV can show that the body is in a tense state. It cannot say why (fear? excitement? joy? coffee?), and certainly not what someone is thinking. Body state ≠ thought — exactly the line drawn throughout the book.

When it sticks

ProblemLikely cause & fix
HRV values jump around wildlyMovement artefacts or misfires in beat detection. Sit more still; drop the odd "outlier" interval (unrealistically short/long) before the calculation.
Webcam pulse unstablerPPG needs even light and a still head. Sit by a window (daylight), face centred, don't speak during the measurement.
HRV doesn't fall under stressTask too easy or too short. Make it harder/longer; make sure the baseline was really relaxed (not straight after running to class).
Chest strap gives no RR intervalsMany apps output only the pulse. Pick an app that exports RR/IBI; moisten the strap electrodes.

Food for thought

Extension

← All activities 5.2 The Six Honest Signals →