Timeout Fehler

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo Freunde,

    ich habe folgendes Problem. Immer wenn ich folgendes Skript starte bekomme ich nur "Timeout" ausgegeben, aber startet nicht :wallbash:. Ich weiß nicht mehr weiter ich hoffe mir kann jemand dabei helfen alles ins laufen zu bekommen.

  • Okay, na dann vielen Dank dir... Linus . Wollte mir nur hier noch einmal Hilfe einholen, damit es vielleicht etwas schneller geht. War nicht irgenwie beleidigend dem Besitzer der Seite gegenüber, weil er mir nach wie du schon gesagt hast 4h nicht direkt antwortet. Bin nun mal leider ein sehr ungeduldiger Mensch und möchte alles schnell hinter mich bringen.

  • Hallo TimRoe,

    das ist für mich (beinahe) logisch bzw. nicht besonders ungewöhnlich:

    Die Bedingung GPIO.input(GPIO_END_PIN) == GPIO.LOW and time.time()-start_time < TIMEOUT bleibt True, solange das Pin GPIO_END_PIN low ist und die gemessene Zeitdifferenz kleiner als die in der Konstanten TIMEOUT definierte Zeitspanne ist. Jetzt stellt sich noch die Frage, ob GPIO_END_PIN in der Zwischenzeit wirklich jemals high wird. Falls nein, beißt grundsätzlich nur die Timeout-Überprüfung an.

    Im else-Zweig der while-Schleife prüfst Du dann zuerst mit if, ob der Timeout eingetreten ist und gibst nur im else-Fall die gemessene Zeit aus. Davon abgesehen, dass ich aus der Ferne nicht feststellen kann, ob der GPIO_END_PIN aufgrund Deiner Beschaltung wirklich high werden kann, ist an Deinem Script auch noch problematisch, dass die zeitkritische Abfrage im Auswerte-if hinterher mittels time.time()-start_time >= TIMEOUT mit time-Funktionsaufrufen und neuer(!) Systemzeit nochmals neu berechnet wird! Bei solchen zeitabhängigen Sachen würde ich lieber bei jedem Schleifendurchlauf eine Variable mit der gemessenen Zeitdifferenz setzen. Damit würde für die gesamten Zeitabfragen über diese Variable eine konstante Zeitdifferenz verwendet und nicht in jeder Bedingung eine möglicherweise leicht unterschiedliche Zeitdifferenz. Das kann bei echten Zeiten knapp am Timeoutwert seltsame und unerwartete Effekte hervorrufen.

    Die sleep-Wartezeit von 1ms für die while-Schleife finde ich auch etwas arg kurz. Hier würde ich eher mit 10ms (oder so) arbeiten. Von Windows (gut, ist kein Maßstab) kenne ich, dass Sleeps eine Granularität von ca. 1/64 Sekunde haben. Ich weiß nicht sicher, ob das unter Linux und speziell auf dem RPi und unter Python besser ist.

    schlizbäda

  • Ach ja, jetzt sehe ich es erst:

    Wird eigentlich der Pin GPIO_BEGIN_PIN durch die Beschaltung jemals LOW (siehe Script Zeile 19)? Falls nicht, hat start_time den Wert 0 aus der Initialisierung (die ist shice, warum nicht start_time = time.time()?) und das bedeutet 01.01.1970 (da flog selbst ich noch mit den Mücken). Auf jeden Fall ist das Ergebnis von time.time()-start_time dann immer größer als jeder vernünftige Timeout und die zweite While-Schleife zur Zeitmessung wird erst gar nicht ausgeführt! Sofort sehen würde man sowas mit einer Printanweisung, die die tatsächlich gemessene Zeitdifferenz auch noch rausschreibt (irgendwas deutlich größer als 10^9 Sekunden)

  • In einem Script gibt es kein exit() das ist nur für die Interaktive Konsole! Bitte importiere sys und nutze dann sys.exit(1) für Fehlerhafte Ausführung und sys.exit(0) für korrekte Ausführung (exit code)

    Desweiteren finde ich den von dir gewählten Weg nicht von Vorteil. Zum einen verfälschen die Blockaden (time.sleep) die Messwerte, zum anderen auch die Abarbeitung der Codezeilen. Hinzu kommt: Wird "time.sleep" zu niedrig gesetzt wird die CPU zu sehr belastet - das Script verursacht dann nahezu 100% Auslastung. Wird das Script aber zu lange blockiert verfälscht es den Messvorgang. Teufelskreislauf :X

    Offensichtlich möchtest du die verstrichene Zeit zwischen START und END messen...

    Wird der GPIO zum START getriggert beginnt die Messung. Wird END getriggert endet die Messung und soll dann anhand der verstrichenen Zeit eine zurückgelegte Strecke ausgeben?

    Zusätzlich hast du auch noch einen TIMEOUT eingebaut oder willst sowas haben... Soweit richtig verstanden?


    PS: Bitte kein Crossposting. Keiner möchte alle anderen Foren abgrasen um evtl. auf dem aktuellen Stand deines Vorhabens zu sein und keiner möchte sich unnötige Arbeit machen falls dein Problem schon anderswo gelöst wurde - sowohl wir noch User in anderen Foren.

  • Desweiteren finde ich den von dir gewählten Weg nicht von Vorteil. Zum einen verfälschen die Blockaden (time.sleep) die Messwerte, zum anderen auch die Abarbeitung der Codezeilen. Hinzu kommt: Wird "time.sleep" zu niedrig gesetzt wird die CPU zu sehr belastet - das Script verursacht dann nahezu 100% Auslastung. Wird das Script aber zu lange blockiert verfälscht es den Messvorgang. Teufelskreislauf :X

    Sehe ich auch so, da wäre eine interruptgesteuerte Auswertung wahrscheinlich viel besser...

  • ...aber der Autor hat in 4,5h noch nicht auf den Kommentar unter dem Tutorial geanzwortet. :shy:

    also wie kann der Autor nur?!?

  • Linus ist jetzt okay, war der größte Fehler meines Lebens nach 4h keiner Antwort hier mal nachzufragen und um weitere Hilfe zu bitten. Gehe mich jetzt umbringen... :@

    Okay genug Ironie für heute.

    meigrafd  schlizbäda

    Wie linusg schon gesagt hat, habe ich das Skript nicht selbst geschrieben, dazu kenne ich mich zu wenig mit Python aus (gar nicht).

    Ich habe diesen von folgender Seite entnommen, da ich das dort aufgeführte am nachbauen bin.

    https://tutorials-raspberrypi.de/infrarot-licht…digkeit-messen/

    Vielleicht könnt ihr mir so weiter Helfen und den Code gegebenenfalls (schnell) korrigieren.

    Hier nochmal meine Variante das Aufbaus (nicht das beste)

    Danke für eure Hilfe <3

  • Hallo linusg,

    Hofei es gibt keine - schau mal in Zeile 27-29 ;)

    zusammen mit Zeile 24 bis 26 ist da auch nichts außer "timeout" zu erwarten.

    Das sagt mir, dass der Code so läuft wie programmiert. Dann muss man nur noch so programmieren, wie man's haben möchte. Die logischen Fehler sind eh die schwersten aufzufindenden Programmierfehler.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Linus: Sobald jemand nicht nur an einem Ort um Hilfe fragt ist es IMHO Crossposting ;)

    schlizbäda: Genau darauf will ich hinaus :fies:

    Zunächst sollte man wissen das ein Interrupt basiertes Script besser ist als eins mit ner while Schleife.. Warum ist relativ einfach: Weniger CPU Auslastung, genauer, einfacher.

    Dann sollte man wissen das in der Interrupt_Callback nichts wildes gemacht werden sollte, da sonst diese wichtige Funktion derweil blockiert wird und in der Zeitspanne kein weiterer ISR erfasst werden kann.

    Und dann sollte man noch wissen das die Callback in einem separaten Thread läuft... Also das Script ist ein Thread, dort können Dinge abgehandelt werden, und die ISR Funktion ist davon abgekoppelt und quasi eigenständig.

    Auf dieser Grundlage erstellt man also ein Script, um 2 Taster zu bedienen, sowie eine Callback die bei einem Flankenwechsel nur den ausgelösten Pin, sowie den Zeitpunkt des Events in ein Queue ablegt. Dieses Queue verarbeitet man dann im Script-Thread.

    Da Du ( TimRoe ) leider keinerlei Angaben zum Sinn und Zweck deines Vorhabens geschrieben hast, muss ich leider mit den spärlichen Informationen irgendwie arbeiten....

    Normalerweise wird der Interrupt-Callback nur channel übergeben, also der GPIO der das Event ausgelöst hat.

    Wir müssen der Funktion aber auch das Queue zugänglich machen und die hierfür eleganteste Vorgehensweise ist mithilfe von partial direkt die Übergabe zu modifizieren.

    Für den Zeitpunkt des Events arbeitet man hier nun am besten mit dem datetime Module, also fügen wir bei einem Interrupt-Event jedes mal ein datetime.now() ins Queue mit ein um den exakten Zeitpunkt des Flankenwechsels zu haben.

    Die beiden Taster nenne ich mal switch_start und switch_end - so sollte eindeutig klar was sich dahinter verbirgt... Generell ist es super die Variablen vernünftig zu benennen.

    Das Grundgerüst sähe dann also wie folgt aus:

    Die while ist wie gesagt unabhängig von den GPIO's. Findet ein Flankenwechsel statt wird dieses Event mit exakter Zeit ins Queue eingetragen. Die while prüft dann nur ob sich etwas im Queue befindet, ruft den Inhalt ab und kann dann den exakten Zeitpunkt verwenden - die while kann auch übelst zu tun haben, was der extra ISR Funktion nicht stört, die Verarbeitung findet dann nur verzögert statt aber die Zeiten bleiben stimmig.

    Da fehlt natürlich noch was... ich kau dir das nicht fix&fertig vor, wenn dann erarbeiten wir das gemeinsam.

  • Hi Andreas,

    Das sagt mir, dass der Code so läuft wie programmiert. Dann muss man nur noch so programmieren, wie man's haben möchte.

    Jup... und die Hardware so aufbauen, dass der Code wie erwartet funktionieren kann.

    war der größte Fehler meines Lebens nach 4h keiner Antwort hier mal nachzufragen und um weitere Hilfe zu bitten

    Das ist ja schön, du hast also noch keine schlimmen Fehler in deinem Leben gemacht. Hiervon geht die Welt nicht unter, ich bin nur von deiner Haltung nicht ganz überzeugt. Wie du selbst sagst, du verstehst den Code nicht, also hast du zwei Optionen, wenn dieser nicht das gewünschte Ergebnis bringt:

    - Selbst lernen und probieren, hat den Nebeneffekt, dass du auch noch eine Programmiersprache lernst. Du musst den Raspi übrigens nicht in Python programmieren

    - Darauf hoffen, dass andere das Problem für dich lösen, sei es der Autor oder im Forum. Das kann Freitags Nachmittags allerdings etwas dauern.

    Ich würde dir, selbst wenn sich das Problem hier lösen lässt, die erste Variante ans Herz legen. Glaube mir, so einen Code selbst schreiben zu können ist deutlich zufriedenstellender als einen fertigen zu nehmen, der nicht geht... finde ich zumindest.

  • Hallo,

    Zitat


    dazu kenne ich mich zu wenig mit Python aus (gar nicht).

    Warum nutzt du dann Python? Bzw. warum lernst du es nicht zumindest so weit, dass du dir grob zu helfen weißt? Was du ja jetzt erwartest, ist, dass dir jemand eine Lösung auf dem Silbertablett serviert... Also jemand in seiner Freizeit dir etwas programmiert, was du selber nicht verstehst und scheinbar nicht wirklich gewillt bis, zu lernen...

    Hier im Forum - wie auch anderen Foren - gibt es Hilfe zur Selsthilfe. Das ist kein "Programmier' mir was" Forum. Für so was gibt es übrigens Entwickler, die das gegen Geld machen. Da bekommst du auch maßgeschneiderten Code nur für dich.

    Zum Code: der ist an vielen Stellen stark suboptimal... solltest du so nicht verwenden und erst recht nicht als brauchbares Beispiel für Python-Programmierung ansehen.

    Gruß, noisefloor

  • Guten Abend,

    meigrafd : Zu deinem Code im Post 17 würde ich gerne ein paar Fragen stellen, bzw. stelle ich ein paar Fragen und würde mich freuen, wenn du mir ein klein wenig "Input" geben könntest.

    1. Eine grundlegende Syntax-Frage: Warum stehen die Argumente in Zeile 33 q.put((datetime.now(), channel)) in doppelter Klammer?

    2. wenn ich in der main() Schleife außerdem überprüfen müsste, ob das Callback mit steigender oder fallender Flanke ausgelöst wurde, ist es dann besser zwei verschiedene callback-Funktionen zu definieren, oder ist es besser das Callback mit einer dritte Variablen aufzurufen?

    Also so:

    oder so:

    oder ist beides falsch?

    vielen Dank schon mal

    und Grüße

    lippih

    Einmal editiert, zuletzt von lippih (21. Januar 2018 um 20:10)

Jetzt mitmachen!

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