GSN前瞻预处理

news2024/9/20 15:33:20
在数控加工等应用中,要求数控系统对机床进行平滑的控制,以防止较大的冲击影响零件的加工质量。 运动控制器的前瞻预处理功能可以根据用户的运动路径计算出平滑的速度规划,减少机床的冲击,从而提高加工精度。 下面用一个实例来说明前瞻预处理的机制优势。假设机床要加工一个长方形的零件,刀具所走的轨迹 如图 7-17 (a) 所示。假设 m 点到 n 点距离 3000 个单位长度,有 30 段规划。 n 点到 p 点距离 2000 个单位长 度,有 20 段规划。每段规划 100 个单位长度。

如果按照图 7-17 (b) 所示的速度规划,即在拐角处不减速,则加工精度一定会较低,而且可能在拐弯 时对刀具和零件造成较大冲击。如果按照图 7-17 (c) 所示的速度规划,即在拐角处减速为 0 ,可以最大限度 保证加工精度,但加工速度就会慢下来。如果按照图 7-17(d) 所示的速度规划,在拐角处将速度减到一个合 理值,既可以满足加工精度又能提高加工速度,就是一个好的速度规划。 为了实现类似图 7-17 (d) 所示的好的速度规划,前瞻预处理模块不仅要知道当前运动的位置参数,还
要提前知道后面若干段运动的位置参数,这就是所谓的前瞻。例如在对图 7-17 (a) 中的轨迹做前瞻预处理 时,我们设定控制器预先读取 50 段运动轨迹到缓存区中,则它会自动分析出在第 30 段将会出现拐点,并依据用户设定的拐弯时间计算在拐弯处的终点速度。前瞻预处理模块也会依照用户设定的最大加速度值计 算速度规划,使任何加减速过程都不会超过这个值,防止对机械部分产生破坏性冲击力。 从下图 7-18 可以直观地了解,使用前瞻预处理功能模块来规划速度,在小线段加工过程中的对速度的 显著提升。前瞻预处理流程图如图 7-19 所示

 

(1) 用户在应用程序中定义一个结构体 TCrdData 的数组作为前瞻缓存区,数组大小用户自己设定,比如 数组大小为 200 ,那么前瞻缓存区长度 N=200 段;然后调用指令 GTN_InitLookAhead 作初始化前瞻。
(2) 用户调用如 GTN_LnXY 等直线插补指令和圆弧插补指令将数据段输入缓存区。这时,插补数据先流 入开辟的前瞻缓存区,当流入前瞻缓存区的数据段数大于了 N 之后,才能逐段流入运动缓存区。运动缓存区是控制器内部资源,大小 4096 段,每一段可以存放一条指令。控制器只能执行压入运动缓存 区中的数据,所以用户一定要确保前瞻缓存区的数据进入运动缓存区。分不同情况分析:
1) 假设用户数据只有 190 段,则当用户调用完后,数据会一直停留在前瞻缓存区,因此,用户需要 调用 GTN_CrdData (1, NULL, 0) 来将前瞻缓存区数据压入运动缓存区。
2) 假设用户数据只有 300 段,则当用户调用完后,有 100 段数据已经流入运动缓存区,但还有 200 段留在前瞻缓存区,同样,用户需要调用 GTN_CrdData (1, NULL, 0) 来将前瞻缓存区数据压入运 动缓存区。
3) 假设用户有数据 5000 段,则在用户调用插补指令过程中,会出现前瞻缓存区和运动缓存区都被
压满的情况,因此,需要注意,若一直压数据,没有启动插补运动,当压入第 4297 段时(前瞻 缓存区和运动缓存区一共 4296 段大小),由于两缓存区都满了,所以调用指令会返回1。此时 需要调用 GTN_CrdSpace 查询运动缓存区的空间,只有当查询到当前运动缓存区有空间时,才能 继续调用插补指令压入剩下的数据。同样,最后用户需要调用 GTN_CrdData (1, NULL, 0) 来将前 瞻缓存区数据压入运动缓存区。

   private void motionDO1_Click(object sender, EventArgs e)
        {
            // TCrdPrm结构体变量,该结构体定义了坐标系
            GTN.mc.TCrdPrm crdprm;
            short sRtn = GTN.mc.GTN_GetCrdPrm(1, 1, out crdprm);
            crdprm.dimension = 2;       // 坐标系为二维坐标系
            crdprm.synVelMax = 800;     // 最大合成速度:500pulse/ms
            crdprm.synAccMax = 8;       // 最大加速度:1pulse/ms^2
            crdprm.evenTime = 50;       // 最小匀速时间:50ms
            crdprm.profile1 = 1;        // 规划器1对应到X轴
            crdprm.profile2 = 2;        // 规划器2对应到Y轴
            crdprm.setOriginFlag = 1;   // 需要指定坐标系的原点坐标的规划位置
            crdprm.originPos1 = 0;      // 坐标系的原点坐标的规划位置为(100, 100)
            crdprm.originPos2 = 0;
            sRtn = GTN.mc.GTN_SetCrdPrm(1, 1, ref crdprm);
            Task.Run(LookAheadTest);

        }

        private static void LookAheadTest()
        {
            short sRtn;
            int space;

            GTN.mc.TCrdData[] crdData = new GTN.mc.TCrdData[200]; //前瞻缓冲区
            int[] posTest = new int[2];

            // 初始化坐标系1的FIFO0的前瞻模块
            sRtn = GTN.mc.GTN_InitLookAhead(
                1,                  //core
                1,                  //crd 
                0,                  //fifo
                5,                  //T          //拐弯时间
                7,                  //accMax 
                200,                //n
                ref crdData[0]);    // 定义前瞻缓存区内存区


            //压插补数据:小线段加工
            posTest[0] = 0;
            posTest[1] = 0;

            {
                sRtn = mc.GTN_LnXY(                            //向前瞻缓冲区冲写入数据共300段
                    1,                 //core
                    1,                 //crd
                    0 + posTest[0], //x
                    0 + posTest[1], //y
                    800,               //vel
                    6,               //acc
                    0,                 //velend
                    0);                //fifo

                if (0 != sRtn)
                {
                    do
                    {
                        // 查询运动缓存区空间,直至空间不为0
                        sRtn = GTN.mc.GTN_CrdSpace(1, 1, out space, 0);

                    } while (0 == space);
                    // 重新调用上次失败的插补指令
                    sRtn = GTN.mc.GTN_LnXY(1, 1, 0 + posTest[0], 0 + posTest[1], 800, 6, 0, 0);

                }


                posTest[0] = 3000000;
                posTest[1] = 0;
                sRtn = mc.GTN_LnXY(                            //向前瞻缓冲区冲写入数据第2段
                   1,                 //core
                   1,                 //crd
                   0 + posTest[0], //x
                   0 + posTest[1], //y
                   800,               //vel
                   6,               //acc
                   0,                 //velend
                   0);                //fifo

                if (0 != sRtn)
                {
                    do
                    {
                        // 查询运动缓存区空间,直至空间不为0
                        sRtn = GTN.mc.GTN_CrdSpace(1, 1, out space, 0);

                    } while (0 == space);
                    // 重新调用上次失败的插补指令
                    sRtn = GTN.mc.GTN_LnXY(1, 1, 0 + posTest[0], 0 + posTest[1], 800, 6, 0, 0);

                }

                posTest[0] = 3000000;
                posTest[1] = 3000000;
                sRtn = mc.GTN_LnXY(                            //向前瞻缓冲区冲写入数据第3段
                   1,                 //core
                   1,                 //crd
                   0 + posTest[0], //x
                   0 + posTest[1], //y
                   800,               //vel
                   6,               //acc
                   0,                 //velend
                   0);                //fifo

                if (0 != sRtn)
                {
                    do
                    {
                        // 查询运动缓存区空间,直至空间不为0
                        sRtn = GTN.mc.GTN_CrdSpace(1, 1, out space, 0);

                    } while (0 == space);
                    // 重新调用上次失败的插补指令
                    sRtn = GTN.mc.GTN_LnXY(1, 1, 0 + posTest[0], 0 + posTest[1], 800, 6, 0, 0);

                }


                posTest[0] = 0;
                posTest[1] = 3000000;
                sRtn = mc.GTN_LnXY(                            //向前瞻缓冲区冲写入数据第4段
                   1,                 //core
                   1,                 //crd
                   0 + posTest[0], //x
                   0 + posTest[1], //y
                   800,               //vel
                   6,               //acc
                   0,                 //velend
                   0);                //fifo

                if (0 != sRtn)
                {
                    do
                    {
                        // 查询运动缓存区空间,直至空间不为0
                        sRtn = GTN.mc.GTN_CrdSpace(1, 1, out space, 0);

                    } while (0 == space);
                    // 重新调用上次失败的插补指令
                    sRtn = GTN.mc.GTN_LnXY(1, 1, 0 + posTest[0], 0 + posTest[1], 800, 6, 0, 0);

                }

                posTest[0] = 0;
                posTest[1] = 0;
                sRtn = mc.GTN_LnXY(                            //向前瞻缓冲区冲写入数据第5段
                   1,                 //core
                   1,                 //crd
                   0 + posTest[0], //x
                   0 + posTest[1], //y
                   600,               //vel
                   5,               //acc
                   0,                 //velend
                   0);                //fifo

                if (0 != sRtn)
                {
                    do
                    {
                        // 查询运动缓存区空间,直至空间不为0
                        sRtn = GTN.mc.GTN_CrdSpace(1, 1, out space, 0);

                    } while (0 == space);
                    // 重新调用上次失败的插补指令
                    sRtn = GTN.mc.GTN_LnXY(1, 1, 0 + posTest[0], 0 + posTest[1], 800, 6, 0, 0);

                }
                
               
            }

            // 将前瞻缓存区中的数据压入控制器
            IntPtr crdDataNULL = new IntPtr();
            sRtn = GTN.mc.GTN_CrdData(1, 1, crdDataNULL, 0);

            // 启动运动
            sRtn = GTN.mc.GTN_CrdStart(1, 1, 0); //mask bit0 对应坐标系 1,bit1 对应坐标系 2,0:不启动该坐标系,1:启动该坐标系。

        }

拐弯时间 (T)
GTN_InitLookAhead 指令的第三个参数,单位: ms T 的经验范围是: 1ms~10ms , T 越大,计算出来的终点速度越大,但却降低了加工精度;反之,提高了加工的精度,但计算出 的终点速度偏低。因此要合理选择 T 值。
最大加速度 (accMax)
GTN_InitLookAhead 指令的第四个参数,单位: pulse/ms2 。系统能承受的 最大加速度,根据不同的机械系统和电机驱动器取值不同。
前瞻缓存区 (pLookAheadBuf)
前瞻缓存区是用户在应用程序中自己定义的,用于存放描述运动轨 迹的数组。用户应根据自己的需要以及计算机的条件定义合适的缓存区大小,并且要在 GTN_InitLookAhead 指令的第五个参数中说明数组的大小
运动缓存区:插补缓存区是运动控制器内部专门用于插补运动的缓存区资源,大小 4096 段,每
一段可以放一条指令。 当前瞻缓存区的段数不为 0 时,用户调用缓存区指令传递的插补数据先进入前瞻缓存区,当前瞻 缓存区放满之后,如果再有新的数据传入,最先进入前瞻缓存区的数据,则会进入插补缓存区。 如果用户所有的插补数据已经输入完毕,前瞻缓存区中还有数据没有进入插补缓存区,这时,需 要调用 GTN_CrdData (1, NULL, 0) ,运动控制器会将前瞻缓存区的数据依次传递给插补缓存区, 直到前瞻缓存区被清空为止。 在数据量比较大的时候,用户需要配合 GTN_CrdSpace 指令查询插补缓存区的剩余空间,在有空 间的时候再调用缓存区指令传递数据,如果插补缓存区已满,调用缓存区指令将会返回错误,说 明该段插补数据没有输入成功,需要再次输入该段插补数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/22132.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文了解Spring MVC(上)

目录 什么是Spring MVC 什么是MVC Spring MVC 和MVC的区别 怎么学Spring MVC Spring MVC的创建和连接 RequestMapping注解 获取参数 传递基础数据类型/包装类型(无注解) 添加RequestParam注解(使用在方法参数上) 传递自…

python——GIL锁详解

文章目录一、GIL全局解释器锁二、为什么会有GIL锁?三、多线程无法利用多核优势?计算密集型和IO密集型计算密集型——采用多进程计算密集型——采用多线程IO密集型——采用多进程IO密集型——采用多线程四、总结一、GIL全局解释器锁 1、GIL锁不是python的…

C语言 数据的存储

C语言 数据的存储一、数据与进制之间的关系1. 十进制与二进制之间的转换2. 二进制与十六进制之间的转换二、整型数据存储1. 原、反、补码2. 整型数据在内存中的存储3. 为什么整型数据存在内存中存储的是补码4. 有符号和无符号的数据类型有符号和无符号的存储范围猜想5. 关于 ch…

Java项目:SSH企业人力资源管理系统

作者主页:源码空间站2022 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 企业人力资源管理系统,分为超级管理员与普通管理员两种角色,超级管理员可以对普通管理员进行添加、删除等操作; 超级管理…

【k8s】1、基础概念和架构及组件

文章目录一、kubernetes概述1、什么是kubernetes?2、应用程序部署方式的演变3、为什么要用kubernetes?二、kubernetes 特性三、Kubernetes集群架构与核心组件1、master组件1.1 kube-apiserver(中央枢纽)1.2 kube-controller-manag…

股价下跌18%后,满帮集团(YMM)的财务业绩正在加速放缓

来源:猛兽财经 作者:猛兽财经 市场与竞争 根据Beroe Advantage Procuremen的一份市场研究报告,2020年中国道路运输服务市场的规模估计为250亿美元。 这意味着这个行业近年来的复合年增长率为6.5%。 物流参与者往往集中在中国的西南和中南部地…

.NET跨平台框架选择之一 - Avalonia UI

1. Avalonia UI简介 Avalonia UI文档教程:https://docs.avaloniaui.net/docs/getting-started 随着跨平台越来越流行,.NET支持跨平台至今也有十几年的光景了(Mono开始)。 但是目前基于.NET的跨平台,大多数还是在使用B/S架构的跨平台上&…

数据分析面试重点

2022年10月求职季,疫情的影响,但是也挡不住各位小伙伴,找工作的热情。目前,数据分析行业大火,相信很多小伙伴都想去这一行业试试水。想要成功进入数据分析行业,就必须得通过数据分析面试,面试的…

计控实验(二)——积分分离PID控制实验

太原理工大学计算机控制技术实验之积分分离PID控制实验 积分分离PID控制实验实验原理实验内容实验结果思考题实验原理 上图是一个典型的PID 闭环控制系统方框图,其硬件电路原理及接线图可设计如下,图中画“○”的线需用户在实验中自行接好,对…

跟艾文学编程《Python基础》PyCharm 安装

作者:艾文,计算机硕士学位,企业内训讲师和金牌面试官,公司资深算法专家,现就职BAT一线大厂。 邮箱:1121025745qq.com 博客:https://edu.csdn.net/lecturer/894?spm1003.2001.3001.4144 内容&am…

[附源码]java毕业设计文具销售系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

6、子查询 、having、(not) exists、表中增加一列并补充数据、删除表中对应的数据-mysql

目录子查询一、需求分析与问题解决1、实际问题2、子查询的基本使用3、子查询的分类二、单行子查询1、单行比较操作符2、 代码示例3、HAVING 中的子查询4、CASE中的子查询5、 子查询中的空值问题6、 非法使用子查询三、多行子查询1、多行比较操作符2、代码示例3、空值问题四、 相…

《Flowable流程引擎从零到壹》Flowable流程引擎介绍和实战项目初始化流程引擎实例

14天学习训练营导师课程: 邓澎波《Flowable流程引擎-基础篇【2022版】》 邓澎波《Flowable流程引擎-高级篇【2022版】》 学习笔记《Flowable流程引擎从零到壹》回城传送 ❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。Java领域优质创…

mysql中的这些日志,你都知道吗?

在使用mysql的过程中,经常会听到mysql具有数据恢复能力,当我们在业务开发中误删了某些数据后,可以将数据库恢复到误删之前的状态。同时还具有故障恢复能力,当数据库所在的机器突然掉电停机后,mysql也可以保证数据一致性…

Java8 Stream 的核心秘密

小伙伴们好呀,我是 4ye,今天来分享下 Java8 Stream 的源码 核心回顾 stream 是一次性的,不是数据结构,不存储数据,不改变源数据.。API 分为终端和中间操作,中间操作是惰性的,碰到终端才去执行。…

python自动化测试

测试软件:pycharm 解释器版本:3.10.7 测试浏览器:谷歌 或 edge 谷歌web驱动下载地址:chromedriver.storage.googleapis.com/index.html edgeweb驱动下载地址:Microsoft Edge WebDriver - Microsoft Edge Developer 第一…

免费查题接口系统后台

免费查题接口系统后台 本平台优点: 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库: 查题校园题库:查题校园题库后台(点…

零基础自学javase黑马课程第十三天

零基础自学javase黑马课程第十三天 ✨欢迎关注🖱点赞🎀收藏⭐留言✒ 🔮本文由京与旧铺原创,csdn首发! 😘系列专栏:java学习 💻首发时间:🎞2022年11月7日&…

springboot视图渲染技术

目录 一、Freemarker简介及入门 二、Freemarker语法 1、取值 1.1默认值 1.2 对null值进行判断 2、条件 3、循环 4、include 5、 局部变量(assign)/全局变量(global) 一、Freemarker简介及入门 学习网址:什么是 FreeMarker? - FreeMarker 中文官方参考手册 …

2022强网拟态pwn-webheap

2022强网拟态pwn-webheap 这题的逻辑是一开始笔者硬逆给逆出来了,但是后面在Ex师傅的点播下成功的在github上找到了这个的原生项目 https://github.com/google/libnop 在审计的过程中发现了至关重要的信息,发现和逆向的格式一样的东西,就是…