c# - Zedgraph,绘制串行数据太多延迟和时间滞后



我是c#编程新手,正在尝试编写一个应用程序,这是我期末论文的一部分。

我有一个微处理器,它通过串行端口不断地将数据从传感器发送到我的计算机。我只想用Zedgraph来绘制这些数据。

问题是图有太多的延迟和时间滞后。问题的发生似乎是因为我不断地以很高的速度更新整个图。这个问题我已经困扰了一个星期,但仍未找到解决办法。如果有人能帮我,我将非常高兴。

这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
using System.IO.Ports;
using System.Threading;
namespace DynamicData
{
public partial class Form1 : Form
{
    private SerialPort port;
    private string buffer = "";
    private void connect()
    {
        port = new SerialPort("COM8", 115200, Parity.None, 8, StopBits.One);
        port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived);
        if (!port.IsOpen) port.Open();
    }
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load( object sender, EventArgs e )
    {
        connect();
        GraphPane myPane = zedGraphControl1.GraphPane;          
        RollingPointPairList list = new RollingPointPairList(500);
        LineItem curve = myPane.AddCurve( "Sensor", list, Color.Blue, SymbolType.None );
        myPane.XAxis.Scale.Min = 0;
        myPane.XAxis.Scale.Max = 10;
        myPane.YAxis.Scale.Min = 0;
        myPane.YAxis.Scale.Max = 300;
        myPane.XAxis.Scale.MinorStep = 0.5;
        myPane.XAxis.Scale.MajorStep = 1;
        zedGraphControl1.AxisChange();
    }

    private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        //sample data: ;100*100000:
        //sampling rate ~100Hz
        buffer += port.ReadExisting();
        //flush incomplete package
        while (buffer[0] != ';')
        {
            buffer = buffer.Remove(0, 1);
            if (buffer.Length < 1) break;
        }
        //got a complete package, go to data handling
        while (buffer.Contains(":"))
        {
            DataHandling();
        }
    }

    private void DataHandling()
    {
        string[] nameArray = buffer.Split(new[] { ";", ":", "*" }, StringSplitOptions.RemoveEmptyEntries);
        //plot sensor data vs. time
        draw(Convert.ToInt32(nameArray[0]), Convert.ToInt32(nameArray[1]));
        //remove handled package in buffer
        var index = buffer.IndexOf(":");
        buffer = buffer.Remove(0, index + 1);
    }
    double time = 0;
    private void draw(int sensor, int t)
    {
        //convert tick to sec (uP clock rate = 16MHZ)
        time = time + (t / 16000000.0);
        // Get the first CurveItem in the graph
        LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem;
        // Get the PointPairList
        IPointListEdit list = curve.Points as IPointListEdit;
        list.Add(time, sensor);

        //Keep the X scale at a rolling 10 second interval, with one
        //major step between the max X value and the end of the axis
        Scale xScale = zedGraphControl1.GraphPane.XAxis.Scale;
        if (time > xScale.Max - xScale.MajorStep)
        {
            xScale.Max = time + xScale.MajorStep;
            xScale.Min = xScale.Max - 10.0;
        }
        //Display sensor data
        this.Invoke(new Action(() => { textBox1.Text = byte1.ToString(); }));
        axisChangeZedGraph(zedGraphControl1);
    }
    delegate void axisChangeZedGraphCallBack(ZedGraphControl zg);
    private void axisChangeZedGraph(ZedGraphControl zg)
    {
        if (zg.InvokeRequired)
        {
            axisChangeZedGraphCallBack ad = new axisChangeZedGraphCallBack(axisChangeZedGraph);
            zg.Invoke(ad, new object[] { zg });
        }
        else
        {
          //  zg.AxisChange();
            zg.Invalidate();
            zg.Refresh();
        }
    }
}
}

感谢您的阅读!

问题是您绘制的每个点都调用invalidate。这会产生非常高的处理器负载。我正在做一个非常类似的项目,USB设备,实时绘图数据。我使用一个单独的线程进行数据采集。这个线程每次接收到一个数据包时都会创建一个事件。数据被放入队列中。用计时器更新图形。你可以在这里找到一个例子。在这段代码中,图形每50毫秒更新一次,实际上没有必要画得更快。在计时器中,我检查队列的大小,并绘制或多或少的点,然后调用invalidate。我不知道这是不是一个好的解决方案(我在c#上只有6个月的经验),但是7500分的效果相当不错。您应该首先尝试使用计时器来刷新图形。

1)。只创建和格式化曲线一次。将其存储在模块级别。

2)。加点时先用curve.AddPoint();再用zg.Refresh();

//this is just to add a point to the plot, the curve object should have already been created
private void draw(int sensor, int t)
    {
        //convert tick to sec (uP clock rate = 16MHZ)
        time = time + (t / 16000000.0);
        //curve should be a module-level variable already set up with proper formatting,
        //just no points yet
        curve.AddPoint(time, sensor);
        //Display sensor data
        this.Invoke(new Action(() => { textBox1.Text = byte1.ToString(); }));
        zg.AxisChange();
        zg.Refresh();
    }

最新更新