Arduino python und die Weboberfläche

  • Hallo Zusammen

    Ich versuche gerade unseren Kickertisch zu automatisieren. Dies wie folgt:

    Ein arduino kontrolliert die laserschranken der Beide Tore. Wenn eine unterbrochen wird zählt er dies Als Tor.

    Diese Daten kann ich jetzt bereits erfolgreich via USB an der Raspi weitergeben und mit einem Phyton Script verarbeiten.

    Nun soll der Punktestand auf einer Webseite angezeigt werden. Direkt am Raspi über ein Touchscreen wie auch von anderen Geräten im Netzwerk.

    Dies stellt nun das Problem dar, da mein Wissen von Phyton oder von Javascript beschränkt ist. (PHP, HTML, mysql ist kein problem)

    Bis jetzt habe ich es geschaft die die Daten von Phyton in ein txt zu schreiben welche ein Jquery aufnimmt und in die Webseite integriert.

    Allerdings sollen mehrere Spielmodus möglich sein. Z.B: bis 5 punkte, bis 10 punkte, zeit spiel u.s.w. Das heisst meiner Meinung nach sollte die Gameengine auf der webseite gemanaget werden. Während die arduino seite nur punkte zählt.

    Wie bringe ich das jetzt am besten umgesetzt:

    Modus wählen auf webseite - webscript starten im gewählten modus - kontrollieren ob spiel beendet ist und gleichtzeitig live feed über punkte stand.
    Natürlich werden die ergebnise am Ende noch in eine Mysql Datenbank gespeichert.

    Ich wäre froh um Lösungsansätze.

    Vielen Dank

    Gruss GL


    Gesendet von iPhone mit Tapatalk

  • Klingt ja schon alles ganz gut. Ein guter Anwendungsentwurf sieht in meinen Augen so aus:

    Ein tornado-Webserver, der nebenlaeufig (therading, oder file-deskriptor-ereignisse) deine Arduino-Schnittstelle ausliest. Diese Ereignisse werden ueber einen websocket an den (oder potentiell mehrere) Clients geschickt. Ausserdem ist der Tornado-Server so konfiguriert, dass er statisch dein HTML, Bilder und Javascript ausliefert.

    Die ganze App ist in Javascript geschrieben. Du schreibst jQuery, ich wuerde auch noch zB backbone.js fuer das Datenmodell vorschlagen. Ich bin aber was Webentwicklung angeht nicht mehr auf dem Stand - die coolen Kinder benutzen Elm, Angular oder React.

    Auf die eingehenden Torereignisse reagierst du in JS. Dort wird auch durch Klickbare Felder der Spieltyp etc. ausgewaehlt.

    Deine SQL-Anbindung halte ich fuer ueberkandidelt (wollt ihr jahrelange Ligen fuehren?), aber *wenn* du die machen willst, mach es auf jeden Fall so, dass die JS-Logik das steuert, indem sie eine Nachricht mit allen relevanten Daten an den Tornado-Server schickt. Der speichert das dann ohne Umschweife in der DB. Grund: die Logik, welche simple Ereignisse (Tor links, Tor rechts) einem konkreten Spiel und dessen Spielstand zuordnet sollte nur *einmal* existieren! Es ist verfuehrerisch, das gleich im Backend zu machen, aus irgendwelchen ueberzogenen Effizienzerwaegungen. Ist aber falsch.

  • Hi __deets__

    Ich glaube wir hatten auch schon mal das Vergnügen, schön wieder Tipps von dir zu erhalten. Das letzte Mal hats genützt :)

    Irgendwie ist mir dass jetzt zu viel Information auf einmal gewesen :)

    Habe mich nun in der letzten Stunde ein wenig mit Tornado auf Youtube beschäftigt. Es ist tatsächlich das was ich benötige. Allerdings habe ich nun eben das Problem, dass ich mich zu wenig mit Phyton auskenne. Auch die JQuery Sache habe ich nur anhand einem Forum fertig gebracht, weil da jemand so nett war und mir dies praktisch pfannenfertig geliefert hat. Bin eben ein Generalist, kann von allem etwas aber nichts richtig :/

    Einen Tipp wie mir der Einstieg in diese Materie am einfachsten gelingt?

    bzgl. Datenbank:
    Es ist in der Tat das Ziel ein Ranking zu erstellen und sämtlich Spielergebnisse zu loggen. Das ganze soll auch noch um einen RFID Leser erweitert werden mit welchem die Spieler sich einloggen. Wenn dieses Test Objekt funktioniert würde ich dies auch für Turniere mit mehreren Tischen einsetzen.

    Übrigens nochmals zum Verständnis:
    Du meinst der Ablauf sollte wie folgt sein.

    Via HTML wir der Spielmodus gewählt und mittels Tornado an Phyton Script übergeben.
    Dieses regelt das ganze Spiel (zählt Punkte und stellt fest wann das Spiel gemäss Modus beendet ist)
    Während des Spiel liefert das Python Script auch via Tornado RealTime den Spielstand an HTML
    nach Beendigung des Spiels meldet Phyton - Tornado das auch ans HTML und dieses fällt zurück auf die Moduswahl, während Phyton noch den Eintrag in die DB macht.

    Ist das korrekt?

    Gruss GL

    Einmal editiert, zuletzt von mc-gl (4. Dezember 2016 um 17:46)

  • Nein, ist so nicht korrekt. Ich wuerde die gesamte Spiellogik in JS machen. Python dient nur zum durchreichen der Sensor-Ereignisse, und ggf. fuer die MySQL und RFID Geschichten.

    Eine so simple Anwending ist im Grunde nur eine einzige Seite HTML, mit einer JS-Applikation. Gerade wenn du dich nicht so gut im Programmieren ausgekennst, verhedderst du dich heillos, wenn du versuchst, die Spiellogik ueber zwei Programmteile, mit zwei Sprachen, zu verschmieren.

    Und da die "harten" Dinge (zumindest am Anfang), naemlich das reagieren auf Ereignisse vom Backend vorne im Browser in jedem Fall zu loesen sind, gibt es dann keinen Grund, darin nicht auch weiter zu machen.

    Ich wuerde auch erstmal ohne MySQL & RFID anfangen. Du kannst anfangen mit einer rein statischen HTML-Seite, in der nur JS laeuft, das auf Knopfdruck (also im Browser auf ein Feld klicken!) einen Spielstand hochzaehlt. Dann ein weiterer Knopf, um den Spielstand zurueckzusetzen. Dann die Anbindung von tor-link/rechts-Ereignissen ueber Websockets, die ersetzen dann die ersten beiden Knoepfe. Und schon hast du einen simplen, aber funktionalen Torcounter.

  • FAQ => Nützliche Links / Linksammlung => SQLite mit Python und PHP Script zur Sortierten Anzeige der Datenbank-Einträge

    Ich würde allerdings eine Lösung in ausschließlich Python (+ HTML und JavaScript) anstreben:

    FAQ => Nützliche Links / Linksammlung => [Python] Webserver, Websocket und ein bisschen AJAX

    Das erfassen und speichern der Daten kannst du in ein Script tun, das abfragen bzw visualisieren in ein weiteres/unabhängiges - man könnte aber auch beides in einem Python Script zusammenfassen, dann allerdings mithilfe von 'multiprocessing' oder 'threading'.

  • Hallo maigrafd

    Super! Danke! Habe schon verzweifelt nach einem guten tutorial gesucht. Mit diesem könnte ich tatsächlich weiterkommen :)

    Melde mich wieder wenn ich mich durch gelesen und meine ersten Schritte gemeistert habe :)

    Gruss Gl


    Gesendet von iPhone mit Tapatalk

  • Hallo Zusammen

    Ich habe nun einiges zum laufen gebracht.

    Habe meine Arduinos umgeschrieben sodass Sie auf die richtigen Befehle antworten und dementsprechend auch eine Antwort geben.

    Auch habe ich das Python Script so bearbeitet dass es via Tornado von einer Webseite einen Befehl erhalten (nach dem Script von meingrafd), diese an die beiden Arduinos auf USB0 und USB1 weitergeben und dann auf Antwort horcht.

    Nun denn: ich erhalte Antworten in der Konsole diese jedoch nur unregelmässig.

    Zum Verständnis:
    Ich senden den Arduinos den Befehl start. Diese lesen nun jeweils eine Laserschranke in Dauerschleife aus. Sollte die Schranke unterbrochen werden, so senden Sie eine Antwort an den Raspi zurück, welcher dann die Antwort splittet um zu erkennen welcher Arduino diese Antwort gesendet hat. Diese erhalte ich, wie ich schon erwähnt habe allerdings nur unregelmässig.

    Ich gehe davon aus das der Pi ein durcheinander hat welcher Port jetzt was sendet. Allerdings habe ich keine Ahnung an was es liegen könnte

    hier mein Tornado Python Script:


    Findet Ihr das Problem in meinem Script? Oder habt Ihr gar eine Lösung?

    Vielen Dank
    Gruss GL

  • Mir faellt nur auf, dass du readline() aufrufst, nur das du dann das Ergebnis wegwirfst. So geht das nicht. Damit wartet der dann blockierend auf die naechste Eingabe, und hat vorher alles weggeworfen.

    Stattdessen solltest du - gut dokumentiert hier: https://pythonhosted.org/pyserial/pyser…rial.in_waiting bzw https://pythonhosted.org/pyserial/pyser…erial.inWaiting - die Anzahl der aufgelaufenen Bytes benutzen.

    Und so vorzugehen wie du das tust geht das nicht. Du benutzt einen blockierende while-Schleife. Stattdessen solltest du mit http://www.tornadoweb.org/en/stable/iolo…oop.add_handler und dem jeweiligen serial-Objekt auf einkommende Daten warten.

  • Hi __deets__

    Ich konnte soeben endlich wieder an das Projekt sitzen. Ich habe mir deine Links nun einmal angesehen. Leider ist es für mich gerade nicht ganz verständlich. Wie bereits erwähnt, ist das eins meiner ersten Phyton Script und ich verstehe im Moment nicht was du genau meinst, bzw. was die Links zu bedeuten haben.


    Mir faellt nur auf, dass du readline() aufrufst, nur das du dann das Ergebnis wegwirfst. So geht das nicht. Damit wartet der dann blockierend auf die naechste Eingabe, und hat vorher alles weggeworfen.


    Wo werfe ich ein Ergebnis weg? meinst du weil ich sie nach dem ausgeben nicht weiter verwende? Das ist nur so, weil ich Das Script noch nicht flüssig zum laufen gebracht habe, ich habe deshalb die Daten noch gar nicht weiter gesendet. Wollte test weise erst in der Console alle Werte laufend sehen und mich dann dem nächsten Step zuwenden.

    Es wäre mir auch lieber die Einkommenden Serial Daten in einem Interrupt als in einer While auszulesen. Allerdings habe ich auf den ersten Blick nicht die richtigen Befehle auf deinen Links gefunden.


    Stattdessen solltest du - gut dokumentiert hier: https://pythonhosted.org/pyserial/pyseri...in_waiting bzw https://pythonhosted.org/pyserial/pyseri....inWaiting - die Anzahl der aufgelaufenen Bytes benutzen.

    Wie müsste der Interrupt denn geschrieben werden?
    Vielleicht um Missverständnisse zu vermeiden: ich verstehe dass der Interrupt die Daten des Serial nur dann ausliest wenn auch tatsächlich vorhnaden sind richtig verstanden?


    Aber was hat das Serielle auslesen mit Tornado zu tun?


    Und so vorzugehen wie du das tust geht das nicht. Du benutzt einen blockierende while-Schleife. Stattdessen solltest du mit http://www.tornadoweb.org/en/stable/iolo…oop.add_handler und dem jeweiligen serial-Objekt auf einkommende Daten warten.

    Vielen Dank für eure Hilfe :)

  • Wenn du so etwas schreibst:

    Code
    if(foo.readline()):
        print(foo.readline())

    dann liest du eine Zeile aus foo aus, aber da du sie keiner Variablen zuweist, wird sie einfach verworfen. Das zweite print-Statement druckt dann also die *naechste* Zeile aus! Damit prozessierst du jede zweite Zeile. So etwas steht halt in deinem Code.

    Interrupts gibt es in der Userspace-Programmierung unter Linux (oder jedem anderen OS) nicht. Der Mechanismus, der stattdessen zum Einsatz kommt sind Benachrichtigungen auf File-Deskriptoren. Das ist die Technik die im Link zur Tornado-Dokumentation beschrieben ist. Du musst ioloop.add_handler benutzen, in etwa so (ungetestet):

Jetzt mitmachen!

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