Cet article présente un cas concret d’utilisation d’un capteur de présence (on/off) pour intégrer dans le temps ses valeurs et ainsi obtenir une valeur numérique plus intéressante.
Notre problématique est simple : on dispose d’un capteur de présence ou de proximité (PROXIR infrarouge dont on a déjà parlé ici) qui nous donne une indication très fugitive "je vois" / "je vois pas" et on voudrait en tirer un peu plus.
La solution est simple : on va mesurer le temps pendant lequel le capteur détecte un passage, même si ce temps est très court.
Le matériel
- un microcontrôleur et sa carte (ici, une Arduino)
- un capteur de présence (ici, un PROXIR mais ça fonctionnerait avec tout autre capteur tout ou rien comme un Sharp GP2D15 ou GP2D150)
- une plaque d’essai et 4 fils
Le montage
Rien de plus simple : on connecte directement le PROXIR à une entrée numérique. C’est un signal "tout ou rien" qui indique si une présence est détectée (valeur LOW) ou pas (valeur HIGH, oui c’est inversé sur ce capteur).
L’exemple de code ci-dessous est destiné à être utilisé dans un "sketch" pour l’environnement de développement Arduino car ce n’est pas seulement une carte, c’est aussi un logiciel. D’un point de vue langage, c’est du C.
/*
* ProxIR connections to Arduino
* -----------------------------
* G - GND -- Gnd
* T - TRM -- Digital Out 12
* R - RCV -- Digital In 11
* V - PWR -- 5V
*/
void setup()
{
pinMode(11, INPUT);
pinMode(12, OUTPUT);
digitalWrite(11,HIGH); // pull-up sur l'entrée
digitalWrite(12,HIGH); // activer la led émettrice du capteur
Serial.begin(9600); // communiquer avec le PC
}
La carte est ensuite reliée au PC pour la programmation et pour l’affichage sur notre oscilloscope minimal.
Première acquisition : tout ou rien
On va vérifier que le capteur fonctionne bien. C’est fondamental et ce petit programme doit être régulièrement réutilisé pour vérifier que le capteur fonctionne bien ou si c’est notre code qui est "cassé".
void loop()
{
// la valeur envoyée à l'oscilloscope (entre 0 et 1000)
int val = 0;
// la valeur lue
int detect = digitalRead(11);
if (detect == HIGH)
{
// toujours rien
val = 250; // affichage bas pour signaler que le capteur est actif
}
if (detect == LOW)
{
// on détecte !
val = 750; // affichage haut, il y a un obstacle devant le capteur
}
// envoi d'une trame sur la liaison série pour l'oscillo Processing
Serial.print(0xff, BYTE);
Serial.print( (val >> 8) & 0xff, BYTE);
Serial.print( val & 0xff, BYTE);
}
Voici le résultat (sur l’oscilloscope minimal de Sofian Audry) obtenu en quelques minutes.
Et maintenant, intégrons le signal
On va mesure le temps pendant lequel le signal est actif. On doit donc détecter le changement de signal (front descendant pour le début de la détection et front montant pour la fin de la détection puisque la valeur reçue est inversée par rapport à notre logique naturelle).
Il faut donc une "mémoire" du signal et un compteur pour le nombre de ms écoulées.
// la valeur précédente de la détection
int memoire = HIGH; // HIGH = inactif pour le PROXIR
// nombre de ms au début de la détection
unsigned long compte = 0;
Et on modifie notre boucle :
– au début de la détection, démarrer le compteur (remise à zéro, ràz)
– en cours de détection, pour l’effet visuel
– à la fin de la détection, pour avoir le temps total et arrêter le compte
void loop()
{
// ce qui va être envoyé à l'oscillo
int val = 0;
// la valeur courante du capteur
int courant = digitalRead(11);
// agir au début de la détection (front descendant) !! attention inversion
if (memoire == HIGH && courant == LOW)
{
// remise à zéro du compteur
compte = millis();
}
else
// agir pendant la détection
if (memoire == LOW && courant == LOW)
{
// on va envoyer la valeur du compteur (ms courantes - ms mémorisées)
val = (int) millis()-compte;
}
else
// agir à la fin de la détection
if (memoire == LOW && courant == HIGH)
{
val = (int) millis()-compte;
// s'agissant de la fin, on pourrait ici lancer un traitement particulier
}
// préparer l'étape suivante en transférant l'état courant dans la mémoire
memoire = courant;
Serial.print(0xff, BYTE);
Serial.print( (val >> 8) & 0xff, BYTE);
Serial.print( val & 0xff, BYTE);
}
Je passe ma main et...
Sans avoir perdu tellement de temps de calcul (juste une lecture du nombre de ms et une soustraction à chaque boucle), on a désormais une information supplémentaire qui peut être beaucoup plus utile que le simple booléen HIGH/LOW que ce capteur offrait par défaut.