Die UART Schnittstelle überträgt nun die Distanzmessungen, vorne und hinten vom Raspberry Pico zum Raspberry Zero 2.
Raspberry Pico:
import utime
from machine import Pin, UART, Timer
# Wichtig: nimmt man hier: uart = machine.UART(0, 115200)
# kann man nicht mehr per USB auf den Pico zugreifen.
uart = UART(1, 115200)
def ultra(trigger_pin, echo_pin):
trigger = Pin(trigger_pin, Pin.OUT)
echo = Pin(echo_pin, Pin.IN)
trigger.low()
utime.sleep_us(2)
trigger.high()
utime.sleep_us(5)
trigger.low()
while echo.value() == 0:
signaloff = utime.ticks_us()
while echo.value() == 1:
signalon = utime.ticks_us()
timepassed = signalon - signaloff
distance = (timepassed * 0.0343) / 2
return distance
def return_distance(t):
distance1 = ultra(3, 2)
distance2 = ultra(20, 21)
uart.write(f"front,{distance1},rear,{distance2}\n")
# durch die Initialisierung kann der timer zur Laufzeit gestoppt werden mit timer.deinit()
timer = None
if __name__ == "__main__":
timer = Timer(freq=5, callback=return_distance)
Merke: Verwende keine while True Schleife, sondern ein Timer Objekt. Damit bleibt die Konsole des Pico verfügbar.
Auf der Gegenstelle wird die Distanz empfangen.
Raspberry Zero 2:
import serial
from Sensors.sensor import Sensor
class UltraSonic(Sensor):
def __init__(self):
self._serial = serial.Serial ("/dev/ttyS0", 115200)
def getPort(self):
return self._serial
def read_one(self):
distance = {}
ser = self.getPort()
# Waiting Strings verwerfen
ser.read_all()
received_data = ser.readline() #read serial port
result = str(received_data.decode('utf-8')).split(",")
distance[result[0]] = round(float(result[1]))
distance[result[2]] = round(float(result[3]))
return distance
Nach der Dekodierung des binären Inputs zu UTF-8 lässt sich die Distanz von „rear“ und „front“ in eine Struktur laden und verarbeiten.
Damit sind die Voraussetzungen für das autonome Herumfahren gegeben. Die Klassenbibliothek habe ich bereits um die Klasse Automation erweitert:
from Automation.automation_events import AutomationEvents
# Automation Klasse
class Automation:
def __init__(self, programs = None):
self._eventController = AutomationEvents()
self._sensors = {}
self._programs = programs
self.get_programs().set_event_controller(self.get_event_controller())
self._car = None
def set_car(self, car):
self.get_programs().set_car(car)
self._car = car
def get_car(self):
return self._car
def get_event_controller(self):
return self._eventController
def add_sensor(self, sensor_name, sensor_object):
self._sensors[sensor_name] = sensor_object
def get_sensors(self):
return self._sensors
def get_programs(self):
return self._programs
def autoprogram(self, program_name):
result = {}
if self.get_programs():
if program_name == "autoprogram_one":
result = self.get_programs().program_one()
if program_name == "autoprogram_stop":
result = self.get_programs().program_stop()
return result
und hier das Programm „autoprogram_one“: Es ist ganz einfach.
from Automation.automation_events import AutomationEvents
class AutomationPrograms:
def __init__(self):
self._car = None
def set_car(self, car):
self._car = car
def get_car(self):
return self._car
def set_event_controller(self, event_controller: AutomationEvents):
self._event_controller = event_controller
def get_event_controller(self):
return self._event_controller
def get_sensors(self):
return self.get_car().get_sensors()
def program_one(self):
result = {}
sensors = self.get_sensors()
eventcontroller = self._event_controller
for sensor_name in sensors:
sensor_result = sensors[sensor_name].read_one()
result[sensor_name] = sensor_result
event = eventcontroller.find_event("FORWARD", "MOVE")
try:
if result["UltraSonic"]["front"] >= 35:
event = eventcontroller.find_event("FORWARD", "MOVE")
elif result["UltraSonic"]["front"] < 35:
event = eventcontroller.find_event("KOLLISIONFRONT", "OBSTACLE")
elif result["UltraSonic"]["rear"] >= 35:
event = eventcontroller.find_event("BACKWARD", "MOVE")
elif result["UltraSonic"]["rear"] < 35:
event = eventcontroller.find_event("KOLLISIONBACK", "OBSTACLE")
except:
pass
result = event
return result
Die Car Klasse besitzt nun eine Automation, die man während der Initialisierung konfiguriert:
import sys
sys.path.append("..")
import time
from Automation.automation import Automation
from Automation.automation_programs import AutomationPrograms
from car import Car
from Motor.bot_motor import BotMotorController
from Sensors.ultrasonic import UltraSonic
sensor_object = UltraSonic()
programs = AutomationPrograms()
selfDriving = Automation(programs)
selfDriving.add_sensor("UltraSonic", sensor_object)
motorcontroller = BotMotorController(default_speed=45, max_speed=100)
motorcontroller.add_motor("Motor1", 19, 13, 26, True, True, 50)
motorcontroller.add_motor("Motor2", 27, 17, 22, True, False, 50)
newcar = Car("Lukes Car", motorcontroller, None, selfDriving)
newcar.start()
newcar.drive("autoprogram_one")
Die Testfahrt per Automation:
Nachtrag:
Um den Pico (oder den ESP32) mit dem JETSON Nano Board verwenden zu können, muss die UART Schnittstelle: /dev/ttyTHS1 angesprochen werden anstatt /dev/ttyS0.