AutoDetectBaudJob.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from UM.Job import Job
  4. from UM.Logger import Logger
  5. from time import time, sleep
  6. from serial import Serial, SerialException
  7. # An async job that attempts to find the correct baud rate for a USB printer.
  8. # It tries a pre-set list of baud rates. All these baud rates are validated by requesting the temperature a few times
  9. # and checking if the results make sense. If getResult() is not None, it was able to find a correct baud rate.
  10. class AutoDetectBaudJob(Job):
  11. def __init__(self, serial_port: int) -> None:
  12. super().__init__()
  13. self._serial_port = serial_port
  14. self._all_baud_rates = [115200, 250000, 500000, 230400, 76800, 57600, 38400, 19200, 9600]
  15. def run(self) -> None:
  16. Logger.debug(f"Auto detect baud rate started for {self._serial_port}")
  17. wait_response_timeouts = [3, 15, 30]
  18. wait_bootloader_times = [1.5, 5, 15]
  19. write_timeout = 3
  20. read_timeout = 3
  21. tries = 2
  22. serial = None
  23. for retry in range(tries):
  24. for baud_rate in self._all_baud_rates:
  25. if retry < len(wait_response_timeouts):
  26. wait_response_timeout = wait_response_timeouts[retry]
  27. else:
  28. wait_response_timeout = wait_response_timeouts[-1]
  29. if retry < len(wait_bootloader_times):
  30. wait_bootloader = wait_bootloader_times[retry]
  31. else:
  32. wait_bootloader = wait_bootloader_times[-1]
  33. Logger.debug(f"Checking {self._serial_port} if baud rate {baud_rate} works. Retry nr: {retry}. Wait timeout: {wait_response_timeout}")
  34. if serial is None:
  35. try:
  36. serial = Serial(str(self._serial_port), baud_rate, timeout = read_timeout, writeTimeout = write_timeout)
  37. except SerialException:
  38. Logger.warning(f"Unable to create serial connection to {serial} with baud rate {baud_rate}")
  39. continue
  40. else:
  41. # We already have a serial connection, just change the baud rate.
  42. try:
  43. serial.baudrate = baud_rate
  44. except ValueError:
  45. continue
  46. # Ensure that we are not talking to the boot loader. 1.5 seconds seems to be the magic number
  47. sleep(wait_bootloader)
  48. serial.write(b"\n") # Ensure we clear out previous responses
  49. serial.write(b"M105\n")
  50. start_timeout_time = time()
  51. timeout_time = time() + wait_response_timeout
  52. while timeout_time > time():
  53. # If baudrate is wrong, then readline() might never
  54. # return, even with timeouts set. Using read_until
  55. # with size limit seems to fix this.
  56. line = serial.read_until(size = 100)
  57. if b"ok" in line and b"T:" in line:
  58. self.setResult(baud_rate)
  59. Logger.log("d", "Detected baud rate {baud_rate} on serial {serial} on retry {retry} with after {time_elapsed:0.2f} seconds.".format(
  60. serial = self._serial_port, baud_rate = baud_rate, retry = retry, time_elapsed = time() - start_timeout_time))
  61. serial.close() # close serial port so it can be opened by the USBPrinterOutputDevice
  62. return
  63. serial.write(b"M105\n")
  64. sleep(15) # Give the printer some time to init and try again.
  65. Logger.debug(f"Unable to find a working baudrate for {serial}")
  66. self.setResult(None) # Unable to detect the correct baudrate.