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.
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Hallo :)
ich muss für ein Projekt mit Python Snake programmieren und dieses auf einen Arduino mit einer LED-Matrix anzeigen lassen. Ich habe im Internet ein Skript gefunden welches dies auf einen RaspberryPi überträgt.. kann man dies so ändern, dass es dies auf den Arduino überträgt ? Und ich würde gerne wissen, ob es sich auch in einen separaten Fenster in Python mit der tk funktion öffnen lässt.
Hier der Code:

Code: Alles auswählen

import RPi.GPIO as gpio
import time
import max7219.led as led
from random import randint

gpio.setmode(gpio.BCM)
taster = [14,15,18,23]
matrixe = 1
matrix = led.matrix(cascaded=matrixe)
height = 7
width = (8*matrixe)-1

def steuerung(gpio):
  global richtung
  if(gpio == 14):   #rechts
    richtung = [1,0]
  elif(gpio == 15): #oben
    richtung = [0,-1]
  elif(gpio == 18): #unten
     richtung = [0,1]
  elif(gpio == 23): #links
    richtung = [-1,0]

for i in taster:
  gpio.setup(i,gpio.IN,pull_up_down=gpio.PUD_UP)
  gpio.add_event_detect(i, gpio.FALLING,
          callback=steuerung)
def startSpiel():
  global snake, richtung, apfel
  snake = [[randint(2,width-4),randint(3,height-3)]]
  richtung = [0,0]
  while richtung == [0,0]:
    matrix.show_message("READY")
  neuerApfel()

def neuerApfel():
  global apfel, snake
  apfelSnake = False
  while apfelSnake == False:
    apfelSnake = True
    apfel = [randint(0,width),randint(0,height)]
    for i in snake:
      if(i == apfel):
        apfelSnake = False
  print(apfel)

def endOfGame():
  for i in range(0,2):
    matrix.clear()
    for i in range(0,width+1):
      for j in range(0,height+1):
        matrix.pixel(i,j,1)
        time.sleep(0.001)
    time.sleep(0.01)
  matrix.show_message("GAME OVER")
  punkte = len(snake)-1
  matrix.show_message(str(punkte)+" PUNKTE")

  startSpiel()

startSpiel()

while True:
  keinePause = False
  newSnake = [snake[0][0]+richtung[0],
              snake[0][1]+richtung[1]]
  for i in snake:
    if(i == newSnake):
      endOfGame()
      pass

  if(newSnake == apfel):
     neuerApfel()
     keinePause = True
  else:
     snake.pop()
  snake.insert(0,newSnake)

  if(snake[0][0] > width or snake[0][1] > height
    or snake[0][0] < 0 or snake[0][1] < 0 ):
    endOfGame()
    pass

  matrix.clear()
  for i in snake:
    matrix.pixel(i[0],i[1], 1)
  matrix.pixel(apfel[0],apfel[1],1)
  if(keinePause == False):
    newLength = (len(snake)-2)*0.01
    time.sleep(0.3-newLength)
  else:
    time.sleep(0.3)
Vielen Dank schon mal für die Hilfe :)
Zuletzt geändert von __deets__ am Sonntag 3. Juni 2018, 10:38, insgesamt 1-mal geändert.
Grund: Code tags
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hallo Laura98,

bitte in Zukunft beim posten von Code die Code-Tags benutzen (das ist der Python-Button im Menue des Editors), weil man sonst deinen Code nicht entziffern kann. In Python sind die Einruekungen wichtig, und die gehen sonst verloren.

Mir ist nicht ganz klar, was deine Aufgabe ist. Soll da Python-Programm AUF dem Arduino laufen? Mir waere nicht bekannt, dass das geht. Selbst MicroPython braucht etwas staerkere Controller. Oder soll der Arduino nur die Darstellung uebernehmen?
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Achso ok mach ich beim nächsten mal, danke für den Tipp:)
Der Arduino soll die Darstellung übernehmen
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Aber das Spiel auf dem PI oder einem anderen Computer laufen? Wenn ja, dann musst du den Ardunino so programmieren, dass du per Serieller Schnittstelle Kommandos entgegennimmst, die das Spielfeld aufbauen. Also im Grunde den Teil der Matrix ersetzen mit etwas, dass den Arduino anspricht via serieller Schnittstelle.
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

An den Arduino soll ne Matrix und Knöpfe gebaut werden und auf dieser Matrix soll das Spiel laufen und es soll durch die Knöpfe gesteuert werden
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Also der arduino kontrolliert ein und ausgabe, aber die spiellogik auf einem anderen Computer? Das ist bei einem so simplen Spiel, das auch direkt auf dem arduino laufen könnte eigentlich ziemlicher Quatsch. Weil es Dinge viel schwieriger macht (serielles Protokoll entwerfen & benutzen, geteilten Zustand verwalten etc) als sie sein müssten.

Wenn du darfst, mach das ALLES auf dem arduino. Wenn du musst, bleibt meine Antwort aber gleich: du musst die serielle Schnittstelle benutzen, und dann eben Tatsendrücke nach oben melden und Bildschirminhalte entgegennehmen.
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

ne das muss über Python und Arduino laufen
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Na gut. Wie gesagt - die serielle Verbindung ist dein Freund. Du brauchst ein simples Protokoll mit dem du Pixel setzen kannst. Und von dem du Tastendrücke geliefert kriegst.

Hier gibt’s eine Reihe von Erklärungen und Beispielen: https://playground.arduino.cc/Interfacing/Python
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

hmm dachte mir kann da jemand direkt bei Code helfen
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Koennen ja. Bei nur ca 10 Leuten am Tag, die sich genau das wuenschen, ist das aber eher unwahrscheinlich. Wenn du zeigst, was du versuchst, und wo es hakt, helfe ich (und die meisten anderen hier) gerne weiter. Einfach fuer lau die Probleme anderer schluesselfertig abliefern komme ich mir ein bisschen sehr ausgenutzt vor. Aber vielleicht hast du ja Glueck, und wer anderes erbarmt sich.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Laura98: Du meinst das was *Du* programmieren sollst, für Dich programmieren? Das ist eigentlich nicht der Sinn von solchen Projekten, dass man nicht selbst programmieren lernt, sondern sich das ganze aus dem Netz zusammen klaut und von anderen anpassen/programmieren lässt. Das hilft Dir ja letztlich nicht beim lernen sondern nur beim betrügen.

Oder wie hast Du Dir jetzt Hilfe beim Code vorgestellt?
“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 will ja auch nicht dass ihr das komplett für mich macht.. ich konnte nur wegen meiner Gesundheit nicht so oft zur Vorlesung und deshalb hänge ich gerade mit Python etwas hinterher...
bei mir hackt es gerade an der separaten Darstellung mit der tk Funktion damit kenne ich mich nämlich gar nicht aus. Wir sollen ds Programm auch in einem Fenster in Python abspielen können
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Laura98: Es machte halt den Eindruck, weil Du noch nichts eigenes gezeigt hast, und keine *konkrete* Frage gestellt hast. Es bleibt von mir die Frage wie die Hilfe denn genau aussehen soll.

Wenn Du mit Python etwas hinterher bist, dann musst Du das halt aufholen. Und wenn Du Dich mit Tk/Tkinter noch nicht auskennst, dann musst Du das halt auch lernen. Das kann Dir niemand abnehmen. Und das kann hier im Forum auch niemand wirklich mit Dir durchgehen, denn das ist beides zu umfangreich. Auf der anderen Seite gibt es da ja bereits Dokumentation, Literatur, und Tutorials.

Und dann ist da noch das etwas abstraktere, was nicht speziell mit Python und Tk zu tun hat, sondern mehr mit Softwareentwicklung allgemein. Also beispielsweise Objektorientierung und Strukturierung von Code, hilfreiche Werkzeuge wie (verteilte) Versionsverwaltungen, usw. Auch das ist umfangreich.

Letztlich gibt es bei Dir ja auch noch eine Vorlesung, wo Ihr ja auch etwas gelernt haben solltet. Eventuell auch Unterrichtsmaterialien? Und falls Du davon krankheitsbedingt nicht alles mitbekommen hast, müsstest Du das nacharbeiten.

Wenn das ein Projekt ist, müsstest Du als ersten Schritt ein wenig planen. Was hast Du, was brauchst Du, wie kommst Du da hin. Neben Python wirst Du für den Arduino auch ein wenig C lernen müssen, falls Du das noch nicht kannst.

Für das Spiel müsstest Du das Spiel programmieren. Unabhängig von der Benutzerinteraktion. Da musst Du eine saubere Schnittstelle anbieten, denn letztlich soll die gleiche Programmlogik sowohl mit einem Arduino mit LED-Matrix und Tastern, als auch mit einer Tk-Oberfläche laufen können. Ich würde mit dem Spiel anfangen und wenn das umgesetzt und getestet ist, die GUI drauf setzen, und den Arduino zum Schluss machen. Für die Spiellogik und GUI braucht man keine zusätzliche Hardware und kein C-Programm + serielles Protokoll, das ist also erst einmal einfacher.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Laura98 hat geschrieben: Sonntag 3. Juni 2018, 18:16 ich konnte nur wegen meiner Gesundheit nicht so oft zur Vorlesung und deshalb hänge ich gerade mit Python etwas hinterher...
das mit deiner Gesundheit tut mir Leid, sowas ist immer Mist.
Meine Tochter studiert auch gerade, wenn auch nichts mit IT, und wenn da mal Verständnisprobleme sind, schließt man/frau sich mit Kommilitonen kurz, Mitstudenten/innen die den gleichen Stoff pauken
müssen und bei anderen Dingen Probleme haben. Man/Frau lernt echt am meisten im Team. Einzelkämpfer/innen haben es schwer.
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
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

ich würde gerne wissen was in dem code genau mit dem RaspberryPi zu tun hat .
ich weiß dass ich das damit irgendwie mit dem Arduino verbinde :

from pyfirmata import Arduino, util
import time
board = Arduino("COM3")
bin echt verzweifelt :(
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Hast Du denn die Firmata-Firmware auf dem Arduino? Und eine LED-Matrix an dem Arduino angeschlossen? Und weisst Du wie die dann angesteuert werden muss über die Pins?

Falls die Frage zu den Teilen die mit dem RaspberryPi zu tun haben, sich auf den Quelltext im ersten Beitrag beziehen: Vergiss den am besten gleich wieder. Der ist an sich schon recht schlecht, nicht zuletzt wegen den vielen ``global``-Anweisungen. Wenn Du dann dann noch alles raus löschst was mit dem Raspi zu tun hat, bleibt nichts übrig was Du ohne es komplett umzuschreiben für zwei verschiedene Frontends wiederverwenden kannst. Unter anderem wegen der ganzen ``global``\s.

Wenn Du verzweifelt bist, könntest Du Dich an einen Tutor oder den Dozenten wenden, oder wer auch immer das Projekt betreut, und dem Deine Probleme schildern und um Rat fragen.

Wie gesagt noch mal mein Rat für die Strukturierung: Erst die Spiellogik ohne Benutzerinteraktion, dann die GUI, und dann erst den Teil mit dem Arduino. Auf die Spiellogik bauen sowohl GUI als auch Arduino auf. Die GUI ist einfacher umzusetzen als das mit dem Arduino. Gleichzeitig bekommt man bei der GUI auch recht schnell Probleme mit der sauberen Trennung zwischen Logik und Benutzerinteraktion mit und gelöst, die man für de Arduino dann ja auch braucht.

Beim Firmata-Protokoll würde ich als erstes evaluieren ob das für die verwendete Hardware geeignet ist, oder ob man da auf dem Arduino nicht am Ende doch selbst Code schreiben muss um die LED-Matrix anzusteuern, weil die vielleicht einen dauerhaft laufenden „refresh“ braucht, wenn das nicht in Hardware, also durch einen entsprechenden Steuerchip gelöst ist.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Hase
User
Beiträge: 100
Registriert: Donnerstag 1. Oktober 2009, 15:17
Wohnort: Bremer Speckgürtel

Die Programmieraufgabe hat, so wie du es geschildert hast, nichts mit dem RaspberryPi zu tun. Der Code sollte daher von allen RaspberryPi bezogenem Code befreit werden.
1) Letzlich bleibt nur sowas übrig wie: hoch, runter, links rechts auf Tastenddruck. Zum Test brauchst du auch keine GUI, es genügt die Ausgabe auf der Kommandozeile.
2) Such dir ein Beispiel, wie der Aurduino das LCD-Display ansteuert. Da gibt es ausreichend in Netz.
3) Jetzt musst du nur noch eine Schnittstelle zwischen Computer und Arduino schaffen, am besten eine Serielle. Python gibt die Kommandos "rechts links oben unten" auf die serielle Schnittstelle aus und der Arduino nimmt sie auf der seriellen Schnittstelle entgegen und leitet sie an das LCD weiter. Das sollte es sein.

So würde ich rangehen. (Wenn ich die Aufgabenstellung richtig verstanden habe. )
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Hase: Es soll sowohl eine Tk-GUI als auch eine Darstellung über den Arduino umgesetzt werden. Also würde man die Richtungen eher nicht *zum* Arduino übertragen, denn das würde ja bedeuten, dass man die Spiellogik für die Tk-GUI in Python hat und dann noch mal in C für den Arduino programmieren müsste. Sinnvoller wäre es auch im Arduino-Fall die Spiellogik in Python zu schreiben, die man dann sowohl für die GUI als auch den Arduino verwenden kann. Die Richtungen könnten aber *vom* Arduino in Richtung PC übertragen werden, falls am Arduino Taster für die Richtungen existieren/angeschlossen sind.

Ausserdem ist am Arduino eine LED-Matrix angeschlossen und kein LCD-Display. Aber auch dafür wird es natürlich Dokumentation und sehr wahrscheinlich auch Beispiele geben.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

EDIT: Meine Antwort hat sich hiermit erübrigt. Zu spät die anderen Beiträge gesehen..

Firmata ist ein Protokoll zur Steuerung von Mikrocontroller, dass so in ziemlich allen Sprachen implementiert ist.

Kurz und Knapp: Das Protokoll macht aus deinem Arduino einen Slave und der Rapsberry Pi ist sein master.
Zuerst überträgst du das Standard-Firmata-Projekt zum Arduino.

Dann verbindest du den RaspberryPi mit dem Arduino, kann auch irgendein anderer Computer sein.
Der USB-Port des Arduino stellt den virtuellen COM (seriellen Port) zur Verfügung. Unter dem Raspberry Pi müsste
der unter /dev/ttyUSB0 erscheinen. Die Namensgebung kann sich aber auch geändert haben.

Der master nutzt dann eins der Frameworks für Firmata. Da gibt es z.B. PyFirmata: https://github.com/tino/pyFirmata
Damit machst du dann nichts anderes, als Eingänge und Ausgänge einzulesen bzw. zu steuern.
Das erfordert dann aber eine derauerhafte Verbindung zwischen Arduino und Raspberry Pi.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Laura98
User
Beiträge: 17
Registriert: Sonntag 3. Juni 2018, 09:59

Danke für eure Antworten :)
ich hab jetzt diese code Komplett selber geschrieben.

Code: Alles auswählen

from random import *
from tkinter import *
from time import *

WELT_GRÖSSE = 200
ZELLEN = 8
SNAKETEMPO = 250

class Welt:
    height = 20
    width = 20
    apfelposition = (1,1)

    def __init__(self, snake):
        self.snake = snake
        self.width = ZELLEN
        self.height = ZELLEN
        self.neueApfelposition()
        

    def neueApfelposition(self):
        self.apfelposition = (randint(1, self.width - 1), randint(1, self.height - 1))

        x = self.apfelposition[0]
        y = self.apfelposition[1]

        for part in self.snake.körper:
            if(x == part.x and y == part.y):
                self.neueApfelposition()
    

class SnakeKörperStück:
    def __init__(self, x, y):
        self.x = x
        self.y = y

class Snake:

    def __init__(self):
        startpunkt = (ZELLEN/2, ZELLEN/2)

        part1 = SnakeKörperStück(startpunkt[0], startpunkt[1])
        part2 = SnakeKörperStück(startpunkt[0], startpunkt[1]+1)
        part3 = SnakeKörperStück(startpunkt[0], startpunkt[1]+2)

        self.körper = [part1,part2,part3]

        self.richtung = "up"
        self.letzte_richtung = "up"

class SnakeSpiel(Frame):

    def __init__(self, welt, snake, master=None):
        Frame.__init__(self, master)
        self.pack()
        self.welt = welt
        self.snake = snake

    def myLoop(self):
        self.zeichneWelt()
        self.Spiellogik()
        self.after(SNAKETEMPO, self.myLoop)         

    def setCanvas(self, canvas):
        self.canv = canvas  

    def zeichneWelt(self):
        self.canv.delete("all")

        # Gitter zeichnen
        zellen_grösse = WELT_GRÖSSE / self.welt.width
        for x in range(self.welt.width):
            for y in range(self.welt.height):
                self.canv.create_rectangle(x * zellen_grösse, y * zellen_grösse, x * zellen_grösse + zellen_grösse,
                                           y * zellen_grösse + zellen_grösse)

        # Essen zeichen
        self.canv.create_oval(welt.apfelposition[0] * zellen_grösse + 3, welt.apfelposition[1] * zellen_grösse + 3,
                              welt.apfelposition[0] * zellen_grösse + zellen_grösse - 3,
                              welt.apfelposition[1] * zellen_grösse + zellen_grösse - 3, fill="darkred")

        # Snake zeichnen
        for part in self.snake.körper:
            self.canv.create_rectangle(part.x * zellen_grösse, part.y * zellen_grösse, part.x * zellen_grösse + zellen_grösse,
                                       part.y * zellen_grösse + zellen_grösse, fill="green")

    
    def Spiellogik(self):
        if(self.snake.richtung == "up"):
            self.snake.letzte_richtung = "up"
            newPart = SnakeKörperStück(self.snake.körper[0].x, self.snake.körper[0].y - 1)
            self.snake.körper.insert(0, newPart)
        elif (self.snake.richtung == "left"):
            self.snake.letzte_richtung = "left"
            newPart = SnakeKörperStück(self.snake.körper[0].x - 1, self.snake.körper[0].y)
            self.snake.körper.insert(0, newPart)
        elif (self.snake.richtung == "right"):
            self.snake.letzte_richtung = "right"
            newPart = SnakeKörperStück(self.snake.körper[0].x + 1, self.snake.körper[0].y)
            self.snake.körper.insert(0, newPart)
        elif (self.snake.richtung == "down"):
            self.snake.letzte_richtung = "down"
            newPart = SnakeKörperStück(self.snake.körper[0].x, self.snake.körper[0].y + 1)
            self.snake.körper.insert(0, newPart)


        xKopf = self.snake.körper[0].x
        yKopf = self.snake.körper[0].y

        xApfel = self.welt.apfelposition[0]
        yApfel = self.welt.apfelposition[1]

        if(xKopf == xApfel and yKopf == yApfel):
            self.welt.neueApfelposition()
        else:
            self.snake.körper.pop()    

        if(xKopf >= welt.width or xKopf < 0 or yKopf >= welt.height or yKopf < 0):
            self.snake = Snake()
            

        körperIter = iter(self.snake.körper)
        next(körperIter)
        for part in körperIter:
            if(xKopf == part.x and yKopf == part.y):
                self.snake = Snake()

    def hochTaste(self, event):
        if(self.snake.letzte_richtung != "down"):
            self.snake.richtung = "up"
    def runterTaste(self, event):
        if(self.snake.letzte_richtung != "up"):
            self.snake.richtung = "down"
    def rechtsTaste(self, event):
        if(self.snake.letzte_richtung != "left"):
            self.snake.richtung = "right"
    def linksTaste(self, event):
        if(self.snake.letzte_richtung != "right"):
            self.snake.richtung = "left"

            
snake = Snake()
welt = Welt(snake)

spiel = SnakeSpiel(welt, snake)
spiel.master.title("Snake-Projekt")
spiel.master.minsize(WELT_GRÖSSE,WELT_GRÖSSE)
spiel.master.maxsize(WELT_GRÖSSE,WELT_GRÖSSE)

spiel.master.bind("<Down>", spiel.runterTaste)
spiel.master.bind("<Up>", spiel.hochTaste)
spiel.master.bind("<Left>", spiel.linksTaste)
spiel.master.bind("<Right>", spiel.rechtsTaste)

canv = Canvas(spiel.master, width=WELT_GRÖSSE, height=WELT_GRÖSSE)
canv.pack()




spiel.setCanvas(canv)
spiel.zeichneWelt()
spiel.myLoop()
spiel.mainloop()
Mir fehlt jetzt leider der Ansatz wie ich es mit dem Arduino wie ESP8266 Wifi shield mit den Arduino verbinde. Es soll ja auch durch das Drücken eines Knopfes nicht nur auf der Matrix gesteuert werden sonder auch auf dem GUI
Antworten