Mesurez Votre Fréquence Cardiaque avec le Capteur KY-039 et Arduino
Composants et fournitures
| Composant | Quantité |
|---|---|
| Arduino UNO | 1 |
| Capteur de pouls KY-039 | 1 |
| Fils de connexion (jumpers) | 1 |
À propos du projet
Dans le kit de 37 capteurs pour Arduino, on trouve un capteur de rythme cardiaque. Son nom promet beaucoup : on s'attend à une valeur numérique via I2C donnant directement les BPM. En réalité, il délivre une simple valeur analogique (0-1023) indiquant la quantité de lumière infrarouge reçue par le phototransistor, c'est-à-dire dans quelle mesure quelque chose fait de l'ombre au capteur. Plus la valeur est haute, moins il y a de lumière IR.
En résumé : placez votre doigt entre la LED IR et le phototransistor. Les battements cardiaques dilatent les vaisseaux sanguins du doigt, modulant la lumière IR. Cela crée un signal pulsé.
Ce projet explique comment convertir ce signal en fréquence cardiaque (ex: 66 BPM).
Les étapes simples
Si vous lisez et affichez directement les valeurs brutes du KY-039, vous obtenez un signal très bruitée :
En calculant une moyenne glissante sur plusieurs lectures, le signal devient exploitable :
On voit alors clairement les pics cardiaques. Il suffit de mesurer l'intervalle entre deux pics significatifs pour déduire les BPM.
(Le petit zigzag résiduel est dû à la lumière artificielle 50 Hz, qu'il faut aussi filtrer.)
Explication détaillée
Lecture brute
// Test simple du capteur
int sensorPin = 0;
void setup() { Serial.begin(9600); }
void loop() {
while(1) {
Serial.print(analogRead(sensorPin));
Serial.print('\n');
}
}
Le signal est très irrégulier (valeurs entières entre ~360 et 383), cadencé par Serial.print().
Lissage par moyenne glissante
#define samp_siz 20
int reads[samp_siz];
int ptr = 0;
long sum = 0;
void loop() {
int reader = analogRead(sensorPin);
sum -= reads[ptr];
sum += reader;
reads[ptr] = reader;
float last = float(sum) / samp_siz;
ptr = (ptr + 1) % samp_siz;
// ...
}
Avec 20 échantillons, le signal est bien plus lisse, mais le bruit 50 Hz persiste.
Élimination du bruit 50 Hz par moyennage sur 20 ms
Comme le secteur est à 50 Hz (période 20 ms), on moyenne toutes les lectures sur une fenêtre de 20 ms :
int n = 0;
unsigned long start = millis();
float reader = 0;
do {
reader += analogRead(sensorPin);
n++;
} while (millis() < start + 20);
reader /= n; // Moyenne sur 20 ms = élimine 50 Hz
Note : en zone 60 Hz, utilisez 16,67 ms.
Détection des pics (battements)
On détecte n valeurs consécutives en hausse (seuil rise_threshold = 5) pour identifier le front montant de chaque pouls. On mesure alors l'intervalle depuis le dernier pic et on calcule les BPM par moyenne pondérée sur les 3 derniers intervalles.
Code final complet
#define samp_siz 4
#define rise_threshold 5
int sensorPin = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
float reads[samp_siz], sum = 0;
long int now, ptr = 0;
float last, reader, start;
float first = 0, second = 0, third = 0, before = 0, print_value = 0;
bool rising = false;
int rise_count = 0;
int n;
long int last_beat = 0;
for (int i = 0; i < samp_siz; i++) reads[i] = 0;
while (1) {
// Moyenne sur 20 ms (anti-50 Hz)
n = 0;
start = millis();
reader = 0;
do {
reader += analogRead(sensorPin);
n++;
now = millis();
} while (now < start + 20);
reader /= n;
// Mise à jour moyenne glissante
sum -= reads[ptr];
sum += reader;
reads[ptr] = reader;
last = sum / samp_siz;
// Détection front montant
if (last > before) {
rise_count++;
if (!rising && rise_count > rise_threshold) {
rising = true;
first = millis() - last_beat;
last_beat = millis();
// Moyenne pondérée sur 3 derniers intervalles
print_value = 60000.0 / (0.4 * first + 0.3 * second + 0.3 * third);
Serial.print(print_value);
Serial.print('\n');
third = second;
second = first;
}
} else {
rising = false;
rise_count = 0;
}
before = last;
ptr = (ptr + 1) % samp_siz;
}
}
Ça fonctionne bien ! La minuscule LED RX de l'Arduino clignote en synchronie avec le cœur (car l'envoi série la fait clignoter).
Pistes d'amélioration
- Calculer la moyenne sur une fenêtre de 15 secondes plutôt que 3 battements.
- Éliminer les valeurs aberrantes (écart-type) pour plus de stabilité.
- Tester sur différents profils physiologiques (rythme très rapide, forme d'onde différente).
Schéma de câblage

Processus de fabrication
- Capteurs de Couleur : Fonctionnement et Applications Clés
- Streaming de données de température en temps réel depuis un ppDAQC Pi‑Plate vers InitialState avec un Raspberry Pi headless
- Construire un système de surveillance température et lumière multi-capteurs avec Raspberry Pi et DS18B20
- D'une lampe solaire à 4 $ à un nœud capteur sans fil intelligent : MSP430 + nRF24L01+ pour surveillance jardin
- Capteur d'occupation de salle de bain basé sur Raspberry Pi avec alertes vocales et SMS via Twilio
- Lire les pulsations cardiaques avec Windows 10 IoT Core sur Raspberry Pi – Guide étape par étape
- Tutoriel capteur de lumière Raspberry Pi – Câbler une LDR et lire les niveaux de lumière avec Python
- Capteur de lumière numérique – Alimenter une LED avec la lumière ambiante via Windows 10 IoT Core
- Système de surveillance cardiaque à distance avec alertes AWS IoT