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

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.mfbz.cn/a/777934.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【课程总结】Day13(下):人脸识别和MTCNN模型

前言 在上一章课程【课程总结】Day13(上):使用YOLO进行目标检测,我们了解到目标检测有两种策略,一种是以YOLO为代表的策略:特征提取→切片→分类回归;另外一种是以MTCNN为代表的策略:先图像切片→特征提取→分类和回归。因此,本章内容将深入了解MTCNN模型,包括:MTC…

Windows 11文件资源管理器选项卡的4个高级用法,肯定有你喜欢的

作为一个每天使用文件资源管理器来管理我的工作流程的人,选项卡帮助我为处于不同完成阶段的工作创建了不同的文件夹。以下是我使用选项卡提高工作效率的最佳技巧。 打开和关闭选项卡 假设你的计算机上安装了Windows 11的最新更新,请按Ctrl+E打开文件资源管理器。在我发现“…

STM32智能家居掌上屏实战:从WiFi连接到MQTT通信,打造你的家庭物联网网关

摘要: 本文深入探讨一种基于STM32的智能家居掌上屏设计方案&#xff0c;详细阐述其硬件架构、软件设计以及通信协议等关键技术细节。该方案利用WiFi构建局域网&#xff0c;实现与各类传感器、执行器的便捷交互&#xff0c;并通过TFT彩屏提供直观的控制和数据展示&#xff0c;旨…

五、保存数据到Excel、sqlite(爬虫及数据可视化)

五、保存数据到Excel、sqlite&#xff08;爬虫及数据可视化&#xff09; 1&#xff0c;保存数据到excel1.1 保存九九乘法表到excel&#xff08;1&#xff09;代码testXwlt.py&#xff08;2&#xff09;excel保存结果 1.2 爬取电影详情并保存到excel&#xff08;1&#xff09;代…

大模型周报|15 篇必读的大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.谷歌推出风格感知拖放新方法 Magic Insert 来自谷歌的研究团队提出了 Magic Insert&#xff0c;用于以物理上可信的方式将用户提供的图像中的对象拖放到不同风格的目标图像中&#xff0c;同时与目标图像的风格相匹…

基于CLIP特征的多模态大模型中的视觉短板问题

【论文极速读】 基于CLIP特征的多模态大模型中的视觉短板问题 FesianXu 20240706 at Tencent WeChat search team 前言 今天读到篇CVPR 24’的论文 [1]&#xff0c;讨论了常见的多模态大模型&#xff08;大多都基于CLIP语义特征&#xff0c;以下简称为MLLM&#xff09;中的视觉…

Git错误分析

错误案例1&#xff1a; 原因&#xff1a;TortoiseGit多次安装导致&#xff0c;会记录首次安装路径&#xff0c;若安装路径改变&#xff0c;需要配置最后安装的路径。

HTML5使用<details>标签:展开/收缩信息

details 标签提供了一种替代 JavaScript 的方法&#xff0c;它主要是提供了一个展开/收缩区域。details 标签中可以使用 summary 标签从属于 details 标签&#xff0c;单击 summary 标签中的内容文字时&#xff0c;details 标签中的其他所有从属元素将会展开或收缩。语法如下&a…

Redies基础篇(一)

Redis 是一个高性能的key-value数据库。Redies支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作&#xff0c;而且这些操作都是原子性的&#xff…

小白必看!推荐三本高质量python书籍,让你直接原地起飞

Python是一种多功能语言。它经常用作Web应用程序的脚本语言&#xff0c;嵌入到软件产品中&#xff0c;以及人工智能和系统任务管理。它既简单又强大&#xff0c;非常适合初学者和专业程序员。 python的自学书籍非常多&#xff0c;涉及基础入门、web开发、机器学习、数据分析、…

印度第二大移动提供商 3.75 亿数据待售

一个名为“xenZen”的威胁行为者已在 BreachForums 上出售 Airtel 的数据库。 该列表包含来自 3.75 亿客户的数据。 数据详情&#xff1a; 手机号码 名 出生日期 父亲的名字 地址 电子邮件ID 类型 国籍 阿达尔 带照片的身份证明详细信息 地址详细信息证明等 鉴于…

003-基于Sklearn的机器学习入门:回归分析(上)

本节及后续章节将介绍机器学习中的几种经典回归算法&#xff0c;所选方法都在Sklearn库中聚类模块有具体实现。本节为上篇&#xff0c;将介绍基础的线性回归方法&#xff0c;包括线性回归、逻辑回归、多项式回归和岭回归等。 2.1 回归分析概述 回归&#xff08;Regression&…

3-3 超参数

3-3 超参数 什么是超参数 超参数也是一种参数&#xff0c;它具有参数的特性&#xff0c;比如未知&#xff0c;也就是它不是一个已知常量。是一种手工可配置的设置&#xff0c;需要为它根据已有或现有的经验&#xff0c;指定“正确”的值&#xff0c;也就是人为为它设定一个值&…

SAP PS学习笔记01 - PS概述,创建Project和WBS

本章开始学习PS&#xff08;Project System&#xff09;。 1&#xff0c;PS的概述 PS&#xff08;Project System&#xff09;是SAP企业资源规划系统中的一个关键模块&#xff0c;主要用于项目管理。 它提供了一个全面的框架来规划、控制和执行项目&#xff0c;涵盖了从项目启…

AttackGen:一款基于LLM的网络安全事件响应测试工具

关于AttackGen AttackGen是一款功能强大的网络安全事件响应测试工具&#xff0c;该工具利用了大语言模型和MITRE ATT&CK框架的强大功能&#xff0c;并且能够根据研究人员选择的威胁行为组织以及自己组织的详细信息生成定制化的事件响应场景。 功能介绍 1、根据所选的威胁行…

03:Spring MVC

文章目录 一&#xff1a;Spring MVC简介1&#xff1a;说说自己对于Spring MVC的了解&#xff1f;1.1&#xff1a;流程说明&#xff1a; 一&#xff1a;Spring MVC简介 Spring MVC就是一个MVC框架&#xff0c;Spring MVC annotation式的开发比Struts2方便&#xff0c;可以直接代…

【TB作品】脉搏测量,ATMEGA8单片机,Proteus仿真,ATmega8控制脉搏测量与显示系统

硬件组成&#xff1a; LCD1602脉搏测量电路&#xff08;带灯&#xff09;蜂鸣器报警按键设置AT24C02 功能&#xff1a; &#xff08;1&#xff09;LCD1602主页显示脉搏、报警上限、报警下限&#xff1b; &#xff08;2&#xff09;五个按键&#xff1a;按键1&#xff1a;切换设…

数据库测试|Elasticsearch和ClickHouse的对决

前言 数据库作为产品架构的重要组成部分&#xff0c;一直是技术人员做产品选型的考虑因素之一。 ClkLog会经常遇到小伙伴问支持兼容哪几种数据库&#xff1f;为什么是选择ClickHouse而不是这个或那个。 由于目前市场上主流的数据库有许多&#xff0c;这次我们选择其中一个比较典…

(软件06)串口屏的应用,让你的产品显得高级一点(下篇)

本文目录 学习前言 单片机代码实现 学习前言 目前市面上我记得好像有IIC的屏幕、SPI的屏幕、并口屏幕、还有就是今天我们介绍的这个串口屏了&#xff0c;串口屏&#xff0c;就是用串口进行通讯的&#xff0c;上篇我们已经介绍了屏幕供应商提供的上位机软件进行配置好了&#…

2000-2019年各省市资源错配指数

资源错配指数&#xff08;Misallocation Index&#xff09;是衡量一个地区或国家资源配置效率的重要经济指标。以下是对资源错配指数相关数据的介绍&#xff1a; 数据简介 定义&#xff1a;资源错配指数是一个反映生产要素配置合理性的指标&#xff0c;高指数意味着资源配置效…