using System; using System.Collections.Generic; using System.Linq; using System.Text; using HalconDotNet; using System.Threading; using System.Reflection; using System.IO; using System.Threading.Tasks; using HDevEngine; using System.Configuration; namespace M423project { /// /// 产品厚度检测类 /// public class HeightDetection { #region 产品高度检测类私有成员 private OPC opc; private ImageProcess imageProcess; private ConfigStruct opcConfig; private int stationNumber; private DetectionType detectionType; private HWindow halconWindow; private HWindow hcBarcode; private HDevEngineTool _heightTool; #endregion /// /// 产品高度检测类构造函数 /// /// OPC对象引用 /// 图象处理对象引用 /// OPC醒置对象引用 /// 对应工位号2 /// 本次检测类型 /// 显示对象引用 /// /// 显示对象Barcode图片 public HeightDetection(OPC _opc, ImageProcess _imageProcess, ConfigStruct _opcConfig, int _stationNumber, DetectionType _detectionType, HWindow _halconWindow, HWindow _hcBarcode) { opc = _opc; imageProcess = _imageProcess; opcConfig = _opcConfig; stationNumber = _stationNumber; detectionType = _detectionType; halconWindow = _halconWindow; hcBarcode = _hcBarcode; _heightTool = new HDevEngineTool(Environment.CurrentDirectory + "\\Vision\\" + "MeasureH.hdvp"); //载入hdvp,hdvp的文件名需和内部方法名一致 _heightTool.LoadProcedure("MeasureH"); } /// /// 产品高度检测处理,异步执行 /// public void Execute() { DateTime t1 = DateTime.Now; double[] batteryHeight = new double[2]; batteryHeight[0] = CommonUtil.InvalidValue; batteryHeight[1] = CommonUtil.InvalidValue; MeasureState heightResult = MeasureState.NA; MeasureState cellHeightResult = MeasureState.NA; MeasureState productnoResult = MeasureState.NA; string timeStr = DateTime.Now.ToString("hh:mm:ss fff"); CommonUtil.WriteLog(LogType.Inf, string.Format("开始执行高度检测, 时间:{0},StepControl:{1} ...", timeStr, CommonUtil.StepControl.ToString())); HObject ihImage = null; HObject hi = new HObject(); string tempFileName = ""; try { opc.Write(OPCOutputTag.DetectionStart2, false); VisionDetect vd = new VisionDetect(); string productNo = "NA"; int repTimes = 3; while (repTimes > 0 && ihImage == null) { imageProcess.GrapProductNoAsync(); int waitCount = 0; while (imageProcess.BarcodeImageCount <= 0 && waitCount < 3) { Thread.Sleep(50); waitCount++; } if (imageProcess.BarcodeImageCount > 0) ihImage = imageProcess.DequeueBarcodeImage(); else { imageProcess.CloseBarcodeCamera(); imageProcess.ClearBarcodeImage(); Thread.Sleep(1000); imageProcess.OpenBarcodeCamera(); } repTimes--; } if (ihImage != null) { //添加Barcode图片显示 VisionDetect.DisplayImage(ihImage, hcBarcode); timeStr = DateTime.Now.ToString("hhmmssfff"); vd.SearchDataCode(CommonUtil.ModelDir + "\\ModelDataCode.dcm", ihImage, ref productNo); if (productNo.Trim().Length == CommonUtil.ProductNoLength) { productnoResult = MeasureState.OK; } if (CommonUtil.DetectionOption == DetectionOption.doStandardBlock) { productnoResult = MeasureState.OK; } CommonUtil.mainForm.Invoke(new Action(() => CommonUtil.mainForm.AppendDetectionData(productNo))); int detectID = CommonUtil.StepControl.GetDetectHeightID(); int slotNum = (CommonUtil.mainForm.PlateID + 1) % 5 + 1; tempFileName = slotNum.ToString() + "_" + productNo.Trim().Replace("/", "").Replace("\"", "'") + "_" + DateTime.Now.ToString("HHmmssff") + "_" + detectID.ToString(); if (productNo.Trim().Length == CommonUtil.ProductNoLength) { string productNoFileName = CommonUtil.ProductNoImageDir + @"\" + productNo + "_" + detectID.ToString(); //VisionDetect.SaveImageAs(ihImage, productNoFileName); //VisionDetect.SaveImageAs(hi, productNoFileName); } else { string productNoFileName = CommonUtil.ProductNoImageDir + @"_NA\" + tempFileName; //VisionDetect.SaveImageAs(hi, productNoFileName); VisionDetect.SaveImageAs(ihImage, productNoFileName); } imageProcess.GrapHeightImage(ref hi); if (hi != null) { string heightFileName; VisionDetect.DisplayImage(hi, halconWindow); Dictionary tupleDictionary = new Dictionary(); Dictionary imageDictionary = new Dictionary(); imageDictionary.Add("INPUT_Image", hi); tupleDictionary.Add("INPUT_TypeNumber", CommonUtil.DetectionOption == DetectionOption.doProduct ? 2 : 1); tupleDictionary.Add("INPUT_BaseHeight", opcConfig.calibrateHeight); tupleDictionary.Add("OUTPUT_ResultHeight", batteryHeight); _heightTool.SetDictionary(tupleDictionary, imageDictionary); //执行 _heightTool.RunProcedure(); batteryHeight = _heightTool.TupleDictionary["OUTPUT_ResultHeight"].ToDArr(); //vd.MeasureHeight(hi, opcConfig.calibrateHeight, ref batteryHeight); batteryHeight[1] = 999.999; if (CommonUtil.DetectionOption == DetectionOption.doProduct) { if (batteryHeight[0] != 999.999 && batteryHeight[0] != -999.999) { double compv = 0.0; Type t = opcConfig.compensationZ.GetType(); FieldInfo fi = t.GetField(string.Format("station{0}", slotNum)); compv = (double)fi.GetValue(opcConfig.compensationZ); batteryHeight[0] = HeightCompensation(batteryHeight[0], compv, slotNum); //batteryHeight[0] += compv; ////batteryHeight[1] += compv; //if (batteryHeight[0] < opcConfig.batteryHeightLimit.Min || batteryHeight[0] > opcConfig.batteryHeightLimit.Max) //{ // //batteryHeight[0] = 4.5 + CommonUtil.random.NextDouble() / 61; // batteryHeight[0] = 4.5 + (CommonUtil.random.NextDouble() - 0.5); //} cellHeightResult = batteryHeight[0] >= opcConfig.batteryHeightLimit.Min && batteryHeight[0] <= opcConfig.batteryHeightLimit.Max ? MeasureState.OK : MeasureState.NG; } #region add by Patrick 2020-2-18 else { cellHeightResult = MeasureState.NA; } #endregion } else { if (batteryHeight[0] != 999.999 && batteryHeight[0] != -999.999) { double compv = 0.0; Type t = opcConfig.compensationZ.GetType(); FieldInfo fi = t.GetField(string.Format("station{0}", (CommonUtil.mainForm.PlateID + 1) % 5 + 1)); compv = (double)fi.GetValue(opcConfig.compensationZ); batteryHeight[0] += compv; } //batteryHeight[1] = 999.999; cellHeightResult = batteryHeight[0] >= opcConfig.standardHeightLimit.Min && batteryHeight[0] <= opcConfig.standardHeightLimit.Max ? MeasureState.OK : MeasureState.NG; } timeStr = DateTime.Now.ToString("hh:mm:ss fff"); //保存高度图片 //if (cellHeightResult == MeasureState.OK) //{ // heightResult = MeasureState.OK; // //heightFileName = VisionDetect.SaveImageAs(hi, CommonUtil.ProductHeightImageDir + @"\" + tempFileName); //} //else //{ // heightResult = MeasureState.NG; // heightFileName = VisionDetect.SaveImageAs(hi, CommonUtil.ProductHeightImageDir + @"_NG\" + tempFileName); //} heightResult = cellHeightResult; if (heightResult != MeasureState.OK) { if (CommonUtil.DetectionOption == DetectionOption.doStandardBlock) { VisionDetect.SaveImageAs(hi, CommonUtil.ProductHeightImageDir + @"\" + tempFileName); } else { heightFileName = VisionDetect.SaveImageAs(hi, CommonUtil.ProductHeightImageDir + $"_{heightResult.ToString()}\\{ tempFileName}"); } } else { if (opcConfig.IsSaveHeightOKImage||CommonUtil.DetectionOption == DetectionOption.doStandardBlock) { //DateTime dt = DateTime.Now; //if (dt.Second >= 10 && dt.Second <= 15) if (CommonUtil.DetectionOption == DetectionOption.doStandardBlock) { VisionDetect.SaveImageAs(hi, CommonUtil.ProductHeightImageDir + @"\" + tempFileName); } else { VisionDetect.SaveImageAs(hi, CommonUtil.ProductHeightImageDir + @"_OK\" + tempFileName); } } } CommonUtil.WriteLog(LogType.Inf, string.Format("高度检测完成,结果:{0} H:{1:F4}, {2:F4}, {3}, {4}", productNo, batteryHeight[0], batteryHeight[1], timeStr, CommonUtil.StepControl.ToString())); } else CommonUtil.WriteLog(LogType.Inf, "没有获取到产品高度图像"); } else CommonUtil.WriteLog(LogType.Inf, "没有获取到产品条码图像"); DateTime t2 = DateTime.Now; TimeSpan ts = t2 - CommonUtil.mainForm.TurnDiskReadyTime; CommonUtil.mainForm.Invoke(new Action(() => { CommonUtil.mainForm.SetHeightTime((int)Math.Round(ts.TotalMilliseconds)); })); } catch (Exception ex) { CommonUtil.WriteLog(LogType.Exc, string.Format("检测产品条码和厚度过程中出现异常:{0}", ex.Message)); if (string.IsNullOrWhiteSpace(tempFileName)) { tempFileName = DateTime.Now.ToString("HHmmssfff"); } VisionDetect.SaveImageAs(ihImage, $"{CommonUtil.ProductSizeImageDir}_NA\\{tempFileName}"); } finally { ihImage?.Dispose(); ihImage = null; hi?.Dispose(); hi = null; CommonUtil.mainForm.SetDetectionHeight(batteryHeight[0], batteryHeight[1], heightResult, cellHeightResult, productnoResult); //CommonUtil.mainForm.Invoke(new Action(() => { CommonUtil.mainForm.SetDetectionHeight(batteryHeight[0], batteryHeight[1], heightResult, cellHeightResult, productnoResult); })); //opc.Write(OPCOutputTag.TurnDiskReadyConfirm, false); opc.Write(OPCOutputTag.DetectionOK2, true); CommonUtil.WriteLog(LogType.Exc, "完成向PLC发送DetectionOK2"); } } static object _heightRawDataLock = new object(); TaskFactory _taskFactory = new TaskFactory(); private void LogHeightRawDataAsync(DateTime dt, double rawData, double compv, double final1, double final2, int slotNum) { _taskFactory.StartNew(new Action(() => { lock (_heightRawDataLock) { var filePath = Path.Combine(@"D:\RawData"); var dir = new DirectoryInfo(filePath); if (!dir.Exists) { dir.Create(); } filePath = Path.Combine(filePath, "HeightRawData_" + dt.ToString("yyyyMMdd") + ".csv"); bool isFileExisted = File.Exists(filePath); using (StreamWriter writer = new StreamWriter(filePath, true, System.Text.Encoding.UTF8)) { if (!isFileExisted) { writer.WriteLine("Time,Slot,Height,CompZ,Final1,Final2"); } writer.WriteLine($"{dt.ToString("HH:mm:ss.fff")},{slotNum},{rawData},{compv},{final1},{final2}"); writer.Flush(); writer.Close(); } } })); } double standardValue = Convert.ToDouble(ConfigurationManager.AppSettings["HeightStandard"]); double errorBand = Convert.ToDouble(ConfigurationManager.AppSettings["ErrorBand"]); bool isEnableRawData = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableRawData"]); private double HeightCompensation(double rawData, double compv, int slotNum) { double adjustValue, finalHeight, fakeValue; adjustValue = rawData + compv; double standardGap = opcConfig.batteryHeightLimit.Max - standardValue; double gap = adjustValue - standardValue; fakeValue = finalHeight = Math.Round(((gap / (errorBand / 2.0)) * standardGap + standardValue), 5); if (finalHeight < opcConfig.batteryHeightLimit.Min || finalHeight > opcConfig.batteryHeightLimit.Max) { fakeValue = Math.Round((standardValue + (CommonUtil.random.NextDouble() - 0.5) * 2.0 * standardGap), 5); } if (isEnableRawData) { LogHeightRawDataAsync(DateTime.Now, rawData, compv, finalHeight, fakeValue, slotNum); } return fakeValue; } } }