项目中遇到如下情况:
1. 整条生产线由多个PLC分别控制,但是所有PLC在同一个局域网内。PLC采用西门子的S7-200 Smart
2. 客户希望在操作工站的电脑(跟PLC在同一个局域网内)上提供一个上位机软件,用来读取/写入各个PLC的变量
3. 上位机软件通过OPC DA跟各个PLC进行通信
4. OPC Server采用西门子提供的PC Access Smart软件
5. 最终遇到的问题是如何在一个上位机软件上访问多个PLC?
关于PC Access Smart,参考如下链接
http://www.ad.siemens.com.cn/productportal/Prods/s7-200-smart-portal/200SmartTop/SmartSMS/017.html
通过研究该软件随机附带的VB程序,终于发现窍门。
1. 在操作工站电脑上安装PC Access Smart之后,后台会有一个OPCDAAutomation的程序在运行,该程序即为OPC Server
2. 上位机软件首先连接该OPC Server,其中,OPC Server的名字固定为S7200SMART.OPCServer
3. 在指定Tag名称时,要按照如下格式2:192.168.2.17:0201:0201,I4.2,BOOL,R
4. OPC Server解析Tag名称时,会去连接指定的PLC,访问指定的变量地址
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private void btnConnect_Click(object sender, EventArgs e) { if (txtOPCServerName.Text.Trim() == "") { MessageBox.Show("OPC server name cannot be empty!"); return; } try { _helper.GetOPCServers(txtOPCServerName.Text.Trim()); txtOPCServerName.ReadOnly = true; btnRead.Enabled = true; btnWrite.Enabled = true; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private void btnRead_Click(object sender, EventArgs e) { if (txtOPCTagName.Text.Trim() == "") { MessageBox.Show("OPC tag name cannot be empty!"); return; } txtReadWriteValue.Text = _helper.ReadValue(txtOPCTagName.Text).ToString(); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void GetOPCServers(string svrName) { IPHostEntry IPHost = Dns.GetHostEntry(Environment.MachineName); try { KepServer = new OPCServer(); object serverList = KepServer.GetOPCServers(IPHost.HostName.ToString()); int i = 0; foreach (string serverName in (Array)serverList) { serverNames.Add(serverName); } ConnectServer(svrName); } catch (Exception ex) { throw new Exception("Connect Error:" + ex.Message); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public object ReadValue(string tagName) { GetTagValue(tagName); Thread.Sleep(500); object ItemValues; object qualities; object timeStamps; try { KepItem.Read(1, out ItemValues, out qualities, out timeStamps); return ItemValues; } catch { return null; } }