在ERP系統中,採集一線的生產數據是重要工作之一,而稱重計量是企業的核心資產數據,人工計重費時費力,還容易出錯,重量數據是否正確,直接影響企業的採購或銷售額。基於此,由系統對接電子秤實現自動抓取數據是企業管理的第一步。
電子秤,一般由重量傳感器、砝碼、底座、儀表等組成。儀表與傳感器相連,儀表一般具有記錄皮重、歸零等基本功能,大部分的儀表廠家都包含了串口數據對接的接口,滿足企業的數據採集需求。
採集數據一般使用DB9 RS232串口線,連接電腦的串口,但是現代電腦基本沒有保留串口頭,可以購買RS232串口轉USB轉接線。
重點來了,上位機如何採集儀表的重量數據?
根據不同廠家的型號不同數據協議也有所不同,以耀華XK3190-A9這款爲例,廠家協議的說明:
協議規定了,起止位、數據位、符號、小數點位置、校驗位等參數說明,根據這個協議進行解析就可以形成上位機的重量數據。
核心代碼:
/// <summary>
/// 耀華A9稱重數據
/// </summary>
/// <param name="byteFrame">幀數據</param>
private string ConvertWeight(byte[] byteFrame)
{
string value = string.Empty;
if (byteFrame == null || byteFrame.Length == 0)
{
return value;
}
//對接收到的數據進行校驗
byte byteVerif = (byte)(byteFrame[1] ^ byteFrame[2] ^ byteFrame[3] ^ byteFrame[4] ^ byteFrame[5] ^ byteFrame[6] ^ byteFrame[7] ^ byteFrame[8]);
//校驗高位
byte verifHigh = (byte)((byteVerif & 0xf0) >> 4);
//校驗低位
byte verifLow = (byte)(byteVerif & 0x0f);
if (verifHigh > 9)
verifHigh = (byte)(verifHigh + 0x37);
else
verifHigh = (byte)(verifHigh + 0x30);
if (verifLow > 9)
verifLow = (byte)(verifLow + 0x37);
else
verifLow = (byte)(verifLow + 0x30);
if (byteFrame[9] == verifHigh && byteFrame[10] == verifLow)
{
List<byte> listDigit = new List<byte>() { (byte)0x30, (byte)0x31, (byte)0x32, (byte)0x33, (byte)0x34, (byte)0x35, (byte)0x36, (byte)0x37, (byte)0x38, (byte)0x39 };
StringBuilder sbDigit = new StringBuilder();
//獲取稱重數據
for (int i = 2; i < 8; i++)
{
if (!listDigit.Contains(byteFrame[i]))
byteFrame[i] = (byte)0x30;
sbDigit.Append(byteFrame[i] - 0x30);
}
//小數點位置
int dotPos = byteFrame[8] - 0x30;
int exponent = -dotPos;
double weightValue = Convert.ToInt32(sbDigit.ToString()) * Math.Pow(10, exponent);
//負數處理
if (byteFrame[1] == 0x2D)
weightValue = -weightValue;
value = FormatWeight(weightValue);
}
return value;
}
同一廠家不同型號的儀表,定義的協議都不一樣,這點比較費事。所以在開發這類需求的時候,可以考慮統一封裝一個稱重基礎類,定義初始化、打開串口、關閉串口、獲取重量等通用接口,不同型號使用子類實現業務邏輯。這樣外層的調用,不需要關心每個儀表型號。如果考慮插播服務,可以使用插件式開發,原理就是使用反射掃描讀取外部dll,只要實現了基類就可以熱加載稱重驅動。
/// <summary> /// 查找外部電子秤驅動 /// 路徑:{root}/ /// </summary> /// <param name="type">類型</param> /// <returns></returns> public static WeightBase FindExt(string type) { WeightBase WeighBase = null; string dirName = AppDomain.CurrentDomain.BaseDirectory + "plugins\\weight"; // 掃描外部電子秤驅動 if (System.IO.Directory.Exists(dirName)) { var files = System.IO.Directory.GetFiles(dirName); foreach (var file in files) { var ext = file.Substring(file.LastIndexOf('.') + 1); if (ext == "dll" || ext == "exe") { var ass = Assembly.LoadFrom(file); if (ass != null) { WeighBase = Find(ass, type); if (WeighBase != null) { break; } } } } } return WeighBase; } public static bool IsScale(Type t) { var tWeighBase = typeof(WeightBase); if (t.BaseType == null) return false; return t.BaseType == tWeighBase || t.BaseType.BaseType == tWeighBase;// 子及孫 }
本人開發的這款PC稱重軟件就是使用了這種方案,可以在不升級主程序的情況下,隨時支持一款儀表驅動。