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联动的主要内容,如果未能解决你的问题,请参考以下文章