Probleme mit unterschiedlichen Ausführungszeiten

  • Hallo liebe Community,

    ich nutze aktuell im Rahmen einer Abschlussarbeit den Raspberry PI und bin quasi absoluter Python-Neuling, jedoch kein Programmierneuling, da ich quasi jeden Tag mit MATLAB arbeite und im Studium auch C/C++ gelernt habe.

    Die Aufgabenstellung ist etwas zu komplex, um sie hier ausführlich darzustellen (wie gesagt -> Abschlussarbeit), daher habe ich mir ein simples Programm überlegt, bei dem ich vor exakt dem selben Problem stehe.

    Ich möchte mithilfe des PIs (PI 3 Model B), einer externen Soundkarte (Daffodil US01), einem Mikrofon (Mikrofon [Anzeige]) und einem Python-Skript die Schallgeschwindigkeit messen.

    Das Programm gibt über einen Mono Lautsprecher einen Sound wieder (ein Sägezahn-beep als wav-Datei mit etwas Verzögerung vorher, da beep bei mir keine Tonausgabe erzeugt) und in einem fest definierten Abstand davor befindet sich das Mikrofon. Dieses Mikrofon nimmt dann wenige Sekunden auf (ich nutze pyaudio), anschließend wird das ganze in ein numpy-Array umgewandelt und über eine for-Schleife mit Schwellwerterkennung festgestellt, zu welchem Abtastwert dieser beep auftrat ..

    Dass das mit dem Schwellwert noch nicht so optimal gelöst ist und mit dem wav-File auch, das sehe ich ein, das bereitet mir aber keine Probleme .. was mir Probleme bereitet ist, dass bei mehrfacher Ausführung die Startzeit des beeps um bis zu 30msec schwankt, bzw. etwa 1000-2000 (!) Abstastwerte .. was eigentlich klar ist, da ja die Zeit für das beepen und dem Beginn der Aufnahme in den seltensten Fällen exakt gleich bleiben wird ..

    Meine Frage ist jetzt: wie bekomme ich das ganze synchron und reproduzierbar (für meine Zwecke später wären etwa 0,2-0,4msec, also 10-20 Abtastwerte Schwankung tolerierbar)

    Hier mal der Quelltext:

    Erzeugt diese Ausgabe:

    ohne_thread.png


    Das Array sieht so aus:

    plot.png

    Dass ich den Peak nicht genau treffe, okay, damit hab ich gerechnet, aber dabei hätte ich immernoch etwa 10 Abtastwerte als Genauigkeit, daran liegt es nicht ..

    Ich habe es dann mal damit versucht, den beep als thread auszulagern, das hat die Situation verbessert, aber noch nicht im akzeptablen Rahmen:

    Mit der Ausgabe:

    mit_thread.png

    Das sieht schon etwas besser aus, aber nur etwas :/

    Vielleicht hat ja jemand eine Idee, eine libary, oder ein Stück Code, das mir hier helfen könnte :)
    Viele Grüße :)

  • Hallo HennesTD,
    zunächst mal allgemein, du kannst beim normalen Raspberrian nie sicher sein, dass eine bestimmte Aufgabe zu einem bestimmten Zeitpunkt ausgeführt wird, das liegt in der Planung der Threads begründet, die eben standardmäßig nicht deterministisch ist. (Der Preempt RT-Patch würde die Sache vermutlich verbessern und zumindest verhindern, dass dir andere Threads dazwischen funken (Real Time Priorität entsprechend setzen))

    Zum Code wäre zu sagen, dass du bei der sequenziellen Abarbeitung immer eine Verzögerung drin haben wirst, der os.system Befehl braucht sicherlich einiges an Zeit, da hier ein neuer Prozess gestartet wird.

    Für deine weitere Untersuchung würde ich mal eine Zeitmessung einbauen und schauen, was wie viel Zeit braucht, bzw. vllt. darüber die tatsächliche Verzögerung bestimmen.

    Allgemein bin ich mir gerade unsicher (ich habe von Python keine wirkliche Ahnung), wie der Programm genau abläuft, startest du die Aufnahme vor oder nach dem Aufruf von "aplay"?

    Gruß
    Chris

    PS: Muss es eigentlich Python sein, mein Gefühl sagt mir, dass Ausführzeiten bei C/C++ vorhersehbarer sind, als bei Python. (Garbage Collection, und andere Ideen des Interpreters die Ausführung mal kurz zu pausieren)

    PS2: Der Versuchsaufbau ist vorgegeben oder selbst ausgedacht? Falls nein könnte man durch einen kleinen Umbau könnte man da alle Zeitprobleme lösen.

    Edited once, last by ChrisvA (April 29, 2016 at 1:27 PM).

  • Hallo Chris,

    danke schonmal für die schnelle Antwort :)

    Das mit dem RT-Patch müsste ich mal ausprobieren, ich habe nur leider erst wieder ab Sonntag Zugriff auf den PI.

    Die Zeitmessung ala start = time.time() vor dem os-Befehl und delay = time.time() - start danach habe ich schon ausprobiert und später den delay von meiner gemessenen Zeit abgezogen, das hat leider keine Verbesserung gezeigt, da sich die beiden Zeiten völlig unabhängig veränderten :/

    Was mir außerdem aufgefallen ist:
    Habe ich kein Delay in der wav-Datei, dh. startet diese sofort mit dem beep, hört man manchmal nur einen Teil des Tons, manchmal sogar gar keinen, die Audioausgabe schient also auch immer eine unterschiedliche Verzögerung zu haben bevor sie überhaupt Sound ausgibt, evtl liegt es auch daran und ich müsste wirklich mit dem System-beep arbeiten, der momentan noch nicht funktioniert ..

    In dem Programm wird das File abgespielt, danach beginnt die Aufnahme mit dem Füllen des ersten Buffers, dieser wird an ein Array angehangen und der nächste Buffer gefüllt, das alles 10 mal, danach beginnt die Verarbeitung des Arrays um die Laufzeit zu bestimmen.
    Im zweiten Code wird das Abspielen des Sounds als Thread vom Hauptprogramm abgekoppelt, ich habe mir davon erhofft, dass die beiden Prozesse sich dann nicht mehr so stark beeinflussen, was ja auch der Fall zu sein scheint, nur nicht genug ..

    Es muss nicht Python sein, es war nur meine erste Wahl wegen des PIs (direkte Ausführung von Code -> direkt alles ausprobieren) und es ist (vor allem mit Numpy) sehr MATLAB-ähnlich, mir gefällt die Struktur einfach gut :)


    Der Versuchsaufbau ist völlig mir überlassen, ich habe auch überlegt ein Mikrofon direkt vor dem Lautsprecher zu platzieren und damit eine Normalisierung durchzuführen, indem ich die Laufzeit zu diesem Mikro abziehe, da habe ich aber das Problem, dass ich nicht weiß, ob ich mit 2 Mikrofonen überhaupt parallel arbeiten kann.
    Was wäre dein Vorschlag für einen Umbau?

    Ich beschreibe mal kurz und knapp worum es geht:
    Ich möchte mit 4 PIs eine Art Lokalisation aufbauen und würde gerne 3 PIs an die Decke hängen, einen vierten PI im Raum rumtragen und mit diesem beepen.
    Über die Laufzeit zu den 3 Decken-PIs soll dann der vierte lokalisiert werden.
    Dazu möchte ich den anderen 3 PIs per TCP mitteilen, dass sie zuhören sollen und die Messung starten, dann wird gebeept, die 3 PIs berechnen wie im Beispiel die Laufzeit und schicken das ganze über TCP o.ä. wieder zurück ..
    Generell basiert das ganze aber auf dem Problem, dass ich mir jetzt ausgedacht habe, denn wenn ich das nicht synchronisiert kriege, dann auch niemals das echte Problem :D

    Viele Grüße :)

  • Hi,
    so wie du das mit dem Versatz beschreibst, dürfte die Verzögerung bei der Ausführung des Befehls liegen. Ich würde deshalb den Sound direkt mit Python generieren und ausgeben (2. Thread!) https://stackoverflow.com/questions/8299…sound-in-python

    Meine Umbauidee geht bei der letzten Anwendung leider nicht mehr, die bestand darin Mikrofon und Lautsprecher an die selbe Stelle zu setzen und dann mit dem Echo eines Gegenstandes zu arbeiten. Daraus hätte man dann auch Abstand/Geschwindigkeit berechnen können.

    Ob das letztendlich aber überhaupt funktioniert weiß ich nicht, da du über TCP/WLAN mit Verzögerungen um Millisekundenbereich zu rechnen hast (Mein Pi 3 WLAN bis Router zeigt bei ping ~4ms an).

    Die Einzige Lösung, wenn du bei der Audiovariante bleiben möchtest , sehe ich darin, dass die 3 Pi's an der Decke ein aktives Echo senden, sobald der 4. Pi piepst und diese den Piep erkennen. Mit verschiedenen Sendefrequenzen kannst du die 3 DeckenPi's in der Aufzeichnung wieder trennen. Ob das aber innerhalb der 0.5ms Genauigkeit möglich ist, weiß ich nicht.

    Etwas komplexer könntest du das wie GPS aufsetzen, also mit gut synchronisierten Uhren.

    Gruß
    Chris

  • Hey,

    das mit den Verzögerungen wollte ich so lösen, dass ich den PIs sage, dass ich erst zu einer bestimmten Zeit anfange.
    Die PIs könnten mit dem Internet verbunden sein, ich könnte also zu (Beispiel!) 9,2 Sekunden sagen "ich piepe genau bei 10 Sekunden, hört ab dann zu!".
    Die TCP-Kommunikation soll also der reinen Informationsübertragung dienen und von der Laufzeitberechnung nachher möglichst getrennt werden (z.B. so wie ich das beschrieben habe).

    Ich würde dann mit synchronisierten Uhren arbeiten, also wie bei GPS, durch die geringe Schallgeschwindigkeit jedoch mit höherer Ortsgenauigkeit bei gleicher Zeitgenauigkeit, das ist die Idee hinter der Sache :)

    Die absolute Notlösung würde darin bestehen alle 4 PIs an die Decke zu hängen und die Soundquelle abzukoppeln und sie verkabelt von einem PC aus anzusteuern, der ebenfalls mit TCP kommuniziert, dann könnte man einen der PIs als "Normalisierungs-PI" nutzen und wäre delay-unabhängig.
    Damit hätte ich immernoch 3 Laufzeiten, die für eine exakte Lokalisation im 3D-Raum ausreichen (jaa, eigentlich braucht man 4, nicht aber wenn man sich nicht über(!) den Sensoren befinden kann :) )
    Aber wie gesagt, das sollte die Notlösung sein, schöner wäre ein verlässliches delay oder zumindest eine verlässliches Messung des delays auf dem Quellen-PI :P

    Grüße

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!