Construire un détecteur de gestes et mouvements avec capteur PIR et Arduino Nano
Composants et fournitures
| Arduino Nano R3 | × | 1 |
| Capteur thermique 8 pixels TPA81 Devantech | × | 1 |
| Capteur PIR infrarouge HC-SR505 (ElectroPeak) | × | 8 |
| Module OLED 0.96" SPI 128x64 (ElectroPeak) | × | 1 |
| Platine d'essai (générique) | × | 1 |
| Fils de liaison Mâle/Femelle | × | 1 |
Applications et services en ligne
- Arduino IDE
À propos de ce projet
Dans cet article, nous montrons comment réaliser un détecteur de gestes avec des composants simples : capteur PIR et Arduino Nano. À la fin, vous saurez :
- Expliquer les applications et le fonctionnement du capteur PIR
- Utiliser le capteur 8 pixels TPA81
- Détecter mouvement et gestes par Arduino
- Créer un détecteur sympa pour augmenter/baisser le volume d'une enceinte

Capteur infrarouge passif (PIR) : Comment ça marche ?
Un capteur PIR mesure le rayonnement infrarouge (IR) émis par les objets dans son champ de vision. Utilisé dans les détecteurs de mouvement. Tout objet au-dessus du zéro absolu émet de l'énergie thermique sous forme de rayonnement (longueurs d'onde infrarouges, invisibles à l'œil nu mais détectables électroniquement).
Passif signifie qu'il ne génère ni n'émet d'énergie pour la détection. Il détecte le rayonnement IR émis ou réfléchi par les objets. Il ne détecte pas la chaleur directement. (Source : Wikipedia)

Le TPA81 est un réseau thermopile détectant l'infrarouge 2-22 µm (longueur d'onde chaleur radiante). Les capteurs pyroélectriques (alarmes, éclairage extérieur) détectent la même bande mais ne voient que les changements de chaleur → détecteurs de mouvement. Ils ne mesurent pas la température d'une source statique.
Le réseau thermopile (thermomètres IR sans contact) a un large angle de détection (~100°), nécessite lentille/écran pour le réduire (~12°). Le TPA81 intègre 8 thermopiles en ligne, électronique et lentille silicium. Il mesure la température de 8 points adjacents simultanément. Peut piloter un servo pour balayer et construire une image thermique. Détecte une flamme de bougie à 2m, insensible à la lumière ambiante !

Les capteurs PIR sont comme des caméras ne voyant que le chaud. Le TPA81 est une caméra thermique 8 pixels. Le corps humain émet toujours de la chaleur. En pilotant le capteur par microcontrôleur et en définissant des gestes, on fait un détecteur de gestes simple.
Ce projet utilise le TPA81 (un peu cher). Alternative économique : 8 capteurs PIR simples sans tête blanche (partie focale). Le TPA81 supporte I2C, compatible Arduino Nano. Projet idéal pour comprendre bases du traitement d'image et détection de gestes.
Circuit

Alternative économique : 8 capteurs PIR simples connectés à l'Arduino, lus séquentiellement.

Code
Pour le premier circuit (TPA81), copiez le code dans l'IDE Arduino. D'abord ajoutez la bibliothèque puis téléversez. Téléchargez la bibliothèque TPA81 depuis le lien fourni. Si première utilisation Arduino :
- Téléchargez l'IDE sur arduino.cc et installez.
- Ouvrez l'IDE, effacez l'éditeur, collez le code.
- Croquis > Inclure bibliothèque > Ajouter bibliothèque .ZIP (bibliothèques téléchargées).
- Outils > Carte > Arduino Nano.
- Connectez Arduino, définissez le port COM (Outils > Port).
- Cliquez Téléverser (flèche).
- C'est prêt !
Test de base : lecture 8 pixels
#include "Wire.h"
#include "TPA81.h"
TPA81 tpa;
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop() {
Serial.print(tpa.getAmbient());
Serial.print(" ");
for (int i = 1; i <= 8; i++) {
Serial.print(tpa.getPoint(i));
Serial.print(" ");
}
Serial.println(" ");
delay(100);
}

Ouvrez le moniteur série. Le premier nombre = température ambiante. Placez votre main devant le capteur : observez la température corporelle. Pour définir un geste, connaissez votre température de main et définissez un seuil (offset). Nous avons mis 29°C. Code suivant pour visualiser le mouvement :
#include "Wire.h"
#include "TPA81.h"
TPA81 tpa;
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop() {
Serial.print(tpa.getAmbient());
Serial.print(" ");
for (int i = 1; i <= 8; i++) {
if (tpa.getPoint(i) > 29) Serial.print("# ");
else Serial.print(". ");
}
Serial.println(" ");
delay(100);
}

Algorithme détection geste (volume + / -)
Algorithme pour détecter geste simple : augmenter/baisser volume. Copiez et testez :
#include "Wire.h"
#include "TPA81.h"
#include "ssd1306.h"
#include "DHT.h"
TPA81 tpa;
#define VCCSTATE SSD1306_SWITCHCAPVCC
#define WIDTH 128
#define HEIGHT 64
#define PAGES 8
#define OLED_RST 9
#define OLED_DC 8
#define OLED_CS 10
#define SPI_MOSI 11 // Broche DIN OLED
#define SPI_SCK 13
uint8_t oled_buf[WIDTH * HEIGHT / 8];
int gesture[8][20];
int tgesture[8];
int sum = 0;
int sflag; // drapeau veille
int gcount;
int c;
int ex;
int vol = 5;
// Bitmaps pour affichage volume (v1 à v11 stockés en PROGMEM)
const uint8_t v1[] PROGMEM = { ... }; // Données bitmap volume niveau 1
const uint8_t v2[] PROGMEM = { ... }; // Niveau 2
const uint8_t v3[] PROGMEM = { ... }; // Niveau 3
const uint8_t v4[] PROGMEM = { ... }; // Niveau 4
const uint8_t v5[] PROGMEM = { ... }; // Niveau 5
const uint8_t v6[] PROGMEM = { ... }; // Niveau 6
const uint8_t v7[] PROGMEM = { ... }; // Niveau 7
const uint8_t v8[] PROGMEM = { ... }; // Niveau 8
const uint8_t v9[] PROGMEM = { ... }; // Niveau 9
const uint8_t v10[] PROGMEM = { ... }; // Niveau 10
const uint8_t v11[] PROGMEM = { ... }; // Niveau 11
void dsply(int input) {
int n1, n2;
if (input < 10) {
SSD1306_char3216(10, 25, '0', oled_buf);
switch(input) {
case 0: SSD1306_char3216(26, 25, '0', oled_buf); break;
case 1: SSD1306_char3216(26, 25, '1', oled_buf); break;
case 2: SSD1306_char3216(26, 25, '2', oled_buf); break;
case 3: SSD1306_char3216(26, 25, '3', oled_buf); break;
case 4: SSD1306_char3216(26, 25, '4', oled_buf); break;
case 5: SSD1306_char3216(26, 25, '5', oled_buf); break;
case 6: SSD1306_char3216(26, 25, '6', oled_buf); break;
case 7: SSD1306_char3216(26, 25, '7', oled_buf); break;
case 8: SSD1306_char3216(26, 25, '8', oled_buf); break;
case 9: SSD1306_char3216(26, 25, '9', oled_buf); break;
}
} else {
n1 = input / 10;
n2 = input % 10;
switch(n1) {
case 0: SSD1306_char3216(10, 25, '0', oled_buf); break;
case 1: SSD1306_char3216(10, 25, '1', oled_buf); break;
case 2: SSD1306_char3216(10, 25, '2', oled_buf); break;
case 3: SSD1306_char3216(10, 25, '3', oled_buf); break;
case 4: SSD1306_char3216(10, 25, '4', oled_buf); break;
case 5: SSD1306_char3216(10, 25, '5', oled_buf); break;
case 6: SSD1306_char3216(10, 25, '6', oled_buf); break;
case 7: SSD1306_char3216(10, 25, '7', oled_buf); break;
case 8: SSD1306_char3216(10, 25, '8', oled_buf); break;
case 9: SSD1306_char3216(10, 25, '9', oled_buf); break;
}
switch(n2) {
case 0: SSD1306_char3216(26, 25, '0', oled_buf); break;
case 1: SSD1306_char3216(26, 25, '1', oled_buf); break;
case 2: SSD1306_char3216(26, 25, '2', oled_buf); break;
case 3: SSD1306_char3216(26, 25, '3', oled_buf); break;
case 4: SSD1306_char3216(26, 25, '4', oled_buf); break;
case 5: SSD1306_char3216(26, 25, '5', oled_buf); break;
case 6: SSD1306_char3216(26, 25, '6', oled_buf); break;
case 7: SSD1306_char3216(26, 25, '7', oled_buf); break;
case 8: SSD1306_char3216(26, 25, '8', oled_buf); break;
case 9: SSD1306_char3216(26, 25, '9', oled_buf); break;
}
}
}
void setup() {
Serial.begin(9600);
Wire.begin();
SSD1306_begin();
SSD1306_clear(oled_buf);
}
void loop() {
// Lecture 8 pixels
for (int i = 0; i <= 7; i++) {
if (tpa.getPoint(i) > 29) {
Serial.print("#");
Serial.print(" ");
gesture[i][0] = 1;
} else {
Serial.print(".");
Serial.print(" ");
gesture[i][0] = 0;
}
}
for (int y = 0; y <= 7; y++) sum += gesture[y][0];
Serial.println(sum);
Serial.println(" ");
delay(100);
////////////////////////////////////////////////////////////////////////////////////// Veille
if (sum == 8) {
sflag = 1;
Serial.println("veille");
} else {
sum = 0;
}
////////////////////////////////////////////////////////////////////////////////////// Détection geste
if (sflag == 1 && sum != 8) {
Serial.println("début geste");
gcount = 0;
c = 0;
sum = 0;
while (sum < 8) {
sum = 0;
for (int i = 0; i <= 7; i++) {
if (tpa.getPoint(i) > 29) {
Serial.print("#");
Serial.print(" ");
gesture[i][gcount] = 1;
} else {
Serial.print(".");
Serial.print(" ");
gesture[i][gcount] = 0;
}
}
for (int y = 0; y <= 7; y++) {
sum += gesture[y][gcount];
delay(5);
}
Serial.println(" ");
delay(50);
gcount++;
}
Serial.print("somme : ");
Serial.println(sum);
Serial.print("longueur geste : ");
Serial.println(gcount);
delay(5);
for (c = 0; c <= 7; c++) {
for (int z = 0; z <= gcount; z++) {
tgesture[c] += gesture[c][z];
delay(5);
}
Serial.println("traitement");
}
tgesture[0] += tgesture[1];
tgesture[2] += tgesture[3];
tgesture[4] += tgesture[5];
tgesture[6] += tgesture[7];
tgesture[0] += tgesture[2];
tgesture[4] += tgesture[6];
if (tgesture[0] < tgesture[4]) {
vol += (gcount / 2);
Serial.print("volume up");
}
if (tgesture[4] < tgesture[0]) {
vol -= (gcount / 2);
Serial.print("volume down");
}
sflag = 0;
}
sum = 0;
SSD1306_clear(oled_buf);
switch (vol) {
case 1: SSD1306_bitmap(0, 0, v1, 128, 64, oled_buf); break;
case 2: SSD1306_bitmap(0, 0, v2, 128, 64, oled_buf); break;
case 3: SSD1306_bitmap(0, 0, v3, 128, 64, oled_buf); break;
case 4: SSD1306_bitmap(0, 0, v4, 128, 64, oled_buf); break;
case 5: SSD1306_bitmap(0, 0, v5, 128, 64, oled_buf); break;
case 6: SSD1306_bitmap(0, 0, v6, 128, 64, oled_buf); break;
case 7: SSD1306_bitmap(0, 0, v7, 128, 64, oled_buf); break;
case 8: SSD1306_bitmap(0, 0, v8, 128, 64, oled_buf); break;
case 9: SSD1306_bitmap(0, 0, v9, 128, 64, oled_buf); break;
case 10: SSD1306_bitmap(0, 0, v10, 128, 64, oled_buf); break;
case 11: SSD1306_bitmap(0, 0, v11, 128, 64, oled_buf); break;
}
SSD1306_display(oled_buf);
}

Et ensuite ?
Avec cette méthode, vous pouvez étendre le code pour détecter d'autres gestes : tapotement, glisser-déposer, étirement, etc. Puis définir des commandes pour exécuter des actions à la détection de chaque mouvement/gesture.
Code (bibliothèques)
Bibliothèque TPA81
Téléchargement uniquement (C/C++).
Bibliothèque SSD1306
Téléchargement uniquement (C/C++).
Processus de fabrication
- Capteurs Arduino : Types, Applications et Projets Réels
- Comment fonctionnent les circuits de capteur PIR : conception, fonctionnement et applications réelles
- Contrôler une LED avec un capteur de mouvement PIR sur Raspberry Pi
- Maîtriser le GPIO Raspberry Pi : Interfacer un capteur PIR de mouvement sur B+/Modèle 2
- Comment connecter, calibrer et programmer le capteur de mouvement PIR HC‑SR501 avec un Raspberry Pi
- Projet capteur DHT11 température/humidité avec indicateurs LED et buzzer piézo
- Robot de détection humaine basé sur Arduino Uno : Intégration capteurs étape par étape
- Bocal Intelligent IoT avec ESP8266, Arduino et Capteur Ultrasonique – Surveillance Temps Réel
- Affichage LED matrice interactif porte avec capteur PIR - Salutations fêtes Arduino