如何使用来自具有多个传感器的 SerialPort 的数据绘制图形 [英] How to plot graphs with data from a SerialPort with multiple sensors
问题描述
我需要绘制来自 pH、温度和湿度传感器的数据,数据作为矩阵从 arduino 通过串行端口发送到 PC.
我可以在 TextBox 中显示数据,但是当我尝试绘制数据时,它不起作用(我不知道该怎么做).
当数据不是矩阵并且它是来自一个传感器的数据时,我只能绘制数据.
使用系统;使用 System.Collections.Generic;使用 System.ComponentModel;使用 System.Data;使用 System.Drawing;使用 System.Linq;使用 System.Text;使用 System.Windows.Forms;使用 System.Threading.Tasks;使用 System.IO.Ports;使用 System.Windows.Forms.DataVisualization.Charting;命名空间grafik1{公共部分类 Form1 :表单{私有串行端口传感;私人日期时间日期时间;私有字符串数据;私有字符串数据2;公共 Form1(){初始化组件();Control.CheckForIllegalCrossThreadCalls = false;}private void Form1_Load(对象发送者,EventArgs e){comboBox1.DataSource = SerialPort.GetPortNames();timer1.Start();}双 rt = 0;布尔值 i = 假;private void timer1_Tick(对象发送者,EventArgs e){rt = rt + 0.1;}private void Form1_FormClosed(对象发送者,FormClosedEventArgs e){sensport.Close();}private void button1_Click(object sender, EventArgs e){if (comboBox2.Text == ""){MessageBox.Show("错误");}别的{sensport = new SerialPort();sensport.BaudRate = int.Parse(comboBox2.Text);sensport.PortName = comboBox1.Text;sensport.Parity = Parity.None;sensport.DataBits = 8;sensport.StopBits = StopBits.One;sensport.Handshake = Handshake.None;sensport.DataReceived += sensport_DataReceived;尝试{sensport.Open();textBox1.Text = "";}捕获(异常前){MessageBox.Show(ex.Message, "Error");}}}void sensport_DataReceived(对象发送者,SerialDataReceivedEventArgs e){如果(我==假){rt = 0;我 = 真;}数据 = sensport.ReadLine();this.chart1.Series["Data1"].Points.AddXY(rt, data);this.Invoke(new EventHandler(displaydata_event));}private void displaydata_event(对象发送者,EventArgs e){日期时间 = 日期时间.现在;string time = datetime.Day + "/" + datetime.Month + "/" + datetime.Year + "\t" + datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;txtData.AppendText(时间 + "\t" + 数据 + "\n");}private void button2_Click(对象发送者,EventArgs e){字符串directorio = textBox1.Text;如果(目录=="){MessageBox.Show("错误");}别的 {尝试{字符串 kayıtyeri = @"" + 目录 + "";this.chart1.SaveImage(("+kayityeri+"), ChartImageFormat.Png);MessageBox.Show("Grafica guardada en " + kayıtyeri);}捕获(例外 ex3){MessageBox.Show(ex3.Message, "错误");}}}private void label4_Click(object sender, EventArgs e){}private void comboBox1_SelectedIndexChanged(object sender, EventArgs e){}private void button3_Click(对象发送者,EventArgs e){sensport.Close();}private void button4_Click(object sender, EventArgs e){尝试{字符串路径文件 = @"C:\Users\MARIO GONZALEZ\Google Drive\VisualStudio\Arduino0_1\DATA";字符串文件名 = "arduinoRTPv1.xls";System.IO.File.WriteAllText(pathfile + filename, txtData.Text);MessageBox.Show("数据已保存");}捕获(例外 ex3){MessageBox.Show(ex3.Message, "错误");}}private void button5_Click(object sender, EventArgs e){}private void chart1_Click(对象发送者,EventArgs e){}}}
假设你已经准备好了你的图表,可能是这样的:
chart1.Series.Clear();chart1.Series.Add("ph");chart1.Series.Add("Temp");chart1.Series.Add("嗡");chart1.Series["ph"].ChartType = SeriesChartType.Line;chart1.Series["Temp"].ChartType = SeriesChartType.Line;chart1.Series["Hum"].ChartType = SeriesChartType.Line;chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;chart1.ChartAreas[0].AxisY2.Title = "Temp";chart1.ChartAreas[0].AxisY2.Maximum = 100;
现在您可以添加一个包含一些数据块的字符串,如注释中所示..
字符串数据 = "7.5 23.8 67 \n8.5 23.1 72 \n7.0 25.8 66 \n";
..像这样:
var dataBlocks = data.Split('\n');foreach(dataBlocks 中的 var 块){var numbers = block.Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries);//rt += 某个时间;(*)for (int i = 0; i < numbers.Length; i++){double n = double.NaN;bool ok = double.TryParse(numbers[i], out n);if (ok) chart1.Series[i].Points.AddXY(rt, n);别的{int p = chart1.Series[i].Points.AddXY(rt, 0);chart1.Series[i].Points[p].IsEmpty = true;Console.WriteLine("一些错误信息..");}}}
我稍微修改了数据以更好地显示更改..
- 请注意,我省略了计时器
rt
的计数,这就是图表显示带有索引 x 值的点的原因.对于真正的实时情节,请在此处包含它 (*)!
如果您不断添加数据,您的图表很快就会变得非常拥挤.
然后,您要么必须从一开始就删除旧数据,要么至少设置最小和最大 x 值以将显示限制为合理数量的数据点和/或打开缩放!
请参阅
I need to plot data from sensors of pH, Temperature and Humidity, the data is sent as a matrix from arduino to PC through the serial port.
I can show the data in a TextBox, but when I try to plot the data, it doesn't work (I don't know how to do it).
I just can plot the data when is not a matrix and it's data from just one sensor.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms.DataVisualization.Charting;
namespace grafik1
{
public partial class Form1 : Form
{
private SerialPort sensport;
private DateTime datetime;
private string data;
private string data2;
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DataSource = SerialPort.GetPortNames();
timer1.Start();
}
double rt = 0;
Boolean i = false;
private void timer1_Tick(object sender, EventArgs e)
{
rt = rt + 0.1;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
sensport.Close();
}
private void button1_Click(object sender, EventArgs e)
{
if (comboBox2.Text == "")
{
MessageBox.Show("Error");
}
else
{
sensport = new SerialPort();
sensport.BaudRate = int.Parse(comboBox2.Text);
sensport.PortName = comboBox1.Text;
sensport.Parity = Parity.None;
sensport.DataBits = 8;
sensport.StopBits = StopBits.One;
sensport.Handshake = Handshake.None;
sensport.DataReceived += sensport_DataReceived;
try
{
sensport.Open();
textBox1.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
}
void sensport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (i == false)
{
rt = 0;
i = true;
}
data = sensport.ReadLine();
this.chart1.Series["Data1"].Points.AddXY(rt, data);
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
datetime = DateTime.Now;
string time = datetime.Day + "/" + datetime.Month + "/" + datetime.Year + "\t" + datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
txtData.AppendText(time + "\t" + data + "\n");
}
private void button2_Click(object sender, EventArgs e)
{
string directorio = textBox1.Text;
if (directorio == "")
{
MessageBox.Show("Error");
}
else {
try
{
string kayıtyeri = @"" + directorio + "";
this.chart1.SaveImage(("+kayityeri+"), ChartImageFormat.Png);
MessageBox.Show("Grafica guardada en " + kayıtyeri);
}
catch (Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
}
private void label4_Click(object sender, EventArgs e)
{
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
sensport.Close();
}
private void button4_Click(object sender, EventArgs e)
{
try
{
string pathfile = @"C:\Users\MARIO GONZALEZ\Google Drive\VisualStudio\Arduino0_1\DATA";
string filename = "arduinoRTPv1.xls";
System.IO.File.WriteAllText(pathfile + filename, txtData.Text);
MessageBox.Show("Data saved");
}
catch (Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
private void button5_Click(object sender, EventArgs e)
{
}
private void chart1_Click(object sender, EventArgs e)
{
}
}
}
Let's assume you have prepared your chart, maybe like this:
chart1.Series.Clear();
chart1.Series.Add("ph");
chart1.Series.Add("Temp");
chart1.Series.Add("Hum");
chart1.Series["ph"].ChartType = SeriesChartType.Line;
chart1.Series["Temp"].ChartType = SeriesChartType.Line;
chart1.Series["Hum"].ChartType = SeriesChartType.Line;
chart1.ChartAreas[0].AxisY2.Enabled = AxisEnabled.True;
chart1.ChartAreas[0].AxisY2.Title = "Temp";
chart1.ChartAreas[0].AxisY2.Maximum = 100;
Now you can add a string that contains some data blocks as shown in the comments..
string data = "7.5 23.8 67 \n8.5 23.1 72 \n7.0 25.8 66 \n";
..like this:
var dataBlocks = data.Split('\n');
foreach (var block in dataBlocks)
{
var numbers = block.Split(new [] {' '}, StringSplitOptions.RemoveEmptyEntries);
// rt += someTime; (*)
for (int i = 0; i < numbers.Length; i++)
{
double n = double.NaN;
bool ok = double.TryParse(numbers[i], out n);
if (ok) chart1.Series[i].Points.AddXY(rt, n);
else
{
int p = chart1.Series[i].Points.AddXY(rt, 0);
chart1.Series[i].Points[p].IsEmpty = true;
Console.WriteLine("some error message..");
}
}
}
I have modified the data a little to show the changes a little better..
- Note that I left out the counting up of your timer
rt
, which is why the chart shows the points with indexed x-values. For a real realtime plot do include it maybe here (*) !
If you keep adding data your chart will soon get rather crowded.
You will then either have to remove older data from the beginning or at least set a minimum and maximum x-values to restrict the display to a reasonably number of data points and or turn on zooming!
See here here and here for some examples and discussions of these things!
这篇关于如何使用来自具有多个传感器的 SerialPort 的数据绘制图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!