Deutsch   English 

3. Sensoren


Sensoren sind Messgeräte für die physikalischen Grössen, wie z.B. Abstand, Lichtintensität, Temperatur, Luftfeuchtigkeit usw. Sie wandeln in der Regel nichtelektrische Messgrössen in elektrische Signale um und liefern ihre Messwerte an den Microprozessor. Der mbRobot verfügt über einen Ultraschallsensor und zwei Infrarot Sensoren, mit welchen die Helligkeit der Unterlage gemessen wird. Ausserdem kann der Beschleunigungs- und Kompasssensor des micro:bits verwendet werden.

 

Weitere Sensoren können über die I2C-Schnittstelle angeschlossen werden. Einige Beispiel werden in den späteren Kapiteln dieses Tutorials beschrieben.


Ultraschallsensor (Distanzsensor)

Der Ultraschallsensor bestimmt die Distanz zu einem Objekt durch die Laufzeit, die ein kurzer Ultraschall-Puls benötigt, um vom Sensor zum Objekt und wieder zurück zu laufen. Der Ultraschallsensor des mbRobot kann die Distanzen im Bereich 2 cm bis ca. 100 cm messen. Die Funktion getDistance() gibt die Entfernung in cm zurück. Die Sensorwerte werden durch Pollen erfasst, d.h. in einer "endlosen" Schleife immer wieder abgefragt.

Beispiel 1: Ein Hindernis detektieren
Der Roboter fährt vorwärts und misst die Entfernung zu Objekten, die vor ihm liegen. Wenn die Entfernung kleiner als 20 cm ist, fährt er eine kurze Strecke zurück und dann wieder vorwärts.

# Mr3a.py
from mbrobot import *

setSpeed(15)
forward()
while True:
    d = getDistance()
    print(d)
    if d < 20:
        backward()
        delay(2000)        
        forward()
    delay(100)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

d = getDistamce() Abstand zum Hindernis in cm
sleep(100) Der Sensorwert wird nur alle 200 Millisekunden abgefragt. Dieser sleep()-Befehl Befehl verhindert, dass der Mikrocontroller in der Schleife unnötig viel Zeit verschwendet und auf andere Befehle nicht mehr reagieren kann, beispielsweise auf den Abbruch des laufenden Programms beim nächsten Programm-Download
while True: Eine "endlose" Schleife. Die Befehle im eingerückten Block werden so lange wiederholt, bis man den Roboter mit dem kleinen Switch-Schalter hinten am Roboter abstellt.

Für die Simulation verwendet man anstelle eines Hindernisobjekts einen horizontalen Balken, den man mit folgendem Context erzeugt:

target = [[200, 10], [-200, 10], [-200, -10], [200, -10]] 
RobotContext.useTarget("sprites/bar0.gif", target, 250, 100)

Die beiden Zeilen muss man für die Ausführung im Realmodus wieder auskommentieren (mit einem vorgestelltem #).

 


Beispiel 2: Ein Regelungssystem für die Distanz zum bewegten Objekt
Der Roboter soll den Handbewegungen folgen, indem er ständig die Distanz 10 cm zu halten versucht. Wenn er eine Distanz kleiner als 10 cm misst, fährt er rückwärts, bei einer Distanz grösser als 10 und kleiner als 30 cm fährt er vorwärts. Wenn sich die Hand zu weit entfernt, bleibt er stehen.

#Mr3b.py
from mbrobot import *

setSpeed(10)
while True:
    d = getDistance()
    if d < 10:
        backward()
    elif d >= 10 and d < 30: 
        forward()
    else:
        stop()
    delay(100)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

d >= 100 and d < 300 Verknüpfte Bedingungen. In Python kann auch 100 <= d < 300 geschrieben werden.

 

Infrarotsensoren


Ein Infrarotsensor besteht aus einer Leuchtdiode (LED), welche Licht im Infrarotbereich aussendet und einer Fotodiode, welche die Intensität des reflektierenden Lichtes misst.  

Da das Infrarottlicht an hellen bzw. dunklen Flächen unterschiedlich reflektiert, können die Sensoren zwischen einer hellen und dunklen Unterlage unterscheiden und geben einen digitalen Wert 0 (dunkel) oder 1 (hell) zurück.

Der MbRobot verfügt über 2 Infrarotsensoren (irLeft, irRight). Man findet sie auf der unteren Seite des Boards, bezeichnet mit Line-R und Line-L.

 

Der Maqueen Plus V2 verfügt über 5 Infrarotsensoren (irL1, irL2, irL3, irR1, irR2, irM), der Maqueen Plus sogar über 6 Infrarotsensoren (irL1, irL2, irL3, irR1, irR2, irL3, irR3), wobei irLeft = irL1 und irRight = irR1. Damit können alle nachfolgende Programme für alle Modelle verwendet werden.

Beispiel 3: Der Roboter reagiert auf eine dunkle Unterlage
Der Roboter soll sich endlos auf einem quadratischen Tisch mit weissem Innenkreis bewegen, ohne herunterzufallen. (Es kann auch um eine Papiervorlage auf dem Boden sein.) Dabei startet er in der Mitte und fährt geradeaus. Erkennt er den Rand, so fährt er rückwärts, dreht um ungefähr 90 Grad nach links und fährt dann wieder vorwärts.

Im Simulationsmodus wird ein Hintergrundbild circle.gif verwendet, das zu Beginn des Programm als Robot.Context eingefügt wird. Für den realen Modus muss man diese Zeile auskommentieren und die Geschwindigkeit etwas reduzieren.

# Mr3c.py
from mbrobot import *

RobotContext.useBackground("sprites/circle.gif")

#setSpeed(15)
forward()
while True:
    v1 = irLeft.read_digital()
    v2 = irRight.read_digital()
    if v1 == 0 or v2 == 0:
        backward()
        delay(1400)
        forward()
        left()
        delay(550)
        forward()        
    delay(100)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

v1 = irLeft.read_digital() Gibt den Wert des linken IR-Sensors als Digitalwert 0 oder 1 zurück, man kann auch v =pin13.read_digital() schreiben
v2 = irLeft.read_digital() Gibt den Wert des rechten IR-Sensors als Digitalwert 0 oder 1 zurück, man kann auch v =pin8.read_digital() schreiben
if v1 == 0 or v2 == 0: Die nachfolgenden Zeilen werden ausgeführt, wenn der Roboter eine dunkle Unterlage erkannt hat

Bemerkung: Eigene Hintergundbilder (500 x 500 Pixel gross und im gif- oder png-Format) für die Simulation können Sie im beliebigen Ordner auf Ihrem Computer speichern. Im Programm müssen Sie den Pfadd der Bilddatei angeben.
Unter Windows z.B.
RobotContext.useBackground("c:/users/UrsMeier/desktop/bilder/mybackground.gif")
oder RobotContext.useBackground("d:/bilder/bild.gif") 

Unter MacOS z.B.
RobotContext.useBackground("/Users/UrsMeier/Desktop/Bilder/mybackground.gif")  

Unter Windows können die Bilder auch im Unterverzeichnis sprites des Unterverzeichnisses /bin des Installationsverzeichnisses gespeichert sein. Mit RobotContext.useBackground("sprites/mybackground.gif")
werden sie automatisch in Ihrem Programm integriert.

Beispiel 4: Selbstfahrendes Auto (self-driving car)
Selbstfahrende Autos sind heute bereits eine Realität. Damit das Auto in jeder Situation richtig gesteuert wird, ist ein komplexer Regelungsprozess mit vielen Sensordaten erforderlich. Das nächste Beispiel stellt eine stark vereinfachte Situation dar. Es ist ein Regelungssysten, das den Roboter so steuert, dass er auf den schwarzen Track abfahren kann. Mit Hilfe seiner beiden Infrarotsensoren kann er entscheiden, ob er geradeaus oder auf dem Links- bzw. Rechtsbogen fahren soll.

# Mr3d.py 
from mbrobot import *

RobotContext.setStartPosition(250, 250)
RobotContext.setStartDirection(-90)
RobotContext.useBackground("sprites/track.gif")

state = "GOTRACK"

#setSpeed(10)
while True:
    left = irLeft.read_digital()
    right = irRight.read_digital()
    if left == 0 and right == 0 and state != "FORWARD":  
        forward()
        state = "FORWARD"
    elif left == 0 and right == 1 and state != "LEFT":
        leftArc(0.1)
        state = "LEFT"
    elif left == 1 and right == 0 and state != "RIGHT":
        rightArc(0.1)
        state = "RIGHT"
    elif left == 1 and right == 1:  # out of track
        if state == "LEFT":
            leftArc(0.1)
        elif state == "RIGHT":
            rightArc(0.1)
        state = "GOTRACK"
    sleep(100)
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

Es ist eine typische Aufgabe für die Zustand-Programmierung. Der Roboter kennt im Wesentlichen vier Zustände:
FORWARD: wenn beide Sensoren den Wert 0 liefern
LEFT : wenn der linke Sensor 0 und der rechte 1 meldet. In diesem Fall muss er nach Links korrigieren
RIGHT: wenn der linke Sensor 1 und der rechte 0 meldet, dann muss er mit dem Rechtsbogen korrigieren
GOTRACK: wenn er den Weg verliert (beide Sensoren liefern 1). Die Wegkorrektur ist in diesem Fall davon abhängig, in welchem Zustand er vorher war.

Mit der Zustandsprogrammierung vermeidet man insbesondere, dass Befehle unnötig wiederholt werden. Wenn der Roboter bereits vorwärts fährt und die beide Sensorwerte 0 sind, muss nicht alle 100 ms erneut der Befehl forward() aufgerufen werden, sondern nur dann, wenn sich der Zustand ändert.

Im realen Modus muss man die drei Zeilen mit RobotContext weglassen und die Geschwindigkeit etwas reduzieren.


Beispiel 5
: Einen Gegenstand finden und hinfahren

Der Roboter dreht sich wie eine Radarantene am Ort und sucht nach einem Gegenstand (Target). Falls er ein Objekt entdeckt, soll er hinfahren. Sobald die Distanz zum Gegenstand kleiner ist als 20 ist, hält er an. Das Programm kann im Real- und Simulationsmodus ausgeführt werden, wobei im Realmodus die Zeilen mit mesh, RobotContext, BeamerArea und ProximtyCircle weggelassen werden (können auskommentiert werden).

Im Simulationsmodus entspricht das sichtbare Target der Bilddatei redtarget.gif. Mit der Variablen mesh werden die Koordinaten der Eckpunkte angegeben, die für die Detektion des Target verwendeet werden


 

Der Roboter dreht sich nach rechts. Falls er ein Target entdeckt, speichert er den Winkel, dreht dann weiter, bis er das Target verliert und speichert wieder den Winkel. Anschliessend dreht er um die Hälfte der Differenz der beiden Winkel zurück und fährt vorwärts.

# Mr3e.py
from mbrobot import *

mesh = [[50,0], [25,43], [-25,43], [-50,0],[-25,-43], [25,-43]] 
RobotContext.useTarget("sprites/redtarget.gif", mesh, 400, 400)

def searchTarget():
   global lt, rt
   found = False
   step = 0
   repeat:  
      right()
      delay(50)
      step = step + 1
      dist = getDistance()
      if dist != -1:
      #if dist != 255:
         if not found:
            found = True
            lt = step
      else:
         if found:   
            rt = step
            break

setBeamAreaColor(Color.green)  
setProximityCircleColor(Color.lightGray)
setSpeed(10)
searchTarget()
left()
delay((rt - lt) * 25)
forward()

while True:
   dist = getDistance()
   print ("Distance = " + str(dist))
   if dist < 40:
      stop()
      break
print ("done")
► In Zwischenablage kopieren
 

Erklärungen zum Programmcode:

def searchTarget(): Definiert den Suchvorgang
print "Distance = " + str(dist): Die Distanz zum Objekt wird im Terminalfenster ausgeschrieben (im Simulationsmodus im im Ausgabefenster von TigerJython-Fenster)
if dist != -1: Falls kein Objekt sichtbar ist, wird im Simulationsmodus die Distanz -1 zurückgegeben.
Achtung: Der reale Roboter gibt in diesem Fall den Wert 255 zurück,

Im Realmodus muss man die Zeile mit mesh und Robotkontext auskommentieren.

Eine moderne Industrieanlage ohne Sensoren ist heute kaum mehr denkbar. Auch in unserem Alltag umgeben uns Sensoren. Die modernen Autos verfügen über 50 - 100 verschiedene Sensoren: Abstandsensoren, Drehzahl- und Geschwindigkeitsensoren, Füllstansensor des Benzintanks, Temperatursensor usw.

Beim Einparkieren werden Distanzsensoren verwendet, die ähnlich funktionieren, wie diejenigen unseres kleinen mbRobots.

 

 

 


Aufgaben:


1)


Der Roboter bewegt sich in einem quadratischen Feld und misst mit seinem Ultraschallsensor die Distanz zur Wand. Wenn der Abstand kleiner als 10 cm ist, fährt er kurz zurück, dreht 90° nach links un fährt weiter in der neue Richtung. Für die Simulation musst du folgende Zeilen einfügen:

mesh_hbar = [[200, 10], [-200, 10], [-200, -10], [200, -10]]
mesh_vbar = [[10, 200], [-10, 200], [-10, -200], [10, -200]]
RobotContext.useTarget("sprites/bar0.gif", mesh_hbar, 250, 100)
RobotContext.useTarget("sprites/bar0.gif", mesh_hbar, 250, 400)
RobotContext.useTarget("sprites/bar1.gif", mesh_vbar, 100, 250)
RobotContext.useTarget("sprites/bar1.gif", mesh_vbar, 400, 250)
 


2)

Ein Roboter bewegt sich in einem begrenzten Feld mit dem Ziel, den Ausgang zu finden. Wenn der Abstand zur Begrenzung kleiner als 5 cm ist, so fährt er eine kurze Strecke zurück, dreht um einen kleinen Winkel nach links und fährt anschliessend wieder vorwärts, so lange, bis es ihm gelingt, den Ausgang zu finden.
 



3)


Dein Programm soll mit Hilfe der Infrarotsensoren den Roboter so steuern, dass er möglichst genau der Kante entlang fährt.

Für die Simulation kannst du das Hintergrundbild oval.gif benutzen

RobotContext.useBackground("sprites/oval.gif")
RobotContext.setStartPosition(150, 400)
 


4)


Ein Roboter soll quer über vier dunkle Streifen fahren und diese mit seinen Infrarotsensoren detektieren. Beim Erkennen des vierten Streifens soll er anhalten.

Bemerkung: Die Lösung ist nicht ganz einfach, denn wenn der Roboter auf einen Streifen fährt und den Streifenzähler um 1 erhöht, weil er schwarz sieht, so sieht er immer noch schwarz, wenn er weiterfährt. Du musst den aktuellen Zustand (ob ausserhalb oder auf Streifen) in mit einer Variablen s speichern. Nur wenn der Zustand ändert,  darfst du weiter zählen.

Für die Simulation kannst du das Hintergrundbild panels.gif verwenden und dieses wie folgt als RobotContext einfügen:

RobotContext.setStartPosition(0, 250)
RobotContext.setStartDirection(0)
RobotContext.useBackground("sprites/panels.gif")
 



5)


Ein Roboter soll mit seinem Ultraschallsensor drei Objekte finden. Er dreht am Ort und misst die Distanz. Wenn er ein Objekt findet, spielt er einen Ton oder eine Melodie ab und sucht weiter, bis er alle drei gefunden hat. Löse die Aufgabe zuerst im Simulationsmodus und folgende Vorlage, um die Gegenstände darzustellen.

mesh = [[-30, -30], [-30, 30], [30, -30], [30, 30]]
RobotContext.useTarget("sprites/squaretarget.gif", mesh, 350, 250)
RobotContext.useTarget("sprites/squaretarget.gif", mesh, 100, 150)
RobotContext.useTarget("sprites/squaretarget.gif" ,mesh, 200, 450)
RobotContext.setStartPosition(40, 450) 
 




6)


Der Roboter soll eine rechteckige Fläche, die auf allen Seiten begrenzt ist, so abfahren, als ob er sie wie ein Rasenmäher mähen würde. Falls er mit seinem Ultraschalsensor eine Begrenzung detektiert, so dreht er 90 Grad, fährt eine kurze Strecke parallel zur Begrenzung, dreht nochmals um 90 Grad und fährt wieder vorwärts, bis er bei der gegenüberliegenden Begrenzung ankommt. Diese Bewegung wiederholt er, bis er das ganze Feld gemäht hat.

Im Simulationsmodus kannst du folgende Feld-Begrenzung verwenden

target = [[200, 10], [-200, 10], [-200, -10], [200, -10]]
RobotContext.useTarget("sprites/bar0.gif", target, 250, 20)
RobotContext.useTarget("sprites/bar0.gif", target, 250, 480)
RobotContext.setStartPosition(430, 480)

Die Aufgabe ist nicht so einfach, da der Roboter abwechslungsweise links und rechts drehen muss. Dies lässt sich mit folgendem Trick lösen: du definierst eine Funktion turn(n), die für gerade n eine Drehung links und für die ungeraden n eine Drehung nach rechts bewirkt. n musst du zu Beginn auf 0 setzen.

def turn(n):
if n % 2 == 0:
gear.left()
else:
gear.right()
Tools.delay(540))