标签 教程 下的文章

出于一些原因我搞到了一台 Ender-3 V2 打印机,拧好了螺丝调好了平之后开机发现它读不出自带的 TF 卡里的文件。于是从树莓派里掏张卡出来,装几个 gcode 文件进去,重启打印机⸺然后发现卡在启动界面了。查打印机的说明书才发现它在开机时会自动读取 TF 卡里 .bin 文件。原来用在树莓派上的卡里肯定有不少 .bin 文件,猜测是打印机把其中的一个当打印机固件读取并刷写了,导致不开机。那怎么修复呢?你想看普通的修复教程?不不,那样就和随处可见(存疑)的论坛帖子没有区别了,这是为了博客特制的,明白吗?请阅读下文以感受我修复之路的痛楚⋯⋯尝试“正常”的修复方法去 创想三维的固件发布页 找到了原版固件,阅读说明得知只要把新固件放进 TF 卡里装进机器就可以自动更新固件。听起来非常的简单是不是,我们动手做一下吧。先把树莓派卡格式化成 FAT32,装上固件⸺等一下,这么多固件我选哪个,怎么也没有说明?从主板盖板下面的缝里打光能看到主板版本是 V4.2.2,就选个比较新而且不花里胡哨的 Ender-3 V2_HW_V4.2.2_SW_V1.0.7 吧。装上 TF 卡,重启打印机,然而并没有解决问题,还是卡在启动画面。换了原装 TF 卡装固件,还是没有作用。上网查一下呢?在 一篇红迪帖子 里找到了修复方法:用一张格式化为 FAT32,簇大小 4096B,容量不超过 32GB 的 TF 卡装上固件插进打印机里。按照指示重新格式化了卡然后装上固件,但依旧没有解决问题。打开主板盖板,拔掉常开风扇、挤出头加热棒、挤出头热敏电阻的线。还是没用。拆开挤出头,松一松固定热敏电阻的螺丝。什么也没有发生。那接下来怎么办?开始发癫抱着试一试的想法插了根线到打印机的 USB 口,然后 lsusb 一下,发现了经典 CH340 串口芯片。用串口终端打开一看,还真收到了打印机发送的信息:Update failed, No SD/TF-Card or error。但我明明装了卡啊,而且一开始不就是因为从这卡上错误地读了二进制文件才导致了问题的吗?猜测是误刷的固件把整块主控都搞得乱糟糟的了(实际上这个猜测错得离谱)。在主板上一通搜索,发现了熟悉的 SWDIO 和 SWCLK SWD 接口。连上 DAPLink 调试器,pyOCD 启动!警告:不要贸然尝试以下的任何代码!SWD 刷写很容易就可以把你的主控送上天!初步尝试 SWD观察主板得知主控芯片是 GD32F303RET6,那就先下载对应的目标文件:pyocd pack install GD32F303RE,成功建立与主控的通信。以防万一先读取备份一下主控的固件:pyocd cmd --target gd32f303re -c reset halt -c savemem 0 0x400000 e3v2_gd32f303_dump.bin(事后发现这个操作救了我)现在我们可以大胆去做了。先 pyocd erase -t gd32f303re -c 清空存储器,然后 pyocd flash --target gd32f303re -v ./GD-Ender-3\ V2Marlin2.0.6.1V1.0.5HW4.2.2 试着刷写原厂固件。然后不出所料地没用。插上 USB 线发现糟了,串口都没输出了。再次上网查资料:神秘的 RepRap 论坛 网友提到 V4.2.2 版本主板的固件应该存在 0x08007000 位置之后,而 0x0800000-0x08006FF 的这一段地址是分配给 bootloader 的。继续查阅 GD32F303 的技术手册,发现 0x00000000-0x002fffff 的这一段地址是映射到位于 0x08000000 - 0x082fffff 的主 FLASH 存储器的,而默认状况下这颗芯片上电后从 0x00000000 开始执行。看来通过 SWD 直写固件不工作的原因是固件需要依赖 bootloader 的存在才能工作,或者是链接时写死的内存位置因为我从 0x0000000 开始直接写入固件也混乱了。那么,原本的 bootloader 似乎不起作用,厂商提供的固件又依赖 bootloader 才能工作,我该怎么办呢?似乎自己编译固件才是唯一的方法了,毕竟这只是个普通的微控制器,也有开源的固件,想整一些非常规的花活应该也不困难。编译固件还好 Ender-3 V2 原装的固件就是基于 Marlin 的,对它的社区支持也相当完善,按照 Marlin 官方指引 很快就改好了一个配置文件。这里要注意创想三维在不改变主板版本号的情况下居然推出了使用两种(甚至更多)主控芯片的主板:有的是 STM32F1 系列,有的是 STM32F3 系列,还有的是 GD32F3 系列,而且(显然的)它们的固件并不通用,这也是为什么在原厂固件下载页面会有带 GD- 前缀和不带的固件版本。真不愧是三轮厂,我无语了。因为我的主板使用 GD32F303,所以要注意在 Configuration.h 里设置 #define MOTHERBOARD BOARD_CREALITY_V422_GD32_MFL。改配置文件本身倒没什么难的,直接复制官方给的配置例子都没什么问题。只是注意如果使用非 CrealityUI 的话,对屏幕的版本也有要求(对,创想三维还搞出了不同屏幕的花活)。然后在 ini/gd32.ini 里修改board_build.offset = 0x7000 board_upload.offset_address = 0x08007000为board_build.offset = 0x0 board_upload.offset_address = 0x08000000然后重新编译固件。现在通过 SWD 直写到 0x0 总能运行了吧?⋯⋯并不能。到底哪出错了?可能是固件的代码并不完全依赖这两个值计算地址,或许在什么地方有控制链接器行为的代码,但要调整那些的话难度也会陡然上升,再折腾下去时间成本就太高了,不如买块新主板了事。从头再来睡了一觉,倔劲又上来了,决定从头再来:看看一开始读取出来的固件,验证一下我之前的猜想。xxd e3v2_gd32f303_dump.bin | less 发现在 0x7000 之前的内容看起来确是 bootloader,且没有用完这段空间,在 0x6100 之后就全都是 0xFF 了,这样就和之前发现的地址布局相符。搜索一下,甚至能在 bootloader 的二进制文件里找到之前的 "Update failed, No SD/TF-Card or error" 字符串。继续往后看,0x7000 之后的空间里居然出现了和树莓派相关的字符串,证明打印机是错误读取了树莓派卡里的二进制文件才导致问题的猜测也是正确的。先刷回原来的 bootloader 试试。如果用 SWD 刷回的 bootloader 能产生串口输出,那我至少没把主控搞坏。用 dd if=ender3fwbk.bin of=extracted_bootloader.bin bs=1 count=$((0x7000)) 提取出二进制固件的前 0x7000 字节即为 bootloader。pyocd erase -t gd32f303re -c 把主控清除。接着 pyocd flash --target gd32f303re -v -a 0x08000000 extracted_bootloader.bin 把提取出的 bootloader 写入到 0x08000000。开机发现串口重新有输出了!继续试验:用回原来的 *.offset 值编译固件,然后 pyocd flash --target gd32f303re -v -a 0x08007000 刷写到 bootloader 之后的预定位置。开机,居然成功解决了问题?难道原来的 bootloader 没有损坏,之后的固件依然能读取?本来想在 0x08007000 之后刷回原厂固件测试一下的,但发现不知为何 SWD 已经连接不上主控了(可能是固件重设了 SWD 的映射引脚),但反正现在的固件也能用,遂作罢。总结清空树莓派 TF 卡,装上几个 GCode 文件插进打印机,发现不识别了。这时候想起来之前查资料的时候看到过 TF 卡的格式要求除了 FAT32 文件系统,4096B 簇大小以外还要求 MBR 分区表,大小不超过 8GB。按照这个要求重新格式化 TF 卡并装上 Gcode 文件,居然能读出来了。现在回想起来,我一开始假设 bootloader 被写坏或许就是错的。bootloader 并没有坏,是我的卡没有按要求格式化,导致装上原厂固件后插进机器不识别,才有了后面兜的大圈子。归根结底是创想三维不明确写明对 TF 卡的格式要求才导致了这一问题的发生,而且受害者远远不止我一个。珍爱生命,远离三轮厂⋯⋯附录:bootloader 文件如果有倒霉蛋不幸搞丢了自己的 bootloader,在此提供一份我提取的:extracted_firmware.bin附录:如何在 GNU/Linux 上按要求格式化 TF 卡插上新的装有 Gcode 的 TF 卡发现还是读不出来,只好重新格式化一下:lsblk 找到卡的块设备名。按照 SIZE 应该很好认出来。比如我的卡就显示为:sdb 8:16 1 29G 0 disk └─sdb1 8:17 1 5.6G 0 part在下文我会以此为例给出命令,请根据自己的系统调整。请再三确认你输对了目标,不然接下来的操作就要让你宝贵的数据进火葬场了。sudo wipefs -a /dev/sdb 清空卡上的所有文件系统。sudo parted /dev/sdb --script mklabel msdos 创建一个 DOS (MBR) 分区表,然后 sudo parted /dev/sdb --script mkpart primary fat32 1MiB 100% 创建一个使用整张卡容量的 FAT32 分区。有人提到过打印机不认大于 8G 的卡,我倒是没有遇到,但你或许可以试试调小分区以防患于未然。sudo mkfs.vfat -F 32 0s 8 -S 512 -n SDCARD /dev/sdb1 把新创建的分区设置到 512B 每扇区 × 8 扇区 = 4096B 簇大小。(题外话:“簇”是什么垃圾翻译?计算机领域的名词怎么都翻译得这么懒?诸位读者以后请务必用心翻译专业名词谢谢喵)你说你用的是 Windows?那不关我的事喵。

如果你使用过一些开源软件(例如Krita, QGIS和FreeCAD),你会发现它们都是基于Qt框架的。尽管它们中的一部分允许你在偏好设置里直接更改应用的字体,但另一部分则由于一些原因而没有加入这种功能。很不幸的是,这些应用在中文Windows系统下的默认字体都是臭名昭著的SimSun,即仿宋体(如下)。不过,由于这些软件使用的都是Qt框架,修改它们的默认字体相当容易。首先,你需要找到这些软件的Qt Stylesheet文件。以FreeCAD为例,你可以在<应用安装目录>\data\Gui\Stylesheets下找到这些.qss后缀的文件。如果这个目录下有多个.qss文件,则说明你的应用程序支持切换颜色主题。你只需要随便选一个,之后再在应用内切换成这个主题文件即可。注意: 你最好在开始下一步前备份一下现在的.qss文件,以免你不小心搞砸了什么东西...接下来,打开这个文件。在它的开头,你可以找到这样的一段代码:* { padding: 0px; margin: 0px; border: 0px; border-style: none; border-image: none; outline: 0; color: #f5f5f5; /* Default color for labels and different text elements that usually use dark colors */ }这段代码规定了该主题下软件的默认样式,而要修改默认字体,你只需要再在color: #f5f5f5;后面添加一行font-family: "Source Sans Pro";。如果你的电脑上有这一字体的话,这行代码会将程序的默认字体设为思源黑体。当然,你也可以将它改成其它的字体,或是根据这个参考页面更改其它的默认参数。完成修改后,保存这个.qss文件。在软件内切换到你修改过的主题或是重启一下软件后,你的设置应该就会生效了。这是将FreeCAD默认字体改成思源黑体后的样子:至此,教程结束。

1. 什么是XMPP?XMPP,全称Extensible Messaging and Presence Protocol (可扩展消息与状态协议), 是一种以XML为基础的开放式即时通信协议。XMPP项目自1998年开始开发,于2000年5月正式发布。虽然你很可能从未听说过它,但实际上你大概率已经多次使用过它了: 许多游戏的内置聊天系统都是基于XMPP的, 天国的Google Talk也使用了这个通信协议。接下来,我将向你介绍XMPP的优势,以及如何使用它。2. XMPP的优势在哪?为什么要使用它?I. 可扩展正如我们之前所提到的一样,XMPP基于XML,也就是eXtensible Markup Language (可扩展标记语言)。这一特性使得XMPP的可扩展性非常强大, 可以支持大量的插件和附加功能。举个例子: 我希望每条消息不仅可以包含原本的文本内容,还可以包含一条发送者所在国家的信息。那么,我们就只需要给客户端加入一个插件,使它可以在发送时添加这条信息并在读取时解读它。比如说,Adam想发送一条内容为"Hello"的信息到Betty的账户上,那么:原来的客户端的信息:<message from="adam@example.com"/> <message to="betty@example.com"> <body>Hello</body> </message>解读的结果就是Adam发送了一条内容为"Hello"的信息给Betty。加入了插件之后,信息变成:<message from="adam@example.com"/> <message to="betty@example.com"> <body>Hello</body> </message> <location type="available" > <country>CA</country> </location> 解读的结果是Adam发送了一条内容为"Hello"的信息给Betty; 同时Adam的客户端支持这个插件,他的所在国家是加拿大。由此可以看出,XMPP可以很简单地进行扩展。这也意味着,这个协议拥有大量的扩展: 在线状态,已读反馈... 这些插件让这个简单的协议变得非常强大。II. 分布式XMPP通信网络的结构和电子邮箱很像: 不同的邮箱域名之间可以互相通信,比如说Gmail和Outlook邮箱之间可以互发消息; XMPP也是这样, 比如这里(sedirk.cn)上的XMPP账号也可以与xabber.org上的另一个账号互发消息。因为这种分布式结构的缘故,即使这个网络里的某一个服务器故障了,其它服务器之间的通信也不受影响, 而不会像那些有中央服务器的通信工具(比如QQ, LINE)一样, 整个网络都陷入瘫痪; 同时, 因为每一台服务器都能连接上这个网络, 用户也有大量的XMPP服务提供商可以选择,而不必被限制只能使用一个提供商的服务。这个特点也使得XMPP的另一个重要特性成为现实,那就是它的自由性。III. 自由与安全我们之前提到用户可以自由选择XMPP服务提供商, 这意味着只要用户对服务提供商的使用协议不满意,可以随时改用另一家提供商的服务; 不仅如此, 用户还可以自行搭建自己的服务器,从而完全将自己的权利掌握在手中。在商业软件(比如QQ, 微信, LINE)中, 用户则根本没有这种选择的权利: 服务提供商可以随时无理由关停或锁死用户的账号, 或是强行要求用户同意它们的使用条款; 而在XMPP中,则不会有这种情况出现,用户也就可以享有最大程度的自由。除此之外,XMPP的核心协议和几乎全部的插件都是开放源代码的。这意味着XMPP通讯协议是完全开放透明的, 用户可以自由开发自己的客户端和服务器端程序,而不必被现有的程序所限制。这一特点在各大XMPP客户端应用上都有着体现: 因为有一整个开发者社区进行优化,它们的体积都非常小,通常小于100MB, 在运行过程中也只会占用极少量的内存空间; 相比之下, QQ等专有软件则有着动辄500MB的体积, 运行时也会占用大量的内存空间。此外,在数据隐私方面,XMPP还拥有OpenPGP, OMEMO等端对端加密程序,因此用户也无须担心自己的聊天内容被服务提供商或第三方获得。3. 那么,我该怎么使用XMPP聊天呢?I. 注册账户首先,你需要一个XMPP账户。在之前的介绍中我也提到,你有许多XMPP服务提供商可以选择。不过, 既然你是在这个提供XMPP服务的网站上看到了这篇文章,为什么不直接在这里注册呢? 当然, 其它服务提供商的注册方式也都与这里十分相似, 你大可以放心去使用它们提供的服务。下图为本网站上的XMPP注册页面:注册步骤:在"Username"中填写你想设置的用户名。"Name"作为你的昵称使用,可以不填。在"Email"中填写你的邮箱地址。这个邮箱将作为你找回密码的渠道使用。可以不填,但如果忘记了密码只能找管理员重置。在"Password"中填写你想设置的密码。在"Confirm Password"中再次填写你想设置的密码,防止填错。点击"Create Account"即可完成创建XMPP账户。现在你就可以开始使用XMPP服务了!II. 客户端现在,你应该已经拥有了自己的XMPP账号。下一步,你需要选择一个客户端。在xmpp.org上有大量针对不同平台的客户端推荐, 你大可以自己选择你喜欢的那一个。我个人推荐在Windows, MacOS或GNU/Linux系统里使用Gajim, 在安卓系统里使用Conversations, 在ios中使用Siskin IM或Monal。在接下来的教程中,我也将以这两个客户端为例。当然,这个网站也提供一个网页版的客户端,登录方式也很简单,在此不做赘述了。