查看: 904|回复: 7
收起左侧

【视学课堂】如何使用编码器,实现物料的高效定位?

邀请回答

马上注册,享受更多特权

您需要 登录 才可以下载或查看,没有帐号?立即注册   

x
作者:kane
背景
在试机检测项目中可能遇到来料位置、数量、角度均不确定的情况,此时若想对每一个来料实现检测较为困难,以下介绍一种可行的处理方式。
适用的情况
主要适用以下两种情况:
1、来料位置、数量、角度均不确定,发送的检测数据不能重复
如下图所示,水平向右运动的皮带上存在位置不确定的物料,实线物料为本次相机拍照物料所处的位置,虚线物料为上一次拍照物料所处的位置。假设在相机视野范围内需要检测的物料信息均可准确的采集到,此时将会出现同一个物料数据采集了多次的情况,如果我们将数据全部发送给接收设备,可能将导致接收设备收到重复的数据进而出现错误。
1.png
2、来料位置、数量、角度均不确定,在视野中不同的位置需进行不同的检测
如下图所示,假设视野分为3个区域(可以是单个相机也可以是多个相机):左右两边因为可以拍到物料侧面,需要检测物料侧面的信息;中间区域正对相机,需要准确识别到物料的位置信息。在这种情况下,我们需要在3个不同的区域且3个不同的时间内对同一个物料实现检测,如何将数据统一是件比较困难的事情。
2.png
具体的实现方式
每次拍照时,均获取拍照时的编码器计数。当输送带向前运动时,由于物料相对于输送带静止不动,每个物料对应的编码器数值会根据输送带移动的距离产生变化。
3.png
针对上述的第一种情况,此刻只需判断本次正在检测的物料于上次是否已经进行了检测,本质是一个数据去重的功能,具体的实现方法为:
4.png
如上图所示,虚线物体为第一次产品的位置,实线物体为第二次产品的位置。假设第一次识别到的位置坐标(机械坐标)为x1:[x11,x21,…],y1:[y11,y21,…],对应的编码器数值为d1,识别到的产品个数为n1;第二次识别到的位置坐标(机械坐标)为x2:[x12,x22,…],y2:[y12,y22,…],对应的编码器数值为d2,识别到的产品个数为n2,编码器分辨率为f。
那么,由以上数据即可得到产品第二次被识别到的位置坐标以及编码器数值的变化量,由此来推算出每个产品上一次拍照的位置,再将推算出的数据与保存的上一次检测的数据做对比,将其中重复的数据去除,余下的数据即为有效数据。脚本执行流程如下:
5.png
第二种情况与第一种类似,只需要根据本次拍照信息推算出之前每次拍照物料的位置坐标,并判断是否需要对数据进行更新即可。
假设本次拍照检测到的数据为:
bencishuju=[
[(10,20),200,1,[1,1],1],#(位置10,20 编码器数值100 数据1:1数据2:(1,1)数据3:1)
[(20,20),200,2,[2,1],1] #(位置20,20 编码器数值100 数据1:1数据2:(2,1)数据3:1)
]
结果数据为
jieguo=[
[(0,11),100,1,1,[1,1],1], #(位置10,20 编码器数值100 数据有效:1数据1:1数据2:(1,1)数据3:1)
[(10,11),100,0,1,[2,1],1] #无效数据
[(10,11),100,0,1,[2,1],1] #无效数据
[(10,11),100,0,1,[2,1],1] #无效数据
[(10,11),100,0,1,[2,1],1] #无效数据
]
由本次检测数据中的编码器数值和结果数据中的编码器数值推算出当前物品在结果数据编码器数值时对应的虚拟绝对坐标,并判断是否处于同一个位置。如若未处于同一位置,则需要对数据进行更新;若未找到对应的数据,则需要在结果数据组中找到空闲的位置,并将检测数据放入其中。脚本执行流程如下:
6.png
总结
利用编码器数值变化来推算物品坐标的方法,解决了随机来料检测困难的问题,相对于原有的切图检测的方式来说,稳定性更高并且更加准确,且不会受到客户产线速度改变与重复启停的影响。
示例
数据去重:
#本张图片去重判断
for i in range(geshu):
    for j in range(geshu-i-1):
        if abs(fasongx-fasongx[i+j+1])<qucongx:
            flagx[i+j+1]=0      
for i in range(geshu):
    for j in range(geshu-i-1):
        if abs(fasongy-fasongy[i+j+1])<qucongy:
            flagy[i+j+1]=0
#与上次拍照去重
flagshangx=range(geshu)
flagshangy=range(geshu)

#初始化
for i in range(geshu):
    flagshangx=1
    flagshangy=1
for i in range(shangcigeshu):
    for j in range(geshu):
        if abs(fasongx[j]-abs(shangcibianmaqi-bianmaqi)*fendu-shangcix)<qucongx:
            flagshangx[j]=0
kl=abs(fasongx[j]-shangcix)
for i in range (shangcigeshu):
    for j in range(geshu):
        if abs(shangciy-fasongy[j])<qucongy:
            flagshangy[j]=0
#去重整合
flagzhenghe=range(geshu)
#初始化
for i in range(geshu):
    flagzhenghe=1
for i in range(geshu):
    if (flagx|flagy|(kaiguanb==0))&(flagshangx|flagshangy|(kaiguans==0)):
        flagzhenghe=1
    else:
        flagzhenghe=0
#重点显示
diancong=range(geshu)
dianzheng=range(geshu)
for i in range(geshu):
    if (flagx|flagy|(kaiguanb==0))&(flagshangx|flagshangy|(kaiguans==0)):
        dianzheng[dz]=(x,y)
        dz=dz+1
    else:
        diancong[dc]=(x,y)
        dc=dc+1
dianzheng=dianzheng[0:dz]
diancong=diancong[0:dc]

数据更新:
#检测结果数据池
jieguo=[
[(11,11),100,1,1,[1,1],1],
[(11,11),100,0,1,[1,1],1],
[(290,31),100,1,1,[1,1],1]
]
#本次检测的数据
bencishuju=[
[(20,11),200,1,[1,1],1],
[(300,31),200,1,[3,4],1],
]
#假设皮带运动仅仅会产生x方向的位移
#与储存的数据对比,找到之前几次对应数据
for i in range(len(bencishuju)):
    for j in range(len(jieguo)):
        #temp:bianma器差值(机械坐标
        temp=(bencishuju[1]-jieguo[j][1])*fendu
           if ((bencishuju[0][0]-temp-jieguo[j][0][0])<piancha) and jieguo[j][2]==1:
               #此时找到了之前位置的数据,可根据条件设置更新的数据
               if bencishuju[0][0]<100:
                   jieguo[j][3]=bencishuju[2]
               if bencishuju[0][0]<=500 and bencishuju[0][0]>=100:
                   jieguo[j][4]=bencishuju[3]
               if bencishuju[0][0]>=500:
                   jieguo[j][5]=bencishuju[4]
           #此时没有找到了之前位置的数据,检测结果池中空余的位置并将数据放入
           if flag==0:
            for n in range(len(jieguo)):
                if jieguo[n][2] == 0:
                    jieguo[n][0]=bencishuju[0]
                    jieguo[n][1]=bencishuju[1]
                    jieguo[n][2]=1
                    #写入初始数据
                    jieguo[n][3]=bencishuju[2]
                    jieguo[n][4]=bencishuju[3]
                    jieguo[n][5]=bencishuju[4]         
#销毁数据,编码器差值超过一定范围将数销毁并将待销毁数据输出
for i in range(len(jieguo)):
    temp=(bencishuju[0][1]-jieguo[1])*fendu
    if abs(temp)>=juli:
        jieguo[2]=0
        xiaohuishuju=xiaohuishuju+[jieguo]

已有 0 人打赏作者

回复 邀请回答送花

使用道具 举报

lianjiamin 2022-4-13 21:15:37 | 显示全部楼层
有个疑问,编码器计数值达到最大值怎么办?循环计数?
回复 送花

使用道具 举报

H工 2022-11-26 13:45:07 | 显示全部楼层
用PLC可以实现这样的功能吗
回复 送花

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册   

本版积分规则

有技术问题,就上汇川技术社区

INOVANCE汇川技术 公众号

扫码下载掌上汇川APP

全国服务热线:8:30-17:30

4000-300124

苏州地址:江苏省苏州市吴中区越溪友翔路16号

深圳地址:深圳市龙华新区观澜街道高新技术产业园汇川技术总部大厦

Copyright © 2003-2100 汇川技术 Powered by Discuz! X3.4 ( 苏ICP备12002088号 )
快速回复 返回列表 返回顶部