如何使用来自具有多个传感器的 SerialPort 的数据绘制图形 [英] How to plot graphs with data from a SerialPort with multiple sensors

查看:20
本文介绍了如何使用来自具有多个传感器的 SerialPort 的数据绘制图形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要绘制来自 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆