2.5 C#视觉程序开发实例1----IO_Manager实现脉冲输出控制
1 目标效果视频
目标效果展示
IO_Manager
2 信号输出流程说明
为了防止线程不同步导致输出信号没有被输出, 尽量使用一个输出队列来进行输出的管理
3 IO_Manager中添加内容
3.0 添加两个类
1 Out_State :输出状态标志
public enum Out_State : int{State_Out = 1,// 输出状态State_Reset = 2,// 复位状态State_Wait = 0,//wait}
2 Task_Out_Server 输出管理类,实现了输出请求队列的管理
/// <summary>
/// Task_IO_Out_Server
/// </summary>
public class Task_Out_Server
{// 最大缓存 buffer个数static int max_buffer = 16;public Out_State state;public List<bool> out_requests;private int index_ok;private int index_ng;private int index_sto;private int out_pulse_width;// 输出脉冲宽度private int reset_pulse_width;// 输出复位脉冲宽度private DateTime cur_starttime;// 当前task 开始时间public object mutex;private int count_output;private int count_reset;private int count_wait;private int output_mode = 0;//0: pulse 1: 开关亮输出public int Tasks_Count{get { return out_requests.Count; }}public string Task_Info{get{return "outcount=" + count_output.ToString() + ",resetcount=" + count_reset.ToString() + ",waitcount=" + count_wait.ToString();}}public Task_Out_Server(){state = Out_State.State_Wait;out_requests = new List<bool>();index_ok = -1;index_ng = -1;index_sto = -1;out_pulse_width = 100;reset_pulse_width = 10;mutex = new object();cur_starttime = DateTime.Now;}public void init_Task(int _index_ok, int _index_ng, int _index_sto, int out_pulse, int reset_pusle){index_ok = _index_ok;index_ng = _index_ng;index_sto = _index_sto;out_pulse_width = out_pulse;reset_pulse_width = reset_pusle;count_output = count_reset = count_reset = 0;}public void Add_One_Task(bool status){lock (mutex){if (out_requests.Count < max_buffer)out_requests.Add(status);// 增加一个任务}}public void Update_Task_State(DateTime cur_time, ref bool[] outstates){if (outstates == null) return;lock (mutex){switch (state){default://waitif (out_requests.Count > 0){bool _status = out_requests[0];out_requests.RemoveAt(0);state = Out_State.State_Out;if (index_ok != -1)outstates[index_ok] = _status;if (index_ng != -1)outstates[index_ng] = !_status;if (index_sto != -1)outstates[index_sto] = true;cur_starttime = cur_time;count_output++;}break;case Out_State.State_Out:// 输出if (cur_time.Subtract(cur_starttime).TotalMilliseconds >= out_pulse_width){//sto 复位if (index_sto != -1)outstates[index_sto] = false; if (output_mode == 0)// pulse输出{if (index_ok != -1)outstates[index_ok] = false;if (index_ng != -1)outstates[index_ng] = false;}state = Out_State.State_Reset;count_reset++;}break;case Out_State.State_Reset://resetif (cur_time.Subtract(cur_starttime).TotalMilliseconds >= out_pulse_width + reset_pulse_width){state = Out_State.State_Wait;count_wait++;}break;}}}
}
3.1 增加代码 初始化Task_Out_Server
增加Task_Out_Server 实例
#region Task_IO_Server 用来管理STO|OK|NG 输出public Task_Out_Server task_out_server_thread0 =new Task_Out_Server();private int pulse_width = 300;// 脉冲输出时长private int pulse_reset_width = 100;// 脉冲复位时长#endregion
IO_Manager()初始化函数中增加Init_Task()
目的: 绑定输出STO|OK|NG pin角,然后脉冲输出宽度和复位宽度
//初始化 task_out_server_thread0,
task_out_server_thread0.init_Task(index_ok,index_ng,index_sto, pulse_width, pulse_reset_width);
3.2 Write()函数更新
//更新STO |OK|NG输出 status
task_out_server_thread0.Update_Task_State(cur,ref Outputs);
public int Write()
{int nRet = 0;DateTime cur = DateTime.Now;try{// DM8 WritePInvoker.SetDM8(array_dm8_out, count_DM8, count_DM8);for (int i = 0; i < count_DM8; i++){if (Outputs[i]) array_dm8_out[i] = 1;else array_dm8_out[i] = 0;} //更新STO |OK|NG输出 statustask_out_server_thread0.Update_Task_State(cur,ref Outputs);GC.KeepAlive(array_dm8_out);}catch (Exception ex){nRet = -2;}return nRet;
}
4 Form_vision中增加代码
4.1 添加一个线程统计的类
实现线程结果的统计,和保存
/// <summary>
/// thread_statistics
/// 线程结果统计
/// </summary>
public class Thread_Statistics
{public int count_ok;//当前线程ok 计数public int count_ng;//当前线程ng 计数public int count_total;//当前线程Total 计数public bool status;// 当前线程状态public Thread_Statistics(){count_ok = 0; count_ng = 0; count_total = 0;status = true;}public void Reset(){count_ok = 0; count_ng = 0; count_total = 0;status = true;}public string toString(){string str = "";str = "总数:" + count_total.ToString() + ",OK:" + count_ok.ToString() + ",NG:" + count_ng.ToString();return str; }/// <summary>/// Update_Statistics/// </summary>/// <param name="status"></param>public void Update_Statistics(bool status){if (status) count_ok += 1;else count_ng += 1;count_total += 1;}
}
4.2 mgAcqRunCCD0 中增加采集事件
触发事件发生后,通知Img_Process现成, newImgEvent_thread.Set()
// 通过判断上升沿进行 相机采集n_trig0_cur =Convert.ToInt32( ContextManager.get_IOCtx().get_Trig0());if (n_trig0_cur > 0 && n_trig0_last == 0) //判断上升沿触发{//相机采集int nRet = 0; if(nRet==0){newImgEvent_thread.Set();}}
4.3 Img_Process线程增加相应的功能代码
1.Create_Thread()中 创建线程 ImgProcess
//创建ImgProcess 现成0
threadProcessCCD=new Task(() => ImgProcessCCD(), TaskCreationOptions.LongRunning);threadProcessCCD.Start();
- ImgProcessCCD(int n_thread_index = 0) 函数增加统计代码
// 添加线程统计信息thead0_summary.Update_Statistics(status);
- ImgProcessCCD(int n_thread_index = 0) 函数增加显示统计结果
bdDisplay_Runsets1.Update_Cam_Text(status, thead0_summary.toString());
- ImgProcessCCD(int n_thread_index = 0) 函数增加输出STO|OK|NG
// 输出脉冲
ContextManager.get_IOCtx().task_out_server_thread0.Add_One_Task(status);
ImgProcessCCD()汇总
private void ImgProcessCCD(int n_thread_index = 0)
{ListViewItem DATA = new ListViewItem();DateTime ts3 = DateTime.Now; bool[] flag = new bool[100]; DateTime current = DateTime.Now;bool status = true;while ( newImgEvent_thread.WaitOne()) //相机1&2都已经已拍照{// 添加线程统计信息thead0_summary.Update_Statistics(status);bdDisplay_Runsets1.Update_Cam_Text(status, thead0_summary.toString());// 输出脉冲ContextManager.get_IOCtx().task_out_server_thread0.Add_One_Task(status);// img process if (StopProgramEvent.WaitOne(0, true)) break;} //end while return;
}