用于光敏聚合物LCD 3D打印机的DIY固件。第2部分





关于为光敏聚合物LCD 3D打印机编写自己的固件的文章的继续。

在这一部分中,我将继续描述项目的各个阶段:

2.使用USB闪存驱动器及其上的文件

3.控制步进电机以移动平台。





-第1部分: 1.用户界面。

-第2部分: 2.在USB记忆棒上使用文件系统。3.步进电机控制平台移动。

-第3部分: 4.在背光显示器上显示图层的图像。5.每件事,例如控制灯光和风扇,加载和保存设置等。6.舒适和便利的附加功能。



2.使用USB闪存驱动器及其上的文件



我以前从未在微控制器上使用USB主机。作为USB设备-我制作了带有CDC类(COM端口仿真)和HID类的固件,但不适用于主机。因此,为了加快处理速度,我在STM32CUBE中创建了该外设的所有初始化。结果,我得到了一个在USB FS模式下工作的主机,该主机支持大容量存储设备。在同一个多维数据集中,我立即将FatFS库连接到文件系统和文件。然后,您只需要将结果源复制到项目中,并弄清楚如何使用它们即可。事实证明这很容易,这里没有太多描述。来自古巴的usb_host.c文件具有一个ApplicationTypeDef类型的全局变量Appli_state:

typedef enum {
  APPLICATION_IDLE = 0,
  APPLICATION_START,
  APPLICATION_READY,
  APPLICATION_DISCONNECT
}ApplicationTypeDef;


在USB主机外围设备发生各种事件时(在中断中),此变量可以采用列出的状态之一,指示主机的当前状态。在程序的主循环中,只需跟踪此变量的更改并做出相应反应即可。例如,如果其值已更改为APPLICATION_READY,则表明已连接闪存驱动器或读卡器并已成功初始化,则可以从中读取文件。



FatFS也没有问题-多维数据集已经完全配置它并“连接”到USB主机,因此在连接闪存驱动器后,您可以立即访问该库的功能来处理文件。的确,新更新的多维数据集包括旧版本的库。将其文件更新为新版本后,我不得不在古巴源代码中的某些位置修复FatFS配置中的定义名称。他们在新版本中进行了更改。但是更新没有带来任何特定的问题,一切都快速而轻松地进行了。



但是,为了使FatFS在文件名和目录名下与Cyrillic一起工作,我不得不进行一些修改。为了使FatFS正确读取西里尔字母名称,必须在其配置中启用Unicode,然后,与FatFS相关的所有字符串都必须仅采用这种编码-磁盘名称,文件名等。同时,IDE和FatFS中的文本编辑器支持高字节位置不同的Unicode-一个使用Little Endian,另一个使用Big Endian,因此不可能简单地用Unicode文本编写源代码。老实说,我也不想。从那时起,我不得不编写从ANSI和UTF-8到Unicode(反之亦然)的转换器,以及一些用于以不同组合使用不同编码字符串的函数。例如,将UTF-8字符串复制到Unicode字符串,或将ANSI字符串附加到Unicode字符串。但是,ANSI字符串似乎是无处不在,所有源都完全转换为UTF-8编码。

因此,现在打开具有给定名称的文件看起来像这样:

tstrcpy(u_tfname, UsbPath);	//    (Unicode)    (Unicode)
tstrcat_utf(u_tfname, SDIR_IMAGES);	//    (Unicode)   (UTF-8)
tstrcat_utf(u_tfname, (char*)"\\");	//    (Unicode)  (UTF-8)
tstrcat(u_tfname, fname);	//    (Unicode)   (Unicode)


一切都很快完成后,我想检查一下从闪存驱动器读取文件的速度。以4 KB的块读取10MB的文件显示出大约9 Mbps的速度,总体而言,这相当不错,非常适合我。



我试图研究将这种情况转移到DMA的问题,但事实证明USB主机的外围设备根本无法访问DMA。好吧,或者我没有找到它:)因此,在CCM(核心耦合内存)中组织USB文件的所有读/写缓冲区似乎是合乎逻辑的-64 KB RAM区域,也没有DMA输出。在同一内存区域中,将其他不适用于DMA的变量/数组放在有意义的位置,只是将更多内存留在常规RAM中是有意义的。顺便说一句,在我看来,内核本身在此内存下的工作要比普通内存快一些。



2.1文件用户界面



我拥有的Anycubic Photon S打印机将文件列表显示为预览图标,每个屏幕4个。原则上,这非常方便-您可以看到文件名,在预览图片中可以大致看到哪种模型。因此,我遵循相同的路径-文件以预览图像的形式每页显示4个文件名。



熟悉的黄色文件夹绘制在目录图标上,齿轮显示在设置文件上。仅显示扩展名属于已知文件之一的那些文件。当前,这些文件是.pws文件(由切片器准备用于打印的文件)和.acfg文件(具有打印机设置的文本文件)。



由于固件还可以处理用户可以输入的目录,因此我在写入当前路径的文件列表上方放置了一行。离开当前目录或向下滚动和向上滚动的按钮仅在它们有意义时才出现-也就是说,当您可以离开当前目录或向下或向上滚动列表时。





我的一个朋友在编写固件时向我展示了所有这一切,他建议了另一个输出文件的选项-以列表,表格的形式。首先,页面上可以容纳更多文件,其次,列表显示得更快,因为不需要从文件中读取预览图像并按比例缩放它们在显示器上绘制;其次,以表格形式,您还可以显示名称以及文件的最后修改时间,这有时非常方便。拒绝一个好主意是一个罪过,因此我添加了一个表列表,同时添加了一个在“图标”和“表”视图之间切换的按钮。表格形式的目录以黄色背景突出显示,并写有“ DIR”行而不是时间日期:





顺便说一句,对于在图标模式下为文件绘制的预览图片,我们并不感兴趣。某些人认为,固件不会分析整个文件以从3D模型生成图像:)切片器本身将这种图片保存在打印文件中,格式类似于BMP(16位像素颜色值的数组)。预览图像的大小存储在文件内的特殊字段中。因此,一切都非常简单。



固件唯一要做的事情就是将图片从文件缩放到显示屏上图标的大小。固件以非常简单的方式执行缩放:它计算缩放因子k(小数)-将原始图像的宽度除以显示器上显示区域的宽度(还计算高度系数,并计算两个值中的最大值),然后从原始图像中获取像素和线条,以k为步长在显示器上显示



这样,您可以同时在正和负之间缩放。当然,由于没有执行插值,因此缩放结果的质量还有很多需要改进的地方,但是在这么小的但不是太高品质的显示上,这是不可察觉的,但是这种算法的速度却很高。



单击.pws文件的图标或行时,将打开一个用于查看有关该文件的信息的屏幕,并可以开始打印该文件。如果单击.acfg文件,则提示用户从该文件加载设置。好吧,如果按下目录,则该目录将成为当前目录,并且文件列表将更新。



2.2打印前查看文件信息



正如您在上一部分的注释中正确指出的那样,当选择文件时,Anycubic没有有关该文件的任何信息。出现开始打印和删除它的按钮。这非常不方便-要找出该文件的估计打印时间,层数或其他参数,您需要开始打印。我决定不重复此缺陷,当我单击剪切文件时,将打开一个屏幕,其中包含有关此





文件的最完整信息:文件名,大小,上次修改时间和几乎所有打印参数。但是,这里的事实是MKS DLP显示屏的分辨率为480x320,而Enikubiks的分辨率更小-320x240,在这一显示屏上,您实际上无法摆弄一堆文字。



2.2.1关于打印时间的计算,我将单独编写。

与所有其他参数不同,此指示符未存储在文件中。他的打印机必须根据他所知道的信息进行独立计算。相同的Anycubic Photon S习惯于这种计算会过冲,并且会往下冲-例如,它承诺打印5小时,而实际上却打印6小时。而Longer Orange 30这次在打印期间来回更改了几乎两次。我决定尽可能谨慎地处理这一点。这段时间由什么组成?

  1. 平台以给定速度下降到下一层高度所需的时间。
  2. 开始曝光前的暂停时间。
  3. 图层曝光时间。
  4. 层暴露后,平台以给定速度上升到给定高度所需的时间。




将这四个参数相加,再乘以层数即可得出总打印时间。如果一切都是基本的,并且具有暂停和曝光时间-它们以毫秒级的精度维护,但是随着平台的移动,一切都已经有些复杂了。



该平台不会立即加快设置的速度,而是会产生一些加速度,这是在设置中设置的。此外,在打印时,这是一个相当小的加速度,因为平台应该开始非常平稳地上升,以使最后的固化层无痛地从镀液底部脱落(是的,不幸的是,聚合物也粘附在了薄膜上)。



事实证明,平台的运动包括三个部分-加速直至达到给定速度,以给定速度匀速运动以及减速至完全停止。这就是选项开始的地方-例如,指定的加速度和举升高度不允许平台达到指定的速度,当平台已经需要减速以停止在指定的高度时,平台仍在加速。或者加速度和高度足以使平台加速至设定速度,并在开始减速之前以稳定的运动方式行进路径的某些部分。我们需要检查所有这些,计算每个组件的时间和距离。



老实说,当我编写打印时间计算功能时,我的头在旋转:)因此,我仍然遇到一个小错误。例如,实际的打印时间是07:43:30,而不是估计的07:34:32。





或05:48:43,而不是计算得出的05:43:23。





但原则上,此错误适合我。我试图在计算中发现错误,但是那里的一切似乎都是正确的。由于步进电机控制的特殊性,实际加速度很可能与指定加速度略有不同。如此顺利,我们进入了下一个阶段:)



3.步进电机控制平台移动。



起初,我想到了编写自己的步进电机控制的想法。板上有一个普通驱动器,这一点也不难,只需在一个引脚上设置旋转方向,然后将步进脉冲驱动到另一个引脚即可。您需要快速旋转-提高脉冲频率,需要缓慢-降低频率。



但是当我开始更具体地解决这个问题时,我意识到它的简单性正在欺骗。不,您可以编写自己的代码,并且可以工作,但是以一种可以正常工作的方式编写代码是一项艰巨的任务。步进电机不太喜欢步进的不规则性,因此有必要在从几赫兹到几十千赫兹的相当宽的频率范围内确保步进脉冲的良好均匀性。有必要确保用于加速和减速的脉冲频率的平滑增加和减少。为了保证知道平台现在在什么位置,有必要精确地计算所产生的脉冲。为了提供所需的加速度,必须在严格定义的时间段内计算脉冲数及其频率变化的周期。



简而言之,这项任务虽然可行,却非常繁琐,这将花费我超过一天的时间。因此,我决定从Marlin撤出引擎管理功能。我认为这很容易。



首先,我从Marlin的源代码中提取了stepper.cpp文件-直接控制步进电机。但是,事实证明,它的工作非常依赖planner.cpp文件中的运动计划器,因此我也必须接受它。好了,对于堆来说,我还从那里获取了endstops.cpp文件-处理轴限位开关,因为我仍然需要处理来自它们的事件,并且这里调度程序和引擎控制已经与此文件关联了限位开关。



我花了很长时间尝试从这些文件中删除所有不必要的文件,并将它们与Marlin生态系统的其余部分解开。事实是,马林鱼在6或7个步进器的控制下同时被磨锐,而它们的工作可能取决于多个加热器的温度,塑料的参数等。那里的系统真的很复杂。我不得不做很多重做,主要是删除不必要的轴和不必要的挤出机,并摆脱一堆宏,这些宏在原始版本中很有用,但在我的应用中却非常困扰。只是为了理解-我从Marlin取得的资源大小已从346 KB减少到121 KB。并且必须谨慎删除每一行。



自然地,在这个艰苦的修剪过程中,我对整个系统的工作及其工作原理有了更深入的了解。为了移动轴,轴的目标位置通过其功能之一传递给调度器(当前位置由调度器存储)。调度程序计算加速,直线运动和减速的步数及其参数,并根据这些数据形成用于直接电机控制功能(步进器)的特殊数据包。这些程序包可以有多个,调度程序会为每个新任务计算并创建一个新的下一个程序包。



处于定时器中断状态且处于空闲状态的步进器从调度程序请求下一个数据包。如果调度程序具有准备好的程序包,则将其放弃并认为已完成。步进器将接收到的数据包投入工作,并根据来自其的数据开始计算引擎的步骤。直到完成它,才请求下一个数据包。



奇怪的是,步进器在低速运行时会在每个中断中发出一个步进脉冲,从而调整计时器,以便在所需的时间段后发生下一个中断。当所需的步速超过某个值时,步进器将在每个中断中开始执行多个步骤。同时,所有的时序选择都非常好,以至于步骤的一致性非常好,出于好奇,我看了示波器。



调度程序还知道如何“加入”相邻数据包。这意味着什么:如果调度程序已经为步进器准备了一个数据包,然后又有新任务出现,那么他将形成下一个数据包并更改前一个数据包,以便作为步进器对这两个数据包进行顺序处理的结果,可以获得一个平稳的移动。



让我举例说明。计划者是自由的,他收到一项任务,以30 mm / s的速度将轴向前移动20 mm。计划者生成第一个数据包,其中描述了从零到30 mm / s的加速度,以该速度的直线运动以及从该速度到零的减速度。如果在步进器从调度程序获取此数据包之前,给调度程序一个新任务,使其将该轴再向前移动50 mm,但已经以40 mm / s的速度移动,那么调度程序将不仅创建加速度为零的新数据包,还更改第一个数据包通过消除减速度并将直线运动扩展其距离,在创建的第二个数据包中,加速度将不是从零开始,而是从前一个数据包的速度开始。



结果是一次运动,其中轴将加速到30 mm / s,行进20 mm,然后再次加速到40 mm / s,再行进50 mm,最后减速到零。但这仅是在步进机尚未设法拾取之前的程序包的情况下,否则这两个任务将作为两个单独的动作进行处理,每个动作的初始速度和最终速度均为零。因此,顺便说一句,在具有手动平台控制的打印机中,如果以10 mm为增量连续几次按下升降台,则平台将在第一个10 mm升降后停止,然后继续移动而不停止到按钮所单击的全高。



在新版本的Marlin中,已经出现了针对这种“生涩”运动的补救措施-现在,如果调度程序包是唯一准备好的步进程序包,则该调度程序在该程序包形成后的一定时间内不会提供步进程序包。这段时间被留作等待-下一个任务将到达,以便您可以将其与现有任务对接。



3.1平台运动控制界面







通常,这里是光聚合物打印机的所有标准配置。顶部是选择轴移动步骤的步骤,右边是用于按所选步骤向上或向下移动轴的按钮。

“归位”按钮用于将平台调零(停车,归位),按下后,平台开始朝着“归位”限位开关移动。到达平台后,平台停止运转,并稍稍向后移动(为了提高准确性),再次进入限位开关。之后,固件肯定会知道平台当前的确切提升高度。



设定按钮 Z = 0”用于校准显示器上方的平台高度。当平台的零点(其在显示屏上方的最佳高度)在“原位”限位开关的触发位置下方1-2毫米时,例如,在Anycubic打印机中使用这种校准系统。在我看来,这种校准系统比最近流行的系统更为正确,当时限位开关的高度同时为平台的零高度。



好吧,最后一个按钮是“停止!” 是平台运动的无条件和立即停止。顺便说一句,当平台处于运动状态时,您不能离开该屏幕,“后退”按钮将不起作用。这样做是为了在平台移动时立即使用“停止”按钮。



3.2平台运动的其他要点



Anycubic光子中有几件事使我非常烦恼。



第一个是为什么平台的手动移动与打印模式下的蜗牛加速相同?键入时,这样小的加速度很有用,但是当手动控制轴时,它会加速2秒钟-这只是一场噩梦。而且移动的速度是马马虎虎。



第二点-为什么在暂停打印时,平台以打印参数中指定的速度上升到暂停的高度?地狱,等待15秒钟让平台上升两(仅)厘米,真是太好了。但是感谢您起床。在Orange 30中,停顿并不意味着将平台抬高一毫米,因此甚至不清楚为什么它在那里。



第三分钟,这真是令人毛骨悚然-打印结束后,平台上升到了最高点。以打印参数中指定的相同速度-1毫米/秒。从5厘米的高度爬升需要100秒!



因此,在固件中,我分别为打印模式和手动平台控制分别设置了可调的速度和加速度。但是有两个限制:

  1. 在通过“原点”按钮将轴复位之前,行进速度将降低三倍。这是因为虽然打印机不知道确切的当前平台高度,但存在挤压显示屏而没有高速停止(惯性,如此)或损坏上轴挡块的危险。在将轴归零之后,打印机已经确切知道平台的位置,并且软件高度限制已生效,这些限制也在设置中进行设置。
  2. 在高度小于30 mm时,无论轴是否归零,速度也将降低三倍。这是为了防止当平台过快地降入光敏聚合物时,光敏聚合物会从桶中溅出。或爬得太快时。




当然,设置中还有其他标准轴参数-每1 mm的步数,运动方向,限位开关的作用等。如果有人感兴趣,那么在扰流板下面是一个文本配置文件,其中包含所有受支持的参数。固件直接从文件列表中删除扩展名为.acfg的此类文件,加载参数,将其保存到EPROM并立即应用它们,而无需重新启动:

配置文件内容
# Stepper motor Z axis settings

[ZMotor]



# .

# : 0 1. : 1.

# .

invert_dir = 1



# .

# : -1 1. : -1.

# -1,

# , . 1

# .

home_direction = -1



# Z . ,

# 0, - .

home_pos = 0.0



# .

# : -32000.0 32000.0.

# : -3.0

# .

# , .

min_pos = -3.0



# .

# : -32000.0 32000.0.

# : 180.0

# .

# , .

max_pos = 180.0



# .

# : 0 1. : 1.

# ,

# 1, - 0.

min_endstop_inverting = 1



# .

# : 0 1. : 1.

# ,

# 1, - 0.

max_endstop_inverting = 1



# 1 .

steps_per_mm = 1600



# ,

# , /. : 6.0.

homing_feedrate_fast = 6.0



# ,

# , /. : 1.0.

homing_feedrate_slow = 1.0



# , /2.

acceleration = 0.7



# , /.

feedrate = 5.0



# ( ,

# ..), /2.

travel_acceleration = 25.0



# ( ,

# ..), /. 30

# ,

# 5 /.

travel_feedrate = 25.0



# , .

current_vref = 800.0



# , .

current_hold_vref = 300.0



# ,

# . . 0

# .

hold_time = 30.0



# ,

# . .

# hold_time. 0 .

# , .

off_time = 10.0



# General settings

[General]



# (0.001 )

# .

# : 0 15000. : 700 (0.7 ).

buzzer_msg_duration = 700



# (0.001 )

# , .

# : 0 15000. : 70 (0.07 ).

buzzer_touch_duration = 70



# 180 .

# .

# : 0 1. : 0.

rotate_display = 0



# , .

# LCD-. -

# .

# : 0 15000. : 10. 0 .

screensaver_time = 10







至此,我将完成本部分,并且已经有太多的文字了:)

和以前一样,我很乐意回答问题并接受评论。



-第1部分: 1.用户界面。

-第2部分: 2.在USB记忆棒上使用文件系统。3.步进电机控制平台移动。

-第3部分: 4.在背光显示器上显示图层的图像。5.每件事,例如控制灯光和风扇,加载和保存设置等。6.舒适和便利的附加功能。



链接



Aliexpress上的MKS DLP套件

GitHub上制造商的原始固件资源GitHub

上两个版本的板的制造商的方案资源GitHub上的

我的资源



All Articles