mirror of
				https://github.com/luc-github/ESP3D.git
				synced 2025-10-24 11:50:52 -07:00 
			
		
		
		
	Add TFT Simulator tool to test ESP board with ESP3D without printer o cnc
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -10,3 +10,4 @@ embedded/node_modules | |||||||
| .vscode/launch.json | .vscode/launch.json | ||||||
| .vscode/arduino.json | .vscode/arduino.json | ||||||
| esp3d/myconfig.h | esp3d/myconfig.h | ||||||
|  | __pycache__ | ||||||
							
								
								
									
										31
									
								
								tools/fw_simulator/esp3d_common.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								tools/fw_simulator/esp3d_common.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | #Common ESP3D snippets | ||||||
|  | import time | ||||||
|  |  | ||||||
|  | class bcolors: | ||||||
|  |     COL_PURPLE = '\033[95m' | ||||||
|  |     COL_BLUE = '\033[94m' | ||||||
|  |     COL_CYAN = '\033[96m' | ||||||
|  |     COL_GREEN = '\033[92m' | ||||||
|  |     COL_ORANGE = '\033[93m' | ||||||
|  |     COL_RED = '\033[91m' | ||||||
|  |     END_COL = '\033[0m' | ||||||
|  |     BOLD = '\033[1m' | ||||||
|  |     UNDERLINE = '\033[4m' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def current_milli_time(): | ||||||
|  |     return round(time.time() * 1000) | ||||||
|  |  | ||||||
|  | def wait(durationms, ser): | ||||||
|  |     nowtime = current_milli_time() | ||||||
|  |     while (current_milli_time() < nowtime + durationms): | ||||||
|  |          if ser.in_waiting: | ||||||
|  |             line = ser.readline().decode('utf-8').strip() | ||||||
|  |             print(bcolors.COL_BLUE+line+bcolors.END_COL) | ||||||
|  |      | ||||||
|  |      | ||||||
|  | def send_echo(ser, msg): | ||||||
|  |     ser.write((msg + "\n").encode('utf-8')) | ||||||
|  |     ser.flush() | ||||||
|  |     print(bcolors.END_COL + msg + bcolors.END_COL) | ||||||
							
								
								
									
										64
									
								
								tools/fw_simulator/fw_simulator.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								tools/fw_simulator/fw_simulator.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | import sys | ||||||
|  | import serial | ||||||
|  | import serial.tools.list_ports | ||||||
|  | import esp3d_common as common | ||||||
|  | import marlin  | ||||||
|  | import grbl | ||||||
|  | import repetier | ||||||
|  | import smoothieware | ||||||
|  |  | ||||||
|  | def main(): | ||||||
|  |     if len(sys.argv) < 2: | ||||||
|  |         print("Please use one of the follwowing FW: marlin, repetier, smoothieware or grbl.") | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |     fw_name = sys.argv[1].lower() | ||||||
|  |  | ||||||
|  |     if fw_name == "marlin": | ||||||
|  |         fw = marlin | ||||||
|  |     elif fw_name == "repetier": | ||||||
|  |         fw = repetier | ||||||
|  |     elif fw_name == "smoothieware": | ||||||
|  |         fw = smoothieware | ||||||
|  |     elif fw_name == "grbl": | ||||||
|  |         fw = grbl | ||||||
|  |     else: | ||||||
|  |         print("Firmware not supported : {}".format(fw_name)) | ||||||
|  |         return | ||||||
|  |     ports = serial.tools.list_ports.comports() | ||||||
|  |     portTFT = "" | ||||||
|  |     print(common.bcolors.COL_GREEN+"Serial ports detected: "+common.bcolors.END_COL) | ||||||
|  |     for port, desc, hwid in sorted(ports): | ||||||
|  |         print(common.bcolors.COL_GREEN+" - {}: {} ".format(port, desc)+common.bcolors.END_COL) | ||||||
|  |         desc.capitalize() | ||||||
|  |         if (desc.find("SERIAL") != -1): | ||||||
|  |             portTFT = port | ||||||
|  |             print(common.bcolors.COL_GREEN + | ||||||
|  |                   "Found " + portTFT + " for ESP3D"+common.bcolors.END_COL) | ||||||
|  |             break | ||||||
|  |     print(common.bcolors.COL_GREEN+"Open port " + str(port)+common.bcolors.END_COL) | ||||||
|  |     if (portTFT == ""): | ||||||
|  |         print(common.bcolors.COL_RED+"No serial port found"+common.bcolors.END_COL) | ||||||
|  |         exit(0) | ||||||
|  |     ser = serial.Serial(portTFT, 115200) | ||||||
|  |     print(common.bcolors.COL_GREEN+"Now Simulating: " + fw_name + common.bcolors.END_COL) | ||||||
|  |     starttime = common.current_milli_time() | ||||||
|  |     # loop forever, just unplug the port to stop the program or do ctrl-c | ||||||
|  |     while True: | ||||||
|  |         try: | ||||||
|  |             if ser.in_waiting: | ||||||
|  |                 line = ser.readline().decode('utf-8').strip() | ||||||
|  |                 print(common.bcolors.COL_BLUE+line+common.bcolors.END_COL) | ||||||
|  |                 #ignore log lines from TFT | ||||||
|  |                 if not line.startswith("["): | ||||||
|  |                     response = fw.processLine(line, ser) | ||||||
|  |                     if (response != ""): | ||||||
|  |                         common.send_echo(ser, response) | ||||||
|  |         except KeyboardInterrupt: | ||||||
|  |             print(common.bcolors.COL_GREEN+"End of program"+common.bcolors.END_COL) | ||||||
|  |             exit(0) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # call main function | ||||||
|  | main() | ||||||
							
								
								
									
										231
									
								
								tools/fw_simulator/grbl.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								tools/fw_simulator/grbl.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # Marlin GCODE parser / responder | ||||||
|  |  | ||||||
|  | import time | ||||||
|  | import re | ||||||
|  | import random | ||||||
|  | import esp3d_common as common | ||||||
|  | positions = { | ||||||
|  |     "X": 0.0, | ||||||
|  |     "Y": 0.0, | ||||||
|  |     "Z": 0.0, | ||||||
|  |     "A": 0.0, | ||||||
|  |     "B": 0.0, | ||||||
|  |     "C": 0.0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | modes = { | ||||||
|  |     "absolute": True | ||||||
|  | } | ||||||
|  |  | ||||||
|  | report_counter = 0 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def wait(durationms, ser): | ||||||
|  |     nowtime = common.current_milli_time() | ||||||
|  |     while (common.current_milli_time() < nowtime + durationms): | ||||||
|  |         if ser.in_waiting: | ||||||
|  |             line = ser.readline().decode('utf-8').strip() | ||||||
|  |             print(common.bcolors.COL_PURPLE+line+common.bcolors.END_COL) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def ok(line): | ||||||
|  |     if (not line.startswith("N")): | ||||||
|  |         return "ok (" + line + ")" | ||||||
|  |     N = re.findall(r'N\d*', line) | ||||||
|  |     if (len(N) > 0): | ||||||
|  |         return "ok " + N[0][1:] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # build the response for the busy response, | ||||||
|  | # simulating the delay of the busy response | ||||||
|  | def send_busy(ser, nb): | ||||||
|  |     v = nb | ||||||
|  |     while (v > 0): | ||||||
|  |         # FIXME: the message is not this one on grbl | ||||||
|  |         # common.send_echo(ser, "echo:busy: processing") | ||||||
|  |         wait(1000, ser) | ||||||
|  |         v = v - 1 | ||||||
|  |  | ||||||
|  | # G0/G1 response | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def G0_G1_response(cmd, line, ser): | ||||||
|  |     global positions | ||||||
|  |     X_val = "" | ||||||
|  |     Y_val = "" | ||||||
|  |     Z_val = "" | ||||||
|  |     A_val = "" | ||||||
|  |     B_val = "" | ||||||
|  |     C_val = "" | ||||||
|  |  # extract X | ||||||
|  |     X = re.findall(r'X[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(X) > 0): | ||||||
|  |         X_val = X[0][1:] | ||||||
|  |     # extract Y | ||||||
|  |     Y = re.findall(r'Y[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Y) > 0): | ||||||
|  |         Y_val = Y[0][1:] | ||||||
|  |     # extract Z | ||||||
|  |     Z = re.findall(r'Z[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Z) > 0): | ||||||
|  |         Z_val = Z[0][1:] | ||||||
|  |     # extract A | ||||||
|  |     A = re.findall(r'A[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(A) > 0): | ||||||
|  |         A_val = A[0][1:] | ||||||
|  |     # extract B | ||||||
|  |     B = re.findall(r'B[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(B) > 0): | ||||||
|  |         B_val = B[0][1:] | ||||||
|  |     # extract C | ||||||
|  |     C = re.findall(r'C[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(C) > 0): | ||||||
|  |         C_val = C[0][1:] | ||||||
|  |     if (modes["absolute"]): | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] = float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] = float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] = float(Z_val) | ||||||
|  |         if (A_val!= ""): | ||||||
|  |             positions["A"] = float(A_val) | ||||||
|  |         if (B_val!= ""): | ||||||
|  |             positions["B"] = float(B_val) | ||||||
|  |         if (C_val!= ""): | ||||||
|  |             positions["C"] = float(C_val) | ||||||
|  |         return ok(line) | ||||||
|  |     else: | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] += float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] += float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] += float(Z_val) | ||||||
|  |         if (A_val!= ""): | ||||||
|  |             positions["A"] += float(A_val) | ||||||
|  |         if (B_val!= ""): | ||||||
|  |             positions["B"] += float(B_val) | ||||||
|  |         if (C_val!= ""): | ||||||
|  |             positions["C"] += float(C_val) | ||||||
|  |         return ok(line) | ||||||
|  |  | ||||||
|  | # $H response | ||||||
|  |  | ||||||
|  | def Home_response(cmd, line, ser): | ||||||
|  |     global positions | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     if (cmd.find("X") != -1): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |     if (cmd.find("Y") != -1): | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |     if (cmd.find("Z") != -1): | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     if (cmd.find("A")!= -1): | ||||||
|  |         positions["A"] = 0.00 | ||||||
|  |     if (cmd.find("B")!= -1): | ||||||
|  |         positions["B"] = 0.00 | ||||||
|  |     if (cmd.find("C")!= -1): | ||||||
|  |         positions["C"] = 0.00 | ||||||
|  |     if (cmd == "G28"): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |         positions["A"] = 0.00 | ||||||
|  |         positiones["B"] = 0.00 | ||||||
|  |         positions["C"] = 0.00 | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Absolute mode | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def G90_response(cmd, line, ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = True | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Relative mode | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def G91_response(cmd, line, ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = False | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | def Jog_response(cmd, line, ser): | ||||||
|  |     if (cmd.find("G91")!= -1): | ||||||
|  |         G91_response(cmd, line, ser) | ||||||
|  |     elif (cmd.find("G90")!= -1): | ||||||
|  |         G90_response(cmd, line, ser) | ||||||
|  |     cmd = cmd.replace("G90", "") | ||||||
|  |     cmd = cmd.replace("G91", "") | ||||||
|  |     cmd = cmd.replace("G21", "") | ||||||
|  |     cmd = cmd.strip() | ||||||
|  |     return G0_G1_response(cmd, line, ser) | ||||||
|  |  | ||||||
|  | # status response | ||||||
|  | # "<Idle|MPos:0.000,0.000,0.000,1.000,1.000|FS:0,0|WCO:0.000,0.000,0.000,1.000,1.000>\n" | ||||||
|  | # "<Idle|MPos:0.000,0.000,0.000,1.000,1.000|FS:0,0|A:S|Pn:P>\n" | ||||||
|  | # "<Idle|MPos:0.000,0.000,0.000,1.000,1.000|FS:0,0|Ov:100,100,100|Pn:XYZ>\n" | ||||||
|  | def status_response(cmd, line, ser): | ||||||
|  |     global positions | ||||||
|  |     global report_counter | ||||||
|  |     wpco = "" | ||||||
|  |     ov = "" | ||||||
|  |     fs = "|FS:0,0" | ||||||
|  |     astate = "" | ||||||
|  |     pn = "" | ||||||
|  |     status = "Idle" | ||||||
|  |     report_counter += 1 | ||||||
|  |     if report_counter == 11: | ||||||
|  |         report_counter = 1 | ||||||
|  |     if report_counter == 1: | ||||||
|  |         wpco = "|WCO:0.000,0.000,0.000,1.000,1.000,1.000" | ||||||
|  |     if report_counter == 2: | ||||||
|  |         #FIXME: use variable to report the override values | ||||||
|  |         ov = "|Ov:100,100,100" | ||||||
|  |         pn = "|Pn:XYZ" | ||||||
|  |     if report_counter >= 3: | ||||||
|  |         astate = "|A:S" | ||||||
|  |         pn = "|Pn:P" | ||||||
|  |          | ||||||
|  |     position = "|MPos:" + "{:.3f}".format(positions["X"]) + "," + "{:.3f}".format( | ||||||
|  |         positions["Y"]) + "," + "{:.3f}".format(positions["Z"]) + "," + "{:.3f}".format(positions["A"]) + "," + "{:.3f}".format(positions["B"]) + "," + "{:.3f}".format(positions["C"]) | ||||||
|  |     return "<" + status + position + fs + wpco + ov + astate + pn + ">\n" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # List of supported methods | ||||||
|  | methods = [ | ||||||
|  |     {"str": "G0", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G1", "fn": G0_G1_response}, | ||||||
|  |     {"str": "$H", "fn": Home_response}, | ||||||
|  |     {"str": "$J=", "fn": Jog_response}, | ||||||
|  |     {"str": "G90", "fn": G90_response}, | ||||||
|  |     {"str": "G91", "fn": G91_response}, | ||||||
|  |     {"str": "?", "fn": status_response}, | ||||||
|  | ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Process a line of GCODE | ||||||
|  | def processLine(line, ser): | ||||||
|  |     time.sleep(0.01) | ||||||
|  |     cmd = line | ||||||
|  |     if (line.startswith("N")): | ||||||
|  |         p = line.find(' ') | ||||||
|  |         cmd = line[p+1:] | ||||||
|  |         p = cmd.rfind('*') | ||||||
|  |         cmd = cmd[:p] | ||||||
|  |     global methods | ||||||
|  |     for method in methods: | ||||||
|  |         if cmd.startswith(method["str"]): | ||||||
|  |             return method["fn"](cmd, line, ser) | ||||||
|  |     if line.startswith("M") or line.startswith("G") or line.startswith("N") or line.startswith("$"): | ||||||
|  |         return ok(line) | ||||||
|  |     if line.find("[esp") != -1 or line.find("[0;") != -1 or line.find("[1;") != -1: | ||||||
|  |         return "" | ||||||
|  |     if line.startswith("ESP-ROM") or line.startswith("Build:") or line.startswith("SPIWP:") or line.startswith("mode:")or line.startswith("load:") or line.startswith("entry "): | ||||||
|  |         return "" | ||||||
|  |     #FIXME: this is not grbl response if the command is not recognized | ||||||
|  |     return "echo:Unknown command: \"" + line + "\"\nok" | ||||||
							
								
								
									
										360
									
								
								tools/fw_simulator/marlin.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								tools/fw_simulator/marlin.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,360 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # Marlin GCODE parser / responder | ||||||
|  |  | ||||||
|  | import time | ||||||
|  | import re | ||||||
|  | import random | ||||||
|  | import esp3d_common as common | ||||||
|  | positions = { | ||||||
|  |     "X": 0.0, | ||||||
|  |     "Y": 0.0, | ||||||
|  |     "Z": 0.0 | ||||||
|  | } | ||||||
|  | temperatures = { | ||||||
|  |     "E0": { | ||||||
|  |         "value": 0.0, | ||||||
|  |         "target": 0.0, | ||||||
|  |         "lastTime": -1, | ||||||
|  |         "heatspeed": 0.6, | ||||||
|  |         "coolspeed": 0.8, | ||||||
|  |         "variation": 0.5 | ||||||
|  |     }, | ||||||
|  |     "B": { | ||||||
|  |         "value": 0.0, | ||||||
|  |         "target": 0.0, | ||||||
|  |         "lastTime": -1, | ||||||
|  |         "heatspeed": 0.2, | ||||||
|  |         "coolspeed": 0.8, | ||||||
|  |         "variation": 0.5 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | modes = { | ||||||
|  |     "absolute": True | ||||||
|  | } | ||||||
|  |  | ||||||
|  | stop_heating = False | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def wait(durationms, ser): | ||||||
|  |     global stop_heating | ||||||
|  |     nowtime = common.current_milli_time() | ||||||
|  |     while (common.current_milli_time() < nowtime + durationms): | ||||||
|  |          if ser.in_waiting: | ||||||
|  |             line = ser.readline().decode('utf-8').strip() | ||||||
|  |             if line=="M108": | ||||||
|  |                 stop_heating = True | ||||||
|  |             print(common.bcolors.COL_PURPLE+line+common.bcolors.END_COL) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def ok(line): | ||||||
|  |     if (not line.startswith("N")): | ||||||
|  |         return "ok (" + line + ")" | ||||||
|  |     N = re.findall(r'N\d*', line) | ||||||
|  |     if (len(N) > 0): | ||||||
|  |         return "ok " + N[0][1:] | ||||||
|  |      | ||||||
|  | # Update the temperatures according context | ||||||
|  | def updateTemperatures(entry, timestp): | ||||||
|  |     global temperatures | ||||||
|  |     roomtemp = 20.0 | ||||||
|  |     v = random.random()*5 | ||||||
|  |     target = temperatures[entry]["target"] | ||||||
|  |     if target == 0: | ||||||
|  |         target = roomtemp | ||||||
|  |     if (temperatures[entry]["value"] == 0): | ||||||
|  |         temperatures[entry]["value"] = roomtemp + v / 2 | ||||||
|  |     if (temperatures[entry]["lastTime"] == -1): | ||||||
|  |         temperatures[entry]["lastTime"] = timestp | ||||||
|  |     if temperatures[entry]["value"] + 5 < target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] + \ | ||||||
|  |             (temperatures[entry]["heatspeed"] * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     elif temperatures[entry]["value"] - 5 > target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] - \ | ||||||
|  |             (temperatures[entry]["coolspeed"] * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     elif target - 2 < temperatures[entry]["value"] and temperatures[entry]["value"] < target + 2: | ||||||
|  |         temperatures[entry]["value"] = target + \ | ||||||
|  |             temperatures[entry]["variation"] * (random.random() - 0.5) | ||||||
|  |     elif temperatures[entry]["value"] < target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] + \ | ||||||
|  |             ((temperatures[entry]["heatspeed"]/3) * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     else: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] - \ | ||||||
|  |             ((temperatures[entry]["coolspeed"]/3) * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |  | ||||||
|  |     temperatures[entry]["lastTime"] = timestp | ||||||
|  |  | ||||||
|  | # build the response for the temperature | ||||||
|  | def generateTemperatureResponse(withok): | ||||||
|  |     global temperatures | ||||||
|  |     response = " " | ||||||
|  |     if (withok): | ||||||
|  |         response = "ok " | ||||||
|  |     response += "T:" + "{:.2f}".format(temperatures["E0"]["value"]) + " /" + "{:.2f}".format(temperatures["E0"]["target"]) + " B:" + "{:.2f}".format( | ||||||
|  |         temperatures["B"]["value"]) + " /" + "{:.2f}".format(temperatures["B"]["target"]) + " @:127 B@:0" | ||||||
|  |     return response | ||||||
|  |  | ||||||
|  | # build the response for the busy response, | ||||||
|  | # simulating the delay of the busy response | ||||||
|  | def send_busy(ser, nb): | ||||||
|  |     v = nb | ||||||
|  |     while (v > 0): | ||||||
|  |         common.send_echo(ser, "echo:busy: processing") | ||||||
|  |         wait(1000, ser) | ||||||
|  |         v = v - 1 | ||||||
|  |  | ||||||
|  | # G0/G1 response | ||||||
|  | def G0_G1_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     X_val = "" | ||||||
|  |     Y_val = "" | ||||||
|  |     Z_val = "" | ||||||
|  |  # extract X | ||||||
|  |     X = re.findall(r'X[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(X) > 0): | ||||||
|  |         X_val = X[0][1:] | ||||||
|  |     # extract Y | ||||||
|  |     Y = re.findall(r'Y[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Y) > 0): | ||||||
|  |         Y_val = Y[0][1:] | ||||||
|  |     # extract Z | ||||||
|  |     Z = re.findall(r'Z[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Z) > 0): | ||||||
|  |         Z_val = Z[0][1:] | ||||||
|  |     if (modes["absolute"]): | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] = float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] = float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] = float(Z_val) | ||||||
|  |         return ok(line) | ||||||
|  |     else: | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] += float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] += float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] += float(Z_val) | ||||||
|  |         return ok(line) | ||||||
|  |  | ||||||
|  | # G28 response | ||||||
|  | def G28_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     if (cmd.find("X") != -1): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |     if (cmd.find("Y") != -1): | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |     if (cmd.find("Z") != -1): | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     if (cmd == "G28"): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # G29 V4 response | ||||||
|  | def G29_V4_response(cmd,line,ser): | ||||||
|  |     common.send_echo(ser, " G29 Auto Bed Leveling") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 50.000 Z: 0.000") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 50.000 Z: 0.016") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 50.000 Z: -0.013") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 50.000 Z: -0.051") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 133.000 Z: -0.005") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 133.000 Z: -0.041") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 133.000 Z: -0.031") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 133.000 Z: -0.036") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 216.000 Z: -0.050") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 216.000 Z: 0.055") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 216.000 Z: 0.051") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 216.000 Z: 0.026") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 299.000 Z: -0.018") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 299.000 Z: -0.064") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 299.000 Z: -0.036") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 299.000 Z: -0.046") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bilinear Leveling Grid:") | ||||||
|  |     common.send_echo(ser, "      0      1      2      3") | ||||||
|  |     common.send_echo(ser, " 0 +0.0000 +0.0162 -0.0125 -0.0512") | ||||||
|  |     common.send_echo(ser, " 1 -0.0363 -0.0313 -0.0412 -0.0050") | ||||||
|  |     common.send_echo(ser, " 2 -0.0500 +0.0550 +0.0512 +0.0262") | ||||||
|  |     common.send_echo(ser, " 3 -0.0463 -0.0363 -0.0638 -0.0175") | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Absolute mode | ||||||
|  | def G90_response(cmd,line,ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = True | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Relative mode | ||||||
|  | def G91_response(cmd,line,ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = False | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M104 extruder control not waiting | ||||||
|  | def M104_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     targettemp = re.findall(r'S\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["E0"]["target"] = float(targettemp[0][1:]) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M105 temperatures query | ||||||
|  | def M105_response(cmd,line,ser): | ||||||
|  |     updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |     updateTemperatures("B", common.current_milli_time()) | ||||||
|  |     val = generateTemperatureResponse(True) | ||||||
|  |     return val | ||||||
|  |  | ||||||
|  | # M106 fan control | ||||||
|  | def M106_response(cmd,line,ser): | ||||||
|  |     return line+"\nok" | ||||||
|  |  | ||||||
|  | # M107 fan stop | ||||||
|  | def M107_response(cmd,line,ser): | ||||||
|  |     if (len(val) > 0): | ||||||
|  |         return "M106 P" + val[0][1:] + " S0\nok" | ||||||
|  |     else: | ||||||
|  |         return "M106 P0 S0\nok" | ||||||
|  |  | ||||||
|  | # M109 extruder control waiting | ||||||
|  | def M109_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     global stop_heating | ||||||
|  |     targettemp = re.findall(r'[SR]\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         stop_heating = False | ||||||
|  |         temperatures["E0"]["target"] = float(targettemp[0][1:]) | ||||||
|  |         target = 20.0 | ||||||
|  |         if (temperatures["E0"]["target"] != 0): | ||||||
|  |             target = temperatures["E0"]["target"] | ||||||
|  |         while ( temperatures["E0"]["value"] < target-2 or temperatures["E0"]["value"] > target+2): | ||||||
|  |             send_busy(ser, 1) | ||||||
|  |             if stop_heating: | ||||||
|  |                 stop_heating = False | ||||||
|  |                 temperatures["E0"]["target"] = 0.0 | ||||||
|  |                 return ok(line) + "\nok" | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |             ser.flush() | ||||||
|  |             wait(1000, ser) | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M114 Positions query | ||||||
|  | def M114_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     val = "X:" + "{:.2f}".format(positions["X"]) + " Y:" + "{:.2f}".format( | ||||||
|  |         positions["Y"]) + " Z:" + "{:.2f}".format(positions["Z"])+" E:0.00 Count X:0 Y:0 Z:0\nok" | ||||||
|  |     return val | ||||||
|  |  | ||||||
|  | # M140 bed control not waiting | ||||||
|  | def M140_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     targettemp = re.findall(r'S\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["B"]["target"] = float(targettemp[0][1:]) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M190 bed control waiting | ||||||
|  | def M190_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     global stop_heating | ||||||
|  |     targettemp = re.findall(r'[SR]\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["B"]["target"] = float(targettemp[0][1:]) | ||||||
|  |         target = 20.0 | ||||||
|  |         if (temperatures["B"]["target"] != 0): | ||||||
|  |             target = temperatures["B"]["target"] | ||||||
|  |             stop_heating = False | ||||||
|  |         while (temperatures["B"]["value"] < target-2 or temperatures["B"]["value"] > target+2): | ||||||
|  |             send_busy(ser, 1) | ||||||
|  |             if stop_heating: | ||||||
|  |                 stop_heating = False | ||||||
|  |                 temperatures["B"]["target"] = 0.0 | ||||||
|  |                 return ok(line) + "\nok" | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |             ser.flush() | ||||||
|  |             wait(1000, ser) | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M220 response | ||||||
|  | def M220_response(cmd,line,ser): | ||||||
|  |     val = re.findall(r'S\d+', cmd) | ||||||
|  |     if (len(val) > 0): | ||||||
|  |         F_R = val[0][1:] | ||||||
|  |         return "FR:"+F_R+"%\nok" | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # List of supported methods | ||||||
|  | methods = [ | ||||||
|  |     {"str": "G0", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G1", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G28", "fn": G28_response}, | ||||||
|  |     {"str": "G29 V4", "fn": G29_V4_response}, | ||||||
|  |     {"str": "G90", "fn": G90_response}, | ||||||
|  |     {"str": "G91", "fn": G91_response}, | ||||||
|  |     {"str": "M104", "fn": M104_response}, | ||||||
|  |     {"str": "M105", "fn": M105_response}, | ||||||
|  |     {"str": "M106", "fn": M106_response}, | ||||||
|  |     {"str": "M107", "fn": M107_response}, | ||||||
|  |     {"str": "M109", "fn": M109_response}, | ||||||
|  |     {"str": "M114", "fn": M114_response}, | ||||||
|  |     {"str": "M140", "fn": M140_response}, | ||||||
|  |     {"str": "M190", "fn": M190_response}, | ||||||
|  |     {"str": "M220", "fn": M220_response}, | ||||||
|  | ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Process a line of GCODE | ||||||
|  | def processLine(line,ser): | ||||||
|  |     time.sleep(0.01) | ||||||
|  |     cmd = line | ||||||
|  |     if (line.startswith("N")): | ||||||
|  |         p = line.find(' ') | ||||||
|  |         cmd = line[p+1:] | ||||||
|  |         p = cmd.rfind('*') | ||||||
|  |         cmd = cmd[:p]    | ||||||
|  |     global methods | ||||||
|  |     for method in methods: | ||||||
|  |         if cmd.startswith(method["str"]): | ||||||
|  |             return method["fn"](cmd,line,ser) | ||||||
|  |     if line.startswith("M") or line.startswith("G")  or line.startswith("N"): | ||||||
|  |         return ok(line) | ||||||
|  |     if line.find("[esp")!=-1  or line.find("[0;")!=-1 or line.find("[1;")!=-1: | ||||||
|  |         return "" | ||||||
|  |     return "echo:Unknown command: \"" + line + "\"\nok" | ||||||
							
								
								
									
										360
									
								
								tools/fw_simulator/repetier.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								tools/fw_simulator/repetier.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,360 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # Marlin GCODE parser / responder | ||||||
|  |  | ||||||
|  | import time | ||||||
|  | import re | ||||||
|  | import random | ||||||
|  | import esp3d_common as common | ||||||
|  | positions = { | ||||||
|  |     "X": 0.0, | ||||||
|  |     "Y": 0.0, | ||||||
|  |     "Z": 0.0 | ||||||
|  | } | ||||||
|  | temperatures = { | ||||||
|  |     "E0": { | ||||||
|  |         "value": 0.0, | ||||||
|  |         "target": 0.0, | ||||||
|  |         "lastTime": -1, | ||||||
|  |         "heatspeed": 0.6, | ||||||
|  |         "coolspeed": 0.8, | ||||||
|  |         "variation": 0.5 | ||||||
|  |     }, | ||||||
|  |     "B": { | ||||||
|  |         "value": 0.0, | ||||||
|  |         "target": 0.0, | ||||||
|  |         "lastTime": -1, | ||||||
|  |         "heatspeed": 0.2, | ||||||
|  |         "coolspeed": 0.8, | ||||||
|  |         "variation": 0.5 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | modes = { | ||||||
|  |     "absolute": True | ||||||
|  | } | ||||||
|  |  | ||||||
|  | stop_heating = False | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def wait(durationms, ser): | ||||||
|  |     global stop_heating | ||||||
|  |     nowtime = common.current_milli_time() | ||||||
|  |     while (common.current_milli_time() < nowtime + durationms): | ||||||
|  |          if ser.in_waiting: | ||||||
|  |             line = ser.readline().decode('utf-8').strip() | ||||||
|  |             if line=="M108": | ||||||
|  |                 stop_heating = True | ||||||
|  |             print(common.bcolors.COL_PURPLE+line+common.bcolors.END_COL) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def ok(line): | ||||||
|  |     if (not line.startswith("N")): | ||||||
|  |         return "ok (" + line + ")" | ||||||
|  |     N = re.findall(r'N\d*', line) | ||||||
|  |     if (len(N) > 0): | ||||||
|  |         return "ok " + N[0][1:] | ||||||
|  |      | ||||||
|  | # Update the temperatures according context | ||||||
|  | def updateTemperatures(entry, timestp): | ||||||
|  |     global temperatures | ||||||
|  |     roomtemp = 20.0 | ||||||
|  |     v = random.random()*5 | ||||||
|  |     target = temperatures[entry]["target"] | ||||||
|  |     if target == 0: | ||||||
|  |         target = roomtemp | ||||||
|  |     if (temperatures[entry]["value"] == 0): | ||||||
|  |         temperatures[entry]["value"] = roomtemp + v / 2 | ||||||
|  |     if (temperatures[entry]["lastTime"] == -1): | ||||||
|  |         temperatures[entry]["lastTime"] = timestp | ||||||
|  |     if temperatures[entry]["value"] + 5 < target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] + \ | ||||||
|  |             (temperatures[entry]["heatspeed"] * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     elif temperatures[entry]["value"] - 5 > target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] - \ | ||||||
|  |             (temperatures[entry]["coolspeed"] * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     elif target - 2 < temperatures[entry]["value"] and temperatures[entry]["value"] < target + 2: | ||||||
|  |         temperatures[entry]["value"] = target + \ | ||||||
|  |             temperatures[entry]["variation"] * (random.random() - 0.5) | ||||||
|  |     elif temperatures[entry]["value"] < target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] + \ | ||||||
|  |             ((temperatures[entry]["heatspeed"]/3) * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     else: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] - \ | ||||||
|  |             ((temperatures[entry]["coolspeed"]/3) * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |  | ||||||
|  |     temperatures[entry]["lastTime"] = timestp | ||||||
|  |  | ||||||
|  | # build the response for the temperature | ||||||
|  | def generateTemperatureResponse(withok): | ||||||
|  |     global temperatures | ||||||
|  |     response = " " | ||||||
|  |     if (withok): | ||||||
|  |         response = "ok " | ||||||
|  |     response += "T:" + "{:.2f}".format(temperatures["E0"]["value"]) + " /" + "{:.2f}".format(temperatures["E0"]["target"]) + " B:" + "{:.2f}".format( | ||||||
|  |         temperatures["B"]["value"]) + " /" + "{:.2f}".format(temperatures["B"]["target"]) + " @:127 B@:0" | ||||||
|  |     return response | ||||||
|  |  | ||||||
|  | # build the response for the busy response, | ||||||
|  | # simulating the delay of the busy response | ||||||
|  | def send_busy(ser, nb): | ||||||
|  |     v = nb | ||||||
|  |     while (v > 0): | ||||||
|  |         common.send_echo(ser, "echo:busy: processing") | ||||||
|  |         wait(1000, ser) | ||||||
|  |         v = v - 1 | ||||||
|  |  | ||||||
|  | # G0/G1 response | ||||||
|  | def G0_G1_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     X_val = "" | ||||||
|  |     Y_val = "" | ||||||
|  |     Z_val = "" | ||||||
|  |  # extract X | ||||||
|  |     X = re.findall(r'X[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(X) > 0): | ||||||
|  |         X_val = X[0][1:] | ||||||
|  |     # extract Y | ||||||
|  |     Y = re.findall(r'Y[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Y) > 0): | ||||||
|  |         Y_val = Y[0][1:] | ||||||
|  |     # extract Z | ||||||
|  |     Z = re.findall(r'Z[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Z) > 0): | ||||||
|  |         Z_val = Z[0][1:] | ||||||
|  |     if (modes["absolute"]): | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] = float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] = float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] = float(Z_val) | ||||||
|  |         return ok(line) | ||||||
|  |     else: | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] += float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] += float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] += float(Z_val) | ||||||
|  |         return ok(line) | ||||||
|  |  | ||||||
|  | # G28 response | ||||||
|  | def G28_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     if (cmd.find("X") != -1): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |     if (cmd.find("Y") != -1): | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |     if (cmd.find("Z") != -1): | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     if (cmd == "G28"): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # G29 V4 response | ||||||
|  | def G29_V4_response(cmd,line,ser): | ||||||
|  |     common.send_echo(ser, " G29 Auto Bed Leveling") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 50.000 Z: 0.000") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 50.000 Z: 0.016") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 50.000 Z: -0.013") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 50.000 Z: -0.051") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 133.000 Z: -0.005") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 133.000 Z: -0.041") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 133.000 Z: -0.031") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 133.000 Z: -0.036") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 216.000 Z: -0.050") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 216.000 Z: 0.055") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 216.000 Z: 0.051") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 216.000 Z: 0.026") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 299.000 Z: -0.018") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 299.000 Z: -0.064") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 299.000 Z: -0.036") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 299.000 Z: -0.046") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bilinear Leveling Grid:") | ||||||
|  |     common.send_echo(ser, "      0      1      2      3") | ||||||
|  |     common.send_echo(ser, " 0 +0.0000 +0.0162 -0.0125 -0.0512") | ||||||
|  |     common.send_echo(ser, " 1 -0.0363 -0.0313 -0.0412 -0.0050") | ||||||
|  |     common.send_echo(ser, " 2 -0.0500 +0.0550 +0.0512 +0.0262") | ||||||
|  |     common.send_echo(ser, " 3 -0.0463 -0.0363 -0.0638 -0.0175") | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Absolute mode | ||||||
|  | def G90_response(cmd,line,ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = True | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Relative mode | ||||||
|  | def G91_response(cmd,line,ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = False | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M104 extruder control not waiting | ||||||
|  | def M104_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     targettemp = re.findall(r'S\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["E0"]["target"] = float(targettemp[0][1:]) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M105 temperatures query | ||||||
|  | def M105_response(cmd,line,ser): | ||||||
|  |     updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |     updateTemperatures("B", common.current_milli_time()) | ||||||
|  |     val = generateTemperatureResponse(True) | ||||||
|  |     return val | ||||||
|  |  | ||||||
|  | # M106 fan control | ||||||
|  | def M106_response(cmd,line,ser): | ||||||
|  |     return line+"\nok" | ||||||
|  |  | ||||||
|  | # M107 fan stop | ||||||
|  | def M107_response(cmd,line,ser): | ||||||
|  |     if (len(val) > 0): | ||||||
|  |         return "M106 P" + val[0][1:] + " S0\nok" | ||||||
|  |     else: | ||||||
|  |         return "M106 P0 S0\nok" | ||||||
|  |  | ||||||
|  | # M109 extruder control waiting | ||||||
|  | def M109_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     global stop_heating | ||||||
|  |     targettemp = re.findall(r'[SR]\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         stop_heating = False | ||||||
|  |         temperatures["E0"]["target"] = float(targettemp[0][1:]) | ||||||
|  |         target = 20.0 | ||||||
|  |         if (temperatures["E0"]["target"] != 0): | ||||||
|  |             target = temperatures["E0"]["target"] | ||||||
|  |         while ( temperatures["E0"]["value"] < target-2 or temperatures["E0"]["value"] > target+2): | ||||||
|  |             send_busy(ser, 1) | ||||||
|  |             if stop_heating: | ||||||
|  |                 stop_heating = False | ||||||
|  |                 temperatures["E0"]["target"] = 0.0 | ||||||
|  |                 return ok(line) + "\nok" | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |             ser.flush() | ||||||
|  |             wait(1000, ser) | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M114 Positions query | ||||||
|  | def M114_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     val = "X:" + "{:.2f}".format(positions["X"]) + " Y:" + "{:.2f}".format( | ||||||
|  |         positions["Y"]) + " Z:" + "{:.2f}".format(positions["Z"])+" E:0.00 Count X:0 Y:0 Z:0\nok" | ||||||
|  |     return val | ||||||
|  |  | ||||||
|  | # M140 bed control not waiting | ||||||
|  | def M140_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     targettemp = re.findall(r'S\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["B"]["target"] = float(targettemp[0][1:]) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M190 bed control waiting | ||||||
|  | def M190_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     global stop_heating | ||||||
|  |     targettemp = re.findall(r'[SR]\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["B"]["target"] = float(targettemp[0][1:]) | ||||||
|  |         target = 20.0 | ||||||
|  |         if (temperatures["B"]["target"] != 0): | ||||||
|  |             target = temperatures["B"]["target"] | ||||||
|  |             stop_heating = False | ||||||
|  |         while (temperatures["B"]["value"] < target-2 or temperatures["B"]["value"] > target+2): | ||||||
|  |             send_busy(ser, 1) | ||||||
|  |             if stop_heating: | ||||||
|  |                 stop_heating = False | ||||||
|  |                 temperatures["B"]["target"] = 0.0 | ||||||
|  |                 return ok(line) + "\nok" | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |             ser.flush() | ||||||
|  |             wait(1000, ser) | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M220 response | ||||||
|  | def M220_response(cmd,line,ser): | ||||||
|  |     val = re.findall(r'S\d+', cmd) | ||||||
|  |     if (len(val) > 0): | ||||||
|  |         F_R = val[0][1:] | ||||||
|  |         return "FR:"+F_R+"%\nok" | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # List of supported methods | ||||||
|  | methods = [ | ||||||
|  |     {"str": "G0", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G1", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G28", "fn": G28_response}, | ||||||
|  |     {"str": "G29 V4", "fn": G29_V4_response}, | ||||||
|  |     {"str": "G90", "fn": G90_response}, | ||||||
|  |     {"str": "G91", "fn": G91_response}, | ||||||
|  |     {"str": "M104", "fn": M104_response}, | ||||||
|  |     {"str": "M105", "fn": M105_response}, | ||||||
|  |     {"str": "M106", "fn": M106_response}, | ||||||
|  |     {"str": "M107", "fn": M107_response}, | ||||||
|  |     {"str": "M109", "fn": M109_response}, | ||||||
|  |     {"str": "M114", "fn": M114_response}, | ||||||
|  |     {"str": "M140", "fn": M140_response}, | ||||||
|  |     {"str": "M190", "fn": M190_response}, | ||||||
|  |     {"str": "M220", "fn": M220_response}, | ||||||
|  | ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Process a line of GCODE | ||||||
|  | def processLine(line,ser): | ||||||
|  |     time.sleep(0.01) | ||||||
|  |     cmd = line | ||||||
|  |     if (line.startswith("N")): | ||||||
|  |         p = line.find(' ') | ||||||
|  |         cmd = line[p+1:] | ||||||
|  |         p = cmd.rfind('*') | ||||||
|  |         cmd = cmd[:p]    | ||||||
|  |     global methods | ||||||
|  |     for method in methods: | ||||||
|  |         if cmd.startswith(method["str"]): | ||||||
|  |             return method["fn"](cmd,line,ser) | ||||||
|  |     if line.startswith("M") or line.startswith("G")  or line.startswith("N"): | ||||||
|  |         return ok(line) | ||||||
|  |     if line.find("[esp")!=-1  or line.find("[0;")!=-1 or line.find("[1;")!=-1: | ||||||
|  |         return "" | ||||||
|  |     return "echo:Unknown command: \"" + line + "\"\nok" | ||||||
							
								
								
									
										360
									
								
								tools/fw_simulator/smoothieware.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								tools/fw_simulator/smoothieware.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,360 @@ | |||||||
|  | #!/usr/bin/python | ||||||
|  | # Marlin GCODE parser / responder | ||||||
|  |  | ||||||
|  | import time | ||||||
|  | import re | ||||||
|  | import random | ||||||
|  | import esp3d_common as common | ||||||
|  | positions = { | ||||||
|  |     "X": 0.0, | ||||||
|  |     "Y": 0.0, | ||||||
|  |     "Z": 0.0 | ||||||
|  | } | ||||||
|  | temperatures = { | ||||||
|  |     "E0": { | ||||||
|  |         "value": 0.0, | ||||||
|  |         "target": 0.0, | ||||||
|  |         "lastTime": -1, | ||||||
|  |         "heatspeed": 0.6, | ||||||
|  |         "coolspeed": 0.8, | ||||||
|  |         "variation": 0.5 | ||||||
|  |     }, | ||||||
|  |     "B": { | ||||||
|  |         "value": 0.0, | ||||||
|  |         "target": 0.0, | ||||||
|  |         "lastTime": -1, | ||||||
|  |         "heatspeed": 0.2, | ||||||
|  |         "coolspeed": 0.8, | ||||||
|  |         "variation": 0.5 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | modes = { | ||||||
|  |     "absolute": True | ||||||
|  | } | ||||||
|  |  | ||||||
|  | stop_heating = False | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def wait(durationms, ser): | ||||||
|  |     global stop_heating | ||||||
|  |     nowtime = common.current_milli_time() | ||||||
|  |     while (common.current_milli_time() < nowtime + durationms): | ||||||
|  |          if ser.in_waiting: | ||||||
|  |             line = ser.readline().decode('utf-8').strip() | ||||||
|  |             if line=="M108": | ||||||
|  |                 stop_heating = True | ||||||
|  |             print(common.bcolors.COL_PURPLE+line+common.bcolors.END_COL) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def ok(line): | ||||||
|  |     if (not line.startswith("N")): | ||||||
|  |         return "ok (" + line + ")" | ||||||
|  |     N = re.findall(r'N\d*', line) | ||||||
|  |     if (len(N) > 0): | ||||||
|  |         return "ok " + N[0][1:] | ||||||
|  |      | ||||||
|  | # Update the temperatures according context | ||||||
|  | def updateTemperatures(entry, timestp): | ||||||
|  |     global temperatures | ||||||
|  |     roomtemp = 20.0 | ||||||
|  |     v = random.random()*5 | ||||||
|  |     target = temperatures[entry]["target"] | ||||||
|  |     if target == 0: | ||||||
|  |         target = roomtemp | ||||||
|  |     if (temperatures[entry]["value"] == 0): | ||||||
|  |         temperatures[entry]["value"] = roomtemp + v / 2 | ||||||
|  |     if (temperatures[entry]["lastTime"] == -1): | ||||||
|  |         temperatures[entry]["lastTime"] = timestp | ||||||
|  |     if temperatures[entry]["value"] + 5 < target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] + \ | ||||||
|  |             (temperatures[entry]["heatspeed"] * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     elif temperatures[entry]["value"] - 5 > target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] - \ | ||||||
|  |             (temperatures[entry]["coolspeed"] * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     elif target - 2 < temperatures[entry]["value"] and temperatures[entry]["value"] < target + 2: | ||||||
|  |         temperatures[entry]["value"] = target + \ | ||||||
|  |             temperatures[entry]["variation"] * (random.random() - 0.5) | ||||||
|  |     elif temperatures[entry]["value"] < target: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] + \ | ||||||
|  |             ((temperatures[entry]["heatspeed"]/3) * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |     else: | ||||||
|  |         temperatures[entry]["value"] = temperatures[entry]["value"] - \ | ||||||
|  |             ((temperatures[entry]["coolspeed"]/3) * | ||||||
|  |              (timestp - temperatures[entry]["lastTime"])) / 1000 | ||||||
|  |  | ||||||
|  |     temperatures[entry]["lastTime"] = timestp | ||||||
|  |  | ||||||
|  | # build the response for the temperature | ||||||
|  | def generateTemperatureResponse(withok): | ||||||
|  |     global temperatures | ||||||
|  |     response = " " | ||||||
|  |     if (withok): | ||||||
|  |         response = "ok " | ||||||
|  |     response += "T:" + "{:.2f}".format(temperatures["E0"]["value"]) + " /" + "{:.2f}".format(temperatures["E0"]["target"]) + " B:" + "{:.2f}".format( | ||||||
|  |         temperatures["B"]["value"]) + " /" + "{:.2f}".format(temperatures["B"]["target"]) + " @:127 B@:0" | ||||||
|  |     return response | ||||||
|  |  | ||||||
|  | # build the response for the busy response, | ||||||
|  | # simulating the delay of the busy response | ||||||
|  | def send_busy(ser, nb): | ||||||
|  |     v = nb | ||||||
|  |     while (v > 0): | ||||||
|  |         common.send_echo(ser, "echo:busy: processing") | ||||||
|  |         wait(1000, ser) | ||||||
|  |         v = v - 1 | ||||||
|  |  | ||||||
|  | # G0/G1 response | ||||||
|  | def G0_G1_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     X_val = "" | ||||||
|  |     Y_val = "" | ||||||
|  |     Z_val = "" | ||||||
|  |  # extract X | ||||||
|  |     X = re.findall(r'X[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(X) > 0): | ||||||
|  |         X_val = X[0][1:] | ||||||
|  |     # extract Y | ||||||
|  |     Y = re.findall(r'Y[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Y) > 0): | ||||||
|  |         Y_val = Y[0][1:] | ||||||
|  |     # extract Z | ||||||
|  |     Z = re.findall(r'Z[+]*[-]*\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(Z) > 0): | ||||||
|  |         Z_val = Z[0][1:] | ||||||
|  |     if (modes["absolute"]): | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] = float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] = float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] = float(Z_val) | ||||||
|  |         return ok(line) | ||||||
|  |     else: | ||||||
|  |         if (X_val != ""): | ||||||
|  |             positions["X"] += float(X_val) | ||||||
|  |         if (Y_val != ""): | ||||||
|  |             positions["Y"] += float(Y_val) | ||||||
|  |         if (Z_val != ""): | ||||||
|  |             positions["Z"] += float(Z_val) | ||||||
|  |         return ok(line) | ||||||
|  |  | ||||||
|  | # G28 response | ||||||
|  | def G28_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     if (cmd.find("X") != -1): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |     if (cmd.find("Y") != -1): | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |     if (cmd.find("Z") != -1): | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     if (cmd == "G28"): | ||||||
|  |         positions["X"] = 0.00 | ||||||
|  |         positions["Y"] = 0.00 | ||||||
|  |         positions["Z"] = 0.00 | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # G29 V4 response | ||||||
|  | def G29_V4_response(cmd,line,ser): | ||||||
|  |     common.send_echo(ser, " G29 Auto Bed Leveling") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 50.000 Z: 0.000") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 50.000 Z: 0.016") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 50.000 Z: -0.013") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 50.000 Z: -0.051") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 133.000 Z: -0.005") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 133.000 Z: -0.041") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 133.000 Z: -0.031") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 133.000 Z: -0.036") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 216.000 Z: -0.050") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 216.000 Z: 0.055") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 216.000 Z: 0.051") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 216.000 Z: 0.026") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 299.000 Y: 299.000 Z: -0.018") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 216.000 Y: 299.000 Z: -0.064") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 133.000 Y: 299.000 Z: -0.036") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bed X: 50.000 Y: 299.000 Z: -0.046") | ||||||
|  |     send_busy(ser, 3) | ||||||
|  |     common.send_echo(ser, "Bilinear Leveling Grid:") | ||||||
|  |     common.send_echo(ser, "      0      1      2      3") | ||||||
|  |     common.send_echo(ser, " 0 +0.0000 +0.0162 -0.0125 -0.0512") | ||||||
|  |     common.send_echo(ser, " 1 -0.0363 -0.0313 -0.0412 -0.0050") | ||||||
|  |     common.send_echo(ser, " 2 -0.0500 +0.0550 +0.0512 +0.0262") | ||||||
|  |     common.send_echo(ser, " 3 -0.0463 -0.0363 -0.0638 -0.0175") | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Absolute mode | ||||||
|  | def G90_response(cmd,line,ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = True | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # Relative mode | ||||||
|  | def G91_response(cmd,line,ser): | ||||||
|  |     global modes | ||||||
|  |     modes["absolute"] = False | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M104 extruder control not waiting | ||||||
|  | def M104_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     targettemp = re.findall(r'S\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["E0"]["target"] = float(targettemp[0][1:]) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M105 temperatures query | ||||||
|  | def M105_response(cmd,line,ser): | ||||||
|  |     updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |     updateTemperatures("B", common.current_milli_time()) | ||||||
|  |     val = generateTemperatureResponse(True) | ||||||
|  |     return val | ||||||
|  |  | ||||||
|  | # M106 fan control | ||||||
|  | def M106_response(cmd,line,ser): | ||||||
|  |     return line+"\nok" | ||||||
|  |  | ||||||
|  | # M107 fan stop | ||||||
|  | def M107_response(cmd,line,ser): | ||||||
|  |     if (len(val) > 0): | ||||||
|  |         return "M106 P" + val[0][1:] + " S0\nok" | ||||||
|  |     else: | ||||||
|  |         return "M106 P0 S0\nok" | ||||||
|  |  | ||||||
|  | # M109 extruder control waiting | ||||||
|  | def M109_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     global stop_heating | ||||||
|  |     targettemp = re.findall(r'[SR]\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         stop_heating = False | ||||||
|  |         temperatures["E0"]["target"] = float(targettemp[0][1:]) | ||||||
|  |         target = 20.0 | ||||||
|  |         if (temperatures["E0"]["target"] != 0): | ||||||
|  |             target = temperatures["E0"]["target"] | ||||||
|  |         while ( temperatures["E0"]["value"] < target-2 or temperatures["E0"]["value"] > target+2): | ||||||
|  |             send_busy(ser, 1) | ||||||
|  |             if stop_heating: | ||||||
|  |                 stop_heating = False | ||||||
|  |                 temperatures["E0"]["target"] = 0.0 | ||||||
|  |                 return ok(line) + "\nok" | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |             ser.flush() | ||||||
|  |             wait(1000, ser) | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M114 Positions query | ||||||
|  | def M114_response(cmd,line,ser): | ||||||
|  |     global positions | ||||||
|  |     val = "X:" + "{:.2f}".format(positions["X"]) + " Y:" + "{:.2f}".format( | ||||||
|  |         positions["Y"]) + " Z:" + "{:.2f}".format(positions["Z"])+" E:0.00 Count X:0 Y:0 Z:0\nok" | ||||||
|  |     return val | ||||||
|  |  | ||||||
|  | # M140 bed control not waiting | ||||||
|  | def M140_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     targettemp = re.findall(r'S\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["B"]["target"] = float(targettemp[0][1:]) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M190 bed control waiting | ||||||
|  | def M190_response(cmd,line,ser): | ||||||
|  |     global temperatures | ||||||
|  |     global stop_heating | ||||||
|  |     targettemp = re.findall(r'[SR]\d+[\.]*\d*', cmd) | ||||||
|  |     if (len(targettemp) > 0): | ||||||
|  |         temperatures["B"]["target"] = float(targettemp[0][1:]) | ||||||
|  |         target = 20.0 | ||||||
|  |         if (temperatures["B"]["target"] != 0): | ||||||
|  |             target = temperatures["B"]["target"] | ||||||
|  |             stop_heating = False | ||||||
|  |         while (temperatures["B"]["value"] < target-2 or temperatures["B"]["value"] > target+2): | ||||||
|  |             send_busy(ser, 1) | ||||||
|  |             if stop_heating: | ||||||
|  |                 stop_heating = False | ||||||
|  |                 temperatures["B"]["target"] = 0.0 | ||||||
|  |                 return ok(line) + "\nok" | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |             ser.flush() | ||||||
|  |             wait(1000, ser) | ||||||
|  |             updateTemperatures("E0", common.current_milli_time()) | ||||||
|  |             updateTemperatures("B", common.current_milli_time()) | ||||||
|  |             val = generateTemperatureResponse(False) | ||||||
|  |             common.send_echo(ser, val) | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # M220 response | ||||||
|  | def M220_response(cmd,line,ser): | ||||||
|  |     val = re.findall(r'S\d+', cmd) | ||||||
|  |     if (len(val) > 0): | ||||||
|  |         F_R = val[0][1:] | ||||||
|  |         return "FR:"+F_R+"%\nok" | ||||||
|  |     return ok(line) | ||||||
|  |  | ||||||
|  | # List of supported methods | ||||||
|  | methods = [ | ||||||
|  |     {"str": "G0", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G1", "fn": G0_G1_response}, | ||||||
|  |     {"str": "G28", "fn": G28_response}, | ||||||
|  |     {"str": "G29 V4", "fn": G29_V4_response}, | ||||||
|  |     {"str": "G90", "fn": G90_response}, | ||||||
|  |     {"str": "G91", "fn": G91_response}, | ||||||
|  |     {"str": "M104", "fn": M104_response}, | ||||||
|  |     {"str": "M105", "fn": M105_response}, | ||||||
|  |     {"str": "M106", "fn": M106_response}, | ||||||
|  |     {"str": "M107", "fn": M107_response}, | ||||||
|  |     {"str": "M109", "fn": M109_response}, | ||||||
|  |     {"str": "M114", "fn": M114_response}, | ||||||
|  |     {"str": "M140", "fn": M140_response}, | ||||||
|  |     {"str": "M190", "fn": M190_response}, | ||||||
|  |     {"str": "M220", "fn": M220_response}, | ||||||
|  | ] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Process a line of GCODE | ||||||
|  | def processLine(line,ser): | ||||||
|  |     time.sleep(0.01) | ||||||
|  |     cmd = line | ||||||
|  |     if (line.startswith("N")): | ||||||
|  |         p = line.find(' ') | ||||||
|  |         cmd = line[p+1:] | ||||||
|  |         p = cmd.rfind('*') | ||||||
|  |         cmd = cmd[:p]    | ||||||
|  |     global methods | ||||||
|  |     for method in methods: | ||||||
|  |         if cmd.startswith(method["str"]): | ||||||
|  |             return method["fn"](cmd,line,ser) | ||||||
|  |     if line.startswith("M") or line.startswith("G")  or line.startswith("N"): | ||||||
|  |         return ok(line) | ||||||
|  |     if line.find("[esp")!=-1  or line.find("[0;")!=-1 or line.find("[1;")!=-1: | ||||||
|  |         return "" | ||||||
|  |     return "echo:Unknown command: \"" + line + "\"\nok" | ||||||
		Reference in New Issue
	
	Block a user