勇哥x,y,z平台的控制程序(GRBL设备的G代码控制程序)

这个平台采用的开源的GRBL,基于单片机Arduino,三个轴的设备。

支持G代码,也就是CNC上面用的G代码。

这个平台如下面所示:


image.png

你可以用它来写字,效果还不错。


控制程序实现了基础的功能:

  • 示教点

  • 步进调试位置

  • 回原点的控制功能


image.png

由于这个平台没有源点感应开关,因此它所谓的原点, 是在开机那一刻的当前位置设置为原点.

因此这个机器不能中途断电, 否则你得重新设置原点.

并且每次结束程序前都会自动回一次原点, 才能断电.


下面列出核心类的代码, 方便大家参考.

代码是需要netMarketing类的支持的.

using netMarketing.automation.communication;
using netMarketing.dataType;
using netMarketing.http;
using sharClass;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace xyzControlPanel
{
    public struct ptStruct
    {
        public string x;
        public string y;
        public string z;
        public string u;
        public string explain;
    }

    public struct ptListStruct
    {
        public string ptName;
        public string x;
        public string y;
        public string z;
        public string u;
        public string explain;
    }

    public struct axisPosStruct
    {
        public double x;
        public double y;
        public double z;
        public double u;
    }

    public class motionControl : Settings
    {
        [Config, Description("串口名称,例如COM7"), Category("xyz平台参数"), DefaultValue("")]
        public string 串口名称 { get; set; }

        [Config, Description("步进距离x,单位mm"), Category("xyz平台参数"), DefaultValue("")]
        public double 步进距离x { get; set; }

        [Config, Description("步进距离y,单位mm"), Category("xyz平台参数"), DefaultValue("")]
        public double 步进距离y { get; set; }

        [Config, Description("步进距离z,单位mm"), Category("xyz平台参数"), DefaultValue("")]
        public double 步进距离z { get; set; }

        [Config, Description("步进距离u,单位deg"), Category("xyz平台参数"), DefaultValue("")]
        public double 步进距离u { get; set; }



        [Config, Description("连续运动增量,x,y,z, 单位mm"), Category("xyz平台参数"), DefaultValue("")]
        public double 连续运动增量 { get; set; }


        [Config, Description("连续运动角度增量,只能轴u, 单位deg"), Category("xyz平台参数"), DefaultValue("")]
        public double 连续运动角度增量 { get; set; }




        [Config, Description("步进模式,0连续运动,1步进运动"), Category("xyz平台参数"), DefaultValue("")]
        public int 步进模式 { get; set; }

        [Config, Description("步进速度"), Category("xyz平台参数"), DefaultValue("")]
        public int 步进速度 { get; set; }

        [Config, Description("示教点列表,每行之间用|分隔"), Category("xyz平台参数"), DefaultValue("")]
        public string 示教点列表 { get; set; }



        private CommPort serial = null;
        private bool isInitFlag = false;
        private Dictionary<string, ptStruct> ptList = new Dictionary<string,ptStruct>();
        public axisPosStruct workPos = default(axisPosStruct);
        private axisPosStruct orgiPos = default(axisPosStruct); 

        public motionControl()
        {
            try
            {
                init();
               
                isInitFlag = true;
                InitCMD();
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 外部更新点列表
        /// </summary>
        /// <param name="data"></param>
        public void updatePtList(List<ptListStruct> data)
        {
            StringBuilder sb1 = new StringBuilder();
            if (data.Count > 0)
            {
                ptList.Clear();
                foreach (var m in data)
                {
                    ptList.Add(m.ptName, new ptStruct() { x = m.x, y = m.y, z = m.z, u = m.u, explain = m.explain });
                }
            }
            Save();
        }



        /// <summary>
        /// 返回点列表,按数据结构 List<ptListStruct> ,主要给外部改新点列表使用。
        /// </summary>
        /// <returns></returns>
        public List<ptListStruct>  getPtList()
        {
            var res = new List<ptListStruct>();
            foreach(var m in ptList)
            {
                res.Add(new ptListStruct() 
                { 
                    ptName = m.Key,
                     x=m.Value.x,
                     y=m.Value.y,
                     z=m.Value.z,
                     u=m.Value.u,
                     explain=m.Value.explain
                });
            }
            return res;
        }

        /// <summary>
        /// 取指定示教点信息
        /// </summary>
        /// <param name="ptName">示教点的名字</param>
        /// <returns></returns>
        public ptStruct getPosInfo(string ptName)
        {
            if (ptList.ContainsKey(ptName))
                return ptList[ptName];
            return default(ptStruct);
        }

        public new void Save() 
        {
            try
            {
                if (ptList.Count > 0)
                {
                    StringBuilder sb1 = new StringBuilder();
                    var list1 = new List<string>();
                    foreach (var m in ptList)
                    {
                        list1.Clear();
                        list1.Add(m.Key);
                        list1.Add(m.Value.x);
                        list1.Add(m.Value.y);
                        list1.Add(m.Value.z);
                        list1.Add(m.Value.u);
                        list1.Add(m.Value.explain);
                        sb1.Append(list1.createCSVRow()); sb1.Append("|");
                    }
                    示教点列表 = sb1.ToString();
                    if (示教点列表.Length > 2)
                    {
                        示教点列表 = 示教点列表.Substring(0, 示教点列表.Length - 1);
                    }

                }
                base.Save();
            }
            catch(Exception ex)
            {
                int k1 = 0;
            }
        }
      
        public new void Load()
        {
            try
            {
                base.Load();
                if (示教点列表.Length > 0)
                {
                    ptList.Clear();
                    var ary1 = 示教点列表.Split('|');
                    foreach (var m in ary1)
                    {
                        var ary2 = m.Split(',');
                        if (ary2.Length == 6)
                            ptList.Add(ary2[0], new ptStruct()
                            {
                                x = ary2[1],
                                y = ary2[2],
                                z = ary2[3],
                                u = ary2[4],
                                explain = ary2[5]
                            });
                    }
                }
                
            }
            catch(Exception ex)
            {
                int k1 = 0;
            }
        }
        /// <summary>
        /// 把当前机器位置设置为原点位置,指令
        /// </summary>
        public void setOriPosCMD()
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                var cmd = "G10 P0L20 X0.0Y0.0Z0.0\r";
                serial.Write(binHelper.toBin<string>(cmd),cmd.Length);
                orgiPos = getAxisMacPosCMD();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// SLP指令,关闭电机
        /// </summary>
        public void SLPCMD()
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                var cmd = "SLP\r";
                serial.Write(binHelper.toBin<string>(cmd), cmd.Length);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// x,y,z平台初始化指令
        /// </summary>
        public void InitCMD()
        {
            try
            {
                var buff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                var msg = binHelper.toBin<string>("$X\r");
                serial.Write(msg,msg.Length);
                Thread.Sleep(50);
                serial.Read(ref buff, buff.Length);
                msg = binHelper.toBin<string>("G10 P0L20 X0.0Y0.0Z0.0\r");
                serial.Write(msg,msg.Length);
                Thread.Sleep(50);
                //机器初始化时,把当前位置设置为原点位置
                orgiPos = getAxisMacPosCMD();

                serial.Read(ref buff, buff.Length);
                msg = binHelper.toBin<string>("$ZL00418467\r");
                serial.Write(msg,msg.Length);
                Thread.Sleep(50);
                serial.Read(ref buff, buff.Length);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 解锁指令
        /// </summary>
        public void unlockCMD()
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                var msg = binHelper.toBin<string>("$X\r");
                serial.Write(msg,msg.Length);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        
        /// <summary>
        /// 所有轴停止运动
        /// </summary>
        public void axisStopCMD()
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");

        }

        /// <summary>
        /// 去原点指令
        /// </summary>
        public void goOrgiCMD()
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                var msg = binHelper.toBin<string>("G01 X0Y0Z0F20000\r");
                serial.Write(msg, msg.Length);
                
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 示教用x轴步进运动
        /// </summary>
        /// <param name="供给量"></param>
        /// <returns></returns>
        public void tMoveXCMD(int speed,bool isForward=true,  double 供给量= 0.08333)
        {
            //$J=G21G91X0Y0.08333Z0F500
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                if (!isForward) 供给量 = 供给量 * -1;
                string msg = string.Format("$J=G21G91X{0}Y0Z0F{1}\r",供给量, speed);
                var strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
                Stopwatch sw1 = new Stopwatch(); sw1.Start();
                while (true)
                {
                    Thread.Sleep(10);
                    var recvBuff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    serial.Read(ref recvBuff, 10);
                    if (binHelper.InBin(recvBuff, new byte[] { (byte)'o', (byte)'k' }) >= 0)
                        break;
                    if (sw1.ElapsedMilliseconds >2000) { break; }
                }
                sw1.Stop();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// <summary>
        /// 示教用y轴步进运动
        /// </summary>
        /// <param name="供给量"></param>
        /// <returns></returns>
        public void tMoveYCMD(int speed, bool isForward = true, double 供给量 = 0.08333)
        {
            //$J=G21G91X0Y0.08333Z0F500
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                if (!isForward) 供给量 = 供给量 * -1;
                string msg = string.Format("$J=G21G91X0Y{0}Z0F{1}\r", 供给量, speed);
                var strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
                Stopwatch sw1 = new Stopwatch(); sw1.Start();
                while (true)
                {
                    Thread.Sleep(10);
                    var recvBuff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    serial.Read(ref recvBuff, 10);
                    if (binHelper.InBin(recvBuff, new byte[] { (byte)'o', (byte)'k' }) >= 0)
                        break;
                    
                    if (sw1.ElapsedMilliseconds > 2000) { break; }
                }
                sw1.Stop();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 示教用Z轴步进运动
        /// </summary>
        /// <param name="供给量"></param>
        /// <returns></returns>
        public void tMoveZCMD(int speed, bool isForward = true, double 供给量 = 0.08333)
        {
            //$J=G21G91X0Y0.08333Z0F500
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                if (!isForward) 供给量 = 供给量 * -1;
                string msg = string.Format("$J=G21G91X0Y0Z{0}F{1}\r", 供给量, speed);
                var strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
                Stopwatch sw1 = new Stopwatch(); sw1.Start();
                while (true)
                {
                    Thread.Sleep(10);
                    var recvBuff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    serial.Read(ref recvBuff, 10);
                    if (binHelper.InBin(recvBuff, new byte[] { (byte)'o', (byte)'k' }) >= 0)
                        break;
                    if (sw1.ElapsedMilliseconds > 2000) { break; }
                }
                sw1.Stop();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool tMoveUCMD(int speed, bool isForward = true, double 供给量 = 0.018)
        {
            return true;
        }

        public bool helpCMD()
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                string msg = string.Format("$\r");
                var strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
               
                while (true)
                {
                    Thread.Sleep(10);
                    var recvBuff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    serial.Read(ref recvBuff, 10);
                    break;
                }
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 取轴的工作位置
        /// </summary>
        /// <returns></returns>
        public axisPosStruct getAxisWorkPosCMD()
        {
            axisPosStruct axispos = default(axisPosStruct);
            var macpos = getAxisMacPosCMD();
            axispos.x = macpos.x - orgiPos.x;
            axispos.y = macpos.y - orgiPos.y;
            axispos.z = macpos.z - orgiPos.z;
            axispos.u = macpos.u - orgiPos.u;
            return axispos;
        }

        /// <summary>
        /// 取轴的机器位置
        /// </summary>
        /// <returns></returns>
         public axisPosStruct getAxisMacPosCMD()
        {
            axisPosStruct axispos=default(axisPosStruct);
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
               
                string msg = string.Format("?\r");
                var strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
                Stopwatch sw1 = new Stopwatch(); sw1.Start();
                while (true)
                {
                    Thread.Sleep(10);
                    var recvBuff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                    serial.Read(ref recvBuff, recvBuff.Length);
                    if (binHelper.InBin(recvBuff, new byte[] { (byte)'P', (byte)'o', (byte)'s', (byte)':' }) >= 0)
                    {
                        var txt=Encoding.Default.GetString(recvBuff);
                        var ary1 = stringHelper.getMidString(txt, "MPos:", "|Bf:").Split(',');
                        if(ary1.Length==3)
                        {
                            axispos.x = double.Parse(ary1[0]);
                            axispos.y = double.Parse(ary1[1]);
                            axispos.z = double.Parse(ary1[2]);
                            axispos.u = 0;
                        }
                        break;
                    }
                    if (sw1.ElapsedMilliseconds > 2000) { sw1.Stop(); return axispos; }
                }
                sw1.Stop();
            
                return axispos;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// xy轴以指定速度移动到绝对位置
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="speed"></param>
        public bool goxyzCMD(double x, double y,double z, int speed)
        {
            if (!isInit()) throw new ArgumentException("运动模板没有初始化(或者没有初始化成功!)");
            try
            {
                //使用绝对坐标
                string msg = string.Format("G90\r");
                var strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
                //齐步走
                msg = string.Format("G1 X{0}Y{1}Z{2}F{3}\r",
                    x.ToString("0.000"), y.ToString("0.000"),z.ToString("0.000"), speed);
                strmsg = binHelper.toBin<string>(msg);
                serial.Write(strmsg, strmsg.Length);
                Stopwatch sw1 = new Stopwatch(); sw1.Start();
                while (true)
                {
                    Thread.Sleep(10);
                    var recvBuff = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                    serial.Read(ref recvBuff, recvBuff.Length);
                    if (binHelper.InBin(recvBuff, new byte[] { (byte)'o', (byte)'k' }) >= 0)
                        break;
                    if (sw1.ElapsedMilliseconds > 10000) { sw1.Stop(); return false; }

                }
                sw1.Stop();
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 运动控制类初始化成功标志
        /// </summary>
        /// <returns></returns>
        public bool isInit()
        {
            return isInitFlag;
        }

        /// <summary>
        /// 初始化运动控制类
        /// </summary>
        public void init()
        {
            try
            {
                serial = new CommPort(串口名称);
                serial.Open();
             
                示教点列表 = "";
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

    }
}


有空勇哥会把程序完善一下,写成一个tcp服务器的服务模块, 以方便视觉程序通讯调用.

目前只能用程序的调试运动功能来配合视觉模块做测试了.


--------------------- 

作者:hackpig
来源:
www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864