用C进行仪器控制系列数字万用表(4)
此为"用C#进行仪器控制系列--数字万用表"的第4篇文章,在此之前已经编写了3篇相关文章了,可参见:
1)用C#进行仪器控制系列——数字万用表(1):该篇文章介绍了如何从零开始创建一个控制台应用程序,实现 Keysight 数字万用表的电压测量,并将结果通过控制台展示;
2)用C#进行仪器控制系列——数字万用表(2):该篇文章在第1篇文章的基础上,以窗体应用程序的形式重写了万用表电压测量程序,并能够自动识别仪器地址,以及能够通过按钮控制测量的开始和停止,电压的显示等。
3)用C#进行仪器控制系列——数字万用表(3):该篇文章在第2篇文章的基础上,通过代码的简单优化,实现了不同测量类型的下拉选择,根据下拉选项执行对应类型的测量功能(电压、电流、电阻、二极管、导通、频率测试等)。
此篇文章是在第3篇文章的基础上,添加波形图表显示功能。优化需求:添加波形图表显示功能,用以观测数据的变化趋势
通过添加波形图表功能,将测量数据实时传递给波形图表,使其能够在界面中显示测量的历史数据,就可以观测到数据的变化趋势了。最终想要实现的效果如下图所示。
需求实现效果优化实现过程
1)窗体界面的优化从工具箱中找到 Visual Studio 自带的 Chart 图表控件,并将其拖拽至窗体面板中。
Chart控件选中新添加的 Chart 控件,在其属性窗口中找到图表的"Series"属性,然后点击该属性右侧的3个小圆点组成的按钮进入"Series"属性设置页,如下图所示
图表的"Series"属性修改数据序列的名称(Name)为"Data",修改图表类型(ChartType)为"Line",即修改图表类型为折线图显示。
修改"Series"属性设置完图表属性后,调整窗体上相关控件的布局,调整后如下图所示。
调整窗体布局
2)代码优化
主要涉及如下3块代码段的修改:在窗体的构造函数中增加曲线图样式的设置语句,包括曲线样式、曲线颜色的设置。public Form1() { InitializeComponent(); // 设置曲线图样式 WaveChart.Series[0].ChartType = SeriesChartType.Line; WaveChart.Series[0].Color = System.Drawing.Color.Blue; }在开始测试的事件响应代码段添加清除曲线代码,实现开始测试时重新绘图。if (btnStart.Text == "开始测试") { btnStart.Text = "停止测试"; // 清空曲线图数据 WaveChart.Series[0].Points.Clear();在测量线程代码段,增加将实时测量数据传递给波形图表的代码。// 循环读取万用表数据 while (true) { // 发送采集命令 messageBasedSession.WriteString(":READ?", true); // 读取返回值 string response = messageBasedSession.ReadString(); // 在控件和图表中输出结果 this.Invoke((MethodInvoker)delegate { resultTextBox.Text = ChangeDataToD(response.Trim()); WaveChart.Series[0].Points.AddY(double.Parse(resultTextBox.Text)); }); }优化效果验证
程序优化后的运行效果如下图所示,可通过下拉选择测量类型,实现不同的测试需求,然后通过Text Box显示控件和Chart波形图表显示数据。
运行效果
通过验证,可以完美的实现测量需求。
附:本文中涉及到的完整源代码using System; using System.Resources; using System.Windows.Forms; using Ivi.Visa.Interop; using System.Threading; using System.Linq.Expressions; using System.Windows.Forms.DataVisualization.Charting; namespace WinForm_ComPorts { public partial class Form1 : Form { private Ivi.Visa.Interop.ResourceManager resourceManager; private FormattedIO488 messageBasedSession; private Thread measurementThread; public Form1() { InitializeComponent(); // 设置曲线图样式 WaveChart.Series[0].ChartType = SeriesChartType.Line; WaveChart.Series[0].Color = System.Drawing.Color.Blue; } #region 端口号下拉选择框下拉事件响应代码 /// /// 端口号下拉选择框下拉事件响应代码 /// /// /// private void cboComPorts_DropDown(object sender, EventArgs e) { try { // 清除下拉列表 this.cboComPorts.Items.Clear(); // 获取设备的所有串口资源 string[] comNames = System.IO.Ports.SerialPort.GetPortNames(); // 添加可用串口号到下拉框中 foreach (string s in comNames) { this.cboComPorts.Items.Add(s); } // 创建VISA资源对象实例 Ivi.Visa.Interop.ResourceManager rm = new Ivi.Visa.Interop.ResourceManager(); // 获取设备的所有仪器资源 string[] usbNames = rm.FindRsrc("?*INSTR"); // 添加可用USB资源到下拉框中 foreach (string s in usbNames) { if (s.Contains("0x")) this.cboComPorts.Items.Add(s); } } catch (Exception) { MessageBox.Show("系统内不存在此类仪器~", "ERROR"); } } #endregion #region 开始测试/停止测试按钮事件响应代码 /// /// 开始测试/停止测试按钮事件响应代码 /// /// /// private void btnStart_Click(object sender, EventArgs e) { try { if (btnStart.Text == "开始测试") { btnStart.Text = "停止测试"; // 清空曲线图数据 WaveChart.Series[0].Points.Clear(); // 创建ResourceManager和MessageBasedSession对象 resourceManager = new Ivi.Visa.Interop.ResourceManager(); messageBasedSession = new FormattedIO488(); // 打开万用表连接,万用表的USB通讯地址通过端口号下拉列表的值传递过来 messageBasedSession.IO = (IMessage)resourceManager.Open(cboComPorts.Text.ToString(), AccessMode.NO_LOCK, 5000, ""); //获取测量类型,根据测量类型选择相应的采集指令 string ConfigCommand = ""; switch (cboMeasType.Text) { case "DC Voltage": ConfigCommand = ":CONF:VOLT:DC AUTO,DEF"; break; case "AC Voltage": ConfigCommand = ":CONF:VOLT:AC AUTO,DEF"; break; case "DC Current": ConfigCommand = ":CONF:CURR:DC AUTO,DEF"; break; case "AC Current": ConfigCommand = ":CONF:CURR:AC AUTO,DEF"; break; case "Resistance 2-wire": ConfigCommand = ":CONF:RES AUTO"; break; case "Resistance 4-wire": ConfigCommand = ":CONF:FRES AUTO"; break; case "Diode": ConfigCommand = ":CONF:DIOD"; break; case "Continuity": ConfigCommand = ":CONF:CONT"; break; case "Frequency": ConfigCommand = ":CONF:FREQ"; break; default: ConfigCommand = ":CONF:VOLT:DC AUTO,DEF"; break; } // 设置采集模式和测量范围 messageBasedSession.WriteString(ConfigCommand, true); // 创建线程执行连续测量 measurementThread = new Thread(new ThreadStart(MeasureThread)); measurementThread.Start(); } else { btnStart.Text = "开始测试"; // 停止测量线程 if (measurementThread != null && measurementThread.IsAlive) { measurementThread.Abort(); measurementThread.Join(); } // 关闭连接 if (messageBasedSession != null) { messageBasedSession.IO.Close(); // messageBasedSession.Dispose(); } if (resourceManager != null) { // resourceManager.Dispose(); // MessageBox.Show("资源释放"); } } } catch (Exception ex) { MessageBox.Show("发生错误:" + ex.Message); } } #endregion #region 测量线程代码 /// /// 测量线程,读取万用表的数据,并将结果反馈至resultTextBox控件 /// private void MeasureThread() { try { // 循环读取万用表数据 while (true) { // 发送采集命令 messageBasedSession.WriteString(":READ?", true); // 读取返回值 string response = messageBasedSession.ReadString(); // 在控件和图表中输出结果 this.Invoke((MethodInvoker)delegate { resultTextBox.Text = ChangeDataToD(response.Trim()); WaveChart.Series[0].Points.AddY(double.Parse(resultTextBox.Text)); }); } } catch (ThreadAbortException) { // 线程被中断 // MessageBox.Show("线程被中断"); // 查询错误 messageBasedSession.WriteString(":SYST:ERR?"); // 读取返回的错误信息 string response = messageBasedSession.ReadString(); // 若仪器返回了"-410"错误(读取万用表读数时被中断导致)或无错误,则忽略 if (response.Contains("-410") || response.Contains("No error")) { } else { MessageBox.Show(response); } } catch (Exception ex) { MessageBox.Show("发生错误:" + ex.Message); } } #endregion #region 数据显示格式转换代码 /// /// 将科学计数法表示的字符串数据转换为double型数据显示格式 /// /// /// 返回double型数据格式的字符串 private string ChangeDataToD(string strData) { Double dData = 0.0; if (strData.Contains("E")) { dData = Double.Parse(strData); } return dData.ToString(); } #endregion } }
你向往的民宿美景来了午后的正果书堂,阳光从明亮的窗子洒入室内,做了一杯手冲咖啡,拿起体验民俗之美这本书,翻看起来。有这么一段序乡愁是我们独有的情怀土地是农民的羁绊日暮乡关,征人望乡人是耸立乡间的树乡是
秋裤必备!冷空气来了综合各地文化和旅游部门通讯运营商线上旅行服务商数据,经文化和旅游部数据中心测算,10月1日至7日,全国国内旅游出游5。15亿人次,按可比口径恢复至疫前同期的70。1。实现国内旅游收
郎平新消息!请老友在上海聚餐,退休后更显年轻自从东京奥运会卫冕失败之后,中国女排的消息越来越少,上一次了解国手的现状还是全运会正赛。而已经卸任中国女排主教练位置的郎导,更是过起了退休后的生活,远离大众视野。但是通过其朋友的社
nba联盟年轻的十三太保十三太保,为唐朝末年节度使李克用的十三位儿子(包括义子)。除三太保李存勖外,其他十二人都是养子。因颇富盛名,中国历史后期许多人物组合团体都以十三太保为号。三太保李存勖三矢雪恨,建立
年轻人,求你别在深夜emo了西班牙有一句谚语如果常常流泪,就不能看见星光。我很喜欢这句话所以即使要哭也只在下午小哭一下夜间要去看星是没有时间哭的再说,我还要去采果子呢三毛写给正在怨天尤人的你01emo,一种情
易烊千玺主演电影票房破60亿,即将成为最年轻百亿影帝,他值得吗近日,由易烊千玺搭档吴京一起出演的抗美援朝题材电影长津湖正式上线,这一部电影自9月30日上线以来,票房持续飙升,成为了今年的年度票房季军,直到现在为止,这一部电影的票房还在逐渐升高
照顾好自己,身体是革命的本钱一定要照顾好自己,身体是革命的本钱,只有身体好了,才会有机会变得更好。即使有再多的钱,有病了,也不算钱了,也买不来生命,而没有钱,身体垮了就都垮了,不好在翻身,所以不管经济条件如何
买国产手机就是爱国,买苹果手机就是不爱国?买手机不是自由的吗我说我不喜欢用国产手机,结果很多人来喷我,你说这个世道都怎么了?我们常常说的开放平等,难道都成了摆设吗?用什么手机不是个人的自由吗?难道组装外国手机的工人,都没给他们发工资吗?还是
三星全新黑科技泄露,三星S21为新机让路现感人价,星粉很受伤半导体工艺不仅是尖端的7532nm,因为有很多芯片不需要太先进的制造工艺,它们往往不会太复杂,但它们对成本非常敏感。今天,三星宣布推出全新的17LPV17nm工艺,意味着低功耗。值
5nm芯片柔性屏159g,跌至1699元,性能超过华为nova9Pro很多手机都推出了千元机,因为千元机是销量的保证,在全球单款手机销量中,除了苹果手机外,上榜的几乎是千元机,因为价格较为便宜,因此用户群体更加的普及,再加上现在的千元机,性能已经比较
红米Note系列引入120W充电,iPhone13仅为千元机充电功率零头?小米科技在去年率先推出了120W快速充电技术,首款采用该技术的智能手机是小米10Ultra,这是一款高端旗舰手机,起售价为5299元小米10Ultra有三个120120Hz刷新率屏