|
|
@@ -1,14 +1,17 @@
|
|
|
-using CCDCount.MODEL.CameraClass;
|
|
|
+using CCDCount.DLL.Tools;
|
|
|
+using CCDCount.MODEL.CameraClass;
|
|
|
using CCDCount.MODEL.ConfigModel;
|
|
|
using CCDCount.MODEL.ShuLiClass;
|
|
|
using LogClass;
|
|
|
using MvCameraControl;
|
|
|
using System;
|
|
|
+using System.Collections.Concurrent;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Diagnostics;
|
|
|
using System.Drawing;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
using System.Runtime.Remoting.Messaging;
|
|
|
using System.Threading;
|
|
|
|
|
|
@@ -31,6 +34,7 @@ namespace CCDCount.DLL
|
|
|
public bool CameraStatic { get { return _CameraStatic; } }
|
|
|
private bool _CameraStatic = false;
|
|
|
|
|
|
+ // 返回交换线程状态
|
|
|
public bool CameraRunStatic { get { return IsSwitch; } }
|
|
|
|
|
|
public bool IsOpenLoadThread { get { return _IsOpenLoadThread; }}
|
|
|
@@ -40,9 +44,15 @@ namespace CCDCount.DLL
|
|
|
public int OkHistoryNum { get { return shuLiClass.GetOkHistoryNum(); } }
|
|
|
public int NgHistoryNum { get { return shuLiClass.GetNgHistoryNum(); } }
|
|
|
|
|
|
- ZmcauxClass zmcauxClass = new ZmcauxClass();
|
|
|
- //private BottingClass Botting = new BottingClass();
|
|
|
- //private MechanicalControlClass MechanicalControl = new MechanicalControlClass();
|
|
|
+ // 数粒信息发送线程
|
|
|
+ Thread SendBottLogicMessageThread = null;
|
|
|
+ bool IsSend = false;
|
|
|
+
|
|
|
+ // Modbus客户端实例
|
|
|
+ ModbusTcpClient modbusTcpClient = null;
|
|
|
+
|
|
|
+ // 颗粒结果待发送队列
|
|
|
+ ConcurrentQueue<ushort> SendQueue = new ConcurrentQueue<ushort>();
|
|
|
|
|
|
/// <summary>
|
|
|
/// 数粒状态计时器
|
|
|
@@ -56,6 +66,21 @@ namespace CCDCount.DLL
|
|
|
#endregion
|
|
|
|
|
|
#region 公共方法
|
|
|
+
|
|
|
+ public void SetModbusClient(ModbusTcpClient modbusTcpClient)
|
|
|
+ {
|
|
|
+ this.modbusTcpClient = modbusTcpClient;
|
|
|
+ if (!this.modbusTcpClient.IsTcpClientConnected())
|
|
|
+ {
|
|
|
+ LOG.error("ModbusTcpClient Connect Failed!");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ StartSendBottLogicMessageThread();
|
|
|
+ LOG.log("ModbusTcpClient Connect Success!", 6);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public MainThreadClass(ShuLiConfigClass configClass,CameraConfig CameraConfig)
|
|
|
{
|
|
|
// 数粒配置文件地址
|
|
|
@@ -108,7 +133,6 @@ namespace CCDCount.DLL
|
|
|
shuLiClass.WorkCompleted += Worker_OneGrainCompleted;
|
|
|
// 开启识别线程
|
|
|
shuLiClass.StartIdentifyFuntion(cameraClass.GetCamereImageSize().Width);
|
|
|
- zmcauxClass.OpenZmcauxCard();
|
|
|
result = true;
|
|
|
return result;
|
|
|
}
|
|
|
@@ -140,7 +164,6 @@ namespace CCDCount.DLL
|
|
|
StartSwitchThread();
|
|
|
// 开启识别线程
|
|
|
shuLiClass.StartIdentifyFuntion(cameraClass.GetCamereImageSize().Width);
|
|
|
- zmcauxClass.OpenZmcauxCard();
|
|
|
result = true;
|
|
|
return result;
|
|
|
}
|
|
|
@@ -156,7 +179,7 @@ namespace CCDCount.DLL
|
|
|
StopSwitchThread();
|
|
|
// 数粒识别线程关闭
|
|
|
shuLiClass.StopIdentifyFuntion();
|
|
|
- zmcauxClass.CloseZmcauxCard();
|
|
|
+ StopSendBottLogicMessageThread();
|
|
|
}
|
|
|
|
|
|
public bool ReLoadCamera(string CameraSN)
|
|
|
@@ -280,7 +303,9 @@ namespace CCDCount.DLL
|
|
|
/// <param name="e"></param>
|
|
|
private void Worker_OneGrainCompleted(object sender, ActiveObjectEventArgsClass e)
|
|
|
{
|
|
|
- LOG.log("有活跃物体转换为了历史物体,回调事件被触发!",6);
|
|
|
+ LOG.log("有活跃物体转换为了历史物体,回调事件被触发!", 6);
|
|
|
+ LOG.log(string.Format("图像处理实例中的待识别图像缓存队列长度{0}", shuLiClass.ImageNum), 6);
|
|
|
+
|
|
|
if (e.Actives.Where(o => o.StateCode == 7).Count() > 0)
|
|
|
{
|
|
|
stopwatch.Restart();
|
|
|
@@ -291,82 +316,34 @@ namespace CCDCount.DLL
|
|
|
stopwatch.Stop();
|
|
|
_ShuLiState = true;
|
|
|
}
|
|
|
+ //往数组中计数
|
|
|
+ ushort result = new ushort();
|
|
|
+ // 事件处理逻辑
|
|
|
foreach (ActiveObjectClass oneActive in e.Actives)
|
|
|
{
|
|
|
- LOG.log(string.Format("输出当前颗粒信息,开始行:{0},结束行:{1},开始时间:{2}结束时间:{3},颗粒状态:{4}",
|
|
|
- oneActive.StartLine, oneActive.LastSeenLine, oneActive.StartCheckTime.ToString("O"), oneActive.EndCheckTime.ToString("O"), oneActive.StateCode), 6);
|
|
|
+ Console.WriteLine(string.Format("输出当前颗粒信息,开始行:{0},结束行:{1},开始时间:{2}结束时间:{3},颗粒状态:{4},通道数:{5}",
|
|
|
+ oneActive.StartLine, oneActive.LastSeenLine, oneActive.StartCheckTime.ToString("O"), oneActive.EndCheckTime.ToString("O"), oneActive.StateCode, oneActive.ChannelNO));
|
|
|
+ LOG.log(string.Format("输出当前颗粒信息,开始行:{0},结束行:{1},开始时间:{2}结束时间:{3},颗粒状态:{4},通道数:{5}",
|
|
|
+ oneActive.StartLine, oneActive.LastSeenLine, oneActive.StartCheckTime.ToString("O"), oneActive.EndCheckTime.ToString("O"), oneActive.StateCode, oneActive.ChannelNO), 6);
|
|
|
|
|
|
- }
|
|
|
- // 事件处理逻辑
|
|
|
- float step = -1;
|
|
|
- float[] floats = new float[9];
|
|
|
- zmcauxClass.GetMessageFromVar("countStep", ref step);
|
|
|
- LOG.log(string.Format("{0}:countStep = {1}", "MainThreadClass-Worker_OneGrainCompleted", step),6);
|
|
|
- if (step < 1 || step>3)
|
|
|
- {
|
|
|
- zmcauxClass.GetMessageFromArray("CCD_DATA4", ref floats, 0, 9);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- switch (step)
|
|
|
+ if (oneActive.StateCode == 0 && oneActive.ChannelNO != -1)
|
|
|
{
|
|
|
- case 1:
|
|
|
- zmcauxClass.GetMessageFromArray("CCD_DATA1", ref floats, 0, 9);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- zmcauxClass.GetMessageFromArray("CCD_DATA2", ref floats, 0, 9);
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- zmcauxClass.GetMessageFromArray("CCD_DATA3", ref floats, 0, 9);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- LOG.log("读取轴卡结果数据:" + floats[0] + " " + floats[1] + " " + floats[2] + " " + floats[3] + " " + floats[4] + " " + floats[5] + " " + floats[6] + " " + floats[7] + " " + floats[8],6);
|
|
|
- foreach (ActiveObjectClass oneActive in e.Actives)
|
|
|
- {
|
|
|
- if (oneActive.StateCode != 0)
|
|
|
- {
|
|
|
- floats[8] += 1;
|
|
|
+ //单通道合格计数
|
|
|
+ result |= (ushort)(1 << (oneActive.ChannelNO));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (oneActive.ChannelNO != -1)
|
|
|
- floats[oneActive.ChannelNO] += 1;
|
|
|
- else
|
|
|
- floats[8] += 1;
|
|
|
+ //单通道不合格计数
|
|
|
+ result |= (ushort)(1 << 8);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
- LOG.log("写入轴卡结果数据:" + floats[0] + " " + floats[1] + " " + floats[2] + " " + floats[3] + " " + floats[4] + " " + floats[5] + " " + floats[6] + " " + floats[7] + " " + floats[8],6);
|
|
|
- if (step < 1 || step>3)
|
|
|
+ LOG.log("当前待发送队列数量:" + SendQueue.Count, 6);
|
|
|
+ if(IsSend)
|
|
|
{
|
|
|
- zmcauxClass.SetMessageToArray("CCD_DATA4", floats, 0, 9);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- switch (step)
|
|
|
- {
|
|
|
- case 1:
|
|
|
- zmcauxClass.SetMessageToArray("CCD_DATA1", floats, 0, 9);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- zmcauxClass.SetMessageToArray("CCD_DATA2", floats, 0, 9);
|
|
|
- break;
|
|
|
- case 3:
|
|
|
- zmcauxClass.SetMessageToArray("CCD_DATA3", floats, 0, 9);
|
|
|
- break;
|
|
|
- }
|
|
|
+ SendQueue.Enqueue(result);
|
|
|
}
|
|
|
- //OnOneGrain(e.Actives);
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 装瓶逻辑
|
|
|
- /// </summary>
|
|
|
- private void BottLogicFunction()
|
|
|
- {
|
|
|
-
|
|
|
- }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 对外通知事件
|
|
|
@@ -441,6 +418,100 @@ namespace CCDCount.DLL
|
|
|
}
|
|
|
stopwatch.Stop();
|
|
|
}
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 启动发送消息线程
|
|
|
+ /// </summary>
|
|
|
+ private void StartSendBottLogicMessageThread()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //zmcauxClass.OpenZmcauxCard();
|
|
|
+
|
|
|
+ timeBeginPeriod(1); // 设置为1ms精度
|
|
|
+ IsSend = true;
|
|
|
+ SendBottLogicMessageThread = new Thread(SendBottLogicMessageProcess);
|
|
|
+ SendBottLogicMessageThread.Start();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LOG.error("Start thread failed!, " + ex.Message);
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 停止发送消息线程
|
|
|
+ /// </summary>
|
|
|
+ private void StopSendBottLogicMessageThread()
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // 标志位设为false
|
|
|
+ IsSend = false;
|
|
|
+ if (SendBottLogicMessageThread != null && SendBottLogicMessageThread.IsAlive)
|
|
|
+ SendBottLogicMessageThread.Join();
|
|
|
+ if (modbusTcpClient != null) modbusTcpClient.Disconnect();
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LOG.error("Start thread failed!, " + ex.Message);
|
|
|
+ throw;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 信息发送线程
|
|
|
+ /// </summary>
|
|
|
+ private void SendBottLogicMessageProcess()
|
|
|
+ {
|
|
|
+ //获取数据
|
|
|
+ ushort sendMessage = 0;
|
|
|
+ bool AllowTransfer = false;
|
|
|
+ bool TransferDone = false;
|
|
|
+ Stopwatch sw = Stopwatch.StartNew();
|
|
|
+ while (IsSend)
|
|
|
+ {
|
|
|
+ LOG.log("进入线程", 6);
|
|
|
+ sw.Restart();
|
|
|
+ sendMessage = new ushort();
|
|
|
+ //读取装瓶状态
|
|
|
+ AllowTransfer = false;
|
|
|
+ TransferDone = false;
|
|
|
+ bool[] ReadResult = modbusTcpClient.ReadCoilsRegister(slaveId: 1, startAddress: 11, numRegisters: 2);
|
|
|
+ if (ReadResult == null)
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ AllowTransfer = ReadResult[1];
|
|
|
+ TransferDone = ReadResult[0];
|
|
|
+ //LOG.log(string.Format("读取值:AllowTransfer[0]:{0},TransferDone[1]:{1}", AllowTransfer, TransferDone), 6);
|
|
|
+ //当允许写入且处于未写入的状态时
|
|
|
+ if (AllowTransfer && !TransferDone)
|
|
|
+ {
|
|
|
+ if (SendQueue.Count() > 0)
|
|
|
+ {
|
|
|
+ if (!SendQueue.TryDequeue(out sendMessage))
|
|
|
+ {
|
|
|
+ LOG.error("MainThreadClass-SendBottLogicMessageProcess-SendQueue.TryDequeue failed!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (sendMessage != 0)
|
|
|
+ {
|
|
|
+ //写入数据
|
|
|
+ modbusTcpClient.WriteSingleRegister(slaveId: 1, registerAddress: 100, value: sendMessage);
|
|
|
+ modbusTcpClient.WriteCoilsRegister(slaveId: 1, CoilsAddress: 11, values: true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sw.Stop();
|
|
|
+ LOG.log(string.Format("离开线程写入值:sendMessage[1]:{0},此次写值耗时:{1}", sendMessage, sw.Elapsed), 6);
|
|
|
+ Thread.Sleep(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 外部函数
|
|
|
+ [DllImport("winmm.dll")]
|
|
|
+ static extern uint timeBeginPeriod(uint period);
|
|
|
#endregion
|
|
|
}
|
|
|
}
|