Problem beim programmieren von Roboterauto

  • Dieses Motor_stop() ist zu viel. Dann dreht er sich gar nicht mehr. Sobald er wieder ausser Reichweite ist, fährt er selber wieder vorwärts.

    Hier habe ich jetzt einen Augenblick überlegen müssen, um zu verstehen, warum das so ist. Mein Tipp war in diesem Punkt also falsch. Da siehst Du, dass auch Leute, die in der Programmierung alt geworden sind, noch Denkfehler machen. That's life.

  • Okey. Dann werde ich ihn fürs erste noch offen lassen. Aber nocheinmal, ich kanns nicht genug sagen, vielen Dank an alle die mich in diesem Thread unterstützt haben.

    Die Hand voller Asse, doch das Leben spielt Schach.


    Erfolg besteht aus drei Buchstaben: Tun

    Goethe

  • Hallo zusammen.

    Ich hätte da eine Frage.

    Um meinem Roboterauto den Autopiloten noch besser zu lernen, möchte ich vier Ultraschallsensoren, hc-sr04, anschliessen.

    Links, Rechts, Hinten und Vorne. Dafür habe ich mir noch einmal zwei Sensoren bestellt und dazu noch den Levelshifter von Joy-It, diesen Hier: https://joy-it.net/files/files/Pr…T-Anleitung.pdf

    Als ich dann den Shifter angeschaut habe, fragte ich mich plötzlich ob ich an das Ding zwei Ultraschallsensoren ran hängen kann. Von den Anschlüssen her, meine ich ja, aber die Stromversorgung macht mir sorgen. Muss ich da auch eine Parallelschaltung für den 3.3v Pin am Raspberry machen? Oder geht es gar nicht? Für den 5v Anschluss verstehe ich das ich eine bauen muss. Und da der 3.3v nur 50ma Strom her gibt, wollte ich zur Sicherheit euch um Rat fragen.

    Freundliche Grüsse und danke im Vorraus

    Raspbifriend

    Die Hand voller Asse, doch das Leben spielt Schach.


    Erfolg besteht aus drei Buchstaben: Tun

    Goethe

  • Mit dem Spannungswandler COM-KY051VT habe ich keine Erfahrung, aber hier ist ein Beschaltungsvorschlag für dieses Bauteil und den Untraschallsensor.

    Interessant finde ich auch diesen Beitrag, bei dem 4 Ultraschallsensoren an einen Raspberry angeschlossen werden sollen, allerdings ohne Spannungswandler, sondern mit Spannungsteilern, die mit Widerständen aufgebaut wurden. Leider steht in dem Beitrag nicht, ob das Vorhaben erfolgreich war. Wichtig finde ich in diesem Beitrag den Hinweis, dass sich Ultraschallsensoren unter ungünstigen Umständen gegenseitig stören können, wenn etwa ein Sensor statt eines direkten Echos einen Ton aufnimmt, der mehrfach reflektiert wurde und folglich bei der Datenauswertung einen großen Abstandwert gibt. Ob dieser Effekt tatsächlich auftritt, wenn die 4 Sensoren in unterschiedliche Richtungen messen, wird sich in der Praxis zeigen. Unter Umständen wird es nötig sein, die Sensoren mit ausreichendem zeitlichem Abstand zu triggern.

  • Vielen Dank. Ich hoffe dass die Sensoren sich nicht gegenseitig stören werden. Ich hätte es auch mit Widerständen machen können, aber ich hatte noch keine Erfahrung und wollte den Sensor nicht in die Luft jagen. Aber ich denke es sollte funktionierte weil der Levelshifter nur für die Datenübertragung notwendig ist und nicht, wie ich zu erst dachte, für die Stromversorgung.

    Ich hoffe dass ich da nicht ganz falsch liege.


    Vielen Dank

    Raspbifriend

    Die Hand voller Asse, doch das Leben spielt Schach.


    Erfolg besteht aus drei Buchstaben: Tun

    Goethe

  • Hallo zusammen

    Ich hätte mal wieder eine Frage.

    Alles läuft hervorragend.

    Doch das Programm kommt fast nicht nach mit den Daten der nun vier Ultraschallabstandsensor HC SR-04.

    Das Programm stoppt die Räder teilweise viel zu spät obwohl die Sensoren schon lange gemeldet haben dass sie zu nahe sind.

    Ich wollte nun fragen wie man in GPIOzero den zeitlichen Abstand zwischen den einzelnen Messungen verändern kann.

    Ich habe das ganze Thema zum Sensor in den ReadTheDocs durchgelesen aber habe nichts gefunden.

    Vielen Dank für Eure Hilfe

    Raspbifriend

    Die Hand voller Asse, doch das Leben spielt Schach.


    Erfolg besteht aus drei Buchstaben: Tun

    Goethe

  • Hallo,

    Ich habe das ganze Thema zum Sensor in den ReadTheDocs durchgelesen aber habe nichts gefunden.

    Edit: Bin im Modul verrutscht!

    Wenn ich mich nicht täusche, habe ich was in der Doku gefunden:

    Zitat
    • sample_rate (float) – The number of values to read from the device (and append to the internal queue) per second. Defaults to 100.

    Wie sieht denn dein Code aus?

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

    Einmal editiert, zuletzt von Dennis89 (11. März 2021 um 13:17)

  • Momentan sieht er so aus.

    Ich hoffe es hat nichts verschoben. Das das Programm teilweise nicht nachkommt ist mir in einer anderen Datei aufgefallen wo es die Entfernung anzeigen soll. Allgemein ist es meiner Meinung nach unnötig dass die Sensoren so vielmal nacheinander messen, da das Auto sowieso nicht so schnell fährt.

    Die Hand voller Asse, doch das Leben spielt Schach.


    Erfolg besteht aus drei Buchstaben: Tun

    Goethe

  • Dein Auto stoppt also teilweise zu spät? Was bedeutet teilweise?

    Damit es rechtzeitig stoppt brauchst du doch jede Veränderung der Wegstrecke, ich verstehe nicht wieso du jetzt sagst, dass du findest die Sensoren werden zu oft abgefragt. Meiner Meinung nach widerspricht sich das.

    Ist dir die Differenz zwischen den Sensorwerten und der Aktion der Motoren jetzt aufgefallen, weil dein Auto zu spät stoppt oder weil ein anderes Programm(wie sieht das aus) dir die Werte nicht wie erwartet angezeigt hat?

    Bitte ganz genau und alle Informationen in einem Beitrag schreiben.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Die wesentliche Dokumentation ist die folgende: Programmierschnittstelle Distanzsensor sowie Quellcode. Der zuletzt angegebene Link erscheint mir besonders ergiebig, obwohl das Verständnis des Quellcodes natürlich einiges Einfühlungsvermögen verlangt. Nach meinem Verständnis des Quellcodes verwenden die meisten Eingabesensoren (nämlich alle, die von SmoothedInputDevice abgeleitet sind, da gehört DistanceSensor dazu) eine Queue, in der sie die eine bestimmte Anzahl der zuletzt gemessenen Werte speichern. Bei der Berechnung der Distanz werden dann Mittelwerte gebildet. Diese Mittelwertbildung führt wohl dazu, dass das Unterschreiten eines Mindestabstands erst mit einiger Verzögung festgestellt wird, wenn der Abstand mit der Methode distance abgefragt wird.

    Eine Queue (der deutsche Ausdruck ist "Warteschlange") ist eine Datenstruktur, die eine feste Zahl von Werten speichert und die so verwendet wird, dass immer die zuletzt erhaltenen Werte gespeichert sind. Wenn eine Queue bereits voll ist und ein weiterer Wert gespeichert werden soll, wird zunächst der älteste Wert gelöscht, um Platz für den neuesten Wert zu schaffen.

    Im Zusammenhang mit Eingabesensoren werden Queues verwendet, um Mittelwerte über die zuletzt erhaltenen Meßwerte binden zu können. Von der Mittelwertbildung erhofft man sich den Ausgleich von Meßungenauigkeiten und zufälligen Meßfehlern.

    Die Länge der Queue für den Distanzsensor wird in der Dokumentation mit 30 angegeben; im oben angegeben Link "Quellcode" steht aber der Wert 9. Welcher Wert stimmt, weiß ich nicht.

    Die Distanzsensoren messen einmal in 60 ms (also einmal in 0.06 s), dieser Wert wird vom Hersteller des Sensors empfohlen, damit einem Echo ausreichend Zeit zum Eintreffen bleibt, bevor der nächste Meßton ausgesendet wird. 30 Messungen verlangen also 1,8 Sekunden, nach dieser Zeit ist die Queue mit Werten gefüllt. Der gemittelte Wert, der durch die Methode distance geliefert wird, ist also ein Mittelwert aus einem Zeitfenster von 1,8 Sekunden.

    Man kann die Länge der Queue einstellen, dazu gibt man bei der Erzeugung des Sensorobjekts das zusätzliche Agrument queue_len an. Statt

    Python
    ultraschall_rechts = DistanceSensor(echo=23, trigger=22)

    ist also zu schreiben:

    Python
    ultraschall_rechts = DistanceSensor(echo=23, trigger=22, queue_len=6)


    Mit einer Queue-Länge von 6 werden nur noch 6 Meßwerte berücksichtigt; die Methode distance bildet die Werte dann über einem Zeitfenster von 6*0.06 = 0.36s. Es könnte also sein, dass wir soeine raschere Reaktion erhalten. Allerdings wird das System dann auch empfindlicher gegenüber Meßfehlern, weil ja die Mittelwertbildung nicht mehr so stark ausgleichen kann, wenn nur noch wenige Werte in die Rechnung eingehen.

    Mein Vorschlag: Die Distanzsensoren versuchsweise mit dem zusätzlichen Argument queue_len herstellen und für dieses zusätzliche Argument verschiedene kleine Werte (z.B. 6, 9, 12, 15) auspobieren. Das sollte natürlich für alle vier Sensoren geschehen, die immer Queues gleicher Länge haben sollen.

    Es wäre interessant, das Ergebnis dieser Versuche zu erfahren.

    ==============================================================

    Noch eine Bemerkung zum Code, die mit dem wahrgenommenen Problem der langsamen Reaktion nichts zu tun hat: Die Anweisungen in den Zeilen 70 und 62 können weggelassen werden, da sie Zufallswerte erzeugen, die nicht verwendet werden. Die Aufrufe von

    Code
    if random.choice([1,2]) == 1:

    in den Zeilen 71 und 63, die ja tatsächlich in if-Anweisungen verwendet werden, sind ausreichend.

    (Das ist natürlich eine ziemlich pingelige Bemerkung, aber ich bin es gewöhnt, auf solche Dinge zu achten. Das ist unvermeidlich, wenn man sein Leben in der Programmierung zugebracht hat. Sorry.)

    Einmal editiert, zuletzt von Boris-Gaertner (11. März 2021 um 21:31)

  • Wobei man da noch ergänzen könnte das if random.choice([1, 2]) == 1: ein bisschen kompliziert und auch willkürlich aussieht. Warum 1 und 2? Warum nicht 0 und 1 oder 42 und 23 oder “joah” und “och nöö”? Man will etwas das mit ~50% wahr oder unwahr ist, also wären bei choice() als Werte eben diese Wahrheitswerte am naheliegendsten if random.choice([True, False]):. Damit spart man sich einen Vergleich, aber das baut jedes mal unnötig eine Liste mit zwei Werten auf. 0 und 1 sind im boole’schen Kontext in Python unwahr und wahr, also if random.randint(0, 1): oder if random.getrandbits(1):.

    Boris-Gaertner Noch ein bisschen Korinthenkackerei: Das was Du allgemein als Queue/Warteschlange beschreibst ist eine Spezialisierung davon: ein „ring buffer“/Ringpuffer. Queues allgemein sind nicht in der Länge begrenzt, beziehungsweise ist das ”vergessen” von zu alten Elementen nur eine Variante mit einer Begrenzung umzugehen. Andere wären ein Fehler/eine Ausnahme oder ein blockierender Aufruf der solange wartet bis wieder Platz ist.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Den ausführlichen Post mit den Daten kann ich euch erst am Abend senden. Aber ich habe 1 und 2 genommen weil es in einem Beispiel so war aber ich kann auch gut 42 und 313 nehmen. Aber ich glaube ich nehme 0 und 1.

    Noch eine Bemerkung zum Code, die mit dem wahrgenommenen Problem der langsamen Reaktion nichts zu tun hat: Die Anweisungen in den Zeilen 70 und 62 können weggelassen werden, da sie Zufallswerte erzeugen, die nicht verwendet werden. Die Aufrufe von
    Code if random.choice([1,2]) == 1:


    in den Zeilen 71 und 63, die ja tatsächlich in if-Anweisungen verwendet werden, sind ausreichend.

    (Das ist natürlich eine ziemlich pingelige Bemerkung, aber ich bin es gewöhnt, auf solche Dinge zu achten. Das ist unvermeidlich, wenn man sein Leben in der Programmierung zugebracht hat. Sorry.)

    Macht nichts. Aber wenn ich das wegnehme, dann wird ja immer bis zum nächsten ändern der Variable der gleiche Wert angezeigt. Das wäre doch irgendwie blöd wenn er immer hinten zu nahe ist und immer in die gleiche Richtung wendet. Natürlich ist es mehr aufwand, aber das Programm ist ja, vermute ich, sehr klein im gegensatz zu andern. Da ist es jetzt nicht so schlimm.

    Die Hand voller Asse, doch das Leben spielt Schach.


    Erfolg besteht aus drei Buchstaben: Tun

    Goethe

  • Tundrameise Wenn Du was wegnimmst? Ich habe nicht gesagt wegnehmen, sondern durch etwas einfacheres, direkteres ohne unnötige Liste und Vergleich ersetzen. Eben direkt eine ganze Zufallszahl zwischen 0 und 1 erzeugen, und ohne unnötigen Vergleich.

    `choice()` muss die Länge der Liste ermitteln, dann einen zufälligen Index zwischen 0 (inklusive) und der Länge der Liste (exlusive) ermitteln und über den Index dann auf die Liste zugreifen. Für den zufälligen Index wird letztlich `random.random()` um eine Gleitkommazahl zwischen 0 und 1 zu erzeugen aufgerufen. Was seinerseits intern wohl `random.getrandbits()` aufruft. Diese Gleitkommazahl wird dann mit der Länge der Liste multipliziert und in eine ganze Zahl umgewandelt. Um damit dann als Index einen Wert aus der Liste zu holen. Den Du dann mit einem festen Wert vergleichst um einen Wahrheitswert zu bekommen.

    Alternativ kann man einfach ``random.getrandbits(1)`` aufrufen. Und das war's. Keine unnötige Liste, keine Gleitkommazahl, keine Multiplikation, kein Umwandeln in eine ganze Zahl, kein Indexzugriff, und kein Vergleich.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Man will etwas das mit ~50% wahr oder unwahr ist, also wären bei choice() als Werte eben diese Wahrheitswerte am naheliegendsten if random.choice([True, False]):. Damit spart man sich einen Vergleich, aber das baut jedes mal unnötig eine Liste mit zwei Werten auf. 0 und 1 sind im boole’schen Kontext in Python unwahr und wahr, also if random.randint(0, 1): oder if random.getrandbits(1):.

    Ich hätte ja spontan random.choice([motor_left, motor_right])() genommen. Da baut man zwar wieder eine Liste, dafür spart man sich die if-Abfrage. Keine Ahnung, was da besser ist, auf jeden Fall wäre es eine weitere Option.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!