2.5 C#视觉程序开发实例1----IO_Manager实现脉冲输出控制

news2025/4/14 5:19:48

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://wait
                   if (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://reset
                   if (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  Write
      PInvoker.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输出 status
      task_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();
  1. ImgProcessCCD(int n_thread_index = 0) 函数增加统计代码
// 添加线程统计信息
 thead0_summary.Update_Statistics(status);
  1. ImgProcessCCD(int n_thread_index = 0) 函数增加显示统计结果
bdDisplay_Runsets1.Update_Cam_Text(status, thead0_summary.toString());
  1. 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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1902454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SpringBoot】SpringBoot内置Servlet容器源码分析-Tomcat

自动装配加载 ServletWebServerFactoryAutoConfiguration 在自动装配的时候&#xff0c;会加载spring.factories&#xff0c;并且添加到IOC容器中。这里包含web自动配置类ServletWebServerFactoryAutoConfiguration &#xff0c;其中本类中注入三个bean&#xff0c;分别是Embed…

vue2 data内对象引用另一个data对象无法使用this的解决办法

背景&#xff1a;data内有一复杂对象&#xff0c;并且内部一属性经常修改&#xff0c;每次修改的话属性.属性会很长&#xff0c;所以希望引用另一简单对象&#xff0c;但data内this用不了。(集合数组是地址引用&#xff0c;基本数据类型这么操作没意义) 如&#xff1a; 解决办法…

【人工智能】-- 智能机器人

个人主页&#xff1a;欢迎来到 Papicatch的博客 课设专栏 &#xff1a;学生成绩管理系统 专业知识专栏&#xff1a; 专业知识 文章目录 &#x1f349;引言 &#x1f349;机器人介绍 &#x1f348;机器人硬件 &#x1f34d;机械结构 &#x1f34d;传感器 &#x1f34d;控…

2024年江苏省研究生数学建模科研创新实践大赛C题气象数据高精度融合技术研究论文和代码分析

经过不懈的努力&#xff0c; 2024年江苏省研究生数学建模科研创新实践大赛C题气象数据高精度融合技术研究论文和代码已完成&#xff0c;代码为C题全部问题的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1模型的建…

高效管理个人日程,智慧校园行政办公全指南

在智慧校园的行政办公体系里&#xff0c;个人日程管理功能担当起协调与优化每位教职员工日常安排的角色&#xff0c;它像一位贴心的时间助理&#xff0c;确保工作与私人生活的和谐并进。这一功能设计得既直观又灵活&#xff0c;让使用者能以自己偏好的视角审视时间规划&#xf…

Gradient Descent

在整个maching learning的第三个步骤要找一个最好的function。在第二步是定义了一个 Loss function L&#xff0c;这个L是一个function的fuction 求完偏微分之后得到的向量就是Gradient&#xff08;黄色部分&#xff09; 随机找一个起始点0&#xff0c;它的等高线的法线方向就…

绝区壹--LLM的构建模块

前言 语言是人类交流的本质&#xff0c;大型语言模型 (LLM) 凭借其出色的理解和生成类似人类的文本的能力&#xff0c;彻底改变了我们与语言互动和利用语言的方式。深入研究 LLM 的构建块&#xff08;向量、标记和嵌入&#xff09;&#xff0c;揭示了使这些模型能够以前所未有…

Nginx的安装与配置 —— Linux系统

一、Nginx 简介 1.1 什么是 Nginx Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&#xff0c;在BSD-like 协议下发行。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务…

layui-表单(输入框)

1.基本使用方法 先写一个表单元素块 form 加上layui-form 里面写行区块结构&#xff0c;如下&#xff1a; 2.输入框选项 placeholder默认文本 autocomplete自动填充 lay-verify required必填

如何监控和分析 PostgreSQL 中的查询执行计划?

文章目录 一、为什么监控和分析查询执行计划很重要二、PostgreSQL 中用于获取查询执行计划的方法三、理解查询执行计划的关键元素四、通过示例分析查询执行计划五、优化查询执行计划的常见策略六、使用工具辅助分析七、结合实际案例的详细分析八、总结 在 PostgreSQL 数据库中&…

vb.netcad二开自学笔记5:ActiveX链接CAD的.net写法

一、必不可少的对象引用 使用activex需要在项目属性中勾选以下两个引用&#xff0c;若找不到&#xff0c;则浏览定位直接添加下面两个文件&#xff0c;可以看到位于cad的安装路径下&#xff0c;图中的3个mgd.dll也可以勾选。 C:\Program Files\Autodesk\AutoCAD 2024\Autodes…

上万组风电,光伏,用户负荷数据分享

上万组风电&#xff0c;光伏&#xff0c;用户负荷数据分享 可用于风光负荷预测等研究 获取链接&#x1f517; https://pan.baidu.com/s/1izpymx6R3Y8JsFdx42rL0A 提取码&#xff1a;381i 获取链接&#x1f517; https://pan.baidu.com/s/1izpymx6R3Y8JsFdx42rL0A 提取…

Python统计实战:时间序列分析之二阶曲线预测和三阶曲线预测

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能&#xff0c;从而更快地掌握解决问题所需的能力。 &#xff08;以下练习题来源于《统计学—基于Python》。请在Q群455547227下载原始数据。&#xff09; 练习题 下表是某只股票…

Leetcode - 周赛404

目录 一&#xff0c;3200. 三角形的最大高度 二&#xff0c;3201. 找出有效子序列的最大长度 I 三&#xff0c;3202. 找出有效子序列的最大长度 II 四&#xff0c;3203. 合并两棵树后的最小直径 一&#xff0c;3200. 三角形的最大高度 本题直接模拟&#xff0c;分别计算一下…

KVM使用命令行添加新磁盘(注:支持热插拔)

1、使用qemu-img创建格式为qcow2的磁盘 [rootkvm ~]# qemu-img create -f qcow2 /var/lib/libvirt/images/test-disk.qcow2 15G 2、显示虚拟机硬盘列表&#xff0c;查看未使用的target [rootkvm ~]# virsh domblklist kvm-client 3、添加硬盘到kvm-client虚拟机中 [rootkvm…

Matlab2023a保姆级安装教程,附下载安装包资料

安装包放在前面&#xff01; 「MATLAB安装包 获取链接&#xff1a;https://pan.quark.cn/s/d8abf7394b3e 温馨提示:路径中不要有中文&#xff01;&#xff01; 1、下载全部的安装包&#xff0c;然后解压得到安装文件 2、解压之后可以看到包含Matlab R2023a安装光驱文件及Cr…

【Linux进阶】文件系统5——ext2文件系统(inode)

1.再谈inode (1) 理解inode&#xff0c;要从文件储存说起。 文件储存在硬盘上&#xff0c;硬盘的最小存储单位叫做"扇区"&#xff08;Sector&#xff09;。每个扇区储存512字节&#xff08;相当于0.5KB&#xff09;。操作系统读取硬盘的时候&#xff0c;不会一个个…

低负载高效率(轻载高效)的BUCK是如何实现的?

-----本文简介----- 主要内容包括&#xff1a; 轻载高效BUCK是何原理&#xff1f; ----- 正文 ----- 先赞↓后看&#xff0c;养成习惯&#xff01; 一、 DC-DC的控制模式与效率 1. PWM模式 如下图是PWM控制模式的DC-DC&#xff0c;PWM(Pulse Width Modulation)&#x…

昇思25天学习打卡营第11天|MindSpore 助力下的 GPT2:数据集加载处理及模型全攻略

目录 环境配置 数据集下载和获取 数据集拆分 处理数据集 模型构建 ​​​​​​​模型训练 ​​​​​​​模型推理 环境配置 “%%capture captured_output”这一行指令通常旨在捕获后续整个代码块所产生的输出结果。首先&#xff0c;将已预装的 mindspore 库予以卸载。随后&a…

奇迹MU 骷髅战士在哪

BOSS分布图介绍 我为大家带来各地区怪物分布图。在游戏前期&#xff0c;很多玩家可能会不知道该去哪里寻找怪物&#xff0c;也不知道哪些怪物值得打。如果选择了太强的怪物&#xff0c;弱小的玩家可能会无法抵御攻击。如果选择了低等级的boss&#xff0c;收益可能并不理想。所…