Folgeaktion bei Mausbewegung / Python

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo zusammen,
    ich bräuchte in Python ein Miniscript welches folgendes bewerkstelligt:
    Wenn die Maus bewegt wird, dann soll in Folge "etwas" passieren.
    Ich habe mit folgenden Script herumprobiert:

    -------------------------------
    [font="Arial"]Fh = file (‚/dev/input/mice‘)[/font]
    [font="Arial"] [/font]
    [font="Arial"]While (1):[/font]
    [font="Arial"] fh.read(3)[/font]
    [font="Arial"] print ‘Maus bewegt sich!’[/font]
    -------------------------------

    Soweit so gut. Das funktioniert. Das Problem ist, dass die Zeile fh.read(3) die Schleife logischer Weise blockiert.
    Ich möchte aber diese Maus-Daten dauernd abfragen und bei Nichtbewegen dies feststellen und z.B. an Ubidots senden, dass nichts passiert ist.
    Ich kann aber laienhaft gesprochen ja nicht sagen "if fh.read(3) dann tue etwas oder halt nicht"

    Ich habe ewig versucht diese File zu öffnen, auszulesen und dann wieder zu schliessen und dann Obiges umzusetzen, aber ich hab definitiv zu wenig Ahnung :(

    Für eine Idee oder Anregung danke ich im Voraus!!!

    Bene

    :helpnew:

    Einmal editiert, zuletzt von Benito (17. März 2016 um 12:33)


  • In der python-Library gibt's doch sicher auch select oder poll.

    select kann mit Timeout auf Daten warten.

    Hi Tell,
    vielen Dank für den Tipp! Das war genau das, was ich gesucht hab!!!

    Hab rumgeschaut und bin auf einen entsprechenden Code gestoßen, welchen ich noch ein wenig ergänzt hab. (Hintergrund ist, dass ich einen Analogen Wasserzähler mit einer Maus auslesen möchte. Die Daten bzw. Bewegungen des Literrädchens (ein Liter = eine Mausbewegung) sammle ich in einem bestimmten Zeitintervall und schicke sie dann in Folge an eine Datenbank etc...)


    Hier der Code:

    --------------------------------------------------------------

    import time
    import pygame

    x = y = 0
    running = 1
    screen = pygame.display.set_mode((640, 400))
    counter = 0
    peoplecount = 0

    while running:
    event = pygame.event.poll()
    if event.type == pygame.QUIT:
    running = 0
           
    elif event.type == pygame.MOUSEMOTION:
    print "mouse at (%d, %d)" % event.pos
    peoplecount += 1

    screen.fill((0, 0, 0))
    pygame.display.flip()

    time.sleep(2)
    counter += 1
     
    if(counter==2): # hier wird alle 2 Sekunden ausgelesen
    print peoplecount
            
    counter = 0
    peoplecount = 0

    --------------------------------------------------------------

    Jetzt zu meinem Problem:

    Ohne die Timesleep-Zeile läuft das alles perfekt: Wenn eine Mausbewegung in dem erzeugten Fenster passiert, dann zählt der Counter.
    ABER: Mit der Timesleep-Zeile startet die Anzeige der Mauskoordinaten und beim Nichtmehrbewegen der Maus, läuft die Anzeigeaktion weiter, wie wenn das alles in einen Puffer läuft, der dann abgearbeitet werden muss. Erst wenn alle Daten angezeigt wurden, kehrt die Anzeige wieder quasi in den "Nichtbewegtmodus".

    Hier muss ich leider wieder passen. Die Timesleep-Funktion brauch ich auf jeden Fall, um zu vermeiden, dass das Literrädchen x-fach Daten produziert die ja nicht stimmen. Ich muss gestehen, dass diese Lösung leider nicht perfekt ist, denn: Wenn das Literrädchen sehr langsam ist und die Zeit von Timesleep kürzer ist, dann gibt es schon wieder falsche Daten.
    Im Prinzip müsste immer nur EIN Durchrauschen des Literrädchens durch die Mauslichtschranke EIN Signal erzeugen...

    Sorry für die lange Erklärung, aber so hat man zu dem Gefragten vielleicht einen besseren Bezug.

    Vielen Dank!
    :)

    Einmal editiert, zuletzt von Benito (18. März 2016 um 14:50)

  • Also ich glaube ja nicht, dass das so ohne weitere funktioniert. Du kannst aus reiner "ist bewegt" Information nicht ein "vieviel ist sich bewegt worden" zaubern. Dein Raedchen dreht sich unterschiedlich schnell, und dem musst du Rechnung tragen.

    Hast du dir das selbst ausgedacht, oder funktioniert das belegbar?


  • Also ich glaube ja nicht, dass das so ohne weitere funktioniert. Du kannst aus reiner "ist bewegt" Information nicht ein "vieviel ist sich bewegt worden" zaubern. Dein Raedchen dreht sich unterschiedlich schnell, und dem musst du Rechnung tragen.

    Hast du dir das selbst ausgedacht, oder funktioniert das belegbar?

    Hi deets,
    da hast du zum Teil leider recht.
    Aber im Irritationen zu vermeiden: Wir reden von einem Literzeiger, nicht Rädchen...sorry.

    Ich hatte eine einigermaßen stabile Lösung: Eine LED hat die weiße Grundfläche des Wasserzählers angeleuchtet. Eine Photodiode hat das Reflexionslicht wiederum aufgefangen. Wenn sich nun das rote Rädchen oder besser der rote Zeiger (pro Liter eine Umdrehung) zwischen die Reflexion und die Photodiode geschoben hat, wurde (durch ein entsprechendes Bauteil) ein Relais geschaltet und in Folge bekam der Raspberry einen Kontakt. Dieser wurde wie beschrieben ausgewertet...
    Es war egal wie schnell sich das Rad drehte. Sobald die Art Lichtschranke unterbrochen wurde, war der Kontakt weg und umgekehrt.
    Leider musste ich dauernd die Empfindlichkeit nachregeln. Warum weiß ich nicht. Hat mich irre gemacht...

    Nun zu deiner Aussage bzgl. der neuen Lösung: Ich denke, dass das doch eigentlich gehen sollte: Es gibt ja einen Beginn und ein Ende der Mausbewegung. Denn die Abtastung wäre an einer Stelle, an welcher der rote Zeiger immer wieder vorbeikommt.
    Ich dachte man könnte sowas in einer Art wie "Beginn bis Ende der Mausbewegung" definieren. Diese Bewegungseinheiten hätte ich dann gezählt. Problematisch bei dieser Lösung wäre in der Tat ein leichtes tröpfeln. Dann würde der rote Zeiger sehr lang eine Bewegung auslösen mit sicherlich falschen Ergebnissen. Solange das Wasser einigermaßen laufen würde, hätte ich das mit time.sleep gelöst. Sprich nach der ersten Bewegungserkennung würde halt z.B. 0,25 sek oder ähnlich gewartet werden. Super sauber ist die Lösung auf jeden Fall nicht. (Die Grundidee war ohnehin eine Meldung, dass viel Wasser verbraucht wird, zwecks Wasserschaden :)

    Noch mal Danke für den Anstoß... ich darf gar nicht sagen, wie lang ich da schon rumbastel.... jetzt mussten schon einige Mäuse daran glauben... beim Versuch die optische Abtastung weiter weg zu verlagern (Der Zeiger liegt ja im Gehäuse des Zählers - somit ca. 1,5 cm von der Optik der Maus entfernt. Vielleicht wäre die bessere Variante mit einem Laser einen Punkt zu setzen, den der Zeiger dann verdeckt. Aber das ist alles so ein Gefummel...

    Bis dahin vielen Dank...

    Einmal editiert, zuletzt von Benito (18. März 2016 um 21:17)

  • Kurze Zwischenmeldung: ich glaube nicht, dass das funktioniert. Mit dem Maussensor wird das extrem fummelig. Klar, wenn du eine bestaendige Drehung haettest (also permanent Wasser verbrauchst), dann kann man aus dem Verhaeltnis von "da bewegt sich was" zu "da bewegt sich nix" etwas schliessen.

    Ich wuerde stattdessen zu OpenCV und Videoerkennung greifen. Weil mich das mal intellektuell herausgefordert hat, habe ich angefangen zu basteln - einen kleinen Videovorgeschmack gibt's hier:

    https://www.dropbox.com/s/chmvq0ajc8sj…aehler.m4v?dl=0

    Wie du siehst wird der Zeiger gut isoliert, und ich bin auch in der Lage, einen Vektor zu berechnen, der recht gut die Richtung anzeigt.

    Bis jetzt habe ich das ganze nur auf meinem Mac getestet, ich denke aber nicht, dass es den PI2 vor groessere Probleme stellen sollte. Ich schau mal, wie weit ich komme/Lust habe :)

    Code gibt's hier: https://github.com/deets/brombeerquark/tree/wasserzaehler

    Da bleibt er auch fuer Nachahmer, selbst wenn ich nicht mehr viel weiter komme.

  • Wenn ich das noch richtig in Erinnerung habe kann man bei pygame einstellen in was für einer Frequenz er eine Aktualisierung durchführen soll: Clock()
    Beispiel:
    [code=php]
    import pygame
    from pygame.locals import *

    # Frames per Second. Update Screen X times in one Sec.
    FPS = 5

    # Enable FPS output to console? (True/False)
    debugFPS = True

    try:
    running = True
    pygame.display.init()
    size = (pygame.display.Info().current_w, pygame.display.Info().current_h)
    screen = pygame.display.set_mode(size, pygame.FULLSCREEN|pygame.DOUBLEBUF)
    width = screen.get_width()
    height = screen.get_height()

    clock = pygame.time.Clock()
    while running:
    clock.tick(FPS)
    for event in pygame.event.get():

    if event.type == pygame.QUIT:
    running = False
    elif event.type == pygame.MOUSEMOTION:
    print "mouse at (%d, %d)" % event.pos

    if debugFPS:
    print 'frame rate: %.2f frames per second' % clock.get_fps()
    except IOError, ioerr:
    print 'IOError: ' + str(ioerr)
    except pygame.error, perr:
    print 'pygame Error: ' + str(perr)
    except (KeyboardInterrupt, SystemExit):
    running = False
    print '\nQuit\n'
    [/php]

    Wie du siehst, kein sleep erforderlich ;)

  • meigrafd: clock.tick ist nichts anderes als ein getarntes sleep - unter der Vorraussetzung, dass man weniger Zeit benoetigt hat, als ein Frame dauert, wartet es einfach den Rest ab. Das hilft sicher fuer so manches Problem, gerade wenn man zB stetige Bewegung haben will (und die nicht in Abhaengigkeit von der tatsaechlich verflossenen Zeit berechnen will).

    Aber der TE braucht sein langes sleep von 2.0 Sekunden ja, um irgendwie zu filtern. Allerdings koennte er natuerlich auch ohne sleep arbeiten, und stattdessen Updates ignorieren oder anders wegfiltern.

    Das ist in meinen Augen aber schon rein konzeptionell mit dem Maus-Sensor alles zu fummelig, und hat wenig Aussicht auf Erfolg.


  • Kurze Zwischenmeldung: ich glaube nicht, dass das funktioniert. Mit dem Maussensor wird das extrem fummelig. Klar, wenn du eine bestaendige Drehung haettest (also permanent Wasser verbrauchst), dann kann man aus dem Verhaeltnis von "da bewegt sich was" zu "da bewegt sich nix" etwas schliessen.

    Ja, das ist leider in der Tat ein Problem. Mit der Lichtschranke hatte man immer einen eindeutigen Liter und konnte z.B. auf Ubidots absolut exakte Aufzeichungen erstellen und auswerten. Mit dem Maussensor bekommen ich genau bei minimalem Verbrauch die Probleme. Das macht keinen Spaß... Weil ich jetzt schon weiß, dass ich das alles irgendwann perfekt haben will.


    Wow, hast du das so schnell gemacht!?
    Das sieht cool aus! Ich kannte das nur im Rahmen der Videoerkennung. Ich wusste nicht, dass man damit solche Sachen machen kann. Kann man da wirklich solche Auswertungen erstellen?
    Muss mich da mal scheinbar näher damit befassen.
    Vielen Dank für den Link und die Infos!
    Schau ich mir heute Abend mal an...
    Falls du noch mehr rausbekommst bin ich sehr gespannt!
    Automatisch zusammengefügt:

    Vielen Dank!
    Werde ich mal mit experimentieren :) (Mit den genannten Problemen...)

    Einmal editiert, zuletzt von Benito (20. März 2016 um 18:01)

Jetzt mitmachen!

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