Tutoriel · Débutant · 25 min de lecture

Capteurs de collision et anti-rebond pour robots

Un interrupteur qui ferme donne neuf fronts, pas un. Le rebote trompe une interruption, coûte une fenêtre anti-rebond, et voici le pare-chocs durable.

Un interrupteur n’est pas un front propre

Pressez un micro-interrupteur à levier et le contact métallique arrive, fléchit, se sépare et arrive de nouveau — plusieurs fois, dans les premières millisecondes, avant de se stabiliser. C’est le rebond de contact, et c’est mécanique : aucun logiciel avant ni aucun condensateur après n’empêche le métal de bouger.

La conséquence ne compte que parce que la broche est lue par quelque chose de bien plus rapide que le métal. Un microcontrôleur échantillonné à 16 MHz voit chacune de ces transitions comme un vrai front.

Deux tracés superposés. Celui du haut montre un signal d'interrupteur sur environ six millisecondes : la broche brute tombe bas, puis oscille entre haut et bas neuf fois sur 4,7 millisecondes avant de se stabiliser bas, tandis que la sortie anti-rebond reste haute jusqu'à expiration de la fenêtre puis tombe proprement. Celui du bas montre le nombre de fronts comptés par une interruption chutant par paliers de neuf à un quand la fenêtre anti-rebond passe de zéro à huit millisecondes, atteignant un à 4,7 millisecondes.
Un appui d'un interrupteur à levier modélisé : neuf transitions sur 4,7 ms. Une fenêtre anti-rebond plus courte que le rebond compte le rebond — et une fenêtre assez longue pour l'éteindre coûte exactement sa longueur en latence, le compromis que personne ne mentionne. Télécharger le SVG

Le panneau du bas est la courbe de conception. Le nombre de fronts chute par paliers quand la fenêtre grandit, atteint un au point où le rebond finit, et y reste. Plus court surcompte ; plus long est de la latence payée pour rien.

Durées de rebond typiques, à mesurer plutôt que croire :

Interrupteur Rebond
Micro-interrupteur à levier de qualité 0,5–2 ms
Bouton tactile bon marché 2–10 ms
Interrupteur reed 0,1–1 ms
Contact de relais 1–20 ms

Le conseil habituel « 5 ms suffisent » est une devinette au milieu de ce tableau. Mesurez le vôtre : c’est une ligne de code et cela transforme une superstition en nombre.

Câblage, avant que tout cela compte

Un interrupteur de collision veut des contacts normalement ouverts vers la masse, avec la broche rappelée au haut :

pinMode(BUMP_L, INPUT_PULLUP);   // idle HIGH, LOW when the bumper is pressed

Trois raisons pour ce montage plutôt que l’autre :

  • Actif bas sûr en panne. Un fil coupé lit HIGH, soit non pressé, donc un fil de pare-chocs arraché ne fait pas croire au robot qu’il entre en collision permanente. Un montage en rappel au bas échoue dans l’autre sens.
  • Le rappel interne est gratuit. Pas de résistance, pas de pièce supplémentaire sur un robot dont l’avant va être frappé à répétition.
  • Le bruit est évacué, pas capté. Un long fil de pare-chocs est une antenne ; le chemin basse impédance vers la masse à l’état fermé l’empêche de capter le pilote moteur voisin.

Utilisez le contact normalement fermé de l’interrupteur et vous obtenez le comportement de panne inverse — un fil coupé ressemble à une collision permanente, le bon choix pour un arrêt d’urgence et le mauvais pour un pare-chocs.

Anti-rebond : choisissez-en un parmi trois

Ignorer-après-accepter. Le paresseux, et correct pour un pare-chocs. Acceptez le premier front instantanément, puis refusez de regarder pendant la fenêtre :

const unsigned long BOUNCE_MS = 6;
unsigned long lastBumpAt = 0;

bool bumped() {
  if (digitalRead(BUMP_L) == HIGH) return false;         // not pressed
  if (millis() - lastBumpAt < BOUNCE_MS) return false;   // still inside the window
  lastBumpAt = millis();
  return true;
}

Zéro latence sur le front qui compte, et le rebond est jeté derrière. C’est voulu quand la réaction est arrêter les moteurs — attendre 6 ms pour être sûr, c’est 6 ms à foncer dans le meuble.

Attendre-la-stabilité. L’approche de l’exemple Arduino : mémorisez quand la lecture a changé pour la dernière fois et n’acceptez qu’une fois stable pendant la fenêtre. Coûte toute la fenêtre en latence et convient à un bouton de menu, où un faux appui est pire qu’un lent.

Matériel. Un condensateur 100 nF aux bornes des contacts plus le rappel donne un RC d’environ 10 ms avec un rappel interne de 100 kΩ — mais le front produit est lent, et un front lent en entrée numérique peut osciller via le seuil. Dans cette voie, ajoutez une entrée à trigger de Schmitt. Généralement pas le prix des pièces.

Notez le point commun des trois : ils sont non bloquants. Un delay(20) après le front anti-rebondit parfaitement et empêche le robot de lire quoi que ce soit d’autre pendant 20 ms, soit 6 mm de parcours aveugle à 0,3 m/s — voyez la temporisation avec millis().

Interruptions et rebond font mauvais ménage

Attacher une interruption à un pare-chocs semble évidemment juste et ne l’est généralement pas.

Neuf transitions signifient neuf déclenchements de l’ISR. Si elle incrémente un compteur, vous avez neuf collisions ; si elle pose un drapeau, vous en avez une, sans dommage. N’utilisez une interruption que si le gestionnaire est idempotent — poser un drapeau, capturer un horodatage — et jamais s’il compte.

volatile bool bumpFlag = false;
volatile unsigned long bumpAt = 0;

void onBump() {                       // idempotent: nine calls do what one call does
  if (millis() - bumpAt < BOUNCE_MS) return;
  bumpAt = millis();
  bumpFlag = true;
}

millis() n’avance pas dans une ISR sur AVR, ce qui rend ceci sûr pendant un rebond mais faux pour plus long — utilisez micros() si la fenêtre compte précisément.

Honnêtement, pour un pare-chocs l’interruption est rarement nécessaire. Une boucle à 200 Hz remarque une collision en 5 ms, et le robot parcourt 1,5 mm pendant ce temps. Scrutez, et réservez les broches d’interruption aux encodeurs vraiment non scrutables.

Construire un pare-chocs qui marche

L’interrupteur est la moitié facile. Le mécanisme devant décide si le robot détecte un pied de chaise touché en biais.

  • Une coque mobile, deux interrupteurs. Un seul panneau avant sur deux points flexibles, avec un interrupteur derrière chaque côté. Interrupteur gauche seul signifie obstacle à gauche, l’information dont le comportement d’évitement a besoin pour choisir le côté de dégagement.
  • Enveloppez les coins. Un pare-chocs avant plat manque tout ce qui est touché à plus d’environ 30°, et les touches rasantes sont la majorité. Menez la coque à au moins 45° de chaque côté.
  • Les ressorts rappellent, pas les interrupteurs. Le ressort propre d’un micro-interrupteur fait 50–100 g et ne repoussera pas fiablement une coque. Utilisez élastiques ou légers ressorts de compression, et laissez l’interrupteur seulement détecter.
  • Donnez course et butée dure. 3–5 mm de mouvement avant actionnement, et une butée qui prend l’impact au lieu du corps d’interrupteur. Les corps d’interrupteurs sont ce qui casse.
  • Ajoutez du sans-contact. Un pare-chocs est un dernier recours — il signale une collision déjà arrivée. Un capteur à ultrasons ou à temps de vol devant évite la plupart ; le pare-chocs attrape le pied de chaise noir, la vitre, et l’objet à la mauvaise hauteur.

Mesurer votre propre rebond

// Count transitions in the 20 ms after the first edge. Run it, press the switch,
// read the number. That number is your debounce window, in your robot, with your wiring.
void loop() {
  if (digitalRead(BUMP_L) == HIGH) return;
  unsigned long start = micros();
  int last = LOW, edges = 0;
  while (micros() - start < 20000) {
    int now = digitalRead(BUMP_L);
    if (now != last) { edges++; last = now; lastEdgeAt = micros(); }
  }
  Serial.print(edges); Serial.print(" edges, settled after ");
  Serial.print(lastEdgeAt - start); Serial.println(" us");
  delay(500);
}

Réglez la fenêtre au temps d’établissement mesuré, plus environ 50 %. Remesurez quand l’interrupteur vieillit — les contacts empirent, jamais l’inverse.

Quand ça tourne mal

Symptôme Généralement
Un choc compté plusieurs fois Pas d’anti-rebond, ou fenêtre plus courte que le rebond
Chocs manqués entièrement Appel bloquant quelque part ; la boucle ne regardait pas
Le robot recule au hasard Long fil de pare-chocs non blindé près du pilote moteur
Signale une collision permanente Fil coupé sur contact normalement fermé, ou pas de rappel
Ne détecte que les chocs frontaux Coque de pare-chocs trop plate — enveloppez les coins
L’interrupteur cesse de marcher après une semaine Le corps d’interrupteur a pris l’impact au lieu d’une butée
Détecte le mur mais pas le pied de chaise Rien de faux à l’interrupteur ; la coque a un trou

Pour la place d’un pare-chocs dans un robot entier, le robot de couverture de pièce est construit sur deux d’entre eux et rien d’autre — et le simulateur de couverture montre exactement jusqu’où va un robot avec un bit de détection.

Explorer le graphe

Fait partie de ces réalisations

Les projets et parcours d'apprentissage qui incluent ce tutoriel.

Pour aller plus loin

Références