Geschwindigkeit mit GPIO Impuls berechnen

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

    benötige Eure Hilfe, da ich absolut auf dem Schlauch stehe.
    Es gibt zur Berechnung viele Beiträge im Netz und auch hier im Forum,
    aber ncihts was zu meinem Problem passt. Bei den Wetterstationen und Stoppuhren habe ich auch schon nachgesehen, aber dort ist die Berechnung etwas anders:

    meine zu lösende Aufgabe ist wie folgt:
    Ich habe eine Scheibe mit D=105mm (105 x 3.14 = 0.33m)
    Darin sind 3 Magnete die einen Impulsgeber triggern
    d.h. jeder Impuls sind 0.11m

    Ich möchte ausgeben: die Strecke während das script läuft und die aktuelle Geschwindigkeit
    Die Range sollte zwischen 2m/min und 50m/min betragen.

    Folgendes Script macht mich verrückt, da ich den Fehler (und auch das Problem) nicht mehr sehe:

    Ich möchte hiermit also die Zeit zwischen 3 Impulsen messen und diese dann zur Geschwindigkeitsberechnung weiterverarbeiten.

    Bin ich da überhaupt auf dem richtigen Weg?
    Brauche wirklich dringend Unterstützung!

    Danke

  • Ich wuerde es so probieren:

    Code
    Zaehlerstand ablesen
    sleep 5sec
    Zaehlerstand ablesen

    Aus der Anzahl der Impulse in 5 Sekunden laesst sich dann
    die Geschwindigkeit berechnen.

    Kleine Zeiten sind unter Linux fast nicht genau zu bestimmen,
    weil halt immer einiges lauft !

    Und den Zaehler nicht als float, sondern als int.

  • Hi,
    der Zentris hat schon richtig! es erkannt. Wo ist Dein stamptime (Zeitstempel)?

    Ich "arbeite" am selben (ähnlicher "Sache") schon lange.
    Bei meinen Testen habe ich mich SEHR!!!! gefreut, dass mir die "Mikrosekunden Auflösung" ausreichend ist.

    Meine Test´s, haben bei puren GPIO abfragen eine 0,2 zu 1500 Relation ergeben.
    D.h. - Zwischen zwei GPIO´s abfragen welche in ca. 200ms ausgelöst waren, wurden ca. 1500 Mikrosekunden generiert. (schon nicht schlecht!)
    Dies wollte ich (WIRD!) mit dem Interrups realisiert. (Nun hier hapert es immer noch an den Programmierungsgrundlagen ... das schaffe ich aber! - irgendwann ... :)

    Für eine Zusammenarbeit werde eventuell (hier! - damit andere auch was davon haben / profitieren, wie auch wir eine Hilfe von Forum- Experten eventuell bekommen) interessiert.

    Meine Deutsch- Artikulierung lässt viel zu wünschen, :blush: das Denken hat auch schwer nachgelassen, ... mal schauen.

    Gruß
    Georg

    Sollte ich "Müll- reden" :blush: - bitte mich (?) "auf die Nuss" hauen. :huh:

  • [/i]Danke für die Informationen und die schnellen Antworten!

    Mit dem stamptime ist genau mein Problem.
    Ich habe in den letzten Wochen sooo viele Seiten gelesen, dass ich schon garnicht mehr weiß, wo die ganzen Informationen waren.
    Es gibt glaube ich gelesen zu haben, das auch recht kurz mit timeit zu realisieren.

    Ich bin absoluter Neuling und kann mir nur mit Codeschnipseln und Try-And-Error helfen, was natürlich recht mühselig ist.

    @ Tell: (erstmal Danke für die Antwort)
    Ich weiß, das ist der eine Weg Zeit vorgeben => dann Zählerstände Neu von Alt subtrahieren.
    Das wollte ich aber so nicht, da ich sonst das Script für 5 sec anhalten muss.
    Die aktuellen Werte werden mit Webiopi auf Localhost gebracht, daher würde ich nur alle 5 sec eine aktualisierung der Werte erhalten. (Oder liege ich da falsch ???)

    Der andere Weg ist halt die Zeit zwischen 3 Impulsen zu messen.
    Das wäre dann im Umkehrschluss so: das System läuft langsam, braucht daher nicht so oft aktualisiert zu werden.

    georg Lu
    Ich bin froh, dass ich nicht alleine bin ... und Deinem Usernamen zu entnehmen, sind wir ungefähr im gleichen Alter.

    Zentris
    ähm, das ist genau mein Problem: ich weiß nicht wie!
    Er nimmt die Zeit nur aus der Variablen die oben angegeben ist und die Geschwindigkeit wird aufaddiert.

    Ich verstehe zwar das Problem, bekomme es aber wie georgLu nicht in Code umgesetzt.

  • Hallo,

    ich bin auch neu im Raspi-Gewerbe :-). Wenn ich mir den Beitrag so durch lese könnte ich mir vorstellen das mit der wiringpi2 library eine Löung zu finden ist. Warum? Es ist eine Funktion enthalten namens millis(). Dises funktion gibt Laufzeit des Programms seit dem ersten Aufruf. Das heisst bei jeder Abfrage bekommt man Miilisekunden, die die Laufzeit des Programms repräsentieren. Wenn nun jetzt bei jedem Impulseingang die millis() aufgerufen wird. der Werden abgespeichert und nach 3 x die Delta Zeit zum ersten Wert der drei Durchläufe ermittelt wird ergibt sich m.E. nach eine Gesamt Deltazeit in der Art ( Deltazeit ist Millisekunden bei 3. Impuls - Millsekunden 1. Impuls), also eine Gesamtlaufzeit. Verrechnet mit den Massen der Scheibe könnte man dooch eine Geschwindikit ermitteln.

    Grüße aus Nürnberg

  • Ich hab' zwar jetzt mit Python so gar nix am Hut ... aber das hat je erst mal nichts mit einem Lösungsansatz zu tun.
    Imho ist das einer der typischen Fälle in dem eine ISR (Interrupt Service Routine) zum Einsatz kommt.
    Die zählt z.B. lediglich Impulse und setzt beim ersten Aufruf einen Zeitstempel.
    Nach einer bestimmten Zeitspanne wird sowohl der Zeitstempel als auch der Zähler zurückgesetzt.
    Aus diesen beiden Werten kannst Du die Drehzahl berechnen.
    Wichtig wäre noch, vor der Berechnung die Anzahl der Umdrehungen ein zweites Mal zu ermitteln, um festzustellen, ob sich die Scheibe überhaupt (noch) dreht.
    Das müsst halt jetzt noch entsprechend ausgefeilt werden, wäre aber der Weg, der mir dazu spontan einfallen würde ...

    cu,
    -ds-

  • Nachdem was ich alles gelesen habe führen mehr als mehrere Weg nach Rom.

    Dieses Script oben ist Teil eines Scriptes, das später implementiert werden soll. Das wird aber erstmal ein anderes Problem werden. Daher möchte ich WiringPi nicht einsetzen, da ich sonst zuviel umstellen muss(glaube ich ... )

    Grundsätzlich würde ich diese Funktion nur gerne ans Laufen bekommen.

    Aber dreamshader, du hast völlig recht, das zurücksetzen ist enorm wichtig und genau imho mein Problem.
    Jedoch : mit dem prüfen ob die Scheibe dreht:
    darum möchte ich ja die Zeit zwischen den Impulsen messen und zur Berechnung nehmen.
    Wenn kein Impuls kommt ist die Geschwindigkeit null (vielleicht verrenne ich mich hier auch in irgendetwas)

    Meine Überlegungen (hauptsächlich zu meinem Verständnis)

    - ich bekomme Impuls auf GPIO22
    - startzeit in Speicher
    - warten bis zum 3. Impuls
    - endzeit ermitteln
    - differenz = endzeit - startzeit
    - schleife wiederholen

    geschwindigkeit = (umfang / 3sensoren) / differenz

    sieht ja einfach aus... isses aber nicht, zumindest nicht für mich. Ein Python Profi weiß hier sicherlich Rat.

    Habe auch mal unter dem Keyword Waterflow-Sensor geschaut, hoffe ich werde da fündig!

  • Hi,


    ...
    - ich bekomme Impuls auf GPIO22
    ...


    fast ... eine ISR wird bei jedem Impuls auf GPIO22 aufgerufen.
    Ist der Zähler 0, wird der Zeitstempel gesetzt. Da nimmst Du z.B. den millis()-Wert. Anschliessend wird der Zähler erhöht.

    Diese Funktionalität ist entkoppelt von Deinem script und läuft automatisch quasi im Hintergrund - ISR eben.
    In einer Funktion in Deinem script:
    holst Du Dir den Wert Umdrehungen,
    machst einen delay mit einer Zeitspanne, in der mindestens ein Impuls eingehen müsste,
    holst den Wert der Umdrehungen nochmals und vergleichst die beiden Werte (vorher - nachher).
    Ist die Differenz 0, dann brauchst Du nicht gross rechnen, denn die Scheibe steht.
    Sonst kannst Du durch die Anzahl der gezählten Impulse und der Differenz von millis() und dem gemerkten Zeitstempel die gewünschten Werte berechnen.
    Wann Du die Werte zurücksetzt, bleibt Dir überlassen. Eine Idee wäre halt nach jeder Berechnung ( Umdrehungen auf 0, Zeitstempel auf millis() ).

    Die Krux ist: je weniger Impulse pro Umdrehung, desto ungenauer der berechnete Wert. Bei zu vielen Impulsen pro Umdrehung stösst Du irgendwann an die Grenzen von Python.

    cu,
    -ds-

  • Danke für die ausführliche Beschreibung!

    werde mich dann wohl noch weiter ins Thema einlesen müssen ... mein Kopf ist nur im Moment voll und habe gefühlte 100 Seiten dazu gelesen, wovon 99% am Thema vorbeigingen.
    wie gesagt: bin in python eher unbeleckt

    Werde mal schaun, ob ich zum Thema ISR mehr finde. Bleibe am Ball ....

  • Hallo,
    @ RSV-Tuono;
    >> ... Ich bin absoluter Neuling und kann mir nur mit Codeschnipseln und Try-And-Error helfen ...
    Ach so ... da sind wir nicht nur in dem selben alter - hihi
    Das alles ist sehr einfach! Nun wir sind keine Pythonprofis. Aber zur Problem.
    Simplen einfache GPIO abfrage. (Hier meine 1- Testversion)

    Weil ich alles in (mir gewöhnliche aus Java) Threads "packen" wollte, habe auf die ISR (Interrupt Service Routine) - was der dreamshader auch angesprochen hat! gestoßen.
    Und dass ist genau das was ich gesucht habe und wir beiden brauchen!
    Die Prozesse sind von dem ?UI / ?Main - Thread entkoppelt. Und somit ist
    VORSICHT FALCHES CODE entstanden.

    Nun das Problem SIND:
    - eine Funktionsvariablen ist nur in der Funktion "sichtbar"
    - wollte mir irgendeine "globale" Variable deklarieren ... habe mich noch nicht durchlesen können wie?
    - habe mit Parameter versucht (Funktion mit Parametern ...) nun habe wegen Zeitmangel aufgegeben.
    Ab Mittwoch werde wieder etwas Zeit haben die Sache nachzugehen.

    Gruß
    Georg

    Ps.
    Irgend wo in meinem Archiv liegt komplette Java- Code dafür. Nun habe damals schlechte Erfahrung mit Java & Embedded Systeme (JControl) gemacht. (Alles war zu träge!) Deshalb keine Jav-lib für RPI sondern -> jetzt Python!

    Sollte ich "Müll- reden" :blush: - bitte mich (?) "auf die Nuss" hauen. :huh:

  • Hi,
    ich hab' mit Python zwar nix am Hut, aber ...


    ...

    Code
    import time	
    ...
    While True:
        GPIO.add_event_detect(17, GPIO.RISING, callback=funktion_t0)
        GPIO.add_event_detect(27, GPIO.RISING, callback=funktion_t1)
        sleep(1)
    GPIO.cleanup()


    das wird so nicht funktionieren. Den Event-Handler in einer Schleife zu aktivieren ist wohl eher eine suboptimale Idee ;)
    Einmal reicht da völlig ...

    cu,
    -ds-

  • Hallo zusammen,

    mit Python habe ich es auch nicht so...

    Ich habe mit der Funktion sleep() so meine Probleme. Während der Schlaf-Zeit dürfte das Programm eigentlich gar nichts von den Umdrehungen mitbekommen.

    Meines Erachtens ist es zielführender, wenn sleep() entfernt wird und stattdessen nach jeder festgestellten Umdrehung per millis() die Zeit ermittelt wird. Ist die Differenz zwischen millis() und der Zeit der ersten ermittelten Umdrehung größer als z.B. eine Sekunde, dann hat man die exakt vergangene Zeit, die Umdrehungen und kann daraus die Geschwindigkeit berechnen.

    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.

  • Hi,
    das sieht doch alles sehr vielversprechend aus. Da können wir uns doch was draus stricken :)
    Habe gestern allerdings aus zeitlichen Gründen aufgeben müssen und komme erst am Wochenende zum nächsten testen.
    Also: lasst mir auch noch ein bischen Code übrig !!!

    Ähm, beim 2. lesen habe ich gesehen, dass du mit 2 GPIO´s arbeitest ...
    das sieht mir sehr nach Keyword "Lichtschranke" aus. HAb da gestern auch noch viel drüber gelesen (aber nix verstanden).

    bis dahin ...

  • Hi,
    habe wieder etwas Zeit für mein Projekt.

    RSV-Tuono
    ... Ähm, beim 2. lesen habe ich gesehen, dass du mit 2 GPIO´s arbeitest ...
    das sieht mir sehr nach Keyword "Lichtschranke" aus ...

    ????
    Erst eins dann zwei dann ... zehn. ...

    Mein (unseren) Vorhaben ist 3 (oder auch mehr) GPIO Impulsen zeitlich zu erfassen.

    Ich kann die 3 Auswertungen (GPIO4, 17, 27) irgendwie nicht zusammenfassen.
    Sehr wahrscheinlich mache ich einen Logischen Fehler?

    (Ohne ISR [] ) werde ich es vielleicht (bin mir sicher -> JA) schaffen können?

    Problem / Frage / Bitte
    Code:

    Wie bringe ich die 3 Auswertungen;
    time_stamp0
    time_stamp1
    time_stamp2
    unter einen Hut?
    Damit ich / wir mit den time_stamp´s "Arbeiten" können.

    LG
    Georg

    Sollte ich "Müll- reden" :blush: - bitte mich (?) "auf die Nuss" hauen. :huh:

  • so ... nächste Runde.
    Komme der Sache schon näher, jedoch ist es immer noch nicht so wie ich das gerne hätte:

    Es wird jetzt zwar alles soweit angezeigt, er holt sich auch die Start / Endzeit, aber halt bei jedem interrupt.
    Ich weiß, dass eine while (impuls < 3): in die def Interrupt(channel) muss, aber nicht wie!!!

    Kann uns bitte einer der Profi Python Experten den entsprechenden Code zukommen lassen?


  • Ich weiß, dass eine while (impuls < 3): in die def Interrupt(channel) muss, aber nicht wie!!!

    Wenn du in die Interrupt Anweisung eine while Schleife tust, zerstörst du diese Anweisung. Was du glaubst zu wissen ist also falsch :fies:

    Überleg mal bitte was passieren muss damit du zu deinem verlangten Ziel kommst.

    Wird der Reedswitch geschlossen und ein Interrupt Event ausgelöst, wird die Anweisung Interrupt aufgerufen - das ist deine callback.
    Was soll nun passieren?
    Wird das Script zum ersten mal gestartet wird ua. die Variable impuls auf 0 gestellt. Wird jetzt zum ersten mal der Reedswitch geschlossen sollte die StartTime gesetzt werden. Was muss dann passieren damit die EndTime gesetzt wird? 3x impuls? Dann prüf das in der Interrupt Anweisung und lass dann die EndTime setzen sowie impuls wieder auf 0... Am besten sogar 2 impuls Variablen wenn du auch noch die Insgesamt-Impulse bemessen willst.


    PS: Oben bei "#Speed Variablen" ein global zu setzen ist Blödsinn. Die Variablen ausserhalb von Anweisungen sind bereits global. Somit machen die meisten deiner anderen gesetzten global's ebenfalls kein Sinn


    //EDIT: Und was passiert eigentlich wenn die Geschwindigkeit so hoch ist das ein Durchlauf schneller als eine Sekunde ist? ;)
    Also deine while Schleife am Ende des Script würde ich auch weg lassen bzw das ganze anders machen.. Ich würd die Ausgabe dann auslösen wenn deine 3 impuls'e (eine Umdrehung?) erreicht wurden.
    Auch bouncetime ist glaub ich etwas kontraproduktiv, da ab einer gewissen Geschwindigkeit ein Event ignoriert werden könnte

    Probier es mal hiermit:

    [/spoiler]

  • @maigrafd: DANKE DANKE DANKE!
    Carmen hätte jetzt zu Robert gesagt: "Dat is der börner!"
    Habe mir Deine Erklärung mehrmals durchgelesen, das Script daneben gehalten und verstanden was Du da gemacht hast...!
    Leider kann ich das mir meinen wenigen Hintergrundinformationen als Newbe nicht so zusammenbringen.

    Wenn Du mein restliches zusammengewürfeltes hier sehen würdest, würde dir wahrscheinlich massivst Übel ....
    aber: bin erst seit 4 Wochen mit dieser Sache hier beschäftigt und hoffe, irgendwann vielleicht auch mal jemandem helfen zu können.
    Danke an jeden, der sich hier mit eingebracht hat. Ich werde Euch bestimmt wieder belästigen!

    Kleine INfo am RAnde: HAbe folgendes geändert:

    Code
    def getSect():
        sec = totalImpuls * section
        return sec


    Sonst wäre die Länge nicht aufaddiert worden ....

    Code
    def getTime():
        #timeEnd = time.time()
        stamptime = timeEnd - timeStart
        stamptime = stamptime / 60
        return stamptime


    Musste durch 60 dividieren um auf Minuten zu kommen

    Code
    GPIO.add_event_detect(gpioPin, GPIO.RISING, callback=Interrupt, bouncetime=150)


    Die Bouncetime brauche ich im Moment noch, da meine Testumgebung(per Taster) sonst schon bei jedem 2.ten reagiert hätte.

    ICH KANN WEITERMACHEN! Super! Danke nochmal!

Jetzt mitmachen!

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