快速入门 | 篇十五:运动控制器运动缓冲简介

之前正运动技术与大家分享了,运动控制器的固件升级、zbasic程序开发、zplc程序开发、与触摸屏通讯和输入/输出io的应用、运动控制器数据与存储的应用、运动控制器zcan、ethercat总线的使用、示波器的应用、多任务运行的特点、运动控制器中断的应用、u盘接口的使用、zdevelop 编程软件的使用以及运动控制器的基础轴参数与基础运动控制指令等。
今天,我们来讲解一下正运动技术运动控制器运动缓冲。
视频教程:http://www.zmotion.com.cn/video/yemian/tvideos22.html
以下是图文详解
01 材料准备与接线参考
02运动缓冲
1.运动缓冲原理
在运行运动指令时,为了防止程序堵塞,控制器提供了一个缓冲区来保存进入运动缓冲的运动缓冲队列,把这个功能叫做运动缓冲,这样程序就能正常向下扫描,不会堵塞。
zmotion运动控制器具有多级的运动缓冲,当运动缓冲开启的时候,程序在扫描识别到程序任务的第一条运动指令时,将运动指令分配到指定轴的运动缓冲区,电机开始运动,此时程序继续向下扫描到第二条运动指令时,再往运动缓冲区中存,在不断扫描存入运动指令的同时,从运动缓冲区中依次取出运动指令执行。
mtype,ntype分别是当前运行的运动指令和第一个缓冲运动指令。
任意一段程序的运动指令都可以进入任意轴的运动缓冲区,由轴号指定。
每个轴的运动缓冲区都是独立的,互不干扰。
缓冲多条运动指令时,为了判断当前运动执行到哪一条,提供move_mark运动标号和move_curmark当前运动标号指令。move_mark运动标号每扫描一条运动指令+1;move_curmark指令为当前运动的标号,提示当前运动到第几条运动指令,所有运动完成后为-1。
当前运动完成后会自动执行运动缓冲区内的下一条运动。运动指令全部执行完后,运动缓冲区为空,或者使用cancel/rapidstop指令清空运动缓冲区。
sp指令也属于运动指令,使用sp运动指令(如movesp、movecircsp等直接在运动指令后方加上sp)时,sp速度force_speed、endmove_speed和stratmove_speed会随sp运动指令写入运动缓存区。
sp运动指令与运动指令的区别:
move(100)的速度是speed=100,movesp(100)的速度是force_speed=200。
2.运动缓冲区堵塞
每个轴的运动缓冲空间是有限的,当扫描太多运动指令放入运动缓冲区时,多级运动缓冲区全部被塞满,如果程序继续扫描到更多的运动指令,程序也会被堵塞,直到运动指令依次完成并退出,运动缓冲区有了空位,运动指令才会继续进入运动缓冲区。
例:以v3.10版本仿真器为例,默认为4096个运动缓冲,下图例程中显示该控制器的运动缓冲区最多能存459条圆弧插补指令,下载程序后后打印i的值为458,表示当前for循环并未执行完,程序堵塞了。
下图中,当从运动缓冲区取出部分运动指令执行之后,缓冲区有了空间,for循环继续执行,并存入运动指令到运动缓冲区。指令执行退出运动缓冲区后,只要运动缓冲区的空间够,新的运动指令一条条往运动缓冲区中存。
每个轴的运动缓冲都是独立的,互不干扰,且缓冲区大小相同,通过指令remain_buffer(mtype) axis(n)查看某个轴的剩余可用缓冲区的个数。
zmc4系列运动控制器每个轴可支持多达4096段运动缓冲(不同型号的控制器缓冲个数有区别,具体情况参见控制器硬件手册说明或使用?*max打印查看),可以手动设置limit_buffered运动缓冲限制。
不同的运动指令占用的缓冲空间是不同的,越复杂的运动占用的运动缓冲空间越多。
例如:
zmc432控制器,运动缓冲区大小为4096,缓冲区一次性可缓冲的move直线插补指令和movecirc圆弧插补指令个数是不同的。
插补运动缓冲在主轴的运动缓冲区。
3.运动缓冲例程
rapidstop(2)
wait idle(0)
wait idle(1)
base(0,1)
atype=1,1
units=100,100
speed=100,100
accel=1000,1000
decel=1000,1000
dpos=0,0
merge=off     '关闭连续插补
trigger
limit_buffered=3     '轴0/1运动缓冲区可缓冲运动指令个数设为3
move(60,40     '进入mtype,buffer0
move(70,50)     '进入ntype,buffer1
move(50,40)     'buffer2
move(60,50)     '缓冲区满,暂不进入
?轴0当前缓冲指令个数= moves_buffered(0)     '结果2
?轴0剩余缓冲区个数= remain_buffer(1) axis(0)     '结果0
?轴1剩余缓冲区个数= remain_buffer(1) axis(1)     '结果3
end
将轴的运动缓冲区可缓冲运动指令个数限制为3,此时运动缓冲区最多能装3条直线插补指令。
共有4个直线插补指令,move(60,40)占用轴0的mtype,轴0还能缓冲2个运动指令,轴0剩余缓冲数为0,且还有1条直线指令因为主轴轴0的运动缓冲区已满,还未进入运动缓冲区。
等到move(60,40)运动完成,move(60,50)才能进轴0的运动缓冲区。
插补运动缓冲在主轴轴0里,故轴1的运动缓冲区是没有指令的,剩余缓冲大小为3。每条move指令占用一个缓冲空间。
4.普通输出与运动缓冲中输出的区别
普通输出指令程序扫描到该行指令便执行输出。
运动缓冲中输出指令在程序扫描之后,将其存入运动缓冲区,运动缓冲区按先进先出的顺序依此取出指令执行,直到取出该输出指令时才会执行输出。
rapidstop(2)
wait idle(0)
base(0)         '选择轴0
dpos=0
units=100     '脉冲当量
speed=100     '速度
accel=1000     '加速度
decel=1000     '减速度
trigger     '触发示波器采样
op(0,3,$0)     '关闭输出口0-3
delay(1000)     '延时
move(100)
move_op(1,on)     '运动缓冲中输出
op(0,on)     '普通输出
例子运行效果:延时1s之后,程序扫描到op指令,输出口0立即执行输出。
move_op把io操作指令填入运动缓冲区,所以在运行完move(100)之后,输出口1才输出。
03 运动缓冲相关指令
1.move_op -- 缓冲输出
语法:move_op (输出编号,输出状态)
此指令随其他运动指令一起进入运动缓冲区,从运动缓冲区中取出执行时才操作op输出,可以控制某个输出口单独输出信号,也可以批量输出,不会打断插补运动的连续性。
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=on    '开启连续插补
trigger     '自动触发示波器
op(0,3,0)     '关闭输出口0-3
move(100)
move_op (0,on)     '等待上条运动完成后,out0输出信号
move(100)
move_op (0,off)     '等待上条运动完成后,out0关闭信号
move_op(1,3,5)     '批量输出,out1,3输出信号,out2不输出,5对应二进制101
例子运行效果:第11-15行的运动指令依此存入运动缓冲区,按先进先出的顺序执行,move(100)运动完后,move_op操作out0输出,继续执行第二个move(100),然后move_op操作out0关闭,紧接着控制out1-3批量输出。
2.move_op2 -- 缓冲输出2
语法:move_op2(输出编号,输出状态,输出多少ms后翻转)
base轴运动缓冲加入一个输出口操作,指定时间后输出状态翻转。
此指令随其他运动指令一起进入运动缓冲区,从运动缓冲区中取出执行时才操作op输出,保持输出一定时间后关闭输出。
单个轴同一时间只支持一个脉冲输出,第二个move_op2指令会自动关闭前面指令的脉冲。不会打断插补运动的连续性。
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
dpos=0
speed=200
accel=1000
decel=1000
merge=on '开启连续插补
op(0,off) '关闭out0口
trigger '自动触发示波器
move(500)
move_op2 (0,on,1000) '等待上条运动完成,输出口0保持输出1s后关闭,输出时不会阻碍下一条运动执行
move(-300)
3.move_delay -- 缓冲延时
语法:move_delay(延时ms数)
base轴运动缓冲加入一个延时。
这个指令缓冲执行时不做任何运动,只延时指定时间。
延时使前面的运动指令结束时速度会自动降为0,会打断插补运动的连续性。‍
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
speed=100
accel=1000
decel=1000
dpos=0
merge=on '开启连续插补
trigger '自动触发示波器
move(100)
move_delay(500) '两个move中间等待500ms
move(200)
4.move_aout -- 缓冲输出模拟量
语法:move_aout(da编号,输出值)
base轴运动缓冲加入一个aout指令。
这个指令缓冲执行时不做任何运动,只修改aout值,不会打断插补运动的连续性。
// 例子
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
speed=100
accel=1000
decel=1000
dpos=0
merge=on '开启连续插补
aout(0)=0 'da0通道赋值0
trigger '自动触发示波器
move(200)
move_aout(0, 30.5) '第一个运动完成后,将da0通道赋值30.5
move(200)
5.move_pause——运动暂停
暂停轴运动,只有在单轴或多轴插补运动时有效,多轴联动时一起暂停。
可以通过axisstatus来查询是否有暂停,暂停中轴的idle状态为0。
当轴已经暂停或不在运动中时,调用这个指令会有警告输出,但不影响程序运行。某些运动不支持暂停,如vmove、同步运动指令等。
语法:move_pause(模式值)
模式值0例子:move_pause(3)的执行效果与move_pause(0)类似。
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
speed=100
accel=1000
decel=1000
dpos=0
merge=on '开启连续插补
move(100) '当前运动
move(200)
move_pause(0) '暂停当前运动
delay(1000)
?dpos(0) '打印结果:0,此时当前运动只运行了极短时间,扫描到move_pause时直接暂停
模式值1例子:模式2在运动标号move_mark自动编号时效果与模式1类似,因为每条运动的标号都是不同的,运动完一条运动指令后,运动标号发生改变,move_mark(2)生效,立即暂停。
模式2在手动设置move_mark时才与模式1不同。
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
speed=100
accel=1000
decel=1000
dpos=0
merge=on     '开启连续插补
trigger     '自动触发示波器
move(100)     '当前运动
move(200)
move_pause(1)     '当前运动运行完暂停
delay(2000)
?dpos(0)     '打印结果:100
move_pause(1)或move_pause(2)
模式值2例子:手动设置move_mark,通过move_pause(2)指令可以在mark不同的边界处暂停。
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=on
trigger
move_mark =1 '设置为标号1
move(100)
move_mark =1 '设置为标号1
move(150)
move_mark =2 '设置为标号2
move(200)
move_pause (2) '标号不一样时暂停
delay(5000)
?dpos(0) '打印结果:250
move_pause(2)
6.move_resume -- 运动恢复
当base轴暂停暂停时,从暂停处继续运动。
可以通过axisstatus来查询是否有暂停,axisstatus显示800000h,表示轴进入了暂停状态。
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=on
trigger
move(100)     '当前运动
move(200)     '缓冲运动
move_pause(1)     '当前运动完成后暂停
delay(2000)     '等待当前运动完成
?dpos(0)     '打印结果:100
move_resume     '继续运行
wait idle(0)
?dpos(0)     '打印结果:300
7.move_table -- 缓冲输出table
base轴运动缓冲加入一个table。
指令缓冲执行时不做任何运动,只修改table,不会打断插补运动的连续性。
语法:move_table(table编号, 要修改的值)
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=on
table(0)=0     '初始值设为0
trigger         '自动触发示波器
move(100)
move_table(0, 60)         '等待运动完成后,table(0)赋值60
move(160)
wait idle(0)
?table(0)         '打印修改后table(0)的值,打印结果,60
轴0运动100后,table(0)赋值60
8.move_para -- 缓冲参数
base轴运动缓冲修改参数。
这个指令缓冲执行时不做任何运动,只修改参数,不会打断插补运动的连续性。
语法:move_para(参数名,参数编号,参数值)
参数名必须是?*set里面的非只读参数。
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
speed=100 '初始速度
accel=1000
decel=1000
dpos=0
merge=on '开启连续插补
trigger '自动触发示波器
move(200) '速度100
move_para(speed,0,200) '修改轴0的speed参数值为200
move(200) '速度200
wait idle(0) '等待轴0停止
?speed '打印结果:200
9.move_pwm -- 缓冲pwm
base轴运动缓冲操作pwm。
指令缓冲执行时不做任何运动,只操作pwm。
pwm只能通过设置占空比为0来关闭,不能通过设置pwm频率为0实现,pwm频率一定要在pwm开启之前调整。
语法:move_pwm(编号,占空比[,频率])
编号为支持pwm功能的输出口编号,查看硬件手册确认。
占空比指有效电平占整个周期的比例;范围0-1,设置0时关闭pwm;一个周期中先输出有效电平,再输出无效电平。
频率缺省为1khz,硬件最大为1mhz,软件最大为2khz。
rapidstop(2)
wait idle(0)
move_pwm(0, 0, 1000)     '关闭pwm
base(0)
atype=1
units=100
speed=100 '初始速度
accel=1000
decel=1000
dpos=0
ticks = 10000
move(10)
move_pwm(0, 0.111, 2000)     '轴0运行到10时,操作pwm0输出
move_delay(100)
move_pwm(0, 0.555, 3000) '延时100ms,修改pwm0输出
move(20)
move_pwm(0, 0, 1000)     '关闭pwm
while not idle(0) 'idle(0)=-1后退出while循环
    ? -ticks,pwm_duty(0),pwm_freq(0)
    delay(30)
wend
例子运行效果:初始化关闭pwm输出,move(10)运动完后,操作pwm0输出,保持100ms之后,修改pwm0输出的占空比和频率,再运行move(20)后关闭pwm输出。while循环在轴0运行时,每隔30ms打印一次pwm输出的占空比和频率,在轴0停止后,退出while循环,不在打印。
10.move_synmove -- 缓冲触发其他轴
base轴运动缓冲触发其他轴运动,当前轴等待,等待其他轴运动完成,当前轴才继续运动。
语法:move_synmove(axisnum,dis[,ifsp])
axisnum:需要同步运动的轴号
dis:相对运动距离
ifsp:是否使用sp运动, 缺省值0不使用,设为其他值使用
rapidstop(2)
wait idle(0)
wait idle(1)
base(0,1)
dpos=0,0
atype=1,1
units=100,100
speed=100,100
accel=1000,1000
decel=1000,1000
merge=on,on
trigger
move(100)
move_synmove(1,120,0)     '轴0运行到100时,轴1开始运动120
move(100)     '待轴同步完成,轴0再继续运动
使用sp运动后的效果如下,将最后一位参数设置非0值 ,此时触发轴1的运动速度为force_speed=200。
11.move_asynmove -- 缓冲触发其他轴2
base轴运动缓冲触发其他轴运动,当前轴不等待,仍继续运动。
语法:move_asynmove(axisnum,dis[,ifsp])
axisnum:需要同步运动的轴号
dis:相对运动距离
ifsp:是否使用sp运动, 缺省值0不使用,设为其他值使用
rapidstop(2)
wait idle(0)
wait idle(1)
base(0,1)
dpos=0,0
atype=1,1
units=100,100
speed=100,100
accel=1000,1000
decel=1000,1000
merge=on,on
trigger
move(100)
move_asynmove(1,120,0) '轴0运行到100时,轴1开始运动120
move(100) '待轴同步完成,轴0再继续运动
12.move_task -- 缓冲开启任务
base轴运动缓冲加入启动task。
这个指令缓冲执行时不做任何运动,只启动任务,不会打断插补运动的连续性。
语法:move_task(任务号, 函数名)
从运动缓冲全区取出move_task指令执行时,将task_move标记的程序作为任务1开启,在任务窗口可以看到任务1已启动。
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=on
trigger
move(100)
move_task(1,task_move)     '第一个运动完成后,将task_move作为任务1启动
move(100)
end
'任务1
task_move:
      print task_move
end
13.move_wait -- 缓冲等待
base轴运动缓冲加入一个条件判断。
指令缓冲执行时不做任何运动,只等待指定的条件满足,前面的运动指令结束时速度会自动降为0。
语法:move_wait(参数名, 参数编号, 比较条件, 比较值)
参数可以为:dpos,mpos,in,ain,vpspeed,mspeed,modbus_reg,modbus_ieee,modbus_bit,vector_buffered,remain
比较条件:1 参数值≥比较值;-1 参数值≤比较值;0 不建议使用
rapidstop(2)
wait idle(0)
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
trigger
move(100)
move_wait(in, 0, 1, 1) '等待in(0)有信号,才执行下一条运动
move(100)
14.move_cancel--缓冲停止
把cancel指令写入运动缓冲。
语法:move_cancel(轴号,模式值)
      0:取消当前运动,继续取缓冲区指令指令
      1:取消缓冲区的运动,当前运动仍然要执行完
      2:取消当前运动和缓冲区的运动,轴立即停止
      3:立即中断脉冲的发送
rapidstop(2)
wait idle(0)
wait idle(1)
base(0,1)
dpos=0,0
atype=1,1
units=100,100
speed=100,100
accel=1000,1000
decel=1000,1000
merge=on,on:
trigger
move(50) axis(0)     '轴0当前运动
move(80) axis(1)     '轴1当前运动
move_cancel(1,2) axis(0)     '轴0缓冲里面写入停止轴1的指令
move(60) axis(0)     '轴0缓冲运动
move(70) axis(1)     '轴1缓冲运动,被取消
例子运行效果:轴0运动50后,move_cancel(1,2) axis(0)指令生效,cancel(2)模式取消轴1的当前运动和缓冲运动,轴1立刻停止,轴0继续运动。
15.loaded -- 缓冲空
用于判断轴的运动缓冲区是否为空,只读参数,返回值0表示运动缓冲区还有指令,返回值为-1表示运动缓冲区空。
base(0)
atype=1
units=100
speed=100
accel=1000
decel=1000
dpos=0
merge=on         '开启连续插补
op(0,off)
trigger
move(100)         '当前运动
move(50)             '缓冲运动,此时缓冲区只有这一条运动
                              '当本条运动执行时,缓冲区就已经清空
wait loaded     '运动缓冲空即可往下执行
op(0,on)             '打开op0
wait loaded 等待缓冲区空
wait idle 等待轴停止
16.move_mark -- 运动标号
下一条要调用的运动指令的mark标号,这个标号会和运动指令一起写入运动缓冲。
每调用一条运动指令,move_mark会自动加一。
如果要强制指定move_mark,需要每次运动前都设定一次。
通过move_pause (2)指令可以在mark不同的边界处暂停。
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=off     '关闭连续插补
op(0,off)
trigger
move_mark=0     '初始值:0
move(100)             '运动指令1
move_delay(1000)     '运动指令2
move(50)     '运动指令3
move_op(0,on)     '运动指令4
move(80)     '运动指令5
print move_mark     '打印结果:5
17.move_curmark -- 当前运动标号
返回当前轴正在运动指令的move_mark标号,编号默认从0开始,到运动指令总数减1。
在轴参数窗口可以监控当前程序扫描到的运动指令个数,查看move_mark;和轴当前运行到了第几个运动指令,查看move_curmark。
base(0)
atype=1
units=100
dpos=0
speed=100
accel=1000
decel=1000
merge=on
op(1,off)
trigger
move_mark =1
move(50)
move_mark =2
move(100)
move_mark =3
move(150)
wait until move_curmark = 2 '等待move(100)开始执行的时候,开输出口1
op(1,on)

人工智能小冰有什么不同
第三方兼容性模块和原装模块的区别是什么
心脏病学的新纪元 机器学习助力修复受损的心脏
断路器是如何工作的
各国发力氢能源汽车发展进入加速阶段
快速入门 | 篇十五:运动控制器运动缓冲简介
SMT贴片的概念是怎样
光伏太阳能板—晶硅片的介绍
盐水电池制作方法
英创ETA108波形数据采集模块性能及使用
一文读懂ametal_hc595接口的学习要点
Directive Games解读ARKit 2.0带来的AR游戏可能性
如何让智慧灯杆在城市管理中发挥优势
关于Deterministic ICE的介绍和研究
葡萄牙用户就苹果降频门发起集体诉讼
加速建设迎接5G商用 北京联通5G畅快体验
中科研究院完成了压缩空气弹射器在无人机中的应用测试
小体积三相四线智能电表的电源解决方案
有关CDMA的术语
四声道环绕的发展历程