Tutorial · Einsteiger · 25 Min.

Bumper-Sensoren und Entprellen bei Roboterkollision

Ein Schalter, der schließt, erzeugt neun Flanken. Wie Prellen einen Interrupt täuscht, was ein Entprellfenster kostet und wie man einen Bumper baut, der hält.

Ein Schalter ist keine saubere Flanke

Drücke einen Hebel-Mikroschalter, und der Metallkontakt trifft auf, federt zurück, trennt sich und trifft wieder auf – mehrmals in den ersten Millisekunden, bevor er sich setzt. Das ist Kontaktprellen, und es ist mechanisch: Keine Software davor und kein Kondensator dahinter bringen das Metall zum Stillstand.

Die Konsequenz zählt nur, weil der Pin von etwas weit Schnellerem als dem Metall gelesen wird. Ein mit 16 MHz abtastender Mikrocontroller sieht jede dieser Flanken als echte Flanke.

Zwei gestapelte Diagramme. Das obere zeigt ein Schaltsignal über etwa sechs Millisekunden: Der rohe Pin fällt auf Low, prellt dann neunmal zwischen High und Low über 4,7 Millisekunden, bevor er sich auf Low setzt, während der entprellte Ausgang bis zum Fensterablauf auf High bleibt und dann sauber fällt. Das untere Diagramm zeigt die Kantenzahl, die ein Interrupt zählen würde, stufenförmig fallend von neun auf eins, während das Entprellfenster von null auf acht Millisekunden wächst, mit eins ab 4,7 Millisekunden.
Ein Tastendruck eines modellierten Hebelschalters: neun Flanken über 4,7 ms. Ein kürzeres Entprellfenster als das Prellen zählt das Prellen mit – und ein Fenster lang genug zum Setzen kostet genau seine eigene Länge an Latenz, was der Kompromiss ist, den niemand erwähnt. SVG herunterladen

Das untere Panel ist die Designkurve. Die Kantenzahl fällt stufenweise mit wachsendem Fenster, trifft bei Prellende auf eins und bleibt dort. Kürzer zählt über; länger ist Latenz, für die du umsonst gezahlt hast.

Typische Prellzeiten, lieber messen als glauben:

Schalter Prellen
Guter Hebel-Mikroschalter 0,5–2 ms
Billiger Taster 2–10 ms
Reedschalter 0,1–1 ms
Relaiskontakt 1–20 ms

Die übliche „5 ms reichen“-Weisheit rät die Mitte dieser Tabelle. Miss deinen: Es ist eine Codezeile und macht aus Aberglauben eine Zahl.

Verdrahtung, bevor das alles zählt

Ein Bumperschalter will Schließerkontakte nach Masse, mit hochgezogenem Pin:

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

Drei Gründe für diese statt die andere Anordnung:

  • Active-Low fällt sicher aus. Ein gebrochener Draht liest HIGH, also nicht gedrückt, ein abgerissener Bumperdraht lässt den Roboter also nicht glauben, er kollidiere dauerhaft. Eine Pull-down-Anordnung fällt andersherum aus.
  • Der interne Pull-up ist gratis. Kein Widerstand, kein Extrateil an einem Roboter, dessen Front wiederholt getroffen wird.
  • Störungen werden abgeleitet, nicht gesammelt. Ein langer Bumperdraht ist eine Antenne; der niederohmige Pfad nach Masse im geschlossenen Zustand hindert ihn, den Motortreiber daneben aufzuschnappen.

Nutze stattdessen den Öffner-Kontakt des Schalters, bekommst du das umgekehrte Ausfallverhalten – ein gebrochener Draht wirkt wie Dauerkollision, was die richtige Wahl für einen Not-Aus und die falsche für einen Bumper ist.

Entprellen: wähle eines von drei

Nach-Annahme-ignorieren. Das faule, und korrekt für einen Bumper. Akzeptiere die erste Flanke sofort, schaue dann für das Fenster nicht mehr hin:

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;
}

Null Latenz auf der Flanke, die zählt, und das Prellen wird dahinter verworfen. Genau das willst du, wenn die Reaktion Motoren stoppen heißt – 6 ms Warten auf Sicherheit sind 6 ms Fahren in die Möbel.

Warten-auf-stabil. Der Ansatz des Arduino-Beispiels: Merke, wann sich der Messwert zuletzt änderte, akzeptiere ihn erst, wenn er für das Fenster stillstand. Kostet das volle Fenster an Latenz und ist die richtige Form für einen Menüknopf, wo ein Fehldruck schlimmer ist als ein langsamer.

Hardware. Ein 100-nF-Kondensator über den Kontakten plus Pull-up ergibt mit 100-kΩ-internem Pull-up etwa 10 ms RC – aber die erzeugte Flanke ist langsam, und eine langsame Flanke in einen Digitaleingang kann durch die Schwelle oszillieren. Gehst du diesen Weg, folge ihm mit einem Schmitt-Trigger-Eingang. Meist die Bauteile nicht wert.

Beachte, was alle drei gemeinsam haben: Sie sind nicht blockierend. Ein delay(20) nach der Flanke entprellt perfekt und hindert den Roboter 20 ms lang, sonst etwas zu lesen – bei 0,3 m/s sind das 6 mm Blindfahrt –, siehe Timing mit millis().

Interrupts und Prellen sind ein schlechtes Paar

Einen Interrupt an einen Bumper zu hängen wirkt offensichtlich richtig und ist es meist nicht.

Neun Flanken heißen, die ISR feuert neunmal. Zählt sie einen Zähler hoch, hast du nun neun Kollisionen; setzt sie ein Flag, hast du eine, harmlos. Nutze einen Interrupt nur, wenn der Handler idempotent ist – ein Flag setzen, einen Zeitstempel nehmen –, niemals wenn er zählt.

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() läuft in einer ISR auf AVR nicht weiter, was das für die Dauer eines Prellens sicher, für alles Längere aber falsch macht – nutze micros(), wenn das Fenster präzise zählt.

Ehrlich: Für einen Bumper brauchst du den Interrupt selten überhaupt. Eine mit 200 Hz laufende Schleife bemerkt eine Kollision innerhalb von 5 ms, und der Roboter fährt in dieser Zeit 1,5 mm. Frage ihn ab und spendiere die Interruptpins den Encodern, die wirklich nicht abfragbar sind.

Einen Bumper bauen, der funktioniert

Der Schalter ist die leichte Hälfte. Der Mechanismus davor entscheidet, ob der Roboter ein schräg getroffenes Stuhlbein erkennt.

  • Eine bewegliche Schale, zwei Schalter. Eine einzelne Frontplatte an zwei Biegepunkten, dahinter je ein Schalter pro Seite. Nur linker Schalter heißt Hindernis links – die Information, die das Ausweichverhalten braucht, um die Drehrichtung zu wählen.
  • Wickle ihn um die Ecken. Ein flacher Frontbumper verpasst alles, was mit mehr als etwa 30° getroffen wird, und Streiftreffer sind die meisten. Führe die Schale auf jeder Seite mindestens bis 45°.
  • Federn stellen zurück, Schalter nicht. Die Eigenfeder eines Mikroschalters ist 50–100 g und drückt keine Schale zuverlässig zurück. Nutze Gummibänder oder leichte Druckfedern und lass den Schalter nur wahrnehmen.
  • Gib ihm Weg und einen harten Anschlag. 3–5 mm Bewegung vor dem Schalten und ein Anschlag, der den Aufprall nimmt statt des Schaltergehäuses. Schaltergehäuse sind das, was bricht.
  • Paare ihn mit etwas Berührungslosem. Ein Bumper ist letzte Zuflucht – er meldet eine bereits geschehene Kollision. Ein Ultraschall- oder Time-of-Flight-Sensor davor vermeidet die meisten davon; der Bumper fängt das schwarze Stuhlbein, das Glas und das Ding in falscher Höhe.

Eigenes Prellen messen

// 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);
}

Setze das Fenster auf die gemessene Beruhigungszeit plus etwa 50 %. Miss neu, wenn der Schalter alt ist – Kontakte werden schlechter, nicht besser.

Wenn es schiefgeht

Symptom Meistens
Ein Bumper zählt als mehrere Kein Entprellen oder Fenster kürzer als das Prellen
Bumper werden ganz verpasst Irgendwo ein blockierender Aufruf; die Schleife schaute nicht hin
Roboter fährt zufällig rückwärts Langer ungeschirmter Bumperdraht neben dem Motortreiber
Meldet Dauerkollision Gebrochener Draht am Öffnerkontakt oder kein Pull-up
Erkennt nur frontale Treffer Bumperschale zu flach – um die Ecken wickeln
Schalter stirbt nach einer Woche Das Schaltergehäuse nahm den Aufprall statt eines Anschlags
Erkennt die Wand, aber nicht das Stuhlbein Nichts falsch am Schalter; die Schale hat eine Lücke

Wo ein Bumper im ganzen Roboter sitzt: Der Raum-Abdeckungsroboter baut auf zwei davon und sonst nichts – und der Abdeckungssimulator zeigt genau, wie weit ein Roboter mit einem Bit Wahrnehmung kommt.

Den Graphen erkunden

Teil dieser Bauprojekte

Projekte und Lernpfade, die dieses Tutorial enthalten.

Weiterführende Literatur

Quellen