How to plot graphs with data from a SerialPort wit

2019-09-03 10:03发布

问题:

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)
    {

    }



}
}

回答1:

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!