EINFÜHRUNG |
Ein Sensor ist ein Messgerät für eine physikalische Grösse, beispielsweise der Temperatur, der Lichtintensität, des Drucks, des Abstands, usw. Meist kann der vom Sensor gelieferte Wert eine beliebige Zahl innerhalb des Messbereichs sein. Es gibt allerdings auch Sensoren, die nur zwei Zustände ähnlich einem Schalter kennen, beispielsweise Füllstanddetektoren, Berührungssensoren, usw. Die physikalische Grösse wird im Sensor üblicherweise in eine elektrische Spannung umgewandelt und von einer Auswertelektronik weiter verarbeitet [mehr...
Für die Verarbeitung mit einem Computer muss die Spannung mit einem 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 Sensor liefert für Distanzen im Bereich von ca. 30 cm und 2 m Werte zwischen 0 und 255, wobei 255 (in der Simulation -1) dann abgegeben wird, wenn kein Objekt im Messbereich ist.
In den meisten Anwendungen wird ein Sensor so in das Programm eingebunden, dass dieses periodisch den Sensorwert abfragt. Man nennt dies Pollen des Sensors. Der in einer Wiederholschleife abgefragte Werte dann im Programm weiter verarbeitet. Die Anzahl Messwerte pro Sekunde (zeitliche Auflösung) hängt vom Sensortyp, der Geschwindigkeit des Rechners und der Datenübertragung vom Brick zum Programm ab. Der Ultraschallsensor liefert nur ungefähr 2 Messwerte pro Sekunde. Der Zustand von Sensoren, die nur zwei Zustände haben, kann ebenfalls durch Pollen abgefragt werden. Oft ist es aber einfacher, den Wechsel des Zustands, also die Zustandsänderung, als einen Event aufzufassen und ihn programmtechnisch mit einem Callback zu verarbeiten. |
POLLEN ODER EVENTS VERWENDEN? |
In vielen Fällen kannst du dich entscheiden, ob du einen Sensor lieber mit Pollen oder mit Events einbinden willst. Dies hängt etwas von der Anwendung ab. Du kannst die beiden Verfahren miteinander vergleichen, wenn du an einem Brick einen Motor und einen Berührungssensor anschliesst. Beim Klicken des Berührungssensors soll der Motor eingeschaltet, beim nächsten Klicken ausgeschaltet werden. Für diese Anwendung sind Events viel eleganter, da sie dir das Drücken des Berührungssensors als Aufruf einer Funktion mitteilen. Du musst beim Erzeugen des TouchSensors diese Funktion als benannten Parameter angeben. Beim Pollen ist es nötig, mit einem Flag dafür sorgen, dass du nur den Übergang vom nicht gedrückten zum gedrückten Zustand verarbeitest. Mit Pollen: from nxtrobot import * #from ev3robot import * def switchMotorState(): if motor.isMoving(): motor.stop() else: motor.forward() robot = LegoRobot() motor = Motor(MotorPort.A) robot.addPart(motor) ts = TouchSensor(SensorPort.S3) robot.addPart(ts) isOff = True while not robot.isEscapeHit(): if ts.isPressed() and isOff: isOff = False switchMotorState() if not ts.isPressed() and not isOff: isOff = True
Mit Events: #from nxtrobot import * from ev3robot import * def onPressed(port): if motor.isMoving(): motor.stop() else: motor.forward() robot = LegoRobot() motor = Motor(MotorPort.A) robot.addPart(motor) ts = TouchSensor(SensorPort.S1, pressed = onPressed) robot.addPart(ts) while not robot.isEscapeHit(): pass robot.exit() |
MEMO |
Sensoren können mit Pollen oder Events programmiert werden. Du musst beide Verfahren kennen und in der Lage sein zu entscheiden, welches in einer bestimmten Situation das zweckmässigere ist. Im Eventmodell definierst du Funktionen, deren Name üblicherweise mit "on" beginnt. Diese werden Callbacks genannt, weil sie vom System beim Auftreten des Events automatisch aufgerufen ("zurückgerufen") werden. Du musst Callbacks bei der Erzeugung des Sensorobjekts mit benannten Parametern registrieren. |
POLLEN EINES ULTRASCHALL-SENSORS |
Vorbemerkung: Falls du in deinem EV3-Bausatz keinen Ultraschall-Sensor hast, so kannst du auch den EV3 Infrarotsensor einsetzen. Einen Sensor musst du immer dann pollen, wenn du laufend seine Messwerte benötigst. Du stellst dir die Aufgabe, dass der Roboter, den du irgendwo auf den Boden stellst, einen Gegenstand (ein Ziel, Target) finden soll und zu diesem hinfährt. Zum Erfassen eines Targets verwendest du einen Ultraschall-Sensor, der ähnlich wie ein Radar-Zielerfassungssystem eingesetzt wird. Um die Eigenschaften eines Sensors kennen zu lernen und ihn auszuprobieren, solltest du den Aufwand nicht scheuen, ein kurzes Testprogramm zu schreiben, das du später nicht mehr brauchen wirst. Dabei ist es zweckmässig, die Sensorwerte auszuschreiben und eventuell auch hörbar zu machen, da du dann Hände und Augen frei hast, um den Roboter und den Sensor zu bewegen. In einer Schleife fragst du die Sensorwerte ab, wobei die Schleifenperiode angepasst wird, je nachdem ob du im autonomen oder fremdgesteuerten Modus bist. # from nxtrobot import * from ev3robot import * robot = LegoRobot() us = UltrasonicSensor(SensorPort.S1) robot.addPart(us) isAutonomous = robot.isAutonomous() while not robot.isEscapeHit(): dist = us.getDistance() print("d = ", dist) robot.drawString("d=" + str(dist), 0, 3) robot.playTone(10 * dist + 100, 50) if dist == 255: robot.playTone(10 * dist + 100, 50) if isAutonomous: Tools.delay(1000) else: Tools.delay(200) robot.exit()
from simrobot import * #from nxtrobot import * #from ev3robot 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 left, right found = False step = 0 while not robot.isEscapeHit(): gear.right(50) step = step + 1 dist = us.getDistance() print("d = ", dist) if dist != -1: # simulation #if dist < 80: # real if not found: found = True left = step print("Left at", left) robot.playTone(880, 500) else: if found: right = step print("Right at ", right) robot.playTone(440, 5000) break left = 0 right = 0 robot = LegoRobot() gear = Gear() robot.addPart(gear) us = UltrasonicSensor(SensorPort.S1) robot.addPart(us) us.setBeamAreaColor(makeColor("green")) us.setProximityCircleColor(makeColor("lightgray")) gear.setSpeed(5) print("Searching...") searchTarget() gear.left((right - left) * 25) # simulation #gear.left((right - left) * 100) # real print("Moving forward...") gear.forward() while not robot.isEscapeHit() and gear.isMoving(): dist = us.getDistance() print("d =", dist) robot.playTone(10 * dist + 100, 100) if dist < 40: gear.stop() print("All done") robot.exit()
|
MEMO |
Meist bestimmt man die Sensorwert durch wiederholtes Abfragen (Pollen) mit einer getter-Methode (getValue(), getDistance(), usw.) Du musst gewisse Werte beim Wechsel zwischen Simulationsmodus und Realmodus anpassen, insbesondere Zeitintervalle. Zudem musst du berücksichtigen, dass der Sensor im Simulationsmodus -1 und im Realmodus 255 zurückgibt, wenn er kein Target findet. In der Simulation bestimmt der verwendete Sensorport die Blickrichtung des Ultraschallsensors:
|
EVENTS MIT EINEM TRIGGERPEGEL |
Die Sensoren besitzen einen Standardwert für den Triggerpegel. Diesen kannst du aber mit setTriggerLevel() verändern.
from simrobot import * #from nxtrobot import * #from ev3robot import * RobotContext.setStartPosition(250, 200) RobotContext.setStartDirection(-90) RobotContext.useBackground("sprites/circle.gif") def onDark(port, level): gear.backward(1500) gear.left(545) gear.forward() robot = LegoRobot() gear = Gear() robot.addPart(gear) ls = LightSensor(SensorPort.S3, dark = onDark) robot.addPart(ls) ls.setTriggerLevel(100) # adapt value gear.forward() while not robot.isEscapeHit(): pass robot.exit()
|
MEMO |
Des Überqueren eines bestimmten Messwerts kann als ein Event aufgefasst werden. Man spricht dabei von Triggerung. Standardwerte des Triggerpegels:
Die Vor- und Nachteile des Event-Modells gegenüber Pollens lassen sich wie folgt zusammenfassen:
|
AUFGABEN |
|
ZUSATZSTOFF |
ARDUINO-SENSOREN VERWENDEN |
Die Verbindung der beiden Geräte erfolgt am einfachsten über einen I2C-Link, da beide Geräte über eine I2C-Schnittstelle verfügen. Dabei ist der EV3 ein I2C-Masters und der Arduino ein I2C-Slave. Die zusätzlich benötigten Python-Module sind bereits in der Distribution von TigerJython enthalten. Der EV3 kann dabei im autonomen oder direkten Modus betrieben werden. Du kannst dich hier genauer informieren. |