3D打印机USB联机打印是如何实现的?(以Cura插件USBPrinting为例)
source link: https://www.eefocus.com/embedded/526616
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
3D打印机USB联机打印是如何实现的?(以Cura插件USBPrinting为例)-嵌入式系统-与非网
新与非网上线通知 2022年10月10日晚10点,更全、更大、更强的新与非网全「星」发布。新与非网整合了原与非网、电路城、摩尔吧,点击了解详情
整理&排版 | 嵌入式应用研究院
众所周知,对3D打印机感兴趣的小伙伴来说,都清楚Cura是3D打印机的切片软件,它的UI部分是基于QT来开发的。而Cura中很多功能其实是基于插件的形式来开发,其中,用于实现Cura的USB转串口联机打印的逻辑就是一个插件,它是使用Python语言来实现的,具体代码位于:
https://github.com/Ultimaker/Cura/tree/main/plugins/USBPrinting
而我前阵子参加开放原子基金会组织的开发者成长激励活动的作品其实也算是联机打印的一种,只是实现的方式不同而已罢了:
开发者成长激励计划-基于TencentOS Tiny FDM 3D打印机云控制系统方案
说到Cura中的USB转串口联机打印,核心逻辑可以梳理下为以下几点:
(1)查找串口设备列表并获取对应的打印机设备端口号,这部分的代码是在USBPrinterOutputDeviceManager.py
这个文件里实现的。
(2)设置串口设备参数并连接设备、启动更新线程来处理串口数据接收
具体的代码实现如下:
def connect(self):
self._firmware_name = None # after each connection ensure that the firmware name is removed
if self._baud_rate is None:
if self._use_auto_detect:
auto_detect_job = AutoDetectBaudJob(self._serial_port)
auto_detect_job.start()
auto_detect_job.finished.connect(self._autoDetectFinished)
return
if self._serial is None:
try:
# 设置串口参数
self._serial = Serial(str(self._serial_port), self._baud_rate, timeout=self._timeout, writeTimeout=self._timeout)
except SerialException:
Logger.warning("An exception occurred while trying to create serial connection.")
return
except OSError as e:
Logger.warning("The serial device is suddenly unavailable while trying to create a serial connection: {err}".format(err = str(e)))
return
CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
self._onGlobalContainerStackChanged()
self.setConnectionState(ConnectionState.Connected)
# 启动更新线程
self._update_thread.start()
(3)启动更新任务线程,更新任务线程的作用是处理以下几件事情:
以readline()
的方式去接收打印机回复的数据,然后处理数据,例如接收到了ok或者温度信息等。
处理接收的数据,并接着发下一条Gcode指令,直到没有得发为止。
处理打印过程中发生的异常事件
发送M105
获取温度命令,这里Cura
是做了一些处理的,发送该条命令的前提是打印机不处于忙状态并且温度到了设定的固件超时时间才会进行发送。Cura的超时设置为3s。
具体的代码实现如下:
# 线程_update_thread->更新任务函数的实现
def _update(self):
while self._connection_state == ConnectionState.Connected and self._serial is not None:
try:
line = self._serial.readline()
except:
continue
# 获取固件信息
# 如果是Marlin,则会输出类似如下所示的信息
# FIRMWARE_NAME:Marlin 1.1.0 ....
if not self._firmware_name_requested:
self._firmware_name_requested = True
self.sendCommand("M115")
# 获取FIRMWARE_NAME并保存起来
if b"FIRMWARE_NAME:" in line:
self._setFirmwareName(line)
# time()是获取时间戳,以秒作为时间间隔,这里的timeout是3,也就意味着,Cura发送获取温度的条件是:
# 1、当前的打印机不处于忙状态
# 2、超时,这里设置的时间是大于3s
# 以上两个条件需要同时满足
if self._last_temperature_request is None or time() > self._last_temperature_request + self._timeout:
self.sendCommand("M105")
self._last_temperature_request = time()
# 使用正则表达式获取由打印机端上报的温度事件,其中T:开头的数据代表喷头温度,B:开头的数据代表热床温度
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*)\s*\/?(\d+\.?\d*)?", line)
# Update all temperature values
# 获取喷头当前/目标温度值并更新到前端显示
matched_extruder_nrs = []
for match in extruder_temperature_matches:
extruder_nr = 0
if match[0] != b"":
extruder_nr = int(match[0])
if extruder_nr in matched_extruder_nrs:
continue
matched_extruder_nrs.append(extruder_nr)
if extruder_nr >= len(self._printers[0].extruders):
Logger.log("w", "Printer reports more temperatures than the number of configured extruders")
continue
extruder = self._printers[0].extruders[extruder_nr]
if match[1]:
extruder.updateHotendTemperature(float(match[1]))
if match[2]:
extruder.updateTargetHotendTemperature(float(match[2]))
# 获取热床当前/目标温度值并更新到前端显示
bed_temperature_matches = re.findall(b"B: ?(\d+\.?\d*)\s*\/?(\d+\.?\d*)?", line)
if bed_temperature_matches:
match = bed_temperature_matches[0]
if match[0]:
self._printers[0].updateBedTemperature(float(match[0]))
if match[1]:
self._printers[0].updateTargetBedTemperature(float(match[1]))
# 空行表示固件空闲
# 多个空行可能意味着固件和 Cura 正在等待
# 因为错过了“ok”,所以我们跟踪空行
# 因为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 each other due to a missed "ok", so we keep track of empty lines
self._firmware_idle_count += 1
else:
self._firmware_idle_count = 0
# 检查到ok字串或者_firmware_idle_count > 1
if line.startswith(b"ok") or self._firmware_idle_count > 1:
# 此时打印机忙状态解除
self._printer_busy = False
# 设置接收事件为True
self._command_received.set()
# 如果当前命令队列不为空,则从队列取出一条命令往打印机串口继续发送
if not self._command_queue.empty():
self._sendCommand(self._command_queue.get())
# 如果处于正在打印中,则继续发送下一条Gcode命令
# 如果此时暂停标志生效,则什么事情都不干
elif self._is_printing:
if self._paused:
pass # Nothing to do!
else:
self._sendNextGcodeLine()
# 如果匹配到Marlin回复了"echo:busy"子串时,则设置打印机为忙状态
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()
# 如果在打印中接收到"resend"或者"rs"这样的字符串,则可以通过 Resend、resend 或 rs 请求重新发送。
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 line.startswith(b"rs"):
# In some cases of the RS command it needs to be handled differently.
self._gcode_position = int(line.split()[1])
在USB转串口联机打印中,也实现了一些打印的基本业务,待后续分析和开源作品分享。
版权声明:与非网经原作者授权转载,版权属于原作者。文章观点仅代表作者本人,不代表与非网立场。文章及其配图仅供工程师学习之用,如有侵权或者其他问题,请联系本站作侵删。 侵权投诉
Recommend
-
1
通常,使用我公司多功能打印服务器TL-PS310U时,用户需要安装一个名为Launch MFP and Storage Server的管理软件来连接到打印机或者其他USB设备。这个软件的使用比较简便但是它有一个很大的缺点就是每次使用打印机时都需要使用配置软件连接打印机,这就意...
-
1
许多用户购买了汉印打印机之后想要打印标签,那么具体的操作流程和步骤是什么样的呢,这里就给大家解读一下操作步骤流程,希望对您有所帮助。 汉印打印机如何打印标签 1、首先需要下载一个汉印官方的软件“汉码”
-
2
华为发布首款激光打印机:打印一张纸只要6分钱 (经理人网9月14日消息),9月13日晚,华为发布旗下首款激光多功能打印机——华为PixLab X1,这也是首款搭载Harmon...
-
2
更宽更好玩 拓展无限打印乐趣 instax Link WIDE照片打印机新品开箱 更宽更好玩 拓展无限打印乐趣 instax Link WIDE照片打印机新品开箱 ...
-
6
打印总是遇到问题?一文教你如何在优麒麟上使用 CUPS 管理打印机! 2022-03-21 09:26:50 ...
-
0
该型号打印服务器支持哪些打印机? 有关我司打印服务器MPS110U/MPS110P/MPS210U兼容的打印机型号,请参考我司网站上提供的打印服务器兼容性列表,如果您的打印机型号不在打印服务器所支持的打印机兼容列表中,则无法保...
-
4
有关我司打印服务器TL-PS110U/PS110P/PS210U/WPS510U兼容的打印机型号,请参考我司网站上提供的
-
4
仍然需要安装打印机驱动。使用打印服务器共享打印机,每台电脑均需要在电脑上安装打印机驱动,这由打印服务器工作原理所决定,与传统的共享打印机方式(只有作为服务器的电脑需要安装打印机驱动)不一样。
-
4
java连接打印机打印PDF 祈雨的博客 2018-03-02
-
5
全文来自:【科普】3D打印机结构大盘点,帮你找到适合自己的机器类型 – 知乎 (zhihu.com) 对于刚刚接触3D打印的朋友们看着市场上琳琅满目的3D打印机肯定会头疼不已。3D打印机不...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK