Sensoren by DL1NOS

4.1 Einleitung

Für den „Rundumblick“ sorgen fünf optische Distanzsensoren der Firma SHARP vom Typ: IS471F. Diese integrierten Schaltkreise besitzen eine eingebaute Elektronik, die nur wenige zusätzliche Bauteile benötigt. In der Minimalbeschaltung fehlt lediglich eine Infrarot-Diode (IR-LED) und ein Kondensator zur Spannungsglättung. Mehr Informationen zu diesen Sensoren sind hier und hier zu finden. Kurz & knapp: Im verschlossenen Gehäuse des Sensors (Abbildung 1, rechts unten) befindet sich ein Frequenzgenerator, der über eine Verstärkung die externe Infrarot-LED (Abbildung 1 silber glänzende Fassung links) moduliert. Das an einem Hindernis refkektierte IR-Licht wird zurück auf den Sensor geworfen, der die empfangene Frequenz des IR-Lichts mit seiner selbst erzeugten Frequenz vergleicht und bei überschreiten einer Schwelle das Hindernis erkennt. Die Sensoren werden so gefertigt, dass die Frequenzgeneratoren etwas von einander abweichen. Somit stören sich die Sensoren nicht gegenseitig und sind unempfindlich gegenüber anderen Lichtquellen.

Bei den ersten Tests musste ich feststellen, dass diese Sensoren keine Analog-Spannung in Abhängigkeit der Entfernung ausgeben, sondern bei Erkennung eines Hindernisses einen etwas verrauschten Low-Pegel, bzw. wenn kein Hindernis erkannt wurde einen High-Pegel. Als Gehäuse für die Infrarot-LED eignen sich am Besten verchromte LED-Fassungen mit Innenreflektor. Diese Fassungen schirmen das seitlich austretende IR-Licht ab und bündeln zusätzlich die Abstrahlung nach vorne. Damit und mit einem zusätzlichen Transistor (Abbildung 1 unten Mitte) zur Ansteuerung der LED sind dann Hinterniserkennungen bis ca. 15cm erreichbar. Die Reichweite hängt von der Farbe des Hindernisses ab. Schwarze Wände schlucken deutlich mehr IR-Licht und es gelangt viel weniger Licht zurück zum Sensor. Damit sinkt die Reichweite beträchtlich, es kann sogar vorkommen, dass gar kein Hindernis wahrgenommen wird.

Abbildung 1: optischer Sensor zur Hinderniserkennung (stark vergrößert)

Abbildung 1: optischer Sensor zur Hinderniserkennung (vergrößerte Abbildung)

 

4.1.1 Bestellliste

Wie immer lohnt es sich, bei den Widerständen mindestens 10 Stück zu bestellen. Benötigt werden mindestens die angegebenen Bauteile:

Nr. Bezugsquelle Best.-Nr. Was Anz. Einz.-Preis Ges.-Preis
1 micromaus.de 00209 SHARP IS471F 5 2,84 14,20
2 reichelt EBF I-5 Einbaufassung, 5mm, Innenreflektor, chrom 5 0,61 3,05
3 reichelt LD 274 5mm IR-LED 5 0,28 1,4
4 reichelt 2N3906 Transistor 5 0,05 0,25
5 reichelt METALL 4,70 Metallschichtwiderstand 4,70 Ohm 5 0,082 0,41
6 reichelt METALL 1,00K Metallschichtwiderstand 1,00 K-Ohm 10 0,082 0,82
7 reichelt MKS-2 330N WIMA Folienkondensator, Rm 5mm, 330nF 5 0,11 0,55
8 reichelt LED 3MM 2MA GN LED 3mm, low-Current, grün 5 0,06 0,30
9 reichelt PT 6-L 5,0K Einstellpotentiometer, liegend, 6mm, 5,0 K-Ohm 5 0,23 1,15
10 reichelt SL 1X36W 2,54 36pol. Stiftleiste, gewinkelt, RM 2,54 1 0,24 0,24

 

4.1.2 Schaltpläne, Platinenlayouts

Abbildung 2: Schaltplan des optischen Distanzsensors is471

Der Schaltplan wurde von dieser Seite übernommen. Das Layout wurde leicht angepasst.

Die Schaltpläne und Platinenlayouts wurden mit dem Layoutprogramm Eagle erstellt und können beim Anklicken des Bildes heruntergeladen werden.

 

4.1.3 Funktionstest

Unbedingt mit einem Labornetzteil und aktiver Strombegrenzung testen! Die Sensorplatine sollte nicht mehr als 20mA bei 5V Betriebsspannung verbrauchen. Anschließend prüfen, ob die LED ohne Hindernis leuchtet und bei einem Abstand von ungefähr 8 cm zum Hindernis erlischt. Jetzt kann die Entfernung mit dem Poti stufenlos eingestellt werden. Wichtig: Wenn die LED am Ausgang verbleiben soll, dann sinkt die Spannung am Ausgang von 5V auf etwa 2,4V. Damit wird die Erkennung eines Hindernisses im Mikrocontroller zum Glückspiel. Der Mikrocontroller erkennt einen High-Pegel erst bei mehr als 2,4V (vgl. TTL-Logik). Der Grund für den Spannungseinbruch ist ein zu hochohmiger Pull-Up Widerstand im IS471. Offenbar ist die gleichzeitige Verwendung einer LED und die Nutzung dieses Ausgangs für einen Mikrocontroller so nicht vorgesehen. Die einfachste Lösung wäre das Auftrennen der Lötbrücke SJ1 (Abbildung 2) und damit deaktivieren der LED. Soll dennoch die LED und die Eingabe am Mikrocontroller verwendet werden, muss ein zusätzlicher, externen Pull-UP Widerstand von 220 Ohm hinzugefügt werden (Abbildung 3 rechts unten). Laut Datenblatt ist der Ausgangstransistor in der Lage, bis zu 50mA gegen Masse zu schalten. Damit können problemlos beide Funktionen genutzt werden.

Abbildung 3: Test der optischen Distanzsensoren is471
Abbildung 3: Test der optischen Distanzsensoren is471

Durch die LEDs kann sehr gut die fehlerfreie Funktion der Sensoren geprüft werden. Anschließend die Sensoren an dem Roboter verbauen (Abbildung 4). Da auf den Sensorplatinen keine Bohrlöcher für die Befestigung der Sensoren vorgesehen ist, kleben wir die Sensoren mit Heißkleber am Gehäuse fest. Dabei immer darauf achten, dass die Kontakte der Platine keine Kurzschlüsse durch das Gehäuse haben. Beim Festkleben daran denken, dass später das Staubsaugerrohr unter dem Roboter entlag geht.

Abbildung 4: Bild von Unten auf die am Roboter verbauten Sensoren

Abbildung 4: Bild von Unten auf die am Roboter verbauten Sensoren

 

4.1.4 Treiber

Im Schaltplan sind die ersten zwei Sensoren mit den Anschlüssen an Port B Nummer 6 und Port B Nummer 7 des Mikrocontrollers verbunden. Wir müssen beim Start des Mikrocontrollers die Datenrichtungsregister auf Eingang konfigurieren:

DDRB &= ~(0b11000000);               //Datenrichtungsregister DDRB6 und DDRB7 auf Eingang

Ebenfalls für die restlichen Sensoren, die an Port D angeschlossen sind:

DDRD &= ~(0b11100000);               //Datenrichtungsregister DDRD5, DDRD6 und DDRD7 auf Eingang

Abfragen können wir die Eingänge über die PIND und PINB Register. Wir möchten, dass die Werte im ASCII-Format an das Funkmodul übergegeben werden, und zwar so, dass der hintere Sensor als 1. Wert gesendet wird und alle nachfolgenden Sensoren im Uhrzeigersinn nacheinander folgen.

Beispiel: Wir bekommen als Antwort auf die Sensor-Abfrage die folgende Zeichenkette: 10110
Das bedeuted:

  • Sensor 1 (hinten) hat kein Hindernis erkannt,
  • Sensor2 (links) hat ein Hindernis erkannt,
  • Sensor3 (vorne links) hat kein Hindernis erkannt,
  • Sensor4 (vorne rechts) hat kein Hindernis erkannt,
  • Sensor5 (rechts) hat ein Hindernis erkannt.

Um das zu gewährleisten könnten wir jeden Sensorwert einzeln abfragen und den Status nacheinander senden, z.B.: Wenn Pin 5 vom Register PIND gesetzt ist, dann sende eine ASCII Eins ansonsten sende eine ASCII Null. Dieses Vorgehen würde zwar prinzipiell funktionieren, hat aber Nachteile. Beim Schreiben von Mikrocontrollerprogrammen sollte man immer auf eine gewisse Effizienz achten. Das heißt, es wäre effizienter, wir würden mit einem Aufruf gleich beide Eingänge sammeln:

unsigned char Ergebnis = PIND;

Noch besser wäre es, wenn wir mit einem Aufruf gleich alle Sensorwerte sammeln. Dann können wir später bequem vergleichen, ob sich der Inhalt ändert (also ob einer oder mehrere Sensoren ein Hindernis erkannt haben oder das Hindernis wieder verschwunden ist). Leider sind die Eingänge auf zwei Ports verteilt, deshalb entfällt die Möglichkeit, einfach einen Port abfragen. Aber wir können beide Ports mit einem logischen oder kombinieren:

unsigned char Ergebnis = (PINB | PIND));

Leider gibts auch hier ein Problem. Die Sensoren sind zwar an zwei verschiedenen Ports verbunden, benutzen aber an beiden Ports die jeweils obersten Bits. Beim logischen oder verknüpfen würden sich die Werte der beider Register gegenseitig überschreiben. Mit folgender Vorgehensweise lösen wir das Problem: Wir fragen das Register PIND ab und schieben das Ergebnis um 5 Stellen nach rechts. Damit füllen wir unsere Ergebnis 1 Variable mit den untersten 3 Bits:

unsigned char Ergebnis_1 = (PIND >> 5));

Dann fragen wir das Register PINB  ab und schieben das Ergebnis um 3 Stellen nach rechts. Damit füllen wir unsere Ergebnis 2 Variable mit den obersten 2 Bits:

unsigned char Ergebnis_2 = (PINB >> 3));

Jetzt brauchen wir die beiden Ergebnisse nur noch mit einem logischen oder zu kombinieren und haben unser Gesamtergebnis:

unsigned char Ergebnis = (Ergebnis_1 | Ergebnis_2);

Wenn wir die beiden Zwischenergebnisse weg lassen, dann können wir den gesamten Befehl in einer einzigen Zeile schreiben:

unsigned char Ergebnis = (((PIND & 0b11100000) >> 5) | ((PINB & 0b11000000) >> 3));

Das logische und sorgt dafür, dass nur die Eingänge miteinander verknüpft werden, die wir auch haben wollen.

Sollen die Werte nun im ASCII-Format gesendet werden, dann brauchen wir eine Schleife, die vom Nullten bis zum Fünften Wert die einzelnen Bits aus der Ergebnis-Variable herausholt, in einen ASCII-Wert wandelt und über den Uart an das Funkmodul weitergibt:

for(unsigned char c = 0; c < 5; c++)
{
while ( !( UCSRA & (1< < UDRE )) );                 //warte bis UART sendebereit ist
UDR = ((Ergebnis & 0x01) + 48);                       //sende den ASCII-Wert
Ergebnis > >= 1;                                             //schiebe ein Bit weiter
}

Der Trick mit der Wandlung in einen ASCII-Wert funktioniert so: Die ASCII-Tabelle besteht aus einer Reihe von 128 verschiedenen Zeichen, Ziffern und Symbolen. Die Großbuchstaben des Alphabets beginnen z.B. ab Nummer 65, die Ziffern beginnen ab Nummer 48. Addiere ich zu einer einstelligen, binären Ziffer 48 hinzu, dann erhalte ich dessen äquivalentes ASCII-Zeichen.

Natürlich sollte man anstelle von Ergebnis einen aussagekräftigeren Variablennamen verwenden um nicht die Übersichtlichkeit zu verlieren.

 

Wird fortgesetzt…

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.