AutoDetectBaudJob.py 3.8 KB

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