此为“用C#进行仪器控制系列--数字万用表”的第4篇文章,在此之前已经编写了3篇相关文章了,可参见:
1)用C#进行仪器控制系列——数字万用表(1):该篇文章介绍了如何从零开始创建一个控制台应用程序,实现 Keysight 数字万用表的电压测量,并将结果通过控制台展示;
2)用C#进行仪器控制系列——数字万用表(2):该篇文章在第1篇文章的基础上,以窗体应用程序的形式重写了万用表电压测量程序,并能够自动识别仪器地址,以及能够通过按钮控制测量的开始和停止,电压的显示等。
3)用C#进行仪器控制系列——数字万用表(3):该篇文章在第2篇文章的基础上,通过代码的简单优化,实现了不同测量类型的下拉选择,根据下拉选项执行对应类型的测量功能(电压、电流、电阻、二极管、导通、频率测试等)。
此篇文章是在第3篇文章的基础上,添加波形图表显示功能。
通过添加波形图表功能,将测量数据实时传递给波形图表,使其能够在界面中显示测量的历史数据,就可以观测到数据的变化趋势了。最终想要实现的效果如下图所示。
1)窗体界面的优化
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
}
}
页面更新:2024-03-05
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号