From cb24d58ab8a023785038fcd8ebf3e0d275b9d01c Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 5 Oct 2018 12:56:40 +0200 Subject: [PATCH 1/4] Don't flood the printer with temperature requests while says it is busy Fixes #3994 --- plugins/USBPrinting/USBPrinterOutputDevice.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 36c5321180..fca0654d30 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -74,6 +74,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): self._accepts_commands = True self._paused = False + self._printer_busy = False # when printer is preheating and waiting (M190/M109), or when waiting for action on the printer self._firmware_view = None self._firmware_location = None @@ -320,8 +321,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice): # Timeout, or no request has been sent at all. self._command_received.set() # We haven't really received the ok, but we need to send a new command - self.sendCommand("M105") - self._last_temperature_request = time() + if not self._printer_busy: # don't flood the printer with temperature requests while it is busy + self.sendCommand("M105") + self._last_temperature_request = time() if self._firmware_name is None: self.sendCommand("M115") @@ -360,7 +362,9 @@ class USBPrinterOutputDevice(PrinterOutputDevice): if b"FIRMWARE_NAME:" in line: self._setFirmwareName(line) - if b"ok" in line: + if line.startswith(b"ok "): + self._printer_busy = False + self._command_received.set() if not self._command_queue.empty(): self._sendCommand(self._command_queue.get()) @@ -370,16 +374,19 @@ class USBPrinterOutputDevice(PrinterOutputDevice): else: self._sendNextGcodeLine() + if line.startswith(b"echo:busy: "): + self._printer_busy = True + if self._is_printing: if line.startswith(b'!!'): Logger.log('e', "Printer signals fatal error. Cancelling print. {}".format(line)) self.cancelPrint() - elif b"resend" in line.lower() or b"rs" in line: + elif line.lower().startswith(b"resend") or line.startswith(b"rs"): # A resend can be requested either by Resend, resend or rs. try: self._gcode_position = int(line.replace(b"N:", b" ").replace(b"N", b" ").replace(b":", b" ").split()[-1]) except: - if b"rs" in line: + if line.startswith(b"rs"): # In some cases of the RS command it needs to be handled differently. self._gcode_position = int(line.split()[1]) From 777470db7f06eb64d70e73468d195ab1140eba42 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Thu, 18 Oct 2018 15:47:25 +0200 Subject: [PATCH 2/4] Don't force sending M105 requests without OK This prevents serial buffer overflow on the printer. --- plugins/USBPrinting/USBPrinterOutputDevice.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index 3609950b7e..ce3342bb72 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -226,14 +226,12 @@ class USBPrinterOutputDevice(PrinterOutputDevice): if self._last_temperature_request is None or time() > self._last_temperature_request + self._timeout: # Timeout, or no request has been sent at all. - self._command_received.set() # We haven't really received the ok, but we need to send a new command - - if not self._printer_busy: # don't flood the printer with temperature requests while it is busy + if not self._printer_busy: # Don't flood the printer with temperature requests while it is busy self.sendCommand("M105") self._last_temperature_request = time() - if self._firmware_name is None: - self.sendCommand("M115") + if self._firmware_name is None: + self.sendCommand("M115") if re.search(b"[B|T\d*]: ?\d+\.?\d*", line): # Temperature message. 'T:' for extruder and 'B:' for bed extruder_temperature_matches = re.findall(b"T(\d*): ?(\d+\.?\d*) ?\/?(\d+\.?\d*)?", line) From 71d365c0c62aee12f6a78c03bfa070efe24dac53 Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 19 Oct 2018 14:37:20 +0200 Subject: [PATCH 3/4] Fix case where Cura and the firmware could be waiting for eachother --- plugins/USBPrinting/USBPrinterOutputDevice.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index ce3342bb72..dc4c31ac9c 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -267,19 +267,27 @@ class USBPrinterOutputDevice(PrinterOutputDevice): if b"FIRMWARE_NAME:" in line: self._setFirmwareName(line) - if line.startswith(b"ok "): + if line == b"": + # An empty line means that the firmware is idle + # Multiple empty lines probably means that the firmware and Cura are waiting + # for eachother due to a missed "ok", so we keep track of empty lines + self._firmware_idle_count += 1 + else: + self._firmware_idle_count = 0 + + if line.startswith(b"ok") or self._firmware_idle_count > 1: self._printer_busy = False self._command_received.set() if not self._command_queue.empty(): self._sendCommand(self._command_queue.get()) - if self._is_printing: + elif self._is_printing: if self._paused: pass # Nothing to do! else: self._sendNextGcodeLine() - if line.startswith(b"echo:busy: "): + if line.startswith(b"echo:busy:"): self._printer_busy = True if self._is_printing: From 68c3023a465482ec25ae5cbf57a0adb279dc182d Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Fri, 19 Oct 2018 14:38:25 +0200 Subject: [PATCH 4/4] Make sure firmware name is only requested once --- plugins/USBPrinting/USBPrinterOutputDevice.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index dc4c31ac9c..e1c39ff8fa 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -74,6 +74,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice): self._command_received = Event() self._command_received.set() + self._firmware_name_requested = False self._firmware_updater = AvrFirmwareUpdater(self) CuraApplication.getInstance().getOnExitCallbackManager().addCallback(self._checkActivePrintingUponAppExit) @@ -224,15 +225,19 @@ class USBPrinterOutputDevice(PrinterOutputDevice): except: continue + if not self._firmware_name_requested: + self._firmware_name_requested = True + self.sendCommand("M115") + + if b"FIRMWARE_NAME:" in line: + self._setFirmwareName(line) + if self._last_temperature_request is None or time() > self._last_temperature_request + self._timeout: # Timeout, or no request has been sent at all. if not self._printer_busy: # Don't flood the printer with temperature requests while it is busy self.sendCommand("M105") self._last_temperature_request = time() - if self._firmware_name is None: - self.sendCommand("M115") - if re.search(b"[B|T\d*]: ?\d+\.?\d*", line): # Temperature message. 'T:' for extruder and 'B:' for bed extruder_temperature_matches = re.findall(b"T(\d*): ?(\d+\.?\d*) ?\/?(\d+\.?\d*)?", line) # Update all temperature values @@ -264,9 +269,6 @@ class USBPrinterOutputDevice(PrinterOutputDevice): if match[1]: self._printers[0].updateTargetBedTemperature(float(match[1])) - if b"FIRMWARE_NAME:" in line: - self._setFirmwareName(line) - if line == b"": # An empty line means that the firmware is idle # Multiple empty lines probably means that the firmware and Cura are waiting