0 Die beiden Sensoren einzeln: wie sie funktionieren und was jeder sieht
Bevor es um das Zusammenspiel geht, ein Blick auf die zwei Bauteile selbst. Beide sind Silizium-PIN-Fotodioden von Vishay mit gleich großem Chip (7,5 mm² lichtempfindliche Fläche) und fast gleichen elektrischen Daten. Der entscheidende Unterschied steckt im Gehäuse: Der BPW34 sitzt in klarem Kunststoff, der BPW41N in schwarzem Kunststoff, der als Tageslichtsperrfilter wirkt.
0a So wird aus Licht ein Messwert
- Ein Photon trifft den Chip. Licht besteht aus Energiepaketen (Photonen). Je kürzer die Wellenlänge, desto mehr Energie trägt ein Photon.
- Reicht die Energie, wird ein Elektron frei. Silizium braucht dafür mindestens 1,12 eV (Bandlücke). Das entspricht einer Wellenlänge von höchstens etwa 1100 nm (λ = 1240 nm·eV / 1,12 eV ≈ 1107 nm). Längerwelliges Licht geht durch den Chip, ohne etwas auszulösen.
- Das Feld trennt die Ladungen. Zwischen p- und n-Schicht liegt eine breite, fast undotierte Zone (i = intrinsisch, daher "PIN"). Dort zieht ein elektrisches Feld Elektron und Loch in entgegengesetzte Richtungen, bevor sie wieder zusammenfinden. Eine Sperrspannung (im Datenblatt 5 V) verbreitert die Zone und macht die Diode schneller.
- Es fließt ein Fotostrom. Jedes getrennte Paar schiebt eine Elementarladung durch den äußeren Stromkreis. Der Strom ist deshalb proportional zur einfallenden Lichtleistung, über viele Größenordnungen linear. Er ist klein: Mikroampere.
- Verstärker und ADC machen daraus Zahlen. Ein Verstärker wandelt den Strom in eine Spannung (typisch ein Transimpedanzverstärker: Spannung = Strom · Rückkopplungswiderstand, etwa 1 µA · 1 MΩ = 1 V), der Analog-Digital-Wandler daraus Zählwerte. Im Modell reicht die Skala bis 4095 (12 bit). Die echte Schaltung für Löschi ist noch nicht festgelegt.
Datenblatt, E = 1 mW/cm² bei 950 nm, 5 V Sperrspannung: BPW41N ca. 45 µA, BPW34 ca. 50 µA
Ganz ohne Licht (Dunkelstrom): ca. 2 nA, also gut 20 000-mal weniger
Schnell genug fürs Flackern. Mit 100 ns Anstiegszeit folgen beide Dioden jeder Helligkeitsänderung praktisch sofort. Das Flackern einer Kerze (im Modell 11 Hz) ist für sie langsam; begrenzend sind erst Verstärker und Abtastung (Modell: eine Messung alle 20 ms, also 50 pro Sekunde, das reicht bis 25 Hz).
0b Die Datenblätter nebeneinander
| Merkmal | BPW41N (IR-Sensor) | BPW34 (sichtbar + IR) |
|---|---|---|
| Gehäuse | schwarz, Licht von der Seite (side view) | klar, Licht von oben (top view) |
| Filter | Tageslichtsperrfilter, abgestimmt auf IR-Sender mit 900 bis 950 nm | keiner |
| Empfindlich von ... bis | 870 bis 1050 nm (50-%-Grenzen) | 430 bis 1100 nm (10-%-Grenzen) |
| Empfindlichkeitsmaximum | 950 nm | 900 nm |
| Lichtempfindliche Fläche | 7,5 mm² | 7,5 mm² |
| Halber Öffnungswinkel (ohne Blende) | ±65° | ±65° |
| Fotostrom bei 1 mW/cm², 950 nm, 5 V | 45 µA | 50 µA |
| Fotostrom bei 1 klx Beleuchtungsstärke, 5 V | nicht angegeben | 75 µA |
| Dunkelstrom (10 V) | 2 nA | 2 nA |
| Anstiegs- und Abfallzeit | 100 ns | 100 ns |
Laut Datenblatt liegt sein Empfindlichkeitsmaximum bei 900 nm, also selbst im nahen Infrarot. Er sieht alles, was der BPW41N sieht, und zusätzlich das sichtbare Licht. Roh gemessen liefert der BPW34 darum bei fast jeder Lichtquelle mehr Strom als der BPW41N. Ein brauchbares Verhältnis "IR zu sichtbar" entsteht erst, wenn man die Kanäle gegeneinander abgleicht (zum Beispiel so, dass Sonnenlicht das Verhältnis 1 ergibt) oder vom BPW34-Wert den IR-Anteil abzieht. Das Modell rechnet gleich mit abgeglichenen Kanälen (Umgebungslicht trifft beide gleich, Abschnitt 3). Eine Alternative wäre ein IR-Sperrfilter vor dem BPW34; das ist nicht entschieden und gehört auf den Sensor-Prüfstand (Gantt Nr. 21).
0c Was jeder Sensor für sich allein sieht
Jede Diode liefert genau eine Zahl: die Summe allen Lichts, das auf sie fällt, gewichtet mit ihrer Empfindlichkeitskurve. Sie liefert kein Bild, keine Farbe, keinen Abstand und ohne Blende nicht einmal eine brauchbare Richtung (±65° halber Öffnungswinkel; erst der Schlitzkollimator aus Abschnitt 2 macht daraus ±3°). Ob die Zahl groß ist, weil eine Kerze nah ist oder weil Sonne hineinscheint, kann eine Diode allein nicht sagen.
| Lichtquelle | BPW41N allein | BPW34 allein |
|---|---|---|
| Kerzenflamme | stark: eine Flamme strahlt im Bereich bis 1100 nm deutlich mehr nahes IR als sichtbares Licht | deutlich: dasselbe IR plus das gelbe Licht |
| Sonne direkt, Sonnenreflex | sehr stark: Sonnenlicht enthält viel nahes IR, der Filter sperrt nur den sichtbaren Teil | sehr stark, übersteuert am ehesten |
| Heller Himmel, Schatten, diffuses Tageslicht | schwach bis mittel (Himmelslicht ist blau-lastig) | mittel bis stark |
| Glitzern (Wasser, Metall, Folie) | kurze helle Blitze | kurze helle Blitze |
| Weiße LED-Lampen, Bildschirme | fast nichts: weiße LEDs strahlen kaum über 780 nm | ja, wie ein normaler Helligkeitssensor |
| Leuchtstoffröhren | fast nichts | ja, mit 100-Hz-Flimmern (doppelte Netzfrequenz) |
| Glühlampe, Halogenstrahler | stark: der heiße Draht (ca. 2700 bis 3000 K) strahlt viel nahes IR | stark |
| IR-Fernbedienung, IR-Licht einer Überwachungskamera (ca. 940 nm) | stark: genau dafür ist er gebaut | ja, 940 nm liegt in seinem Bereich |
| Warme Gegenstände: Hand, Motor, sonnenwarmer Stein | nichts | nichts |
| Dunkelheit | nur Dunkelstrom (ca. 2 nA) und Rauschen | dasselbe |
Die Zeile "warme Gegenstände" ist wichtig für das Verständnis: Ein 30 °C warmer Körper strahlt um 10 000 nm, weit jenseits der Silizium-Grenze. Fotodioden sehen keine Wärme, sondern nur sehr heiße Strahler (Flamme, Glühdraht, Sonne). Wärme sieht ein Wärmebildsensor wie AMG8833 oder MLX90640, der nach einem anderen Prinzip arbeitet.
Vishay-Datenblätter BPW41N (Dokument 81522, Rev. 1.6) und BPW34 (Dokument 81521, Rev. 2.1), abgerufen am 30.10.2026 von vishay.com; Bandlücke Silizium 1,12 eV (Lehrbuchwert). Die Tabelle "Was jeder Sensor allein sieht" ist eine eigene Einschätzung aus den Empfindlichkeitsbereichen, keine Messung.
1 Überblick in einem Bild
Die Erkennung ist eine Kette. Jedes Glied beantwortet eine einfache Frage, und erst die ganze Kette macht aus Licht eine Zielrichtung. Die Kästen (Schritte A bis H) sind anklickbar und springen zum passenden Abschnitt.
fsm.js: makeSample(), findCandidates(), stVERIFY(), acquire(); sensors.js: sampleEye(), flickerFlag(). Die Zeiten stammen aus PDEF (SCAN_RATE 60°/s) und den Konstanten in stVERIFY() (0,4 s Ruhe, 0,3 s Messzeit).
2 Wo sitzt das Sensorpaar?
Das Paar sitzt im Inneren der Kuppel, 73 mm von der Kuppelachse entfernt (EYE_R) und 95 mm über dem Boden (EYE_Z). Es schaut radial nach außen und dreht mit der Kuppel mit. Vor den Dioden steht ein Schlitzkollimator, eine schmale Blende, die nur Licht aus einem engen Winkelbereich durchlässt: waagerecht nur ±3° (HALF_AZ), senkrecht dagegen ±12,5° (HALF_EL). Das untere Paar ist waagerecht ausgerichtet (Neigungswinkel 0°).
Warum so schmal? Mit der schmalen Keule ist die Richtung sofort klar: Sieht der Sensor etwas, liegt die Flamme innerhalb von etwa ±3° vor ihm. Die große senkrechte Öffnung sorgt dafür, dass Kerzen in unterschiedlicher Höhe überhaupt in die Keule fallen.
Seitenansicht maßstabsgetreu (x und z gleich skaliert). Die Flammenhöhen 87,5 / 135 / 215 mm und Podesthöhen 70 / 120 / 200 mm sind G.FLAMES und G.PODESTS in geom.js; die Abstände 0,3 / 0,5 / 0,7 m sind nur Beispiele für die Zeichnung.
VEH in field.js.So sieht es in der Simulation aus: Die orange Keule ist die Sichtkeule des Sensorpaars (Schalter "Sensorkegel" in der Sim, standardmäßig an). Violett und blau sind die Ultraschall-Sensoren, die hier nicht interessieren.
sensors.js: P.EYE_R 73, P.EYE_Z 95, P.HALF_AZ 3, P.HALF_EL 12,5, eyeView(); Kuppelbereich ±90° aus servos() in sim.js (F.clamp(cmd.domeAz, -90, 90)).
3 Warum zwei Sensoren (IR und sichtbar)?
Ein einzelner Helligkeitssensor kann Flamme und Sonne nicht unterscheiden: Beide machen ihn heller. Der Trick ist das Verhältnis zweier Kanäle mit verschiedener Empfindlichkeit.
- Der IR-Sensor BPW41N ist eine Fotodiode mit Tageslichtsperrfilter. Er misst vor allem nahes Infrarot.
- Der Sensor BPW34 daneben ist breitbandig; im Modell ist er der Kanal für sichtbares Licht (VIS).
- Eine Kerzenflamme (etwa 1900 K) strahlt relativ viel mehr nahes Infrarot als sichtbares Licht ab. Das Modell setzt NIR / VIS = 4 für die Flamme (
NIR_VIS). - Sonnen- und Hallenlicht treffen beide Kanäle im Modell etwa gleich (Verhältnis um 1; die Kanäle weichen pro Lauf um ±3 % ab,
nirGain).
Qualitative Skizze, keine Messung. Die Kurven sind Planck-Strahler (Formel der Wärmestrahlung) mit 1900 K und 5800 K, jeweils auf ihr Maximum normiert. Die farbigen Streifen zeigen schematisch, wo die beiden Dioden empfindlich sind; die echten Kurven stehen im Datenblatt und wurden hier nicht eingezeichnet. Silizium-Dioden sehen nur bis etwa 1100 nm.
sensors.js: P.NIR_VIS, sampleEye() (Umgebungslicht amb auf beiden Kanälen, nirGain aus hidden); Bausteinliste 2026-10-24_Funktionsentscheidungen_Bausteine.md (Entscheidung F6: BPW41N + BPW34 je Sensorpaar). Das Spektrum-Diagramm und die Plausibilitätsrechnung sind eigene Überlegungen.
4 Das Signalmodell
Das Modell berechnet für jede Messung, wie viel Licht der Flamme auf jede Diode fällt. Die Formel steht in eyeView() und besteht aus fünf Faktoren:
NIR = S + Umgebung_NIR + Rauschen
VIS = S / 4 + Umgebung_VIS + Rauschen
- K = 225 Zählwerte: Signal einer Flamme in 1 m Abstand, genau auf der Achse. kRun = 1 ± 0,1 ist ein Zufallsfaktor je Lauf (Modellannahme: "jeder Lauf variiert ±10 %").
- prof(u) = cos²(π·u / 2) für |u| < 1, sonst 0. Das ist die Keulenform; u ist der Winkel geteilt durch die Halbbreite (3° waagerecht, 12,5° senkrecht).
- d = Abstand Sensor bis Flamme in Metern; das Signal fällt mit 1/d².
- Flackern = 1 + 0,30 · sin(2π · 11 Hz · t + Phase) + weißes Rauschen (Anteil 0,06). Es wirkt nur auf die Flamme, nicht auf das Umgebungslicht.
- Umgebung je Kanal = 4,5 Zählwerte (Halle) + 15 Zählwerte bei voller Sonne. Rauschen je Kanal: Standardabweichung 1,0 + 0,06 · Pegel.
Beispiel mit Zahlen. Kerze in 1 m auf der Achse (niedrig, Flackern 1, kRun 1): S = 225 · 1 · 1 / 1² = 225. Der NIR-Kanal bekommt 225, der VIS-Kanal 225 / 4 = 56,25. In 2 m: S = 225 / 4 = 56,25 und VIS-Anteil 14,1. In 3 m: S = 25 und VIS-Anteil 6,25.
4a Die Keulenform
Das cos²-Profil fällt weich auf null ab: Bei der Hälfte der Halbbreite ist das Signal auf die Hälfte gesunken. Waagerecht heißt das: 1,5° neben der Achse nur noch 50 %, bei 3° gar nichts mehr. Der Suchschwenk muss deshalb die Flamme mit einer sehr schmalen Keule "erwischen".
Oben: waagerecht (HALF_AZ = 3°). Unten bzw. rechts: senkrecht (HALF_EL = 12,5°). Der gelbliche Streifen ist der Bereich oberhalb der halben Leistung. Formel prof() in sensors.js.
4b Signal über den Abstand
Die durchgezogene Linie ist das reine Flammensignal im NIR-Kanal, die gestrichelte das im VIS-Kanal. Das Umgebungslicht ist eine waagerechte Linie mit Rauschband (±3 Standardabweichungen). Solange die Flammenlinien weit über der Umgebungslinie liegen, ist die Flamme gut zu sehen; wo sich VIS-Flamme und Umgebung nähern, verschwindet der Verhältnis-Vorsprung.
Logarithmische Achse. Nach rechts bis 5,5 m gezeichnet, damit die rauschfreie Grenze der Halle (siehe 5) sichtbar wird. Formeln aus eyeView(), Umgebung aus create() in sensors.js (A_HALL, A_SUN, NOISE0, NOISE_REL).
4c Die Höhe der Flamme zählt auch
Das untere Paar schaut waagerecht. Eine hohe Flamme liegt je nach Abstand schon außerhalb der senkrechten Keule: In 0,5 m Abstand erscheint die hohe Flamme (215 mm, also 120 mm über der Sensorhöhe) unter einem Neigungswinkel von 13,5° und damit hinter der Nullstelle bei 12,5°. Dafür gibt es das zweite, 15° höher geneigte Paar, das hier ausgeklammert ist.
Neigungswinkel = atan2(Flammenhöhe - 95 mm, Abstand); Faktor = prof(Neigungswinkel / 12,5°). Die hohe Flamme (215 mm) ist unterhalb von etwa 0,55 m für dieses Paar unsichtbar (Faktor 0). Hidden-Versatz eyeEl (±0,5° je Lauf) hier weggelassen.
| Größe | Wert | Fundstelle im Code (Modellannahme, nicht gemessen) |
|---|---|---|
| Position Sensorpaar | 73 mm / 95 mm | sensors.js, P.EYE_R, P.EYE_Z |
| Halbbreite waagerecht / senkrecht | 3° / 12,5° | sensors.js, P.HALF_AZ, P.HALF_EL |
| Flammensignal in 1 m | 225 Zählwerte | sensors.js, P.K |
| NIR / VIS der Flamme | 4 | sensors.js, P.NIR_VIS |
| Umgebung Halle / zusätzlich Sonne | 4,5 / 15 | sensors.js, P.A_HALL, P.A_SUN |
| Rauschen (Standardabweichung) | 1,0 + 0,06 · Pegel | sensors.js, P.NOISE0, P.NOISE_REL |
| Flackern | 11 Hz, Tiefe 0,30, Weiß 0,06 | sensors.js, P.FLICK_HZ, FLICK_DEPTH, FLICK_WHITE |
| kRun, Achsversatz, Verstärkungsabweichung | ±10 %, ±0,4° / ±0,5°, ±3 % | sensors.js, hidden in create() (kRun, eyeAz, eyeEl, nirGain) |
| Messtakt | 20 ms | sensors.js, S.update(): tick % 2 bei DT = 10 ms |
5 Entscheidung pro Messung
Aus jeder Messung (NIR, VIS) rechnet die Steuerung drei Größen aus und prüft sie gegen eine Schwelle. Nur wenn alle drei erfüllt sind, zählt die Messung als Treffer (im Code det):
- Verhältnis NIR / max(VIS, 0,5) > 1,7. Das ist der Flammen-Test: Sonne liegt bei etwa 1, Flamme deutlich darüber.
- Summe NIR + VIS > 20. Zu wenig Licht heißt: nichts Verlässliches, sonst würde das Rauschen bei kleinen Werten ein Verhältnis vortäuschen.
- D = NIR - VIS > 6. Der NIR-Überschuss muss absolut spürbar sein, nicht nur relativ.
fsm.js: makeSample() (det = ratio > RATIO_MIN && sum > SUM_MIN && D > D_MIN), PDEF: RATIO_MIN 1,7, SUM_MIN 20, D_MIN 6; Verhältnis in sensors.js sampleEye(): n / Math.max(v, 0.5). Abweichung zur Ein-Paar-Sicht: Der Code nimmt je Messung das bessere der beiden Paare (das mit dem größeren D); hier gibt es nur das untere.
Beispielrechnungen (ohne Zufall, kRun 1, Flackern 1, Flamme auf der Achse)
| Fall | NIR | VIS | Verhältnis | Summe | D | Ergebnis |
|---|---|---|---|---|---|---|
| Kerze 1 m, Halle | 229,5 | 60,8 | 3,78 | 290 | 168,8 | Treffer |
| Kerze 2 m, volle Sonne | 75,8 | 33,6 | 2,26 | 109 | 42,2 | Treffer |
| Kerze 3,5 m, volle Sonne | 37,9 | 24,1 | 1,57 | 62 | 13,8 | kein Treffer (Verhältnis) |
| keine Flamme, volle Sonne | 19,5 | 19,5 | 1,00 | 39 | 0 | kein Treffer (Verhältnis, D) |
Rechenweg Zeile 3: S = 225 / 3,5² = 18,4; NIR = 18,4 + 19,5 = 37,9; VIS = 18,4 / 4 + 19,5 = 24,1; Verhältnis 37,9 / 24,1 = 1,57. Es fehlt nicht Licht, sondern der relative Vorsprung: Die Sonne macht den Kanal-Vergleich unscharf.
Widget: Erkennung ausprobieren
Stelle Abstand, Sonne und seitliche Abweichung ein. Die Formeln sind dieselben wie im Code, mit Neigungswinkel der gewählten Flammenhöhe. Mit "Messwert würfeln" kommt Rauschen und Flackern dazu; "100 Messungen" zeigt, wie oft die Entscheidung unter Zufall "Flamme" ergibt.
- Fahre bei 0 % Sonne den Abstand hoch: Wo kippt die Summe unter 20? (Rauschfrei bei etwa 5,1 m.)
- Setze die Sonne auf 100 %: Jetzt kippt zuerst das Verhältnis, bei etwa 3,1 m.
- Verschiebe die Flamme seitlich auf 1,5°: Das Signal halbiert sich. Bei 3° ist es null.
- Wähle "hoch" und gehe unter 0,55 m: Die Flamme verschwindet in der senkrechten Keule.
Rauschfreie Grenzen: eigene Rechnung mit diesen Formeln, nirGain = 1, kRun = 1, Flackern = 1. Hall: Summe > 20 greift bei S < 8,8, also d > 5,06 m. Sonne: Verhältnis > 1,7 braucht S > 1,217 · 19,5 = 23,7, also d < 3,08 m.
6 Der Suchschwenk
Die Kuppel schwenkt im Stand von -90° bis +90° mit 60°/s (SCAN_RATE). In dieser Zeit läuft alle 20 ms eine Messung; das sind 1,2° Kuppelwinkel pro Messung. Die Keule ist nur ±3° breit (Halbwertsbreite 3°), also fallen nur wenige Messungen auf die Flamme. Die Steuerung sucht deshalb nach Clustern: mindestens zwei Treffer in Folge (eine Lücke von höchstens einer Messung ist erlaubt); der gewichtete Schwerpunkt der Treffer (Gewicht = D) ist der Schwenkwinkel des Kandidaten.
Die folgenden Kurven sind echte Läufe des Sensormodells: Seed 38, kRun = 1,015, Kerze niedrig (87,5 mm) bei +25° links, Schwenk -90° bis +90° mit 60°/s. Die Kerze steht einmal 1 m und einmal 2 m vom Sensor entfernt, jeweils in der Halle und in voller Sonne.
Ganzer Schwenk, Kerze in 1 m
Links Halle (Umgebung 4,5), rechts volle Sonne (Umgebung 19,5). Orange Punkte NIR, blaue Quadrate VIS (auf den Messwert-Rand begrenzt). Außerhalb der Flamme liegen beide Kanäle auf dem Umgebungspegel: Eine Flamme ist ein schmaler Ausschlag auf einer flachen Linie. Der grüne Strich ist der Schwerpunkt des Clusters. Die zusätzlichen schmalen Ausschläge (Halle bei +52°, Sonne bei -65°) sind Glitzerpulse des Modells, je 2 Messungen lang. Ihr Verhältnis liegt hier unter 1,7 (1,6 und 1,2 bis 1,3), deshalb sind es keine Treffer; Abschnitt 7 zeigt, was passiert, wenn es einmal darüber liegt.
Vergrößert um die Flamme
Von links oben nach rechts unten: 1 m Halle, 1 m Sonne, 2 m Halle, 2 m Sonne. Punkte sind die echten Messungen (NIR orange, VIS blau); grüne Ringe markieren Treffer; gestrichelt das rauschfreie Modell ohne Flackern (Flamme plus Umgebung). Dass die Punkte um die Kurve streuen, liegt am Flackern (±30 %) und am Rauschen.
| Lauf | Treffer | Schwerpunkt | Spitze von D |
|---|---|---|---|
| 1 m, Halle | 4 von 150 | 25,09° | 122 |
| 1 m, Sonne | 4 von 150 | 24,98° | 118 |
| 2 m, Halle | 3 von 150 | 25,20° | 32 |
| 2 m, Sonne | 2 von 150 | 24,61° | 32 |
Die Flamme liegt in dieser Aufstellung bei 25,05° Kuppelwinkel auf der Sensorachse; der Schwerpunkt trifft sie auf einige Zehntelgrad. Die Spitze von D ist kleiner als der Idealwert 0,75 · 225 = 169 (1 m), weil die Messungen selten genau auf den Gipfel treffen und das Flackern gerade ein Tal erwischen kann. Das schlägt direkt auf die Entfernungsschätzung durch (Abschnitt 8).
So sieht der Schwenk in der Simulation aus
Die Karte "Was Löschi sieht" der Sim zeigt den letzten Suchschwenk als Polarplot (oben = geradeaus, links = Kuppel +). Die orange Kurve ist die NIR-Summe, die blaue gestrichelte das Verhältnis, grüne Punkte sind Treffer. Hinweis: Der Polarplot der Sim summiert beide Kanalpaare; mit dem hier betrachteten unteren Paar allein sieht die Kurve für eine niedrige Flamme praktisch gleich aus.
Wie weit reicht ein Schwenk?
Wir haben die Frage mit dem Modell durchgespielt: Kerze (niedrig, +25°) im Abstand d, voller Schwenk, 60 verschiedene Zufallsläufe (Seeds 1 bis 60) je Abstand und Beleuchtung. Gezählt wird, ob ein Cluster innerhalb von 4° um die wahre Richtung entsteht.
Eigene Auswertung mit dem Sensormodell (gen.js), nur unteres Paar. Orange = Halle, blau gestrichelt = volle Sonne. Die senkrechten Linien sind die rauschfreien Grenzen aus Abschnitt 5.
Ergebnis: In der Halle findet der Schwenk die Kerze noch in 4 m Abstand in 68 % der Läufe (im untersuchten Bereich bis 4 m sinkt die Trefferquote nie unter 50 %), in voller Sonne in der Hälfte der Läufe nur bis etwa 2,7 m. In 3 m Abstand sind es in der Sonne nur noch 27 % der Läufe.
Was die Steuerung selbst annimmt. Nach dem ersten Schwenk misst sie das Hintergrundlicht als Median des VIS-Kanals über den Schwenk (measureBackground()) und rechnet daraus eine Suchreichweite für ihre Planung: r = 1875 mm · sqrt(4,5 / Hintergrund), begrenzt auf 700 bis 2000 mm. Im Log der Sim steht das z. B. als "Hintergrundlicht 20,1 Zähler: rechne mit 0,9 m Suchreichweite" (Sonne) gegen "Hintergrundlicht 4,9 Zähler: rechne mit 1,8 m" (Halle). Diese Planungsreichweite liegt deutlich unter der Detektionsgrenze des Modells. Warum sie so konservativ gewählt wurde, steht im Code nicht; ich vermute einen Sicherheitsabstand (Vermutung, nicht belegt).
fsm.js: sweepStart(), sweepTick() (Winkelschritt rate · dtk mit dtk = 20 ms), findCandidates() (Gewicht Math.max(1, s.dLo + s.dUp), Lücke gap > 1 beendet den Cluster, cur.n >= 2), measureBackground(), PDEF: SCAN_RATE, COV_R0 1875, COV_BG0 4,5, COV_RMIN 700, COV_RMAX 2000. Abweichung: Im Code sind D und Gewicht Summen beider Paare (dLo + dUp); für eine niedrige Flamme trägt das obere Paar praktisch nichts bei.
7 Bestätigen per Flackern
Ein Kandidat ist noch keine Flamme. Jetzt fährt die Kuppel auf den Schwenkwinkel des Kandidaten, wartet 0,4 s (Kuppel zur Ruhe kommen lassen) und misst dann mindestens 0,3 s lang im Stand. Dabei zählt die Steuerung, wie viele der Messungen Treffer sind, und fragt zusätzlich, ob das Signal flackert.
Die Flamme einer Kerze flackert, im Modell mit etwa 11 Hz und ±30 % Tiefe. Sonne, Hallenlicht und Glitzer (kurze Spiegelreflexe) tun das nicht. Der Flackertest ist ein Sinus-Fit auf die letzten 15 Messungen (0,3 s): x(t) = c + a·sin(ωt) + b·cos(ωt) mit ω = 2π · 11 Hz. Das Flackern gilt als erkannt, wenn alle drei Bedingungen stimmen:
- Mittelwert c > 8 (genug Signal),
- Amplitude / c ≥ 0,06 (relative Flackertiefe),
- Amplitude / max(σ, 0,8) ≥ 2,2 (Sinus klar größer als der Restfehler σ des Fits).
Angenommen wird der Kandidat, wenn mindestens 60 % der Messungen Treffer sind und (Flackern in mindestens 30 % der Messungen oder mindestens 90 % Treffer und mittleres D > 15). Sind 60 % erreicht, aber kein Flackern, gibt es einmal eine Wiederholung; sonst steht im Log "Verworfen".
Echte Zeitreihen aus dem Modell
Kuppel steht auf der Flamme (niedrige Kerze), Ausschnitt 0,6 s. Orange Punkte: NIR-Kanal. Der Fit läuft über das letzte Fenster von 0,3 s (blau getönt); die Kurve ist grün, wenn der Test besteht, rot, wenn nicht.
Links: Kerze 1 m, Halle. c = 235, Amplitude/c = 0,28, Amplitude/σ = 4,7; Flackern-Flag: JA. Rechts: Kerze 2 m, Halle. c = 62, Amplitude/c = 0,26, Amplitude/σ = 4,6; Flackern-Flag: JA. Die Zahlen sind aus dem Sinus-Fit über das Fenster, hier für den NIR-Kanal des unteren Paars berechnet (der Code fittet die Summe beider NIR-Kanäle; das Ergebnis ist dasselbe Prinzip, die Zahlen weichen leicht ab).
Ein Fall, in dem es schiefgeht: Kerze 2 m, volle Sonne. Bei t = 0,42 s fällt ein Glitzerpuls (NIR 225, VIS 126) in das Fenster. Der Sinus-Fit hat danach einen großen Restfehler (σ = 47), Amplitude/σ = 0,8 und das Flackern-Flag bleibt aus (c = 93, Amplitude/c = 0,39, Amplitude/σ = 0,8; Flackern-Flag: NEIN). In der Steuerung wiederholt sich der Test in jeder Messung; entscheidend sind die 30 % der Messungen mit Flackern-Flag, ein einzelner Puls verdirbt also nur einen Teil.
Und das Gegenbeispiel: ein Glitzerpuls
Ein Glitzerpuls dauert im Modell 40 ms (GLITTER_LEN), das sind genau 2 Messungen. Er tritt in der Halle im Mittel 0,12-mal pro Sekunde auf, in voller Sonne 0,7-mal pro Sekunde (GLITTER_RATE_HALL, GLITTER_RATE_SUN). Er hebt VIS um (15 + 70 · Zufall) · (1 + 2 · Sonne) Zählwerte an und NIR um denselben Wert mal ein Verhältnis von 1,7 ± 0,4 (GLITTER_RATIO). Das liegt also um die Schwelle 1,7: Mancher Puls erfüllt alle drei Bedingungen und kann im Suchschwenk als Mini-Cluster aus zwei Treffern durchgehen.
Echte Modellreihe (Seed 1, volle Sonne, keine Kerze, Kuppel steht). Der Puls bei t = 0,38 s dauert 2 Messungen: NIR springt auf 521 und VIS auf 270, das Verhältnis liegt mit 1,93 über der Schwelle 1,7 (Treffer). Der Sinus-Fit passt nicht (Amplitude/σ = 0,5), das Flackern-Flag bleibt aus.
Wie oft entsteht ein falscher Kandidat? Mit dem Modell gezählt (200 Läufe, Schwenk ohne Kerze, nur unteres Paar): im Mittel 0,14 falsche Cluster je Schwenk in der Halle und 0,67 in voller Sonne. Ein solcher Kandidat wird beim Bestätigen in der Regel verworfen: Zwei Messungen in 0,3 s sind 13 % und damit weit unter der 60-%-Schwelle, und das Flackern fehlt.
So steht es im Log der Sim (Seed 2, volle Sonne): erst ein verworfener Kandidat bei +40° ("Verhältnis 1,1, Flackern nein, 0 % der Messungen über Schwelle"; vermutlich war der Glitzerpuls schon vorbei, als die Kuppel dort ankam, das Log nennt die Ursache nicht), dann die bestätigte Flamme bei +9°.
sensors.js: flickerFlag() (c > 8 && amp / c >= 0.06 && amp / Math.max(sig, 0.8) >= 2.2), P.FLICK_HZ, P.FLICK_WIN 15, P.FLICK_STILL 0,3 s (Flag nur nach mindestens 0,3 s Ruhe der Kuppel), Glitzer in sampleEye() (P.GLITTER_*); fsm.js: stVERIFY(), beginVerify().
8 Entfernung schätzen
Nach der Bestätigung braucht die Steuerung eine Entfernung, um die Parallaxe (die Kuppelachse liegt 140 mm vor der Hinterachse, das Paar 73 mm daneben) herauszurechnen und die Anfahrt zu planen. Das einzige, was sie hat, ist die Signalstärke S: die Spitze von D im Cluster, oder der mittlere D-Wert der Bestätigung, je nachdem was größer ist. Aus dem 1/d²-Gesetz wird umgekehrt:
Die Konstante 150 ist kleiner als das Idealsignal 0,75 · 225 = 168,75 (D einer Flamme in 1 m): Selbst im Idealfall liegt die Schätzung etwa 6 % zu kurz (r = 943 mm statt 1000 mm).
Links: die Formel mit den Idealwerten bei 1, 2 und 3 m. Rechts: 100 Läufe des Modells je Abstand (Halle, niedrige Kerze, unteres Paar): Punkt = Median, Strich = Bereich von 10 % bis 90 % der Läufe.
| wahrer Abstand | Licht | Flammenhöhe | r 10 % | r Median | r 90 % | Läufe |
|---|---|---|---|---|---|---|
| 1 m | Halle | niedrig | 0,83 | 0,95 | 1,11 | 100 |
| 2 m | Halle | niedrig | 1,67 | 1,89 | 2,19 | 100 |
| 1 m | Halle | mittel | 0,87 | 0,97 | 1,14 | 100 |
| 1 m | Halle | hoch | 1,28 | 1,48 | 1,79 | 100 |
| 2 m | Halle | hoch | 1,83 | 2,08 | 2,50 | 100 |
| 1 m | Sonne | niedrig | 0,82 | 0,94 | 1,09 | 100 |
| 2 m | Sonne | niedrig | 1,61 | 1,85 | 2,20 | 97 |
Geschätzter Abstand r in Metern nach rFromIntensity() aus der Cluster-Spitze von D, nur unteres Paar. Läufe = Anzahl von 100 Seeds, in denen ein Kandidat entstand.
Warum so grob?
- kRun ±10 % ändert S um ±10 % und r damit um etwa ±5 % (die Wurzel halbiert den Fehler).
- Flackern ±30 % hängt an der Messung, die gerade die Spitze ist: Die Spitze kann in einem Tal liegen.
- Gipfel nicht getroffen: Bei 1,2° pro Messung und ±3° Keule liegt die beste Messung bis zu 0,6° neben dem Gipfel.
- Flammenhöhe: Eine hohe Flamme liegt am Rand der senkrechten Keule, das Signal ist dort schwächer. Die Tabelle zeigt es: Bei 1 m gibt das untere Paar für die hohe Flamme im Median etwa 1,5 m, also viel zu weit. Im Code kommt hier das obere Paar dazu (S = dLo + dUp), das diesen Fehler verkleinert; bei diesem einen Paar nicht.
applyPedFix() in fsm.js; hier nicht behandelt). Die Intensitätsschätzung bleibt als Startwert und als Plausibilitätsprüfung: Weicht das Echo um mehr als 0,6 · r + 250 mm ab, wird es verworfen.fsm.js: rFromIntensity() (1000 * Math.sqrt(150 / Math.max(Ssum, 3))), acquire() (rFromIntensity(Math.max(c.S, dmean)), Parallaxe über eyePos()), applyPedFix(). Tabelle und Streuung: eigene Auswertung mit dem Sensormodell.
9 Grenzen des Verfahrens
Die Simulation macht diese Grenzen sichtbar. Alle Zahlen sind Modellannahmen und müssen am echten Aufbau geprüft werden.
Sonne senkt die Reichweite
Sonnenlicht hebt beide Kanäle um 15 Zählwerte an (Modell). Die rauschfreie Grenze sinkt von 5,1 m auf 3,1 m, und im Schwenk mit Zufallsstreuung findet er die Kerze in der Sonne nur bis etwa 2,7 m (Hälfte der Läufe) gegen mehr als 4 m in der Halle. Der Sensor misst das Hintergrundlicht selbst über den VIS-Kanal (Median) und stellt die Suchplanung darauf ein (1,8 m gegen 0,9 m im Log, Abschnitt 6). Wie stark echte Sonne den Sensor stört, ist ausdrücklich offen: Die Sim sagt selbst, dass A_SUN = 15 unkalibriert ist.
Glitzern
Spiegelungen (Metall, Wasser, nasser Boden) erzeugen kurze Pulse. Im Modell 0,12 pro Sekunde in der Halle, 0,7 in voller Sonne, 40 ms lang, mit einem Verhältnis um die Schwelle. Folge: 0,14 falsche Kandidaten je Schwenk in der Halle, 0,67 in der Sonne. Das Bestätigen fängt sie ab (Abschnitt 7), kostet aber Zeit: Jeder falsche Kandidat bedeutet eine Fahrt der Kuppel und mindestens 0,7 s Stand.
Verdeckung durch Podeste
Die Funktion occluded() prüft, ob die Sichtlinie vom Sensor zur Flamme einen anderen Podest-Zylinder (Radius 25 mm) in einer Höhe unterhalb der Podesthöhe schneidet. Dann zählt die Flamme als verdeckt und liefert dem Modell kein Signal. Ein hohes Podest (200 mm) direkt vor einer niedrigen Flamme verdeckt sie also vollständig, weil die Sichtlinie in etwa 95 mm Höhe verläuft.
Wind
Im Freien verschiebt Wind die Flamme. Das Modell verschiebt den Schwerpunkt der Flamme um 5 mm je m/s Windgeschwindigkeit in Windrichtung (WIND_SHIFT; Annahme, laut Kommentar "5 bis 15 mm in Böen"). Bei 3 m/s und 1 m Abstand sind das (quer zur Blickrichtung) 15 mm oder 0,9°; die Keule hat ±1,5° bei halber Leistung, der Wind kostet also bereits einen Teil des Signals. Zusätzlich wächst das weiße Flackerrauschen mit (1 + 0,2 · Windgeschwindigkeit). In der Sim steht der Wind standardmäßig auf 0 (Regler 0 bis 8 m/s); die Steuerung weiß von ihm nichts.
Flammenhöhe und Neigungswinkel
Das untere Paar sieht die niedrige Flamme überall, die mittlere (135 mm) und die hohe (215 mm) nur ab einem Mindestabstand, weil sie sonst über der senkrechten Keule liegen (Abschnitt 4c).
Hidden-Parameter
Das Modell würfelt je Lauf kleine Fehler: Achsversatz der Keule (±0,4° waagerecht, ±0,5° senkrecht), kRun (±10 %), Verstärkungsabweichung der Kanäle (±3 %). Das bildet nach, dass ein echter Aufbau nie perfekt justiert ist. Für die Seite bedeutet das: Die Kurven sind ein Lauf, nicht der Mittelwert.
sensors.js: occluded(), P.A_SUN, P.GLITTER_*, P.WIND_SHIFT, eyeView() (windShift, flick), hidden; fsm.js: measureBackground(); Aussage zur Kalibrierung im Hinweistext der Sim (head.html, Abschnitt "Was die Simulation nicht zeigt").
10 Selbsttest
Versuche zuerst selbst zu antworten, dann klappe die Antwort auf.
1. Warum reicht ein einzelner Helligkeitssensor nicht, um eine Flamme von Sonnenlicht zu unterscheiden?
2. Eine Kerze steht in 2 m Abstand, auf der Achse, in der Halle. Was erwartest du für NIR, VIS und das Verhältnis (ohne Zufall)?
3. Welche der drei Bedingungen scheitert bei wachsendem Abstand zuerst: in der Halle, und in voller Sonne?
4. Kann ein einzelner Glitzerpuls im Suchschwenk als Kandidat durchgehen? Und was verhindert, dass der Roboter darauf losfährt?
5. Warum wartet die Kuppel vor dem Messen im Stand 0,4 s, und warum wird das Flackern-Flag erst nach 0,3 s Ruhe gesetzt?
6. Ein Cluster hat die Spitze S = 38. Welchen Abstand schätzt die Steuerung? Und was ist der Haken?
7. Die Flamme steht 1,5° neben der Sensorachse, in 1 m Abstand, niedrig. Wie groß ist ihr Signal ungefähr, und was passiert bei 3°?
8. Warum ist eine hohe Flamme (215 mm) in 0,5 m Abstand für das untere Paar unsichtbar?
11 Quellen und Parameter
Alle Zahlen dieser Seite stammen aus den Quelldateien der Simulation (Verzeichnis entwurf/quelle/sim/). Eigene Rechnungen sind als solche markiert.
| Datei | Konstante / Funktion | Wert / Aufgabe |
|---|---|---|
| sensors.js | P.EYE_R, P.EYE_Z | 73 mm, 95 mm |
| sensors.js | P.HALF_AZ, P.HALF_EL | 3°, 12,5° |
| sensors.js | P.K, P.NIR_VIS | 225, 4 |
| sensors.js | P.A_HALL, P.A_SUN | 4,5; 15 |
| sensors.js | P.NOISE0, P.NOISE_REL | 1,0; 0,06 |
| sensors.js | P.FLICK_HZ, FLICK_DEPTH, FLICK_WHITE, FLICK_WIN, FLICK_STILL | 11 Hz; 0,30; 0,06; 15 Messungen; 0,3 s |
| sensors.js | P.GLITTER_RATE_HALL, _SUN, _LEN, _RATIO, _RATIO_SD | 0,12/s; 0,7/s; 0,04 s; 1,7; 0,4 |
| sensors.js | hidden.kRun, eyeAz, eyeEl, nirGain | ±10 %; ±0,4°; ±0,5°; ±3 % |
| sensors.js | eyeView(), sampleEye(), flickerFlag(), occluded() | Signalmodell, Messung alle 20 ms, 11-Hz-Fit, Verdeckung |
| fsm.js | PDEF RATIO_MIN, SUM_MIN, D_MIN | 1,7; 20; 6 |
| fsm.js | PDEF SCAN_RATE; in stVERIFY(): Ruhezeit domeStillT >= 0.4 | 60°/s; 0,4 s Ruhe vor dem Messen |
| fsm.js | makeSample(), findCandidates(), stVERIFY(), acquire(), rFromIntensity() | Treffer, Cluster, Bestätigen, Peilung, Abstand |
| fsm.js | PDEF COV_R0, COV_BG0, COV_RMIN, COV_RMAX | 1875; 4,5; 700; 2000 |
| geom.js | FLAMES, PODESTS | 87,5 / 135 / 215 mm; 70 / 120 / 200 mm |
| field.js | VEH, PODEST_R | Fahrzeugmaße; 25 mm |
| 2026-10-24_Funktionsentscheidungen_Bausteine.md | F6 | BPW41N + BPW34 je Sensorpaar |
Eigene Auswertungen (Skript gen.js, nur Lesen der Sim-Quellen): Suchschwenk-Kurven (Seed 38), Zeitreihen Flackern und Glitzern, Reichweite über 60 Seeds, falsche Cluster über 200 Seeds, Abstandsschätzung über 100 Seeds, rauschfreie Grenzen, Plausibilitätsrechnung zum Spektrum.