===== Emulation und Driver (Helper) ===== {{ :efinf:blcks2017:tetristable:tigerjython.zip |nur Dateien vom tigerjython Ordner, neu mit Joystick-Emulation}} {{ :efinf:blcks2017:tetristable:helper.py |helper.py für den ESP32 (neu mit Joystick-Unterstützung)}}, Drähte von Eingängen D32 und D25 vertauschen, siehe [[efinf:blcks2017:tetristable:bauanleitung#verdrahtung|Verdrahtung]]. {{ :efinf:blcks2017:tetristable:mcp.py |mcp.py}} für den ESP32. Verwenden Sie dieses Archiv für ein Update (die Datei helper.py unterhalb des tigerjython Verzeichnisses soll nicht überschrieben werden). * {{ :efinf:blcks2017:tetristable:tetris-table.zip |Zip-Archiv mit Demo (Lauffähig auch in TigerJython)}} Die Datei ''helper.py'' unterhalb des tigerjython Verzeichnisses muss eventuell angepasst werden für den eigenen Tisch. Alle Zugriffe auf die Hardware müssen über die Helper-Klasse erfolgen. So sind die Programme auf allen Tischen lauffähig. Eigene Programme werden idealerweise wie die Demos erstellt. So sind diese sehr einfach auszutauschen und einzubauen. ===== Wifi: Verbund von Tischen ===== Hier mal ein POC (Proof of concept). Die Benutzung ist wie folgt: - Server starten - Clients starten - Beim Server einen der unteren Knöpfe drücken (-> warten auf eingehenden Verbindung). - Beim ersten client einen der unteren Knöpfe drücke (-> Verbindung mit Server) - Die letzten zwei Schritte für alle clients wiederholen - Beim Server einen der oberen Knöpfe drücken (-> Demo startet). ==== Client ==== import network import time import usocket as socket # Hack to get ticks_ms() method in Tigerjython working if not hasattr(time, 'ticks_ms'): from types import MethodType def ticks_ms(self): return int(round(self.time() * 1000)) time.ticks_ms = MethodType(ticks_ms, time) def sleep_ms(self,a): time.sleep(a/1000.0) time.sleep_ms = MethodType(sleep_ms, time) # END of Hack class WifiClient: def __init__(self,helper): self.helper = helper def setup(self): self.wlan = network.WLAN(network.STA_IF) self.wlan.active(True) self.wlan.connect('esp32') while not self.wlan.isconnected(): print(self.wlan.status()) time.sleep_ms(1000) # 1 second sleep print("WLAN ok") def connect(self): self.addr = socket.getaddrinfo('10.42.42.1', 80)[0][-1] self.sk = socket.socket() self.sk.connect(self.addr) print("Connected to server") def update(self): bytesread = 0 buf = b'' while bytesread<450: chunk = self.sk.recv(450) buf+=chunk bytesread+=len(chunk) if bytesread==450 and self.helper: for y in range(15): for x in range(10): p = 3*(y*10+x) self.helper.setPixel(x,y,(buf[p], buf[p+1], buf[p+2])) self.helper.np.write() #print("Updated") def sendButtons(self): if self.helper: btns = bytearray([self.helper.getButtons()]) self.sk.send(btns) def play(self): self.setup() if self.helper: while self.helper.getButtons()!=255: pass while self.helper.getButtons()==255: pass self.connect() while True: self.update() # Start with execfile("wificlient.py") if __name__=="__main__": from helper import Helper # Import der Klasse helper = Helper() # Erzeugen der Instanz # helper = None c = WifiClient(helper) c.play() ==== Server ==== # See https://docs.micropython.org/en/latest/esp8266/library/network.html import network import socket import math import time # Hack to get ticks_ms() method in Tigerjython working if not hasattr(time, 'ticks_ms'): from types import MethodType def ticks_ms(self): return int(round(self.time() * 1000)) time.ticks_ms = MethodType(ticks_ms, time) def sleep_ms(self,a): time.sleep(a/1000.0) time.sleep_ms = MethodType(sleep_ms, time) # END of Hack class WifiServer: def __init__(self, helper): self.helper = helper def setup(self): self.ap = network.WLAN(network.AP_IF) self.ap.active(True) self.ap.config(essid='esp32', authmode=0) self.ap.ifconfig(('10.42.42.1', '255.255.255.0', '10.42.42.1', '10.42.42.1')) print("AP up an running") self.connections=[] # self.cfiles=[] self.graphBuffers=[] self.buttons=bytearray([]) addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] self.sk = socket.socket() self.sk.bind(addr) self.sk.listen(1) print("Server up an running") def clearBuffers(self): if self.helper: for i in range(150): self.helper.np[i]=(0,0,0) for b in self.graphBuffers: for i in range(450): b[i]=0 def waitForConnection(self): print("Wait for connection...") cl, addr = self.sk.accept() self.connections.append(cl) print('client connected from', addr) #cl_file = cl.makefile('rwb', 0) #self.cfiles.append(cl_file) self.graphBuffers.append(bytearray([0 for i in range(450)])) self.buttons.append(255) def setPixel(self,x,y,color): if (x<10): if self.helper: self.helper.setPixel(x,y,color) else: table = x//10-1 if table=0 and n<149: self.graphBuffers[table][3*n]=color[0] self.graphBuffers[table][3*n+1]=color[1] self.graphBuffers[table][3*n+2]=color[2] def getButtons(self): # Get list with available bytes available = select.select(self.connections, (), (),0) for i in range(len(self.connections)): if self.connections[i] in available: b = self.connections[i].recv(1) if b=='': self.buttons[i]=255 else: self.buttons[i]=b[0] def write(self): if self.helper: self.helper.np.write() for i in range(len(self.connections)): totalsent = 0 while totalsent<450: sent = self.connections[i].send(bytes(self.graphBuffers[i][totalsent:])) if sent == 0: print("socket connection broken") break totalsent+=sent time.sleep_ms(40) # 25 fps #print("sent") def demo(self,i): xmax = (len(self.connections)+1)*10; self.clearBuffers() for x in range(xmax): y = int(math.sin(0.1*(x+i))*7+8) self.setPixel(x, y, (255,0,0)) self.setPixel(x, y+1, (50,0,0)) self.setPixel(x, y-1, (50,0,0)) y = int(math.sin(0.06189*(x+i+5))*7+8) self.setPixel(x, y, (0,255,0)) self.setPixel(x, y+1, (0,50,0)) self.setPixel(x, y-1, (0,50,0)) y = int(math.sin(0.04189*(x+i+10))*7+8) self.setPixel(x, y, (0,0,255)) self.setPixel(x, y+1, (0,0,50)) self.setPixel(x, y-1, (0,0,50)) self.write() def play(self): self.setup() if self.helper: while True: while self.helper.getButtons()!=255: pass while self.helper.getButtons()==255: pass if (self.helper.getButtons()^0xff) &0xf>0: self.waitForConnection() else: break else: self.waitForConnection() i=0 while True: self.demo(i) i+=1 # Start with execfile("wifiserver.py") if __name__=="__main__": print("Start Main") # from helper import Helper # Import der Klasse # helper = Helper() # Erzeugen der Instanz helper = None print(helper) s = WifiServer(helper) s.play() ===== Ablauf der Programmierung ===== **Achtung**: Wenn Putty verbunden ist, funktioniert ampy nicht (und umgekehrt). * Entwicklung des Codes im Texteditor, speichern einer Datei, z.B. ''beispiel.py'' * Eventuell Datei lokal mit Python ausführen, erste Bugs werden so schon gefunden. * Datei mit ''ampy'' auf EPS laden. * Wenn die Datei ''main.py'' heisst (oder von main.py aufgerufen wird): * Reset am Tisch * Sonst: * Verbinden mit Putty (oder pico-dingsbums auf Mac), evtl. Ctrl-C um Programm zu stoppen * Programm mit ''import beispiel.py'' ausführen, Fehlermeldungen verstehen. ===== Tools auf dem ESP ===== * Dateien anschauen, löschen, umbennen, direkt auf dem ESP: * Mit Putty verbinden * ''import os'' * ''help(os)'' (Zeigt Befehle an, wie Liste der Dateien, löschen, umbenennen). ===== Joysticks testen ===== Auf der Konsole (putty oder screen) import helper h = helper.Helper() while True: print(h.getJoyStick(0))