发布时间:2025-12-09 11:45:11 浏览次数:1
本文感谢富源盛 (Fysetc) 赞助的 Spider King 主板。最初接触8轴主板就是当时买的 mks monster8 v1 和三叉戟自带的 spider v1.1。后来关注 fys 的 mix 二合一主板,期望很高,实际情况有很大落差,这次交流之后也解开了一些既往的困惑。每家 3D 打印机主板制造商都有其设计思路,可以从产品上反映出来,"阅读一本书,就像是和作者对话",在仔细了解一个硬件的同时,也会有这种感觉。
【KlipperBoxConfigs 配置文件数据库】已加入 fys-spiderking-407 主板支持,提供引脚定义文件和一键编译、升级固件功能。
原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎指正交流。
文章如有更新请访问 DFRobot 社区 或者 cnblogs 博客园。
欢迎对 Klipper 固件,以及对改版 CNC 加工的 Voron 三叉戟、v0、v2.4 感兴趣的朋友加**流(QQ Group:490111638)
为了方便,我们约定:Spider King 使用 SKing 缩写,四轴BIG5160插槽简称大4槽,四轴普通插槽简称小4槽。
开箱视频可以移步 《富盛源FYSETC 蜘蛛王主板开箱视频》by 恶化 和 《开箱FYSETC-SPIDER-King 3D打印机10轴主板 支持4路6A 6路3A 可更换核心》。还有饼子的 《给蜘蛛king上十个电机摇一摇》。我就写点别的吧。
尺寸:177*108mm,整体要比 mks monster8 和 btt octopus 略大一圈,属于富源盛家的旗舰级产品。各主板对比图前文有,主要是 mcu核心板、板子中间的隔离模块以及 BIG5160 驱动插槽比较占地方。
将 mcu 做成模块,可以 独立使用,包括 boot0、reset,下载引脚等。
这种设计官方介绍是可以方便更换、升级核心,也就是核心板 + 底板的模式,比较灵活。比如升级到 STM32H7 核心以获得更高的性能。
问题来了:
目前只有 F407 核心板,万里长征第一步,这种设计还是挺新颖的。
出厂自带 RepRapFirmware (RRF) 固件。短接跳帽从USB启动,显示设备为
Bus 001 Device 005: ID 16c0:27dd Van Ooijen Technische Informatica CDC-ACM class devices (modems)
板载一个 reset 按钮和 FLASH 指示灯,短接 boot0 和 3.3v 进入 dfu 模式可以烧录固件(此时 FLASH 灯亮起)。
注意,使用usb供电时,SKing 主板上的 5V 灯不亮,应该是采用了隔离的缘故。正式安装使用时,拔掉 5V USB 供电跳帽。
【5000V全IO隔离】采用工业级标准设计,板载大功率隔离电源,控制核心板 与 所有高压外设 隔离,就像开启多重影分身的鸣人多方位无死角呵护着雏田。
你就说这样稳不稳吧。
驱动供电分为两部分,是独立分开供电的,与 Octopus 设计不同:
前文介绍了 Octopus 的方案,全部 10 轴都支持高压供电,且可以使用跳帽来选择电压,当都使用主板供电时,可以不接独立驱动供电。
而 SKing 则采用 4+6 分开独立供电 的方式,想要使用 4 轴需要额外供电,此 4 轴支持 12-55V 供电。6 轴支持 12-28V 供电。6路传统模式没太多说的,讲讲 4 路强力驱动。
由于没有电压选择功能,此 4 路供电相同:
目前 TMC2209 v4.0 和 BIG5160 都是搭配主板售卖,尚未零售。
我们规划 3D 打印机运动部分时,常规可能会选择 X/Y 电机使用 TMC5160 高压驱动,那么剩下两个驱动插座就不能接 TMC2209 使用,浪费了两个插座。除非各轴都使用 TMC5160 高压或者像 K3/VzBot 那样 X/Y 使用四个电机的情况,总的来说,可能带来浪费插座的情况,当然,10轴本身大多数情况下是冗余备份设计,使用上并无大碍。
此外注意4轴使用端子座而不是 XH2.54 连接电机,适配更大电流。
观察主板时我们发现4小槽无限位归零那里有4个引脚,而不是传统的2个引脚,对照引脚图和TMC5160驱动可知,此为连接 ABN 编码器使用,期待未来更多相关信息和模块。
ABN编码器接口:TMC5160可以外接增量式编码器,编码器不仅用于失步的判断,还可实现运动控制器的归零功能(替代参考开关)。可编程预分频器设置编码器分辨率以适应电机分辨率。TMC5160内部包含一个32位编码器计数器。
进一步阅读资料:
TMC5160控制/驱动IC 让步进电机性能更强大
TMC5160和TMC2160的使用
基于TMC5160StallGuard2实战案例分享 | 关于无限位归位参考
数据手册 第13页
此功能通过 STC 单片机(宏晶 STC8G1K08A | SOP8 STC8G1K08 系列1T8051)实现。目前仅支持三款驱动:
插入上述驱动,在配置文件中设置即可可以自动识别 SPI/UART/Standalone 三种模式。
想要使用其他驱动需要短接如下焊盘来手动指定 SPI 或是 UART 模式,对于非 Fysetc 的驱动,注意检查驱动通讯引脚,不同厂家的 TMC 驱动 UART 引脚顺序可能有所不同。
我希望能有独立的跳帽来选择更方便,但是得到反馈是板子上空间不够了。
众所周知啊,除了初版树莓派,现在都是 40-Pin 了,所以官方配套一根 26-Pin 的排线,我这恰巧没有。查看原理图可知引出了三部分功能:
这里的 SPI 用于 RRF固件,不过既然是总线通讯,也可以引出一路用于连接加速度计(连接到上位机、下位机都可以),当然,现在更推荐使用 USB-ADXL345 模块了。相信此 SPIBus 未来还有更多其他用途。
当然了,不止能插树莓派,只要是 40Pin 兼容的开发板都可以使用,比如香橙派等。甚至单独使用这些引脚也是可以的,比如使用 USB-TTL 模块连接 UART 引脚。
文档错误,板载没有测试 LED 灯与 WS2812 控制引脚 PD3 相连
BIG5160 驱动丝印印刷有瑕疵,且没有标明方向,与 2209 驱动和主板丝印相反,安装时务必注意 不要装反 了,这么高电压,相信场面一定很刺激。
EXT-5V 用于输出,给高功率灯带等设备用的
PT1000 上拉电阻是 4k7 与 Octopus 不同
核心板上有 24LC32(4K EEPROM) 存储,估计是 Marlin 固件使用
发热部分集中散热的设计,不知道在哪,有条件的朋友可以用热成像仪测试下,怀疑在中间
随机附送一个 ESP32 模块,且有一个烧录 USB 接口很不错,其实可以采用零售的方式降低成本,毕竟越来越多的人不选择 RRF 固件了
接近开关可选 5v/24v 电压
支持12cm风扇直接固定散热,买个可调速的 12v PC 风扇,有静音又凉快
拓展接口丰富,支持 EXP1 和 EXP2 Ramps 接口,及 EXP3-Duet 串口屏接口,当然也可以转为他用
限位开关电压选择
编译参数:STM32F407,8M,32KB。
下载 klipper.bin 并重命名为 firmware.bin 拷贝到格式化为 FAT32 文件系统的 SD卡中插入主板,断电或者按下RESET按钮,稍等片刻20s左右即可完成烧录,之后文件名称会变成 FIRMWARE.CUR。
按住boot0按钮,再按下reset按钮,稍等片刻设备进入DFU烧录模式
cd ~/klippersudo dfu-util -p 1-1 -R -a 0 -s 0x08008000:leave -D out/klipper.bin(推荐)如果系统已经烧录了新版 Klipper 系统,则无需使用boot0按钮即可自动进入dfu模式,编译后直接烧录
cd ~/klippermake flash FLASH_DEVICE=/dev/serial/by-id/usb-Klipper_stm32f407xx_fys-sking-407-if00注意dfu烧录固件并不会破坏sd卡升级功能
虽然 Sking 的高性能 STM32H7 核心模块还没发布,但是我很想知道 F407 和 H723 性能对比如何。传统的有 coremark 等测试程序,这里我们想看看 klipper 相关的性能对比。查阅 Klipper 文档,可知 Klipper 目前有上位机性能测试、下位机性能测试、命令传输性能测试。本次我们关注下位机性能测试,剩下的下次再说。
官方提供的方法,与 mcu 直接通讯,基础知识见前文:跟着思兼学习Klipper(21)新一代全能选手: Octopus Max EZ 简要使用记录
Klipper 默认将 Gcode 命令转换为机器语言,当然我们也可以直接与下位机主板通讯。这与 /tmp/printer 不同。参考文档包括:
这里的 Step rate benchmark test 用于mcu 同时控制一个或多个步进电机,发出运动指令,逐渐降低每个指令之间的间隔,找到 mcu 能负担的最小间隔,通过换算得到单位时间内步进电机控制性能,反映 mcu 的性能。直观就是 STM32 32位处理器要比 mega2560 能支持的打印速度更快。
【不同 mcu 性能对比】Source:klipper3d.org
注意:
# 使用 console.py 连接 mcu,注意设备号# 支持canbus连接:~/klippy-env/bin/python ~/klipper/klippy/console.py -c can0 1b93bb79de21sudo systemctl stop klipper~/klippy-env/bin/python ~/klipper/klippy/console.py /dev/serial/by-id/usb-Klipper_stm32f407xx_fys-sking-407-if00# 屏蔽干扰信息, [stats] 可以改成其他关键字SUPPRESS stats# 初始化H723/F407,定义指定数量对象,选择合适的步进电机引脚(step/dir_pin).以下内容直接复制黏贴,使用 shift+insert 黏贴,ctrl+c 在 Linux 下是退出# 文档中有不同 mcu 的参考引脚配置,多数情况下可以直接使用allocate_oids count=3config_stepper oid=0 step_pin=PE9 dir_pin=PD3 invert_step=-1 step_pulse_ticks=0config_stepper oid=1 step_pin=PA15 dir_pin=PA8 invert_step=-1 step_pulse_ticks=0config_stepper oid=2 step_pin=PE2 dir_pin=PE3 invert_step=-1 step_pulse_ticks=0finalize_config crc=0# 设置变量,开始时间start_clock 和 次数ticks# 定义三个电机,0 1 2。也可以只定义单个电机# 下面代码段同样整段直接复制黏贴SET start_clock {clock+freq}SET ticks 10reset_step_clock oid=0 clock={start_clock}set_next_step_dir oid=0 dir=0queue_step oid=0 interval={ticks} count=60000 add=0set_next_step_dir oid=0 dir=1queue_step oid=0 interval=3000 count=1 add=0reset_step_clock oid=1 clock={start_clock}set_next_step_dir oid=1 dir=0queue_step oid=1 interval={ticks} count=60000 add=0set_next_step_dir oid=1 dir=1queue_step oid=1 interval=3000 count=1 add=0reset_step_clock oid=2 clock={start_clock}set_next_step_dir oid=2 dir=0queue_step oid=2 interval={ticks} count=60000 add=0set_next_step_dir oid=2 dir=1queue_step oid=2 interval=3000 count=1 add=0# 如果没有报错则稍等片刻,修改上方ticks的值,再次复制黏贴,直到报错:"Rescheduled timer in the past" 或者 "Stepper too far in past" ,代表 ticks 值太小了(导致 stepping rate 太快)# 一般 ticks 每次减半,报错则使用下方命令清除 shutdown 状态,重新选择合适的值。clear_shutdown# 找到合适的 ticks 值,使用如下公式计算 stepper performance## 由于文档没有更新,部分命令使用方法可以使用 LIST 和查阅源码,例如# https://github.com/Klipper3d/klipper/blob/master/src/stepper.c | config_stepper小结:
stepper performance K = 3 × freq ÷ ticks ÷ 1000,其中 3 是步进电机数量
此值仅针对 TMC 驱动有参考意义
获得的数值仅是理论值,当控制其他变量后,可以对比不同 mcu 的性能
mcu支持 STEPPER_BOTH_EDGE=1 的(使用console.py连接时最后面)可以设置如下参数进行优化
invert_step=-1 step_pulse_ticks=0否则设置
step_pulse_ticks为100ns查看源码,搜索 STEPPER_BOTH_EDGE 可知目前支持此特性的主控芯片包括 :
The benchmarks are run with parameters suitable for TMC Drivers. For micro-controllers that support
STEPPER_BOTH_EDGE=1(as reported in theMCU configline when console.py first starts) usestep_pulse_duration=0andinvert_step=-1to enable optimized stepping on both edges of the step pulse. For other micro-controllers use astep_pulse_durationcorresponding to 100ns.step_pulse_duration: The minimum time between the step pulse signal edge and the following "unstep" signal edge. This is also used to set the minimum time between a step pulse and a direction change signal. The default is 0.000 000 100 (100ns) for TMC steppers that are configured in UART or SPI mode, and the default is 0.000 002 (which is 2us) for all other steppers.
【上述内容涉及 step_pulse_duration 】和丢步有关,有待进一步研究。最后测试结果和官方表格类似。
基于以下来源:https://pastebin.com/yPfSMBGF 修改,这也就是大家常见的测速宏:
如上图,真实测试,涉及因素包括电机响应速度,MCU同一时间能处理的脉冲数,步进电机驱动能处理的脉冲数,电机不丢步下能达到的速度。通过调参,找到最优设置。对步进电机驱动各项寄存器参数进行优化。
上述实机测试好是好,但是:
所以这里我们要排除电机因素,仅观察上位机能达到的理论数据,为此我们创建一个测速用参考文件,不需要热床、风扇、挤出机,仅需要xyz,不定义TMC驱动(避免通讯失败报错以及24V供电),仅让上位机输出step/dir/en 驱动信号。
[include misc/board.cfg][include misc/fake_speed_test.cfg][include misc/fluidd.cfg][printer]# cartesiankinematics: corexymax_velocity: 1000max_accel: 100000square_corner_velocity: 5.0max_z_velocity: 5max_z_accel: 100###################################################################### X/Y/Z 步进电机设置 | X/Y/Z Stepper Settings#####################################################################[stepper_x]step_pin: MOT0_STEPdir_pin: !MOT0_DIR # X轴电机方向引脚设置,可以通过添或删除引脚前面的!来改变电机方向enable_pin: !MOT0_ENmicrosteps: 64 # 推荐16细分以达到较好的精度和静音效果position_max: 1000# step_pulse_duration: 0.000004rotation_distance: 40 # 同步轮周长mm(2GT-20T带轮40,2GT-16T带轮32)endstop_pin: ^!ESTOP0 # X_MINposition_endstop: 0 # X Offset,用于设置打印平台偏移[stepper_y]step_pin: MOT1_STEPdir_pin: !MOT1_DIRenable_pin: !MOT0_ENmicrosteps: 64position_max: 1000# step_pulse_duration: 0.000004rotation_distance: 40endstop_pin: ^!ESTOP2 # Y_MINposition_endstop: 0 # Y Offset[stepper_z]step_pin: MOT2_STEPdir_pin: !MOT2_DIRenable_pin: !MOT0_ENmicrosteps: 16step_pulse_duration: 0.000004rotation_distance: 4 # 根据情况修改position_endstop: 0.5 # disable to use BLTouchendstop_pin: ^!ESTOP4 # disable to use BLTouch, Z_MINposition_min: 0position_max: 300# original_url: https://pastebin.com/yPfSMBGF# 参数:# ACCEL_STEPS (文字,逗号隔开整数):测试的加速度值,调用方式:ACCEL_STEPS="5000, 10000, 20000"# TEST_STEPS (文字,逗号隔开文本):测试目标,如:TEST_STEPS="x_test,y_test,rect_test,diag_test"#- 选项:# - x_test = 移动x轴# - y_test = 移动y轴# - rect_test = 矩形移动# - diag_test = xy对角移动# - circle_test = 圆形移动Moves in a circle twice# DISTANCE_STEPS (文字,逗号隔开浮点数):测试移动距离, DISTANCE_STEPS="30, 22, 45.221"# SPEED_STEPS (文字,逗号隔开浮点数): 测试移动速度, SPEED_STEPS="100, 120, 120.22"# feed_rate_test TEST_STEPS="x_test,y_test,rect_test,diag_test" SPEED_STEPS="200, 400" DISTANCE_STEPS="400" ACCEL_STEPS="10000, 50000"# 清空当前日志并生成负载图; python3 ~/klipper/scripts/graphstats.py ~/printer_data/logs/klippy.log -o ~/loadgraph.png; systemctl stop klipper; echo > ~/printer_data/logs/klippy.log; systemctl start klipper[gcode_macro FEED_RATE_TEST]description: 打印机速度测试,仅涉及XY空跑或者虚拟跑。original_url: https://pastebin.com/yPfSMBGF# TODO: 判断是否开启 respondgcode: {% if printer.configfile.config.respond is not defined %} {action_raise_error("This gcode_macro requires the [respond] section in your printer.cfg")} {% endif %} # Ugly code to convert a string into an array in jinja # TEST_STEPS conversion # TODO: 读取参数设置 {% set ns_test_steps = namespace(collector="", arr=[]) %} {% for char in params.TEST_STEPS|default("x_test,y_test,rect_test,diag_test")|string %} {% if char == "," or loop.last %} {% if loop.last %} {% set ns_test_steps.collector = ns_test_steps.collector ~ char %} {% endif %} {% set ns_test_steps.arr = ns_test_steps.arr + [ns_test_steps.collector|string] %} {% set ns_test_steps.collector = "" %} {% else %} {% set ns_test_steps.collector = ns_test_steps.collector ~ char %} {% endif %} {% endfor %} # SPEED_STEPS conversion {% set ns_speed_steps = namespace(collector="", arr=[]) %} {% for char in params.SPEED_STEPS|default("80.0")|string %} {% if char == "," or loop.last %} {% if loop.last %} {% set ns_speed_steps.collector = ns_speed_steps.collector ~ char %} {% endif %} {% set ns_speed_steps.arr = ns_speed_steps.arr + [ns_speed_steps.collector|float] %} {% set ns_speed_steps.collector = "" %} {% else %} {% set ns_speed_steps.collector = ns_speed_steps.collector ~ char %} {% endif %} {% endfor %} # DISTANCE_STEPS conversion {% set ns_distance_steps = namespace(collector="", arr=[]) %} {% for char in params.DISTANCE_STEPS|default("40.0")|string %} {% if char == "," or loop.last %} {% if loop.last %} {% set ns_distance_steps.collector = ns_distance_steps.collector ~ char %} {% endif %} {% set ns_distance_steps.arr = ns_distance_steps.arr + [ns_distance_steps.collector|float] %} {% set ns_distance_steps.collector = "" %} {% else %} {% set ns_distance_steps.collector = ns_distance_steps.collector ~ char %} {% endif %} {% endfor %} # ACCEL_STEPS conversion {% set ns_accel_steps = namespace(collector="", arr=[]) %} {% for char in params.ACCEL_STEPS|default(printer.toolhead.max_accel|string)|string %} {% if char == "," or loop.last %} {% if loop.last %} {% set ns_accel_steps.collector = ns_accel_steps.collector ~ char %} {% endif %} {% set ns_accel_steps.arr = ns_accel_steps.arr + [ns_accel_steps.collector|int] %} {% set ns_accel_steps.collector = "" %} {% else %} {% set ns_accel_steps.collector = ns_accel_steps.collector ~ char %} {% endif %} {% endfor %}# TODO: 读取机器变量 # Variable assignment {% set center_x_position = printer.toolhead.axis_maximum.x / 2 %} {% set center_y_position = printer.toolhead.axis_maximum.y / 2 %} # Conversion steps variable assignment {% set accel_steps = ns_accel_steps.arr %} {% set test_steps = ns_test_steps.arr %} {% set distance_steps = ns_distance_steps.arr %} {% set speed_steps = ns_speed_steps.arr %} SAVE_GCODE_STATE NAME=speed_testing_macro {% set testRunCounter = namespace(value=0) %} RESPOND PREFIX="Speed-Test - " MSG="使用以下参数进行测试:" RESPOND PREFIX="- " MSG="distance_steps={distance_steps}" RESPOND PREFIX="- " MSG="speed_steps={speed_steps}" RESPOND PREFIX="- " MSG="accel_steps={accel_steps}" RESPOND PREFIX="- " MSG="test_steps={test_steps}" RESPOND PREFIX="" MSG="--------------------"# TODO: 归位,虚假和实际 # Homing {% if printer.toolhead.homed_axes != "xyz" %} # G28 SET_KINEMATIC_POSITION X=0 Y=0 Z=0 {% endif %} G90 G1 X{center_x_position} Y{center_y_position} Z25 F4000 {% for distance_step in distance_steps %} {% for speed_step in speed_steps %} {% set speed_feedrate_step = speed_step * 60 %} {% for accel_step in accel_steps %} {% set testRunCounter.value = testRunCounter.value + 1 %} M204 S{accel_step} RESPOND PREFIX="Speed-Test - " MSG="Test-Run {testRunCounter.value} => distance: {distance_step} speed: {speed_step} acceleration: {accel_step}" {% for test_step in test_steps %} _{test_step|upper} FEEDRATE={speed_feedrate_step} DISTANCE={distance_step} {% endfor %} {% endfor %} {% endfor %} {% endfor %} RESTORE_GCODE_STATE NAME=speed_testing_macro[gcode_macro _X_TEST]description: Moves the head left/rightgcode: {% set speed_feedrate = params.FEEDRATE|default(4800)|float %} {% set distance = params.DISTANCE|default(100)|float %} G91 G1 x{distance} F{speed_feedrate} G1 x-{distance * 2} F{speed_feedrate} G1 x{distance} F{speed_feedrate} G90 M118 Done_X_TEST[gcode_macro _Y_TEST]description: Moves the head forward/backwardgcode: {% set speed_feedrate = params.FEEDRATE|default(4800)|float %} {% set distance = params.DISTANCE|default(100)|float %} G91 G1 y{distance} F{speed_feedrate} G1 y-{distance * 2} F{speed_feedrate} G1 y{distance} F{speed_feedrate} G90 M118 Done_Y_TEST[gcode_macro _RECT_TEST]description: Moves the head in a rectanglegcode: {% set speed_feedrate = params.FEEDRATE|default(4800)|float %} {% set distance = params.DISTANCE|default(100)|float %} G91 G1 x-{distance} F{speed_feedrate} G1 y-{distance} F{speed_feedrate} G1 x{distance * 2} F{speed_feedrate} G1 y{distance * 2} F{speed_feedrate} G1 x-{distance * 2} F{speed_feedrate} G1 y-{distance} F{speed_feedrate} G1 x{distance} F{speed_feedrate} G90 M118 Done_RECT_TEST[gcode_macro _DIAG_TEST]description: Moves the head diagonally. First spinning the stepper_x, then the stepper_y. (CoreXY)gcode: {% set speed_feedrate = params.FEEDRATE|default(4800)|float %} {% set distance = params.DISTANCE|default(100)|float %} G91 G1 x{distance} y{distance} F{speed_feedrate} G1 x-{distance * 2} y-{distance * 2} F{speed_feedrate} G1 x{distance} y{distance} F{speed_feedrate} G1 x{distance} y-{distance} F{speed_feedrate} G1 x-{distance * 2} y{distance * 2} F{speed_feedrate} G1 x{distance} y-{distance} F{speed_feedrate} G90 M118 Done_DIAG_TEST[gcode_macro _CIRCLE_TEST]description: Moves the head in a circle twice.gcode: {% set speed_feedrate = params.FEEDRATE|default(4800)|float %} {% set distance = params.DISTANCE|default(100)|float %} {% if printer.configfile.config.gcode_arcs is not defined %} {action_raise_error("The circle test requires the [gcode_arcs] section in your printer.cfg")} {% endif %} {% for count in range(2) %} G2 I{distance} J{distance} F{speed_feedrate} {% endfor %} M118 Done_CIRCLE_TESTSET_KINEMATIC_POSITION X=0 Y=0 Z=0Done_XXXX_TEST 避免干等feed_rate_test TEST_STEPS="x_test,y_test,rect_test,diag_test" SPEED_STEPS="200, 400" DISTANCE_STEPS="400" ACCEL_STEPS="10000, 50000"我们使用 Klipper 自带的系统负载生成工具。
# 清空日志systemctl stop klipperecho > ~/printer_data/logs/klippy.logsystemctl start klipper# ——>开始比赛<——# 生成负载图python3 ~/klipper/scripts/graphstats.py ~/printer_data/logs/klippy.log -o ~/loadgraph.png大概结果如下:
这个图后面再做分析,写累了。
参考 Prusa 计算器,太高的速度和加速度对于一般用户来说意义也不大,瓶颈在挤出头。
Fysetc Spider King 这块主板,读下来的感觉就是一个字:稳。工业标准的理念贯穿其中,就是太贵了,普通用户买不起,听说以后随着物料成本的降低也会降价,先做期待。