,
(天津大学 精密仪器与光电子工程学院,天津 300100)
应用于现代焊装过程的激光焊接技术在线作业时会频频产生熔渣飞溅。飞溅物将会随机性地粘附在作业中的激光焊头保护镜片上。由于保护镜片上粘有金属熔溅物,激光光束的传递光路极有受阻的可能性,将造成焊体受热不均匀,产生坏焊的现象[1]。国际上的汽车厂商依靠人工定期更换保护镜片完成对保护镜片产生缺陷的预防,一些国内汽车厂商尝试加入气动喷嘴来预防飞溅粒子[2],但均无法满足低成本、高利用率的要求。
镜面检测本身难度较大,迄今尚无视觉检测保护镜片的有效方法。针对以上需求,设计了一种基于嵌入式Linux的激光焊接保护镜片的视觉镜面缺陷检测系统。由于保护镜片上的飞溅粒子体积小、散布随机,所以需要高分辨率图像作为视觉样本;同时出于高效生产考虑,系统不能采用传统的字符设备和块设备的内存管理方式,而是选用高效快捷、高健壮性[3]的V4L2框架。以流的方式连续将高分辨率图像映射到Linux的用户空间并利用核心算法进行图像识别。如果检测到缺陷,系统通过CAN总线向机器人报警并终止线上作业。该系统摆脱传统工业现场的总机控制,可通过触摸屏进行人机交互功能,具有良好的便携性。
基于嵌入式Linux的激光焊接保护镜片的视觉镜面缺陷检测系统的硬件结构框图如图1所示。
图1 系统硬件结构框图
该系统硬件结构以S5PV210微处理器为核心、同时包括电源、DDR2、Flash、UART接口、MT9M031传感器、AT043TN24液晶显示触摸屏、SD卡插槽等。S5PV210微处理器主要负责各模块间的控制和核心算法的运行。MT9M031传感器通过以太网口将拍摄的图像映射到Linux的用户空间,并通过上层应用程序储存进DDR2和插入的SD卡中。检测系统与机器人通过CAN总线连接。
S5PV210是三星公司推出的一款适用于智能手机和平板电脑等多媒体设备的应用处理器,采用ARM CortexTM-A8内核,主频可达1 GHz并具有丰富的外围接口。
MT9M031是由Aptina公司推出发行的一款1/3英寸高清图像传感器。激光焊接保护镜片的视觉信息通过MT9M031转化为数字图像。由于现代芯片的高度集成化,MT9M031的A/D转换器集成在芯片内部,其外部电路设计十分简单。
AT043TN24为CHIMEI INNOLUX公司推出的一款4.3英寸的液晶触摸屏,常白显示,通透式,分辨率为480(RGB)*272。
由于激光焊接的工业机器人大多使用CAN总线来进行通讯,所以该系统配有CAN转UART协议转换模块来适应现场作业环境。该模块内部已经集成DeviceNet从站协议栈代码,可支持高达128字节I/O报文传输,适用于各种干扰强、实时性要求高的工业环境。
基于以上硬件平台,应用Linux操作系统作为嵌入式开发环境。Linux是一款具有高时代性、高移植性的开源操作系统,可应用于个人PC机、服务器和嵌入式开发等[4]。较于其他应用于嵌入式开发的系统,如:WinCE、VxWorks,具有内核开源、强大的网络协议支持、
广泛的硬件支持等独有的特性。
在嵌入式Linux开发的过程中,用户需要对其内核进行修改、编译,同时增加对应硬件的驱动模块并在设备树中进行修改添加。主要操作如下:
1)裁剪和移植内核。只保留嵌入式设备需要的内核模块,节约空间;
2)移植和修改驱动模块。使得系统外设,如MT9MO31传感器,可被系统识别并访问;
3)修改和编译设备树。设备树文件是描述设备的属性和设置之间的关系,并且将设备树的配置最终通过驱动作用于实际的设备。该设计大大简化了驱动的移植与开发,当设备参数需要修改时,只需编译设备树文件,而不需重新编译内核。
2.2.1 MT9M031传感器驱动
MT9M031驱动主要完成对相机的图像采集和配置的功能。图像从传感器发出后,通过CMOS控制器的调用,完成拍照。方案如图2所示。
图2 MT9M031传感器驱动方案
首先在内核的设备树文件下添加MT9M031设备信息:
mt9m031@5d {
compatible = "aptina,mt9m031";
reg = <0x5d>
port {
mt9m031_1: endpoint {
remote-endpoint = <&vpfe0_ep>;
mclk-frequency = <50000000>;
...
i2c的设备地址为0x5d。compatible属性的内容非常重要,该属性是和驱动匹配的唯一依据," aptina" 代表厂家," mt9m031"代表CMOS传感器型号。" remote-endpoint"代表和CMOS连接的外设," mclk-frequency "代表CMOS的输入时钟。
然后修改vpfe外设侧为:
&vpfe0 {
...
port {
vpfe0_ep: endpoint {
remote-endpoint = <&mt9m031_1>;
if_type = <2>;
hdpol = <0>;
vdpol = <0>;
bus_width = <16>;
...
只需要修改VPFE远端连接的是MT9M031这款CMOS图像传感器即可。其中,if_type代表图像格式,2代表raw格式。" bus_width "代表总线宽度。" hdpol "代表行同步的极性,0表示高电平有效,下降沿触发DMA中断,1表示低电平有效,上升沿触发DMA中断。" vdpol "代表场同步的极性,0代表高电平有效,1代表低电平有效。
然后是MT9M031驱动程序的移植。由于Linux内核中自带了OmniVision公司生产的OV2659传感器的驱动,通过修改其驱动文件完成MT9M031传感器的驱动移植。关键修改如:寄存器的读写函数、增加分辨率支持等。
首先将OV2659驱动文件中所有的字符串“ov2659”全部替换为“mt9m031”。由于替换众多,可以在vim编辑器的控制模式下使用全局命令:%s/ov2659/mt9m031/g来进行全文档范围内的字符串替换。
下一步参照MT9M031的datasheet在该驱动文件中增加MT9M031的常用寄存器地址以及常量的宏定义,如: define MT9M031_CHIP_ID_REG 0x3000等。
由于ov2659的i2c寄存器是16位地址,8位数据,而mt9m031的i2c寄存器是8位地址,16位数据,需要进行修改。修改如下:
static int mt9m031_write(struct i2c_client *client, u8 reg, u16 data){
return i2c_smbus_write_word_swapped(client, reg, data);}
static int mt9m031_read(struct i2c_client *client, u8 reg, u16 *val){
u16 *p_val = val;
*p_val = i2c_smbus_read_word_swapped(client, reg);
return 0;}
由于Linux启动之后,会自动匹配外接设备和驱动。一旦设备匹配成功后,操作系统会自动调用外设驱动中的probe函数。probe函数将进行设备号的读取。如果读取到的设备号与CMOS的设备号(芯片ID)相匹配,系统就会根据设备树中的配置信息对驱动设备进行初始化配置。配置结束以后,注册设备,驱动程序获得外接设备地址。在mt9m031_probe下的mt9m031_detect_sensor函数中添加以下内容,进行复位CMOS芯片、关闭输出、使能CMOS芯片和读取CMOS芯片的版本号。该代码段中省略掉了错误处理部分:
ret = mt9m031_write(client,MT9M031_RESET,1);
mdelay(5);
ret = mt9m031_write(client,MT9M031_RESET,0);
ret = reg_write(client, MT9M031_OUTPUT_CONTROL, 0);
ret = reg_write(client, MT9M031_CHIP_ENABLE, 1);
ret = mt9m031_read(client,0x00, &ver);
mt9m031->id = ver;
if (mt9m031->id MT9M031_ID)
dev_info(&client->dev, "Found sensor,the version is %04x ",
mt9m031->id);
else{
dev_err(&client->dev, "Sensor detection failed (%04X, %d) ",
mt9m031->id, ret);
ret = -ENODEV;}
由于在前面设备树文件下添加MT9M031设备信息中提到的compatilble属性是和驱动匹配的唯一依据,所以在MT9M031驱动文件中也需要添加和设备树中compatilble属性相同的信息。这样才可以完成设备和驱动的匹配工作。在static const struct of_device_id ar0134_of_match[]中添加语句:{ .compatible = "aptina,mt9m031", }, 。同时在static struct i2c_driver ar0134_i2c_driver中的.driver项段中添加语句:.of_match_table = of_match_ptr(mt9
m031_of_match), 。
由于图像坏点的面积微小,系统要求采集1024x1280的灰度图像,为了支持这种格式的采集,需要使用分辨率为1024x640的YUYV图像格式进行替代。而1024x640的分辨率在原有驱动中并没有,需要在mt9m031_framesizes结构体中增加对这种分辨率的支持:
static const struct mt9m031_framesize mt9m031_framesizes[] = {
...
{ /* 1024x1280 */
.width = 640,
.height = 1024,
.regs = mt9m031_vga,
... }
由于V4L2框架层与MT9M031驱动层之间存在着一个CCDC Driver层(VPFE接口),所以此处需要涉及到VPFE接口驱动的修改。一般的视频采集涉及到的VPFE接口驱动是不需要修改的,针对该系统的视觉算法对图像的要求只需要修改内核源路径下的vpfe.c文件即可。该文件所处路径如下:
内核源路径/drivers/media/platform/ti-vpfe/vpfe.c
由于Linux内核中自带驱动的OV2659的像素时钟是上升沿锁存数据,而MT9M031的像素时钟是下降沿锁存数据,需要修改pclk的时钟极性。注释掉原有的VPFE配置语句:isif_write(isif, cfg, ISIF_VPFE_CONFIG); ,将参数cfg改为cfg|0x0001,即将最低位置1表示下降沿锁存:isif_write(isif, cfg|0x0001, ISIF_VPFE_CONFIG);
由于微处理器SDK中图像采集默认丢弃第一行像素,而MT9M031的第一行像素是有效的,不能丢弃,所以要修改VPFE接口驱动对采集图像第一行像素的处理。在frm_fmt ISIF_FRMFMT_INTERLACED判断条件成立后的if语句段中注释掉语句vert_start += 1; 。vert_start变量表示VPFE接口采集图像的行起始标志。SDK默认第一行像素丢弃,所有vert_start标志自加1,从第二行开始实时采集图像。注释掉该语句,VPFE接口直接从第一行像素进行采集。
以上各个驱动程序修改完成后,将要进行Linux内核的重新编译。当在Linux源码树的顶层输入make menuconfig的时候,会出现内核编译的配置界面。该界面最终生成的就是依赖Kconfig文件(.config文件),将编译的配置选项传递给makefile,从而控制内核编译的过程。编辑内核源路径/drivers/media/i2c/Kconfig文件,新增MT9M031的相关信息:
config VIDEO_MT9M031
tristate "APTINA MT9M031 sensor support"
depends on I2C && VIDEO_V4L2
select VIDEO_V4L2_SUBDEV_API
---help---
This is a V4L2 sensor-level driver for the APTINA
MT9M031 camera sensors.
与此同时接收内核编译配置选项的makefile也需要进行一些修改。打开控制驱动文件mt9m031.c编译的makefile文件,该文件路径为:内核源路径/drivers/media/i2c/Makefile。在原ov2659驱动控制编译语句下面添加MT9M031的驱动控制编译语句:
obj-(CONFIG_VIDEO_MT9M031) += mt9m031.o
最后将刚才修改的MT9M031的驱动文件的文件名改为mt9m031.c,同时其对应的头文件名改为mt9m031.h。在Linux源码树下输入 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig。选择Device Drivers->Multimedia support-> Encoders, decoders, sensors and other helper chips -> APTINA MT9M031 sensor support,选择该编译选项以后保存退出。然后开始编译内核,即可将MT9M031以上修改的所有驱动全部编译移植到新的内核镜像文件zImage文件。将该镜像文件和设备树编译后的.dtb文件通过sd卡烧进核心板,就完成了整个视频采集系统的内核移植和系统搭建工作。
2.2.2 AT043TN24液晶触摸屏驱动
对于480x272的电阻屏的驱动,内核已经提供,但是刷新方式为横屏模式。由于图像的分辨率的关系,利用竖屏显示的支持方案效果最佳。只需要在QT编译的过程中,加入支持旋转的编译选项,将QT的库文件更新到文件系统中,然后在系统启动配置件中增加旋转屏幕的参数即可。
V4L2框架下可以在程序中直接打开图像设备获取图像设备的能力,例如是否支持内存映射、设置图像格式(YUYV/UYVY)等。向驱动申请帧缓冲[5],并且映射到用户空间。将映射到用户空间缓冲区入队列[6],即可启动采集。启动采集以后,轮询是否采集到数据,当采集到以后,将帧缓冲出队列,对图像数据进行图像处理或者传输保存。出队列的缓冲使用完毕以后,继续入队列,等待下一次采集。当采集条件满足,例如采集到设定的帧数以后,停止采集,并且关闭设备。图像采集程序流程图如图3所示。
该系统的图像识别核心算法是基于OpenCV2库函数实现的。当进入图像处理算法流程后,首先在图像内寻找保护镜片。因为同轴光会经过透射反射进入照相机,所以图像内的镜片应该为亮白色。如果找到则利用霍夫变换[7]来定位镜面区域,并判断是否发生定位区域越界。如果发生越界则提示镜片不存在,未发生越界则取定位区域的外接矩形为感兴趣区域。在外接矩形感兴趣区域内首先进行保护镜片以外、外接矩形以内的区域置白,将隶属于以上区域中的像素点的像素值全部设置为255。之后在保护镜片内部进行阈值设定和像素值二值化,目的是为了检索圆形镜片区域中的坏点轮廓。最后经过计算检索到的坏点像素面积以及比较其与预先人工设定的坏点面积的大小,得到最终的坏点判断。
图3 图像采集程序流程图
为了验证该基于嵌入式Linux的激光焊接保护镜片的视觉镜面缺陷检测系统的设计有效性,特进行了相关的实验操作和数据分析。实验共分为两种:1.实验室条件下,对带有熔渣的缺陷保护镜片与无缺陷保护镜片混合检测;2.在焊接现场对线上作业的保护镜片进行检测。实验数据如图4所示。
图4 不同条件下对带有缺陷的保护镜片和无缺陷的保护镜片的混合检测
该镜面缺陷检测系统的实物设备如图5所示。由实验数据可知,在实验室条件下,混合检测的正检率一直保持在100%,系统搭建的有效性和核心算法的正确性得以验证。可是在工业现场中,熔渣的飞溅导致系统的照相机镜头上会粘附熔渣,直接影响到采图的客观真实性。因此随着检测样本的增加,正检率随意性变化。
基于飞溅物粘附在照相机镜头上导致误检的问题,拟将一个通气导管放置在照相机镜头旁侧并时刻通气流斜向吹击照相机镜头。这样成功消除了飞溅物落附在照相机镜头上的可能性。增添通气除杂环节后,经核心算法处理后的镜片图像如图6所示。
图5 镜面缺陷检测系统的实物设备图
图6 系统采集到的缺陷保护镜片的信息图像
本设计是服务于现汽车生产线上激光焊接保护镜片的缺陷检测。首先采用了S5PV210微处理器,提高运算速度,降低采集能耗;然后选择MT9M031图像传感器并将保护镜片图像通过DMA映射到用户空间并使用V4L2框架以流的方式进行图像采集,这样可以快速高效地从相机处获取高分辨率的图像信息;设计CAN转UART协议转换模块和液晶触摸显示屏AT043TN24,提高该系统的人机交互能力和现场适应度;最后基于opencv2函数库的核心算法编写:当检测出坏点时,红色线标记轮廓并报警。实验证明了本系统设计的有效性和算法的正确性,补充实验进一步完善了该系统对工业现场的适应性。
参考文献:
[1] 陈 勰. 启辰白车身激光焊接质量影响因素研究[D].长沙:湖南大学,2011.
[2] 唐霞辉, 朱海红, 朱国富. 激光焊接专用气动喷嘴的研究[J]. 激光技术, 2000, 24(2): 95-98
[3] Michael H Schimek, Bill Dirks, Hans Verkuli. Video for Linux two API specification [EB/OL]. http://v4l2spec.bytesex.org/ v4l2spec/v4l2.pdf.2008.
[4] 邹自明,刘晓阳. 基于嵌入式Linux的结构化道路车道线识别系统的研究[J]. 计算机测量与控制,2014,22(4):1260-1263
[5] 史 涛,裴海龙. 基于Linux的嵌入式实时视频跟踪系统[J]. 计算机测量与控制,2014,22(5):1523-1526
[6] 徐 家, 陈 奇. 基于V4L2的视频设备驱动开发[J]. 计算机工程与设计, 2010, 31(16):3569-3572
[7] A. L. Fisher, P. T. Highnam. Computing the Hough transform on a scan line array processor[J], IEEE Trans. Pattern Anal. Mach. Intel, 1989, 11(3):262-265.