Python mit Arduino

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Zuerst das Grundsätzliche. Benutze keine *-Importe, sondern gib die Namen explizit an, die Du importieren willst. Aus random benutzt Du nur randint, aus time gar nichts. Methoden und Funktionen werden klein_mit_unterstrich geschrieben und sollten Tätigkeiten beschreiben.
if und elif sind keine Funktionen, deshalb ist es unsinnig, die Bedingung noch zu klammern.
Die Klassenattribute von Welt werden gar nicht benutzt, sondern in __init__ gleich von Instanzattributen versteckt, die können also weg. SnakeKörperStück kann eigentlich komplett durch ein 2-Tuple ersetzt werden, wie Du es ja auch schon für Apfelposition benutzt. In neueApfelposition benutzt Du Rekursion, wo man besser eine einfache while-Schleife einsetzen würde. Wären die Schlangenteile eine Liste von Tupeln, könnte das so aussehen:

Code: Alles auswählen

    def neueApfelposition(self):
        while True:
            position = (randint(1, self.width - 1), randint(1, self.height - 1))
            if position not in self.snake.körper:
                break
        self.apfelposition = position
 
In SnakeSpiel ist die Spielelogik immer noch nicht sauber von der Tk-Anzeige getrennt. In der Methode Spiellogik sind jeweils zwei Zeilen der ersten if-elif-Kaskade in jedem Block identisch, die können also herausgezogen werden. Außerdem erzeugst Du neue Snake-Objekte, obwohl das ürsprüngliche Snake-Objekt von außerhalb gekommen ist, das ist verwirrend, wenn man von außerhalb noch etwas mit snake machen möchte.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Hallo Laura,
bevor hier einige Profis deinen Code zerlegen und ihn dir um die Ohren hauen, (Edit: zu spät :cry: )
möchte Ich dir sagen: Toll gemacht! Ich bin stolz auf dich.
Er ist nicht perfekt aber er läuft.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Laura98: Okay, vorsicht, viel Kritik, bitte nicht davon erschlagen lassen. :-)

Die Sternchenimporte sollten nicht sein. Dadurch weiss man nicht mehr so einfach wo welcher Name her kommt, und speziell bei `tkinter` holst Du Dir ca. 190 Namen ins Modul von denen dann nur ein ganz kleiner Bruchteil tatsächlich verwendet wird. Zudem besteht bei Sternchenimporten die Gefahr von Namenskollisionen.

Das sich das Programm auf die implizite Erstellung eines `Tk`-Exemplars verlässt ist ungewöhnlich. Das würde ich explizit erstellen. So wie es jetzt ist, kann man `SnakeSpiel` auch nur mit einem `Tk`-Exemplar verwenden und nicht in einen anderen Rahmen einbetten. Das ist ein bisschen unflexibel. Da wäre es besser gleich von `Tk` zu erben, statt von `Frame`.

Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Wenn man das macht, dann fallen ein paar Fehler im Programm auf, denn an einigen Stellen greifen Methoden in `SnakeSpiel` auf `welt` ausserhalb der Klasse auf Modulebene zu, statt auf das `welt`-Attribut des eigenen Objekts.

Es gibt keinen vernünftigen Grund `canvas` nicht auszuschreiben und stattdessen `canv` zu schreiben. Abkürzungen erschweren das flüssige lesen des Quelltextes, ausser es sich allgemein bekannte Abkürzungen.

Insgesamt stimmen an einigen Stellen die Verantwortlichkeiten nicht, das heisst es wird da von aussen zu tief in Objekte hinein- und durchgegriffen. Das zum Beispiel sie `Snake`-Klasse überhaupt gar keine Methoden hat ist ein Warnzeichen dafür. Und was im Hauptprogramm alles mit `spiel.master` gemacht wird, gehört dort auch nicht hin.

Die `Snake`-Klasse sollte als einzige wissen müssen wie sie intern aufgebaut ist. Wenn man zum Beispiel die Darstellung von einer Python-Liste mit `SnakeKoerperTeil`-Elementen auf eine verkettete Liste mit entsprechend geänderten `SnakeKoerperTeil`-Objekten ändern würde, dann sollten Codeänderungen dafür *nur* in der `Snake`-Klasse nötig sein. Du hast den ganzen Code dafür aber in der `SnakeSpiel`-Klasse stehen.

Was auch etwas mit dem Problem zu tun hat da jetzt noch den Arduino mit zu integrieren. `SnakeSpiel` macht zu viel. Das ist die Spiellogik *und* die GUI in einer Klasse. Das sollte getrennt sein. Dann kann man nämlich die Spiellogik so in einer Klasse kapseln, dass das selbe Objekt als Grundlage für Anzeige und Steuerung für GUI und Arduino-Schnittstelle dienen kann, und auch GUI- und Arduino-Code unabhängig voneinander sind.

Warum wird der `Canvas` ausserhalb der `SnakeSpiel`-Klasse erzeugt? Und wenn man das so macht, waraum wird das `Canvas`-Objekt dann nicht beim erzeugen der `SnakeSpiel`-Klasse übergeben, sondern erst später mit einem trivialen Setter von aussen gesetzt? Nach dem die `__init__()` durchgelaufen ist, sollte eine Klasse alle Attribute besitzen und verwendbar sein. Zudem sind trivialle Getter- und Setter-Methoden ”unpythonisch”. Man greift in solchen Fällen in Python direkt auf die Attribute zu.

Die Namensschreibweisen halten sich nicht an den Style Guide for Python Code. `Spiellogik` hat neben der Schreibweise als Klasse, noch das Problem das es keine Tätigkeit beschreibt. Denn üblicherweise sind Funktions- und Methodennamen die Tätigkeit die von der Funktion oder Methode durchgeführt wird.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Es soll ja auch nicht perfekt sein bin ja noch Anfängerin..
Hab mir mehr Hilfe für die Verbindung mit dem Arduino gewünscht, da die Hardware auch schon steht
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dafür fehlen uns die Informationen. Irgendwas mit Wifi, arduino oder doch esp8266 und so weiter. Das ist nichts, womit man was anfangen kann :K
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Laura98: Die Strukturierung und Aufteilung des Codes hat ja durchaus etwas mit der Anbindung des Arduino zu tun. Das ist einfacher wenn man alles sauber trennt und nicht Spiellogik und GUI vermengt, denn dann muss man am Ende ja auch noch den Arduino-Code da *auch* noch mit rein schreiben und es wird noch unübersichtlicher.

„Ich bin ja noch Anfängerin“ ist kein Argument das nicht besser zu machen, bzw. für uns doch kein Grund zu sagen was daran noch getan werden muss. Gerade Anfängern muss man das doch sagen. Leute die keine Anfänger mehr sind, machen diese Fehler ja nicht. Und vom Anfänger-Status kommt man nicht runter wenn man keine Verbesserungen vorgeschlagen bekommt und umsetzt.

Konkretere Hilfe zur Einbindung des Arduino kann man nur geben, wenn Du konkretere Probleme damit beschreiben würdest. So allgemein kann man halt nur sagen Programmlogik und GUI trennen, denn der Arduino ist im Grunde ja noch eine weitere GUI die mit der selben Programmlogik interagieren muss.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

ich bin natürlich dankbar für die Tipps:-) aber bekomm gerade zeitdruck. Ich weiß zum Beispiel gar nicht mit welchen befehlen und in wie fern ich den Arduino in den Python Code einbinden soll, es soll ja mit einem ESP8266 verbunden werden
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Also, Dein Arduino ist mit einem ESP8266 verbunden, am Arduino hängen Taster und ein LED-Display. Dann mußt Du also Arduino-Code schreiben, der über ein wie auch immer geartetes TCP-Protokoll Befehle entgegen nimmt und das LED ansteuert, bzw. über TCP Tastendrücke zurücksendet. Auf Python-Seite mußt Du also einen TCP-Client schreiben, der mit dem ESP8266 als Server kommuniziert.

Dieses Setup hat den Vorteil, dass Du einfach einen Arduino-Emulator schreiben kannst, weil der ja einfach ein TCP-Server ist (z.B. wiederum in Python geschrieben).

In wie weit weißt Du schon, wie man einen ESP8266 mit einem Arduino anspricht?
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Danke @Sirius3 für die Antwort, damit kenn mich leider noch kaum aus, hätteste du ein paar Tipps wie ich es schnell verstehe?
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Warum Arduino *und* ESP8266? Was bringt der ESP8266 was der Arduino nicht bringt — oder umgekehrt‽
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Esp8266 ist ja auf den Arduino gesteckt, es soll ja eine Wifi Verbindung bestehen
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich wundere mich halt bloss weil der ESP8266 ja selbst so etwas wie ein Arduino ist (Microcontroller, GPIOs, …), wozu man dann noch den Arduino braucht. :-)
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du musst schon ein bisschen weiter ausholen. Du denkst mit solchen zwei Schlagworten wuesste hier jeder bescheid - dem ist nicht so. Der ESP8266 ist sein eigener MicroController (deutlich dem Arudino ueberlegen was Rechenleistung angeht) und ich betreibe den alleine, ohne Arduino. Das du ein darauf basierendes WIFI-Shield hast, kann keiner erraten. Dazu kommt dann die Frage, wie die beiden verbunden sind, ob du schon eine WIFI-Verbindung aufgebaut hast, ob du schon mit dem Arduino kommunizieren kannst, wie die LED-Matrix aussieht (nicht optisch. Technisch). Und und und. Bis hin zu Fotos von deinem Aufbau, wenns geht. Du wirst schon ein bisschen liefern muessen, denn das ist ein weites Feld, und fuer die ca 100000 verschiedenen Moeglichkeiten dieses Setup aufzubauen Code abzuliefern kann hier wohl kaum jemand leisten. Nicht zuletzt, weil den Code auszprobieren mangels eigener Hardware nicht geht.
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Das WIFI shield funktioniert bei uns nicht einzeln dass muss auf den Arduino gesteckt werden
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Bleiben die schon mehrfach gestellten Fragen, was Du schon auf Arduino-Seite programmiert hast. Wie sieht die Ansteuerung der LCD-Matrix aus, wie sprichst Du das WIFI-Modul an? Welches Protokoll verwendest Du oder gedenkst Du zu verwenden, um mit Python zu kommunizieren?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Laura98 hat geschrieben: Dienstag 19. Juni 2018, 10:15 Das WIFI shield funktioniert bei uns nicht einzeln dass muss auf den Arduino gesteckt werden
Ich geb auf. Da du offensichtlich ausser Einsatz-Beschreibungen deines Problems nichts beitragen magst, kann ich da nicht weiter helfen. Viel Erfolg.
Antworten