0

I’m currently venturing into the world of c# and have created my first windows application. Everything is working however I believe its efficiency here that is letting me down.

I am currently reading serial data from an Arduino. All the data is send in the format of “Letter” (newline) “Number” (newline) “letter” etc. From here I sort the data into relevant columns in a table. I have 6 sets of data coming from the Arduino. This data is then plotted onto a graph using zed graphs, with only 5 seconds of data being shown at once. So a moving axis.

After about 20s of plotting data to the graphs the plotting speed slows and eventually I am left with a moving graph with no points as they are trailing behind.

I tried flushing the serial buffer but this slowed everything down even more.

private void IncomingDataSort()
{ 

        string IncomingSerial = serialPort1.ReadLine(); // Read incomming serial data
        string StrIncomingSerial = IncomingSerial.ToString(); // convert this data to workable string
        elapsed_time = (stopwatch.ElapsedMilliseconds); // How many milliseconds since stopwatch (read serial button) started
        elapsed_time_sec = elapsed_time / 1000;
        Timems.Text = elapsed_time.ToString();

        if (StrIncomingSerial.Contains("Z") || StrIncomingSerial.Contains("Y")) // If this string contains a "Z" or "Y"
        {
            if (StrIncomingSerial.Contains("Z"))
            {
                string Number = serialPort1.ReadLine(); // Read Serialport
                double Num; // Create variable "Num"
                bool isNum = double.TryParse(Number, out Num); // Is the incomming serial data a number?
                if (isNum) // If it is a number...
                {
                    int NumberInt = Convert.ToInt16(Number); // convert string to int
                    Heat1Temp.Text = Number;
                }
            }
            if (StrIncomingSerial.Contains("Y"))
            {
                string Number = serialPort1.ReadLine(); // Read Serialport
                double Num; // Create variable "Num"
                bool isNum = double.TryParse(Number, out Num); // Is the incomming serial data a number?
                if (isNum) // If it is a number...
                {
                    int NumberInt = Convert.ToInt16(Number); // convert string to int
                    Heat2Temp.Text = Number;
                }
            }
            CreateGraph1(zedGraphControl1, elapsed_time, Convert.ToInt16(Heat1Temp.Text), Convert.ToInt16(Heat2Temp.Text)); // plot gragh
        }
       }

    private void CreateGraph1(ZedGraphControl zgc, long time, int IncomingData, int IncomingData2)
    {
        GraphPane myPane = zgc.GraphPane; // setup graph

        zgc.AutoScroll = true;
        myPane.Title = "Graph 1"; // Titles 
        myPane.XAxis.Title = "Time (s)"; 
        myPane.YAxis.Title = "";
        myPane.Legend.IsVisible = false; // remove legend (DONT MAKE TRUE!!)
        myPane.XAxis.Min = myPane.XAxis.Max - GraphTimeSpan;

        PointPairList GraphInput = new PointPairList(); // create a new list
        PointPairList GraphInput2 = new PointPairList(); // create a new list

        long x;
        int y1;
        long x2;
        int y2;
        x = time; // x axis 1
        y1 = IncomingData; // y axis 1
        x2 = time; // x axis 2
        y2 = IncomingData2; // y axis 2

        GraphInput.Add(x, y1); // add to list
        GraphInput2.Add(x2, y2); // add to list

        LineItem myCurve = myPane.AddCurve("FirstSettings", GraphInput, Color.Red, SymbolType.Diamond); // draw points
        LineItem myCurve2 = myPane.AddCurve("SecondSettings", GraphInput2, Color.Blue, SymbolType.Diamond);

        zgc.AxisChange(); // update axis
        zgc.Refresh();
    } 
charley
  • 87
  • 4
  • 17
  • As you get each set of data - you are adding new curves to the graph & modifying the X-Axis. As time goes by, you have a large number of curves that are not being displayed - but all of these need checking to see if they do need to be displayed - hence the time taken to update is going to get slower & slower. – PaulF Oct 13 '16 at 12:15
  • That makes sense as I had to disable the legend as it kept on adding more and more until it took over the page! Have you got any suggestions on how to update the curve rather than adding another one? – charley Oct 13 '16 at 12:41

2 Answers2

0

As a follow on to my comment - rather than adding a new curve each time you get data you only need to append the new points to the existing PointPairLists - that way you will only ever have the two curves the graph needs to handle. Separating the initialisation & update of the graph would be a good idea - so something like this :

PointPairList GraphInput;
PointPairList GraphInput2;
LineItem myCurve;
LineItem myCurve2;

private void InitGraph(ZedGraphControl zgc)
{
    GraphPane myPane = zgc.GraphPane; // setup graph

    zgc.AutoScroll = true;
    myPane.Title = "Graph 1"; // Titles 
    myPane.XAxis.Title = "Time (s)"; 
    myPane.YAxis.Title = "";
    myPane.Legend.IsVisible = false; // remove legend (DONT MAKE TRUE!!)

    GraphInput = new PointPairList(); // create a new list
    GraphInput2 = new PointPairList(); // create a new list
    myCurve = myPane.AddCurve("FirstSettings", GraphInput, Color.Red, SymbolType.Diamond); // draw points
    myCurve2 = myPane.AddCurve("SecondSettings", GraphInput2, Color.Blue, SymbolType.Diamond);
}

private void UpdateGraph(ZedGraphControl zgc, long time, int IncomingData, int IncomingData2)
{
    GraphPane myPane = zgc.GraphPane; // setup graph

    myPane.XAxis.Max = time;
    myPane.XAxis.Min = myPane.XAxis.Max - GraphTimeSpan;

    GraphInput.Add(time, IncomingData); // add to list
    GraphInput2.Add(time, IncomingData2); // add to list

    // AT THIS POINT YOU COULD SEARCH THROUGH THE POINT LIST & REMOVE ANY POINTS PRIOR TO THE MIN TIME
    while (GraphInput[0].X < myPane.XAxis.Min)
    {
      GraphInput.RemoveAt(0);
    }
    while (GraphInput2[0].X < myPane.XAxis.Min)
    {
      GraphInput2.RemoveAt(0);
    }

    zgc.AxisChange(); // update axis
    zgc.Refresh();
} 

Another time saving may be to update each curve independently - as you are adding points to GraphInput & GraphInput2 regardless of whether you actually had points to enter for both. Having separate UpdateGraph1 & UpdateGraph2 methods may cut the points to be plotted in half.

There are several other things that could be tidied up in the code too - but they are not causing you severe time issues (you convert the numbers from strings, then convert back to strings, then convert back to numbers - for example).

PaulF
  • 6,673
  • 2
  • 18
  • 29
0

Thanks so much for all your help, sorry it took me so long to respond but wanted to make sure I had a working piece of code before re-posting.

Here is the solution I found to work encase it helps anyone else. Although please bare in mind I am a beginner so will almost definitely need tidying up!

 private void InitGraph1 (ZedGraphControl zgc)
        {
            GraphPane myPane = zgc.GraphPane; // setup graph

            zgc.AutoScroll = true;
            myPane.Title = "Graph 1"; // Titles 
            myPane.XAxis.Title = "Time (s)";
            myPane.YAxis.Title = "";
            myPane.Legend.IsVisible = false; // remove legend

            GraphInput1 = new PointPairList(); // create a new list
            GraphInput2 = new PointPairList(); // create a new list
            myCurve = myPane.AddCurve(DataOutputZ, GraphInput1, Color.Red, SymbolType.Diamond); // draw points
            myCurve2 = myPane.AddCurve(DataOutputY, GraphInput2, Color.Blue, SymbolType.Diamond);

         }

-

 private void UpdateGraph(ZedGraphControl zgc, long time, int IncomingData, int IncomingData2)
        {
            {
                GraphPane myPane = zgc.GraphPane;
                myPane.XAxis.Min = time - GraphTimeSpan;
                myPane.XAxis.Max = time + (GraphTimeSpan/4); // put new points in last quarter of graph

                // Get the first CurveItem in the graph
                LineItem myCurve = zgc.GraphPane.CurveList[0] as LineItem;
                LineItem myCurve2 = zgc.GraphPane.CurveList[1] as LineItem;

                PointPairList GraphInput1 = myCurve.Points as PointPairList;
                PointPairList GraphInput2 = myCurve2.Points as PointPairList;

                // add new data points to the graph
                GraphInput1.Add(time, IncomingData);
                GraphInput2.Add(time, IncomingData2);

                while (GraphInput1[0].X < myPane.XAxis.Min)
                {
                    GraphInput1.RemoveAt(0);
                }
                while (GraphInput2[0].X < myPane.XAxis.Min)
                {
                    GraphInput2.RemoveAt(0);
                }

                // force redraw
                zgc.Invalidate();
                zgc.AxisChange(); // update axis
                zgc.Refresh();
            }
        }

Thanks again!

charley
  • 87
  • 4
  • 17