Halcon与C#联合编程:使用S7协议实现机器视觉上位机与西门子PLC联动

Posted 虎鲸不是鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Halcon与C#联合编程:使用S7协议实现机器视觉上位机与西门子PLC联动相关的知识,希望对你有一定的参考价值。

Halcon与C#联合编程(一)

项目概述

笔者利用下班时间琢磨出一个上位机软件,用以实现较康耐视智能相机(二手康耐视智能相机花费了11600)更低成本的机器视觉解决方案。系虎彩全厂首个源码可控的机器视觉与西门子PLC联动的上位机软件。

功能

将摄像头放置于合适位置后,利用形状检测,通过判断IQOO手机盒的‘5G’标记个数/QR码是否相同来判断天盖的正反并解决混款问题。下位机使用西门子PLC即可。

上位机原理解析

机器视觉算法

形状检测算法实现

在Halcon中调出算法,并导出为C#源码。此时得到的源码并不能直接使用,需手动修改。

public void action2()
    
        // Local iconic variables 
        bool result = false;
        
        if (key == "")
        
            System.Windows.Forms.MessageBox.Show("请选择连接字符串");
            return;
        
        //此处开始为Halcon检测5G标识

        // Local iconic variables 

        HObject ho_Image, ho_ModelRegion, ho_TemplateImage;
        HObject ho_ModelContours, ho_TransContours;

        // Local control variables 

        HTuple hv_AcqHandle = new HTuple(), hv_ModelID = new HTuple();
        HTuple hv_ModelRegionArea = new HTuple(), hv_RefRow = new HTuple();
        HTuple hv_RefColumn = new HTuple(), hv_HomMat2D = new HTuple();
        HTuple hv_Row = new HTuple(), hv_Column = new HTuple();
        HTuple hv_Angle = new HTuple(), hv_Score = new HTuple();
        HTuple hv_I = new HTuple();

        //counter1 = int.Parse(hv_I.ToString());

        // Initialize local and output iconic variables 
        HOperatorSet.GenEmptyObj(out ho_Image);
        HOperatorSet.GenEmptyObj(out ho_ModelRegion);
        HOperatorSet.GenEmptyObj(out ho_TemplateImage);
        HOperatorSet.GenEmptyObj(out ho_ModelContours);
        HOperatorSet.GenEmptyObj(out ho_TransContours);


        //
        //Matching 01: ************************************************
        //Matching 01: BEGIN of generated code for model initialization
        //Matching 01: ************************************************
        HOperatorSet.SetSystem("border_shape_models", "false");
        //
        //Matching 01: Initialize acquisition
        hv_AcqHandle.Dispose();
        HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb",
            -1, "false", "default", key, 0, -1, out hv_AcqHandle);
        //
        //Matching 01: Obtain the model image
        ho_Image.Dispose();
        HOperatorSet.ReadImage(out ho_Image, "E:/工作文件夹/2020.12.16/WIN_20201217_13_55_05_Pro.jpg");
        //
        //Matching 01: Build the ROI from basic regions
        ho_ModelRegion.Dispose();
        HOperatorSet.GenRectangle1(out ho_ModelRegion, 1215.17, 1236.49, 1288, 1427.91);
        //
        //Matching 01: Reduce the model template
        ho_TemplateImage.Dispose();
        HOperatorSet.ReduceDomain(ho_Image, ho_ModelRegion, out ho_TemplateImage);
        //
        //Matching 01: Create the shape model
        using (HDevDisposeHelper dh = new HDevDisposeHelper())
        
           
            HOperatorSet.CreateShapeModel(ho_TemplateImage, 4, (new HTuple(0)).TupleRad()
                , (new HTuple(360)).TupleRad(), (new HTuple(1.5553)).TupleRad(), (new HTuple("none")).TupleConcat(
                "no_pregeneration"), "use_polarity", ((new HTuple(10)).TupleConcat(26)).TupleConcat(
                6), 4, out hv_ModelID);
        
        //
        //Matching 01: Get the model contour for transforming it later into the image
        ho_ModelContours.Dispose();
        HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_ModelID, 1);
        //
        //Matching 01: Get the reference position
        hv_ModelRegionArea.Dispose(); hv_RefRow.Dispose(); hv_RefColumn.Dispose();
        HOperatorSet.AreaCenter(ho_ModelRegion, out hv_ModelRegionArea, out hv_RefRow,
            out hv_RefColumn);
        hv_HomMat2D.Dispose();
        HOperatorSet.VectorAngleToRigid(0, 0, 0, hv_RefRow, hv_RefColumn, 0, out hv_HomMat2D);
        ho_TransContours.Dispose();
        HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_TransContours, hv_HomMat2D);
        //
        //Matching 01: Display the model contours
        if (HDevWindowStack.IsOpen())
        
            HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
        
        if (HDevWindowStack.IsOpen())
        
            HOperatorSet.SetColor(HDevWindowStack.GetActive(), "green");
        
        if (HDevWindowStack.IsOpen())
        
            HOperatorSet.SetDraw(HDevWindowStack.GetActive(), "margin");
        
        if (HDevWindowStack.IsOpen())
        
            HOperatorSet.DispObj(ho_ModelRegion, HDevWindowStack.GetActive());
        
        if (HDevWindowStack.IsOpen())
        
            HOperatorSet.DispObj(ho_TransContours, HDevWindowStack.GetActive());
        
        // stop(...); only in hdevelop
        //
        //Matching 01: END of generated code for model initialization
        //Matching 01:  * * * * * * * * * * * * * * * * * * * * * * *
        //Matching 01: BEGIN of generated code for model application
        //
        while (true)
        
            //
            //Matching 01: Obtain the image
            ho_Image.Dispose();
            HOperatorSet.GrabImage(out ho_Image, hv_AcqHandle);

            ho_Image1=ho_Image;
            ChangeImage(ho_Image1);
            //
            //Matching 01: Find the model
            using (HDevDisposeHelper dh = new HDevDisposeHelper())
            
                hv_Row.Dispose(); hv_Column.Dispose(); hv_Angle.Dispose(); hv_Score.Dispose();
                HOperatorSet.FindShapeModel(ho_Image, hv_ModelID, (new HTuple(0)).TupleRad()
                    , (new HTuple(360)).TupleRad(), 0.78, 0, 0.5, (new HTuple("least_squares")).TupleConcat(
                    "max_deformation 32"), (new HTuple(4)).TupleConcat(1), 0.75, out hv_Row,
                    out hv_Column, out hv_Angle, out hv_Score);
            
            //
            //Matching 01: Transform the model contours into the detected positions
            if (HDevWindowStack.IsOpen())
            
                HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
            
            for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Score.TupleLength())) - 1); hv_I = (int)hv_I + 1)
            
                hv_HomMat2D.Dispose();
                HOperatorSet.HomMat2dIdentity(out hv_HomMat2D);
                using (HDevDisposeHelper dh = new HDevDisposeHelper())
                
                    HTuple ExpTmpOutVar_0;
                    HOperatorSet.HomMat2dRotate(hv_HomMat2D, hv_Angle.TupleSelect(hv_I), 0, 0,
                        out ExpTmpOutVar_0);
                    hv_HomMat2D.Dispose();
                    hv_HomMat2D = ExpTmpOutVar_0;
                
                using (HDevDisposeHelper dh = new HDevDisposeHelper())
                
                    HTuple ExpTmpOutVar_0;
                    HOperatorSet.HomMat2dTranslate(hv_HomMat2D, hv_Row.TupleSelect(hv_I), hv_Column.TupleSelect(
                        hv_I), out ExpTmpOutVar_0);
                    hv_HomMat2D.Dispose();
                    hv_HomMat2D = ExpTmpOutVar_0;
                
                ho_TransContours.Dispose();
                HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_TransContours,
                    hv_HomMat2D);
                if (HDevWindowStack.IsOpen())
                
                    HOperatorSet.SetColor(HDevWindowStack.GetActive(), "green");
                
                if (HDevWindowStack.IsOpen())
                
                    HOperatorSet.DispObj(ho_TransContours, HDevWindowStack.GetActive());
                
                //stop ()
            
            counter1 = int.Parse(hv_I.ToString());
            //GC.Collect();
        
        //
        //Matching 01: *******************************************
        //Matching 01: END of generated code for model application
        //Matching 01: *******************************************
        //






    

QR码算法实现

public void action3()
    
        // Local iconic variables 
        bool result = false;



        if (key == "")
        
            System.Windows.Forms.MessageBox.Show("请选择连接字符串");
            return;
        
        //此处开始为Halcon检测QR码

        // Local iconic variables 

        HObject ho_Image = null, ho_SymbolXLDs = null;

        // Local control variables 

        HTuple hv_AcqHandle = new HTuple(), hv_DataCodeHandle = new HTuple();
        HTuple hv_ResultHandles = new HTuple(), hv_DecodedDataStrings = new HTuple();
        // Initialize local and output iconic variables 
        HOperatorSet.GenEmptyObj(out ho_Image);
        HOperatorSet.GenEmptyObj(out ho_SymbolXLDs);
        //Image Acquisition 01: Code generated by Image Acquisition 01
        hv_AcqHandle.Dispose();
        HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb",
            -1, "false", "default", "[0] WEB CAM", 0, -1, out hv_AcqHandle);
        HOperatorSet.GrabImageStart(hv_AcqHandle, -1);
        while (true)
        
            ho_Image1 = ho_Image;
            ChangeImage(ho_Image1);
            ho_Image.Dispose();
            HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);
            ho_Image1 = ho_Image;
            ChangeImage(ho_Image1);
            //Image Acquisition 01: Do something
            hv_DataCodeHandle.Dispose();
            HOperatorSet.CreateDataCode2dModel("QR Code", new HTuple(), new HTuple(), out hv_DataCodeHandle);
            ho_SymbolXLDs.Dispose(); hv_ResultHandles.Dispose(); hv_DecodedDataStrings.Dispose();
            HOperatorSet.FindDataCode2d(ho_Image, out ho_SymbolXLDs, hv_DataCodeHandle,
                new HTuple(), new HTuple(), out hv_ResultHandles, out hv_DecodedDataStrings);
            StringQR = hv_DecodedDataStrings.ToString();
            //ch1 = StringQR.ToCharArray();
        
        HOperatorSet.CloseFramegrabber(hv_AcqHandle);

    

大部分代码为Halcon导出。

下位机控制

使用西门子的S7.dll即可实现PLC的连接。首先初始化连接。

 Plc plc = new Plc(CpuType.S71200  , "192.168.1.100", 0, 1);//设置默认PLC连接
private void button3_Click(object sender, EventArgs e)
        
            if ((comboBox2.Text != "") && (textBox2.Text != "") )//判断PLC类型、IP地址、插槽 机架信息
            
                string ip = textBox2.Text;//PLC IP地址
                short jijiahao = 0;// Convert.ToInt16(textBox2.Text);//PLC机架号
                short chacaohao =1;//Convert.ToInt16(textBox3.Text);//PLC插槽号
                switch (comboBox2.Text)
                
                    case "Siemens S7-200SMART":
                        plc = new Plc(CpuType.S71200 , ip, jijiahao, chacaohao);
                        break;
                    default: break;
                

                try
                
                    plc.Open();
                    if (plc.IsConnected)//判断PLC链接是否成功
                    
                        timer2.Enabled = true;
                        MessageBox.Show("已连接到PLC!"); 
                    
                    else
                    
                        MessageBox.Show("PLC连接不成功,请检查PLC类型、IP地址是否正确!!!");
                    
                
                catch
                
                    MessageBox.Show("PLC连接不成功,请检查PLC类型、IP地址是否正确!!!");
                
            
        

断开连接使用如下方法。

private void button4_Click(object sender, EventArgs e)
        
            plc.Close();
            if (!plc.IsConnected)
            
                timer2.Enabled = false;
                MessageBox.Show("已断开连接!!");
            
            else
            
                MessageBox.Show("PLC断开连接失败!!!");
            
        

手动功能部分。

private void button5_MouseDown(object sender, MouseEventArgs e)
        
            Image Image1;
            Image Image2;
            Image1 = new Bitmap(@"E:\\work\\技术攻关\\C#运动控制卡\\练习程序\\2020.11.15\\运动控制卡~练习\\Resources\\灯-绿.png");//绿色代表低电平
            Image2 = new Bitmap(@"E:\\work\\技术攻关\\C#运动控制卡\\练习程序\\2020.11.15\\运动控制卡~练习\\Resources\\灯-红.png");//红色代表高电平
            pictureBox1.Image = Image2;
            if (plc.IsConnected)
              plc.Write("M10.0", 1);
        

        private void button5_MouseUp(object sender, MouseEventArgs e)
        
            Image Image1;
            Image Image2;
            Image1 = new Bitmap以上是关于Halcon与C#联合编程:使用S7协议实现机器视觉上位机与西门子PLC联动的主要内容,如果未能解决你的问题,请参考以下文章

机器视觉Qt联合Halcon编程之显示多图片

机器视觉Qt联合Halcon编程之显示图片

机器视觉Qt联合Halcon编程之显示图片

C#联合halcon开发框架源码。 拖拽式编程,无halcon基础也能上手,匹配

C#与WinCC通讯之西门子S7-1200数据读取详解

西门子S7-1200 PLC与C#(上位机)通讯(TCP协议)