Capteur de distance comme détecteur de présence
// Conception interactive // Capteur de distance comme détecteur de présence
Pour l’installation Chœur, produite par les productions Rhizome sous la direction artistique de Simon Dumas, l’idée était que l’installation soit déclenchée lorsqu’une personne entrait dans une zone délimitée par trois lumières au sol : une rouge, une verte et une bleue.
Une première version imprécise
La première version du système où ces espaces lumineux agissaient comme des boutons (ou des déclencheurs) utilisait des capteurs de distance comme celui-ci :
La première version du dispositif où ces espaces lumineux agissaient comme des boutons (ou des déclencheurs) utilisait des capteurs de distance comme celui-ci :
Ce type de capteurs utilise les ultrasons pour évaluer la distance d’un objet. Même si nous arrivions toujours à les faire fonctionner, c’était chaque fois assez difficile pour les raisons suivantes :
- Le fait que nous en utilisions trois, un pour chaque « bouton de lumière », faisait en sorte qu’il fallait bien s’assurer que les ultrasons d’un capteur n’atteignent pas un autre capteur, car cela créait des interférences, ce qui rendait le système non fonctionnel.
- Le fait que ces capteurs utilisent le son pour calculer la distance fait que toutes les matières qui absorbent le son sont plus difficiles à détecter, par exemple, un être humain.
- Ce type de capteurs perd rapidement en précision lorsqu’on s’en éloigne. Lorsqu’on l’installait sur un plafond haut, il fallait fréquemment sous-percher ceux-ci assez près du sol pour assurer une fiabilité adéquate.
- Nous utilisions la sortie analogique du capteur, avec de longs câbles qui se rendaient jusqu’à un Arduino à la régie, où un ordinateur lui transférait les informations via son port USB. Un signal analogique perd beaucoup de précision et accumule beaucoup d’interférences sur de longues distances, ce qui rendait les capteurs encore moins précis.
- Les ports USB des ordinateurs sont fréquemment la source de bogues, donc il s’agit d’une autre source de problèmes potentiels.
Une deuxième version performante
En 2023, j’ai conçu une nouvelle version beaucoup plus fiable en remplaçant les capteurs à ultrason par des capteurs infrarouges comme celui-ci :
L’emploi de ce type de capteur, qui utilise un faisceau de lumière infrarouge pour calculer la distance au lieu d’ondes ultrasoniques, a réglé bon nombre de problèmes:
- Comme la lumière peut être beaucoup plus directionnelle que le son, il est beaucoup plus précis.
- Il y a moins de risques d’interférences l’un avec l’autre.
- Il détecte plus facilement diverses matières. Il fonctionne, bien entendu, un peu moins bien avec les couleurs sombres, mais jusqu’à maintenant ça n’a pas été un problème.
- Il garde une bonne précision, peu importe la distance de l’objet.
Après quelques recherches, mon choix s’est posé sur ce capteur : https://www.sparkfun.com/products/16977. Il est accessible, pas trop dispendieux, facile d’utilisation et peut détecter des objets jusqu’à 6 mètres de distance.
Un autre élément important qui a rendu le système beaucoup plus fiable est l’utilisation d’un microcontrôleur par capteur. Le microcontrôleur qui a été choisi pour ce projet est celui-ci : https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware.
La principale raison pour laquelle je l’ai choisi est le fait que l’alimentation et le transfert des données se font via le même câble réseau. Cette particularité permet de n’avoir qu’un seul câble à passer de l’ordinateur au capteur. Il suffit d’utiliser une switch réseau avec des ports POE (Power Over Ethernet) et le tour est joué. Nous aurions pu utiliser des microcontrôleurs WiFi, mais il aurait fallu tout de même passer un fil pour alimenter le capteur. Le fait d’utiliser un câble réseau permet une installation plus fiable.
Un autre élément important de cette nouvelle version des capteurs est l’abandon de tout signal analogique :
- Le capteur communique avec microcontrôleur via le protocole UART.
- Le microcontrôleur communique avec l’ordinateur via le protocole OSC (Open Sound Control).
Voici le code utilisé pour ce projet. Celui-ci prend les données du capteur et les transforme en messages OSC, qui sont ensuite traités par le logiciel qui gère l’installation Chœur.
Finalement, la première version de ce capteur était installée de façon un peu bancale dans une boite de plastique générique. Pour cette deuxième version, les nouvelles technologies d’impression 3D ont été utilisées afin de créer un boitier sur mesure. J’ai fait le modèle dans le logiciel Fusion 360 :
Voici ce dont ils ont l’air une fois terminés et fonctionnels :
Le code
#include <ETH.h>
#include <OSCMessage.h>
#include <WiFiUdp.h>
WiFiUDP Udp;
const IPAddress ipEth(192, 168, 1, 203);
const IPAddress gateway(192, 168, 1, 1);
const IPAddress subnet(255, 255, 255, 0);
static bool eth_connected = false;
// for OSC
unsigned int receivePort = 8888;
IPAddress outIp(255, 255, 255, 255);
unsigned int outPort = 7003;
#define RX1_PIN 36
#define TX1_PIN 4
int dist; /*----actual distance measurements of LiDAR---*/
int strength; /*----signal strength of LiDAR----------------*/
float temprature;
unsigned char check; /*----save check value------------------------*/
int i;
unsigned char uart[9]; /*----save data measured by LiDAR-------------*/
const int HEADER=0x59; /*----frame header of data package------------*/
int rec_debug_state = 0x01;//receive state for frame
void setup() {
delay(2000);//wait for the controlleur to be ready
// Serial 0 (console) et 1 (Lidar)
Serial.begin(115200);
Serial1.begin(115200, SERIAL_8N1, RX1_PIN, TX1_PIN);
// ETH
WiFi.onEvent(WiFiEvent);
ETH.begin();
ETH.config(ipEth, gateway, subnet);
}
void loop() {
Get_Lidar_data();
OSCMessage msg("/dist");
msg.add(dist);
Udp.beginPacket(outIp, outPort);
msg.send(Udp);
Udp.endPacket();
msg.empty();
OSCMessage msg2("/strength");
msg2.add(strength);
Udp.beginPacket(outIp, outPort);
msg2.send(Udp);
Udp.endPacket();
msg2.empty();
}
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex()) {
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
void Get_Lidar_data(){
if (Serial1.available()) //check if serial port has data input
{
if(rec_debug_state == 0x01)
{ //the first byte
uart[0]=Serial1.read();
if(uart[0] == 0x59)
{
check = uart[0];
rec_debug_state = 0x02;
}
}
else if(rec_debug_state == 0x02)
{//the second byte
uart[1]=Serial1.read();
if(uart[1] == 0x59)
{
check += uart[1];
rec_debug_state = 0x03;
}
else{
rec_debug_state = 0x01;
}
}
else if(rec_debug_state == 0x03)
{
uart[2]=Serial1.read();
check += uart[2];
rec_debug_state = 0x04;
}
else if(rec_debug_state == 0x04)
{
uart[3]=Serial1.read();
check += uart[3];
rec_debug_state = 0x05;
}
else if(rec_debug_state == 0x05)
{
uart[4]=Serial1.read();
check += uart[4];
rec_debug_state = 0x06;
}
else if(rec_debug_state == 0x06)
{
uart[5]=Serial1.read();
check += uart[5];
rec_debug_state = 0x07;
}
else if(rec_debug_state == 0x07)
{
uart[6]=Serial1.read();
check += uart[6];
rec_debug_state = 0x08;
}
else if(rec_debug_state == 0x08)
{
uart[7]=Serial1.read();
check += uart[7];
rec_debug_state = 0x09;
}
else if(rec_debug_state == 0x09)
{
uart[8]=Serial1.read();
if(uart[8] == check)
{
dist = uart[2] + uart[3]*256;//the distance
strength = uart[4] + uart[5]*256;//the strength
temprature = uart[6] + uart[7] *256;//calculate chip temprature
temprature = temprature/8 - 256;
Serial.print("dist = ");
Serial.print(dist); //output measure distance value of LiDAR
Serial.print('\n');
Serial.print("strength = ");
Serial.print(strength); //output signal strength value
Serial.print('\n');
Serial.print("\t Chip Temprature = ");
Serial.print(temprature);
Serial.println(" celcius degree"); //output chip temperature of Lidar
while(Serial1.available()){Serial1.read();} // This part is added becuase some previous packets are there in the buffer so to clear serial buffer and get fresh data.
delay(250);
}
rec_debug_state = 0x01;
}
}
}