void btnGetPIDData_Click(object sender, EventArgs e)
 {
     this.btnGetPIDData.Enabled = false;
     GrblPIDData.Load();
     PIDPlot.Refresh();
     btnGetPIDData.Enabled = true;
 }
        public static void Load()
        {
            GrblPIDData.RawData = "";
            GrblPIDData.data.Clear();

            Comms.com.DataReceived += new DataReceivedHandler(GrblPIDData.Process);

            Comms.com.PurgeQueue();
            Comms.com.WriteCommand(((char)GrblConstants.CMD_PID_REPORT).ToString(CultureInfo.InvariantCulture));

            while (Comms.com.CommandState == Comms.State.DataReceived || Comms.com.CommandState == Comms.State.AwaitAck)
            {
                Application.DoEvents();
            }

            Comms.com.DataReceived -= GrblPIDData.Process;

            if (GrblPIDData.RawData != "")
            {
                int      i = 0, s = 0; double target = 0.0, actual = 0.0;
                string[] header  = GrblPIDData.RawData.Split('|');
                string[] samples = header[1].Split(',');
                foreach (string sample in samples)
                {
                    switch (s)
                    {
                    case 0:
                        target = GrblPIDData.parseDouble(sample);
                        s++;
                        break;

                    case 1:
                        actual = GrblPIDData.parseDouble(sample);
                        GrblPIDData.data.Rows.Add(new object[] { ++i, target, actual, Math.Round(actual - target, 3) });
                        s = 0;
                        break;
                    }
                }
            }
        }