写在前面:本人对Arduino、Labview、CNC都了解不多,如有错误,请私信指正。
需求
- 设计雕刻机上位机,能够向下位机发送G代码
- 下位机能解释G代码并控制电机行动
设计
设计流程图
-
实现流程图
实现过程如下:
-
操作流程图
实际情况操作流程如下:
上位机部分
设计思路:
参考了一些现有的雕刻机上位机软件(以下贴图来自奎享雕刻软件,其他也差别不大),发现基本功能如下:
1.建立连接,选择端口、波特率、烧录的固件,由于我使用的是GRBL固件,所以没有添加选择固件的功能(还有其他固件如Gcode-Interpreter,都大同小异)
2.可以确认机器状态,可以设置工作位置和实时显示机器位置,方便做出调整。
3.设置起点,单独设置X,Y,Z轴的起点和返回工作位置(原点)。
4.设置XYZ轴移动步长(由于X和Y都在水平方向所以放在一起,当然,如果是读入.nc文件是直接根据文件中的信息来设置的),设置主轴运转的速度。
5.基本的三轴移动功能。
6.开启和关闭主轴。
7.读入.nc文件并执行。
参考上述的功能,设计了如下基于Labview的雕刻机上位机控制系统。(关于读取G代码的部分,由于时间和精力的限制暂时还未能做出来,如果后续有机会实现,会贴在最后)
其整体前面板如下:
实现了基本的开关、选择串口、串口状态提示、显示历史命令、清除历史命令、通过上位机控制XYZ轴移动、打开/关闭主轴、选择主轴正/反转、设置主轴转动速度、直接发送G命令、设置工作原点、返回工作原点、设置XYZ轴移动步长、显示工作坐标和机械坐标的功能。前面板的功能顾名思义,下面是程序内部的说明。
整个程序设计思路较为简单,主要是通过检查按钮的01状态来实现功能,所有的操作都放在一个if判断中,由总的开关控制,外套接一个while循环。
接下来,就每个功能说明实现方法:
显示及清除历史命令:
设置一个显示字符串的前面板控件,通过该控件来显示历史命令。
具体的操作为,在每个命令执行后(向下位机发送G代码字符串),分开一条支路连接到历史命令,通过字符串拼接完成对所有命令的显示。
历史命令清除,是通过将空字符串覆盖到历史命令控件中实现,较为简单。
正转、反转、关闭主轴:
查阅G代码资料发现,控制主轴运动主要由M3 M4 M5及Sxxx组成。其中,M3表示主轴正转,M4表示主轴反转,M5表示主轴停止转动。而Sxxx,如S500则是用于控制主轴转速的G代码,基于此,通过将M3/M4/M5发送至串口下位机接收完成对主轴的控制操作。
对工作原点的设置:
查阅G代码资料,发现G10 P0 L20然后设置X0 Y0 Z0是对工作原点的设置代码,同样的,发送相应的代码即可完成设置,不过需要在上位机设置相应的显示控件,如我这里选择了三个数值量来显示,当设置工作原点后,将三个数值量置0,表明设置完成,也方便后续查看。
单独G命令的发送:
将文本输入框控件连接到该if框架中,点击发送后串口传输对应的内容,还设置了一个小的发送后清零,通过发送后判断标志,如果成功发送则将命令输入框清空。
对XYZ轴转动的控制:
查阅G代码发现,G21G91G0X/Y/Z增量F1000,G90 G21可以完成对三轴的移动,通过选择X/Y/Z及其步长来控制运动。由于X/Y/Z轴、正负都是相同的结构,这里不再赘述。
串口的连接检测:
通过将VISA serial的错误输出簇拆分出Status,并将其接到一个小灯来查看串口是否正确连接。
返回原点:
通过G90 G0+X0/Y0/Z0的命令来完成三轴步进电机返回初始位置的功能。
主轴转速控制:
使用一个滑动杆来设置主轴的转速,读取滑动杆数值后,将其向下取整并转化为字符串,在前边添加S后边添加换行字符即可。设置好后通过按下确定按钮操作。
其他:
由于if结构在为真时执行,需要将按钮的机械动作选择为:释放时触发,否则可能因为操作不当陷入死循环或者发送很多次。
关于读取.nc文件:
由于时间等原因并未实现该功能,但是基于.NC文件的格式,给出以下实现的思路:使用note pad++打开.NC文件查看其格式,发现前两行也许是类似于前缀之类的,从第三行开始执行N20,N30,N40。这些NX0代表第X步的操作。根据以上思路,可以用Labview打开后逐行读取.nc文件,丢掉前两行后开始执行后边的内容(如果有用的话则保留,我没有查阅到相关信息),逐行通过串口发送即可。
下位机部分
使用Arduino UNO板来作为G代码的解释器和控制电机。由于手头并没有实物,所以使用了Proteus中的仿真仪器进行实验。
关于Arduino的导入:
1.可以选择下载Arduino UNO Library for Proteus器件库,从而在器件中选择UNO板。Load好lib后搜索Arduino如下:
2.可以选择不下载器件库,使用原生的ATmega328P,和UNO板没有差别。此种方式需要在创建新工程的时候选择->从开发板,选择Arduino 328P器件,如下图。
进入Proteus界面后,该种方式和导入器件库不太一样,显示的是没有封装壳的样式,但引脚均和UNO板一致。
GRBL介绍:
GRBL是一款针对Arduino的G代码编译和运动控制的开源程序(由于其开源特性也被移植到了诸如STM32之类的平台)。本身GRBL就带有上位机,叫做GRBL Controller,与上学期使用的GRBL control类似,估计后者就是用这个开源的版本修改的。作为硬件程序的下位机部分则被普遍称为GRBL固件,可运行在ATmega168/328P上,串口接收到上位机的Gcode指令即可转换为对应的控制电机指令。对于使用者的我们,只需要知道哪个口输出控制什么的信号、通过串口传输指令就好了,而这些都在cpu_map_atmega328p.h这个配置文件中给出了。
关于Gcode:是用于数控的语言。 NC 代码主要包含了各种准备功能的 G 指令、辅助功能的 M 指令、坐标功能字、进给功能字 F、主轴转速功能字 S、刀具功能字 T 和其他指令。该系统所能识别的指令包括 9 组,即非模态控制指令 G4、G10、G28、G30、G53、G92,运动控制指令G0、G1、G2、G3、G80,平面选择指令G17、G18、G19,相对/绝对坐标 G90、G91,程序停止M0、M1、M2、M3,进给速度 G93、G94,单位选择 G20、G21,主轴旋转控制M3、M4、M5,坐标系选择指令G54、G55、G56、G57、G58、G59。
电路设计:
-
步进电机部分
由于Proteus库中并没有集成的电机驱动模块,所以使用了L297和L298芯片作为步进电机的控制芯片。其中,L297是一款步进脉冲时序分配器,可以驱动两个半桥和一组全桥电路,而L298是一个由两个独立半桥组成的全桥电路,既可驱动两只有刷电机(需要正反转时),也可驱动一只两相步进电机。由于本实验中烧录了GRBL固件,无法对Arduino的管脚进行操作,所以选择了L297+L298的组合作为步进电机的驱动。组合后,每只步进电机都只需步进脉冲(由L297提供)和正反转信号即可。
L297和L298如下:
其管脚配置和使用说明如下:
L298:可视为直流电机的驱动芯片,将AB使能端给高电平供电,将SENSA和SENSB(电流监测端)接地(如果需要使用则接两个对应步进电机功率的电阻到地)。将L297输出的步进脉冲输入到L297的IN1~IN4口作为输入,输出接到42步进电机。
L297:L297芯片是一个步进电机控制器,可以产生四相驱动信号。该芯片内部的PWM斩波器允许在关模式下控制步进电机绕组电流,由于相序也是由内部产生的,所以它只需要时钟、方向和模式输入信号就能控制步进电机,可减轻处理器和程序设计的负担。将Arduino输出的控制信号和方向信号输出到CW和CLOCK端口,再通过L297控制L298完成对步进电机的控制。
根据GRBL配置文件,可以看到X、Y、Z轴的控制信号和方向信号分别由如下引脚控制:
通过将这些引脚接到L297完成单片机->电机驱动芯片的连接。 -
主轴电机部分
根据GRBL程序说明,烧录GRBL固件之后的Arduino板使用PIN11和PIN12分别作为主轴的PWM控制和方向控制。
同样,由于器件库不完备,使用L298作为直流电机的驱动芯片。
L298作为直流电机驱动时,当使能端为高电平时,输入端IN1为PWM信号,IN2为低电平信号时,电机正转;输入端IN1为低电平信号,IN2为PWM信号时,电机反转;IN1与IN2相同时,电机快速停止。当使能端为低电平时,电动机停止转动。
因此,为了功能完好地使用正转和反转功能,需要两片L298芯片,分别在正转时选通和反转时选通,用于产生对应的信号。
使用了一个非门来获得方向信号的反电平,这是由于正转时方向输出低电平,为了能让其选通使能端用了一个非门。这样,就能根据方向信号选通L298中的一只,从而完成对主轴的方向控制。而主轴的转速,则通过解析G代码后发出的PWM信号控制。
整体电路图如下:
其中, 是仿真用的,将在联合调试中说明, 为四相步进电机, 为直流电机,其他的元器件(328P板,L298,L297)则是在上边详细说明了。
联合调试
准备工作:
1.为了完成Labview上位机和Proteus虚拟下位机的联合调试,还需要建立二者的通信,这需要一个虚拟串口软件来完成。在网上查阅资料后,发现VSPD(Virtual Serial Port Driver)可以很好地满足我们的需求。
VSPD使用说明:
打开虚拟串口驱动,可以看到左边有实际的端口和虚拟的端口。
选择两个虚拟的端口,点击添加端口,这样就创建了一组虚拟串口端口,例如我的是COM3和COM7.
这样,就完成了虚拟串口的互联。需要注意的是,如果接收的一方使用某个端口,比如COM3,则需要发送的一端使用COM7对COM3发送,这也是为什么是一对的原因。
2.为了在Proteus这边接收到串口数据,需要使用Proteus提供的串口组件。在元器件库中搜索Compim,得到如下结果:
使用该虚拟串口组件作为接收端的串口。
连接如下:
将串口的RXD(接收)和TXD(发送)引脚分别与Arduino的RXD、TXD引脚(PIN0与PIN1)相连即可。
3.还需要一个虚拟的终端来显示接收到的数据,以确认无误。
虚拟终端的创建可以在左侧仪器仪表目录下的Virtual Terminal中选择。
由于我们只需要显示接收到的数据就好了,所以将接收端RXD与串口的RXD连接即可。
建立连接:
双击点开串口,选择需要使用的端口,并配置波特率。由于Grbl新版的波特率要求是115200,所以选择115200的波特率,关于波特率这里还有一个小坑,会在遇到的问题提到。
这样,串口方面就算配置完成了。
Arduino板程序的烧写:
将程序烧录到虚拟的Arduino中,需要其编译完成的Hex文件。对Grbl固件编译,需要先在github上下载其代码,链接如下:
https://github.com/grbl/grbl
将文件夹导出后,在Arduino-IDE中添加Grbl库,如下:
添加相应文件夹,之后可以在下列的库中看到grbl库。
之后,打开文件目录下的grbl->examples->grblUpload,打开如下文件
进行编译。
编译完成后,选择
就可以在这个ino文件的目录下生成对应的hex文件。
在Proteus中,双击328P板,将Program File选择对应的hex文件即可。
测试:
使用串口调试助手测试是否能收到数据。
发送你好,接收到你好。(这里是用9600的波特率发送的,原因会在问题里汇总)
功能正常。
初始配置:
使用$命令可以查看所有的grbl可选项,包括一些参数和设置的修改。
我将xyz的都设成了53.333(初始的是100,感觉太大了),还有一些其他的设置,需要的时候可以在这里修改。
Labview和Proteus的联合调试:
在Labview中循环运行程序,打开开关后选择串口
打开Proteus仿真,
二者就连接好了。
测试XYZ轴移动、发送命令、设置初始点、主轴的正反转及调速,均工作正常。由于是动态的过程不方便演示,以录制视频的形式做了展示。
现实中的方案
以上是仿真时使用的方案,然而在现实生活中,如果要做一个雕刻机,有更多更方便好用的选择。
方案一:
Arduino CNC 盾板,专为数控雕刻机设计的拓展,其原理图如下。
CNC Shield V3.0可用作雕刻机,3D打印机等的驱动扩展板,板上一共有4路步进电机驱动模块的插槽,可驱动4路步进电机,而每一路步进电机都只需要2个IO口,也就是说,6个IO口就可以很好的管理3个步进电机,使用起来非常的方便,告别传统步进电机操作繁琐。将Arduino CNC Shield V3.0插到Arduino UNO上,并且安装GRBL固件就可以进行操作。
一般搭配A4988使用的较多,直接插上去就能用了,示意图如下:
使用Arduino的控制方法如下:
Arduino引脚 8 ———————– CNC 扩展板 EN ( 所有电机驱动板使能引脚/低电平有效 )
Arduino引脚 5 ———————– CNC 扩展板 X.DIR ( X端口方向控制引脚)
Arduino引脚 2 ———————– CNC 扩展板 X.STEP ( X端口步进控制引脚)
Arduino引脚 6 ———————– CNC 扩展板 Y.DIR ( Y端口方向控制引脚)
Arduino引脚 3 ———————– CNC 扩展板 Y.STEP ( Y端口步进控制引脚)
Arduino引脚 7 ———————– CNC 扩展板 Z.DIR ( Z端口方向控制引脚)
Arduino引脚 4 ———————– CNC 扩展板 Z.STEP ( Z端口步进控制引脚)
Arduino引脚 13 ———————– CNC 扩展板 A.DIR ( A端口方向控制引脚)
Arduino引脚 12 ———————– CNC 扩展板 A.STEP ( A端口步进控制引脚)
控制多个步进电机的接法如下:
方案二:
使用EasyDriver。EasyDriver是一款步进电机驱动器,如下是v4.4版本的示意图。
每个EasyDriver能为两级步进电机提供大约750mA的驱动(一共1.5A)。它默认设置为8步细分模式(所以如果你的电机是每圈200步,你使用EasyDriver时默认为每圈1600步),更多细分模式可以通过将MS1或MS2两个接脚接地进行设置。
这样的话,思路就很清晰了,Arduino接出来三个EasyDriver控制三个轴就是了。
方案三:
使用A4988驱动步进电机。硬件连接如下图,也是只需两个管脚即可完成控制。
但是根据网友们的反应来看,发热严重,并不推荐
方案四:
使用TB6560,或者其升级版,TB6660。这两款都是额定电流在3A及以上(6660能到4.5A)的大功率驱动。但由于并未使用,我查阅的资料不多,不再详细讲述。
总结:
以上几种方法是对驱动步进电机的不同方案的探讨,Arduino还是刷相应的Grbl固件。首先,实际中肯定不会使用L298+L297这样的芯片,而会选择集成的驱动,但究竟应该选择哪一种方案,我觉得还是应该从预算、预期的功能(如需要大功率的就可以考虑TB6560)等方面考虑,此处提出几种只是将几种合理的办法汇总,如果有需要可以按需做出选择。
操作过程中遇到的问题及解决办法
1.一开始想使用STM32作为主控,但是在调试过程中奇怪地爆RAM了,我并没有做什么别的操作,只是把例程打开在虚拟环境运行而已。
可以看到程序卡在了Debug模式。
此外,STM32 for Labview的程序在2012年就停止更新了(我用的2012的Labview跑的不然不兼容),我想也许是当时程序里就有一些bug把,再加上没办法拿实物连,更无从下手。
这个问题至今仍未解决,使用STM32的方案被我抛弃了。
2.一开始,程序烧录的是0.9c版本,这是因为从0.9d版本开始,波特率就从9600变成了115200。而根据Proteus的虚拟串口组件来看,只能选择到57600的波特率,由于条件的不支持,我一开始一直是用的老版本的9600的波特率。
但是这个问题在调试主轴的时候就暴露了出来。
相关资料显示,旧版本的主轴控制是用的开关量,也就是纯粹的高低电平(我没想懂怎么控制速度的),为了让电机能够转动,我测试了正转、反转、停止转动三种情况下三个口的电平,得到了目标函数,根据数字电路所学的知识,我搭建了能让其正常转动的电路。(当然,没有加驱动,所以转的特别慢)
这样,就是我完成的第一版主轴,但是这样的主轴不但功率很低,而且不能调速度。
后来,我发现Proteus里串口的波特率不用非得选择那几个选项,而是可以自己设定的,这个问题也就解决了。不过这样同时也导致了另一个问题,由于Proteus内置并不支持这么高的波特率,所以在115200的情况下虚拟终端显示的是乱码,不过这个在后期调试已经完成的情况下影响不大。
于是,我烧录了0.9j版本的新版固件,这样一来,就可以通过PWM来控制主轴转动了。
3.由于Labview程序运行逻辑的问题,强制关闭后并不会运行“关闭串口”的指令,所以在离开Labview时一定要关掉绿色开关,否则该串口会一直被占用,如下图:
4.换行的问题。Labview向Arduino串口发送数据时,并不会自己换行,这就导致如果不换行并不会执行命令,使用Labview字符串中的换行字符串与原字符串拼接得到换行的效果。
5.由于之前使用LIFA库(Labview Interface For Arduino)使用的是Arduino1.05-r2版本,这个版本过低,在生成hex文件时并不能像新版一样直接在目录那里选择生成,而是需要进行一些设置。
可以看到并没有直接生成hex文件的选项。
需要点击文件->参数设置
在 中编辑。
注意编辑的时候要关掉IDE,否则会自动取消保存
在最后一行加上需要保存hex文件的目录,这样编译就会生成相应的hex文件了。
个人的一些其他想法
1.使用pyserial/micropython+GUI来做上位机
可以使用pyqt一类的GUI库来设计交互界面,而上位机和下位机的通讯采用pyserial或者micropython来实现。
Pyserial:pyserial是python的一个串口通信库,上手比较简单,网络上也有很多教程。随便贴一个吧:
Pyserial教程
Micropython:micropython的来头就更大了,是由剑桥大学的理论物理学家乔治.达明设计,遵循MIT许可协议,与Arduino类似,拥有自己的解析器、编译器、虚拟机和类库等,MicroPython更强大。目前它支持基于32-bit的ARM处理器,比如STM32F405、STM32f407等,也就是说ARM处理器STM32F405上直接可运行Python语言,用Python语言来控制单片机。在单片机上能运行Python,实际上Python已经完全脱离系统,也就是说,你可以通过Python脚本语言开发单片机程序。
2.查阅资料的过程中发现前些年好多人拿光驱中的步进电机来做激光雕刻机,成本也不高,大概在100~200左右,还挺有意思的。
总结和感悟
由于器材的限制导致只能完成仿真,这也导致了在仿真过程中的一些麻烦,一路上踩了不少坑,从stm32爆RAM到控制主轴输出的是开关量,都让我印象很深刻。就本次雕刻机仿真来说,因为没有什么头绪,前期感觉花在查阅资料上的时间太多了,导致后期时间并不是很充裕,但也给了我一些相关的知识,下次再遇见类似的问题可以快速构建一个解决方案。
本次设计让我了解了开源硬件的乐趣,我也在了解Grbl这种固件之后知道了Arduino也可以玩出这么多花样,才真正理解了“开源”的含义,完成本实验的仿真后,我在考虑购入esp8266,做一些物联网相关的小东西。
关于雕刻机,我的Labview程序当然还有很多可以,甚至说是需要优化的地方,比如之前提到的直接关掉会占用串口,如何绕过这个关闭串口,等等,都是可以进行提升的地方。
总的来说,虽然过程很痛苦,但是从结局来看还是学到了不少,如Proteus的使用,对Labview的理解等提升了一些。
参考资料
Grbl:
https://github.com/grbl/grbl
https://blog.csdn.net/abbrCN/article/details/80119099
Arduino CNC拓展盾:
http://www.taichi-maker.com/homepage/reference-index/motor-reference-index/arduino-cnc-shield/
L297+L298控制步进电机:
http://www.51hei.com/bbs/dpj-81319-1.html
https://zhidao.baidu.com/question/122096928.html
https://wenku.baidu.com/view/af6b16126c175f0e7cd137ec.html
EasyDriver:
https://www.geek-workshop.com/thread-8746-1-1.html
主轴控制(Grbl版本需≥0.9c):
http://bbs.mydigit.cn/read.php?tid=1826080
http://www.ndiy.cn/thread-37518-1-14.html
虚拟串口
https://blog.csdn.net/qq_34202873/article/details/88391265