工業視覺項目少不了與下位PLC進行資料通訊,例如産品就位通知視覺進行拍照檢測,視覺開始觸發光源相機拍照 進行圖像處理,最後結果輸出形成閉環,像我們常用的西門子PLC三菱PLC等等都有相應的通訊方式,大都是定義通訊标記的位址,進行位址輪詢校驗識進行對應的操作。本篇以西門子為例,西門子的S7協定,用了的Hsl的開源協定庫封裝了對S7協定的連接配接讀寫方法。
NUGET安裝類庫7.0 屬于免費版本。
public bool Connect(out ResultMessage resut, string serverUrl = "192.168.10.10", int port = 4000, PLCModelEnum pLCModel = PLCModelEnum.S7_1200)
{
if (pLCModel == PLCModelEnum.S7_1200)
{
if (Plc == null)
{
Plc = new SiemensS7Net( SiemensPLCS.S1200,serverUrl)
{
ConnectTimeOut = 5000,
ReceiveTimeOut = 500
};
}
try
{
var open = Plc.ConnectServer();
if (open.IsSuccess)
{
IsConnect = true;
//PLC打開成功
resut = new ResultMessage()
{
IsSuccess = true,
ErrorMsg = open.Message
};
return true;
}
else
{
IsConnect = false;
Plc = null;
resut = new ResultMessage()
{
IsSuccess = false,
ErrorMsg = open.Message
};
return false;
}
}
catch (Exception ex)
{
IsConnect = false;
Plc = null;
resut = new ResultMessage()
{
IsSuccess = false,
ErrorMsg = $"Connect PLC Error:{ex.Message}"
};
return false;
}
}
else
{
IsConnect = false;
resut = new ResultMessage()
{
IsSuccess = false,
ErrorMsg = "Unknow PLC Model"
};
return false;
}
}
public T ReadNode<T>(string tag, out ResultMessage result, ushort length = 0)
{
T ret = default;
if (Plc == null)
{
result = new ResultMessage()
{
IsSuccess = false,
ErrorMsg = "未初始化連接配接"
};
return ret;
}
result = default;
Type type = typeof(T);
switch (type.Name)
{
case nameof(Boolean):
{
var r = Plc.ReadBool(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(Int16):
{
var r = Plc.ReadInt16(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(UInt16):
{
var r = Plc.ReadUInt16(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(Int32):
{
var r = Plc.ReadInt32(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(UInt32):
{
var r = Plc.ReadUInt32(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(Int64):
{
var r = Plc.ReadInt64(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(UInt64):
{
var r = Plc.ReadUInt64(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(Single):
{
var r = Plc.ReadFloat(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(Double):
{
var r = Plc.ReadDouble(tag);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(String):
{
//如果長度為0,這設為預設值1
if (length == 0)
{
length = 1;
}
var addressStr = tag;
var index = tag.IndexOf(".");
var lastIndex = tag.LastIndexOf(".");
if (lastIndex != index && lastIndex < tag.Length - 1)
{
try
{
addressStr = tag.Substring(0, lastIndex);
length = Convert.ToUInt16(tag.Substring(lastIndex + 1));
}
catch
{
}
}
// 讀取時讀取的字元往後偏移2位
if (addressStr.IndexOf(".") > -1) {
var addressArr = addressStr.Split('.');
addressStr = $"{addressArr[0]}.{addressArr[1].ToInt() + 2}";
}
var r = Plc.ReadString(addressStr, length);
result = new ResultMessage() { IsSuccess = r.IsSuccess, ErrorMsg = r.Message };
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content, typeof(T));
}
break;
case nameof(Char):
{
var r = Plc.ReadString(tag, 1);
result = new ResultMessage()
{
IsSuccess = r.IsSuccess,
ErrorMsg = r.Message
};
if (r.IsSuccess)
ret = (T)Convert.ChangeType(r.Content.ToCharArray()[0], typeof(T));
}
break;
default: break;
}
return ret;
}
public bool WriteNode(string tag, object value, out ResultMessage result)
{
if (Plc == null)
{
result = new ResultMessage()
{
IsSuccess = false,
ErrorMsg = "未初始化連接配接"
};
return false;
}
OperateResult ret = default;
switch (value.GetType().Name)
{
case nameof(Boolean):
{
ret = Plc.Write(tag, (bool)value);
}
break;
case nameof(Int16):
{
ret = Plc.Write(tag, (short)value);
}
break;
case nameof(UInt16):
{
ret = Plc.Write(tag, (ushort)value);
}
break;
case nameof(Int32):
{
ret = Plc.Write(tag, (int)value);
}
break;
case nameof(UInt32):
{
ret = Plc.Write(tag, (uint)value);
}
break;
case nameof(Int64):
{
ret = Plc.Write(tag, (long)value);
}
break;
case nameof(UInt64):
{
ret = Plc.Write(tag, (ulong)value);
}
break;
case nameof(Single):
{
ret = Plc.Write(tag, (float)value);
}
break;
case nameof(Double):
{
ret = Plc.Write(tag, (double)value);
}
break;
case nameof(String):
{
string strValue = (string)value;
var addressStr = tag;
var index = tag.IndexOf(".");
var lastIndex = tag.LastIndexOf(".");
if (lastIndex != index && lastIndex < tag.Length - 1)
{
try
{
addressStr = tag.Substring(0, lastIndex);
int len = tag.Substring(lastIndex+1).ToInt();
if (value.ToString().Length < len) {
strValue = strValue.PadRight(len,'\0');
}
}
catch
{
}
}
ret = Plc.Write(addressStr, strValue);
}
break;
default: break;
}
result = new ResultMessage()
{
IsSuccess = ret.IsSuccess,
ErrorMsg = ret.Message
};
return ret.IsSuccess;
}