C# 串口数据实时图表

Real Time Chart with Serial port Data in C#

我想用从串行端口 Arduino 设备读取的数据在 c# 中绘制实时图表我不知道如何用 c# 执行此操作。 我想要我的程序中的 2d 和 3d 图表任何人都可以帮助我吗? 在我的程序中,我从串行端口读取数据并且数据时间已经到达,所以我的图表有 2 个数据,其中一个是信息,另一个是时间。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using port.dbDataSetTableAdapters;
using System.Threading.Tasks;

namespace Factory_Performance
{
    public partial class FrmMain : Form
    {
        int sfs = 0;
        string filename;
        string line;
        string s;
        string temp="";
        string temp1="";
        Series series = new Series();
        SerialPort ComPort = new SerialPort();

        internal delegate void SerialDataReceivedEventHandlerDelegate(object sender, SerialDataReceivedEventArgs e);
        internal delegate void SerialPinChangedEventHandlerDelegate(object sender, SerialPinChangedEventArgs e);
        private SerialPinChangedEventHandler SerialPinChangedEventHandler1;
        delegate void SetTextCallback(int ReadByte);
        int InputData = 0;


        private int CountData;
        private string StrData;
        double[] Values;
        public FrmMain()
        {
            InitializeComponent();
            SerialPinChangedEventHandler1 = new SerialPinChangedEventHandler(PinChanged);
            ComPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);
        }

        private double calculate_input(int s2, int s3)
        {


            return double.Parse(s2.ToString() + "/" + s3.ToString());

        }

        private void GetAllIDInDB()
        {
            tblIDTableAdapter.Fill(dbDataSet.TblID);
            CmbID.Items.Clear();

            for (int i = 0; i < dbDataSet.TblID.Rows.Count; i++)
                CmbID.Items.Add(dbDataSet.TblID.Rows[i]["ID"].ToString());
        }
        private void GetAllID_DetailsInDB(int ID)
        {
            tblID_DetailsTableAdapter.FillByID(dbDataSet.TblID_Details, ID);
            listreadtxt.Items.Clear();
            for (int i = 0; i < dbDataSet.TblID_Details.Rows.Count; i++)
                listreadtxt.Items.Add(dbDataSet.TblID_Details.Rows[i]["Value"].ToString());

        }

        private void GetInfoPorts()
        {
            try
            {
                string[] ArrayComPortsNames = null;
                int index = -1;
                string ComPortName = null;
                cboPorts.Items.Clear();
                cboBaudRate.Items.Clear();
                cboStopBits.Items.Clear();
                cboParity.Items.Clear();
                cboHandShaking.Items.Clear();
                //Com Ports
                ArrayComPortsNames = SerialPort.GetPortNames();
                do
                {
                    index += 1;
                    cboPorts.Items.Add(ArrayComPortsNames[index]);


                } while (!((ArrayComPortsNames[index] == ComPortName) || (index == ArrayComPortsNames.GetUpperBound(0))));
                Array.Sort(ArrayComPortsNames);

                if (index == ArrayComPortsNames.GetUpperBound(0))
                {
                    ComPortName = ArrayComPortsNames[0];
                }
                //get first item print in text
                cboPorts.Text = ArrayComPortsNames[0];
                //Baud Rate
                cboBaudRate.Items.Add(115200);
                cboBaudRate.Items.Add(300);
                cboBaudRate.Items.Add(600);
                cboBaudRate.Items.Add(1200);
                cboBaudRate.Items.Add(2400);
                cboBaudRate.Items.Add(9600);
                cboBaudRate.Items.Add(14400);
                cboBaudRate.Items.Add(19200);
                cboBaudRate.Items.Add(38400);
                cboBaudRate.Items.Add(57600);
                cboBaudRate.Items.ToString();
                //get first item print in text
                cboBaudRate.Text = cboBaudRate.Items[0].ToString();
                //Data Bits
                cboDataBits.Items.Add(8);
                cboDataBits.Items.Add(7);
                //get the first item print it in the text 
                cboDataBits.Text = cboDataBits.Items[0].ToString();

                //Stop Bits
                cboStopBits.Items.Add("One");
                cboStopBits.Items.Add("OnePointFive");
                cboStopBits.Items.Add("Two");
                //get the first item print in the text
                cboStopBits.Text = cboStopBits.Items[0].ToString();
                //Parity 
                cboParity.Items.Add("None");
                cboParity.Items.Add("Even");
                cboParity.Items.Add("Mark");
                cboParity.Items.Add("Odd");
                cboParity.Items.Add("Space");
                //get the first item print in the text
                cboParity.Text = cboParity.Items[0].ToString();
                //Handshake
                cboHandShaking.Items.Add("XOnXOff");
                cboHandShaking.Items.Add("None");
                cboHandShaking.Items.Add("RequestToSend");
                cboHandShaking.Items.Add("RequestToSendXOnXOff");
                //get the first item print it in the text 
                cboHandShaking.Text = cboHandShaking.Items[0].ToString();


            }
            catch
            {
                MessageBox.Show("خطا در گرفتن اطلاعات پورت");
            }
        }

        private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
        {



            InputData = ComPort.ReadByte();


            object firstByte = InputData;

            if (ComPort.IsOpen==true)
            {


                s = Convert.ToString(Convert.ToChar(firstByte));
                temp1 += s;
                lock (firstByte) {    
                if (Convert.ToInt32(firstByte) == 13)
                    {

                    temp = temp1;
                    temp1 = "";
                        ComPort.DiscardInBuffer();
                        ComPort.DiscardOutBuffer();
                        LstGetInfo.BeginInvoke(new Action(()=>
                    { 
                        if (temp !=null)
                        { 
                    LstGetInfo.Items.Add(temp);


                            if (LstGetInfo.Items.Count >= 100)
                            {


                                    LstGetInfo.Items.Clear();


                            }
                            FileStream fs = new FileStream(filename, FileMode.Append);
                            var data = System.Text.Encoding.UTF8.GetBytes(String.Format("{0} {1}", temp, DateTime.Now.ToString("hh mm ss")) +"\r\n");
                            fs.Write(data, 0, data.Length);
                            fs.Close();

                        }
                    }));
                        LstGetInfo.BeginInvoke(new Action(() =>
                                {
                                    LstGetInfo.TopIndex = LstGetInfo.Items.Count - 1;
                                }));

                }

                }
            }
        }
        internal void PinChanged(object sender, SerialPinChangedEventArgs e)
        {

        }
        private void button1_Click(object sender, EventArgs e)
        {
            Values = new double[CountData];
            for (int i = 0; i < CountData; i++)
                Values[i] = (int)StrData[i];
            Array.Reverse(Values);
            chart1.Titles.Clear();
            chart1.Titles.Add(TxtTitle.Text);
            chart1.Series.Clear();
            series.Points.Clear();
            for (int i = 0; i < CountData; i++)
                series.Points.AddXY(TxtTitleSeries.Text + " " + i.ToString(), Values[i]);
            chart1.Series.Add(series);

        }
        private void button2_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void CmbPalette_SelectedIndexChanged(object sender, EventArgs e)
        {
            chart1.Palette = (ChartColorPalette)CmbPalette.SelectedIndex;
        }

        private void CmbChartType_SelectedIndexChanged(object sender, EventArgs e)
        {
            series.ChartType = (SeriesChartType)CmbChartType.SelectedIndex;

        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            chart2.Series.Clear();
            // TODO: This line of code loads data into the 'dbDataSet.TblID_Details' table. You can move, or remove it, as needed.
            this.tblID_DetailsTableAdapter.Fill(this.dbDataSet.TblID_Details);
            // TODO: This line of code loads data into the 'dbDataSet.TblID' table. You can move, or remove it, as needed.
            this.tblIDTableAdapter.Fill(this.dbDataSet.TblID);
            GetInfoPorts(); 
            CmbPalette.SelectedIndex = 1;
            CmbChartType.SelectedIndex = 4;
            CountData = 0;
        }
        private void btnGetSerialPorts_Click(object sender, EventArgs e)
        {
            GetInfoPorts();
        }
        private void btnPortState_Click(object sender, EventArgs e)
        {
            if (sfs == 1) { 
            try
            {
                if (btnPortState.Text == "ارتباط با دستگاه")
                {
                        temp1 = "";
                        temp = "";
                    btnPortState.Text = "قطع ارتباط با دستگاه";
                    ComPort.PortName = Convert.ToString(cboPorts.Text);
                    ComPort.BaudRate = Convert.ToInt32(cboBaudRate.Text);
                    ComPort.DataBits = Convert.ToInt16(cboDataBits.Text);
                    ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStopBits.Text);
                    ComPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), cboHandShaking.Text);
                    ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), cboParity.Text);
                    ComPort.Open();
                    LstGetInfo.Items.Clear();

                }
                else if (btnPortState.Text == "قطع ارتباط با دستگاه")
                {
                    btnPortState.Text = "ارتباط با دستگاه";
                    ComPort.Close();

                }
            }
            catch
            {
                btnPortState.Text = "ارتباط با دستگاه";
                ComPort.Close();
                MessageBox.Show("خطا در انجام عملیات");
            }
        }
            else
            {
                MessageBox.Show("برای ذخیزه فایل محلی را انتخاب کنید");
            }
        }
        private void button1_Click_1(object sender, EventArgs e)
        {
            savedata();

        }
     private void savedata()
        {
            try
            {
                if (LstGetInfo.Items.Count < 0) return;
                int ItemCount = int.Parse(listreadtxt.Items[0].ToString());
                int ItemIDCount = 0;
                int ItemID = 0;
                int ItemValue1 = 0, ItemValue2 = 0;
                TblIDTableAdapter tblid = new TblIDTableAdapter();
                TblID_DetailsTableAdapter tblid_details = new TblID_DetailsTableAdapter();
                tblid.DeleteAllID();
                LstGetInfo.Items.RemoveAt(0);
                for (int i = 0; i < ItemCount; i++)
                {
                    ItemID = int.Parse(LstGetInfo.Items[0].ToString());
                    LstGetInfo.Items.RemoveAt(0);
                    tblid.Insert(ItemID);
                    if (LstGetInfo.Items.Count > 0)
                    {

                        ItemIDCount = int.Parse(LstGetInfo.Items[0].ToString());
                        LstGetInfo.Items.RemoveAt(0);
                        for (int j = 0; j < ItemIDCount; j += 2)
                        {
                            ItemValue1 = int.Parse(LstGetInfo.Items[0].ToString());
                            LstGetInfo.Items.RemoveAt(0);
                            ItemValue2 = int.Parse(LstGetInfo.Items[0].ToString());
                            LstGetInfo.Items.RemoveAt(0);
                            tblid_details.Insert(ItemID, calculate_input(ItemValue1, ItemValue2));
                        }
                    }
                }
            }
            catch
            {
                // MessageBox.Show("در ساخت نمودار مشکلی پیش آمده است");
                try
                {

                    LstGetInfo.Items.RemoveAt(0);
                }
                catch
                {
                }
            }
            finally
            {
                GetAllIDInDB();
            }
            ShowChart();
        }
        private void CmbID_SelectedIndexChanged(object sender, EventArgs e)
        {
            GetAllID_DetailsInDB(int.Parse(CmbID.Text));
            if (listreadtxt.Items.Count > 0)
                ShowChart();
        }

        private void CmbPalette_SelectedIndexChanged_1(object sender, EventArgs e)
        {
            chart1.Palette = (ChartColorPalette)CmbPalette.SelectedIndex;
        }

        private void CmbChartType_SelectedIndexChanged_1(object sender, EventArgs e)
        {
            series.ChartType = (SeriesChartType)CmbChartType.SelectedIndex;
        }
        private void ShowChart()
        {
            CountData =listreadtxt.Items.Count;
            Values = new double[CountData];
            for (int i = 0; i < CountData; i++)
                Values[i] = double.Parse(listreadtxt.Items[i].ToString());
            chart1.Titles.Clear();
            chart1.Titles.Add(TxtTitle.Text);
            chart1.Series.Clear();
            series.Points.Clear();
            for (int i = 0; i < CountData; i++)
                series.Points.AddXY(TxtTitleSeries.Text + " " + i.ToString(), Values[i]);
            chart1.Series.Add(series);


        }

        private void button3_Click_3(object sender, EventArgs e)
        {
            GetAllIDInDB();
        }



        private void button4_Click(object sender, EventArgs e)
        {

            openFileDialog1.FileName = string.Empty;
            DialogResult result = openFileDialog1.ShowDialog();
            if (result == DialogResult.OK) {
            listreadtxt.Items.Clear();
                Stream fs = openFileDialog1.OpenFile();
                StreamReader reader = new StreamReader(fs);

            while ((line = reader.ReadLine()) != null)
            {
                listreadtxt.Items.Add(line);


            }

            reader.Close();
            }
        }

        public void button5_Click(object sender, EventArgs e)
        {

            dateTimePicker1.BeginInvoke(new Action(() =>
            {



                DialogResult result1 = saveFileDialog1.ShowDialog();
                dateTimePicker1.Format = DateTimePickerFormat.Custom;
                string formatvalue =Convert.ToString( dateTimePicker1.Value.Date.ToString("  yyyy-MM-dd"));                
                filename = saveFileDialog1.FileName + formatvalue + ".csv";
                if (result1==DialogResult.OK) 
                {
                    sfs = 1;
                }




            }));
        }

        private void button6_Click(object sender, EventArgs e)
        {
            try {
                ComPort.Close();          
            CountData = LstGetInfo.Items.Count;
            Values = new double[CountData];
            for (int i = 0; i < CountData; i++)
                Values[i] = double.Parse(LstGetInfo.Items[i].ToString());
            chart2.Titles.Clear();
            chart2.Titles.Add(TxtTitle.Text);

            series.Points.Clear();
            for (int i = 0; i < CountData; i++)
                series.Points.AddXY(System.DateTime.Now, Values[i]);
            chart2.Series.Add(series);
            }
            catch
            {
                LstGetInfo.Items.Remove(0);
            }
            finally
            {

                ComPort.Open();

            }
        }


    }
}

问题是在

series.Points.AddXY(System.DateTime.Now, Values[i]);

您正在添加相同 X 值设置为 System.DateTime.Now 的点。结果你在 X 轴上只有一个点。

我找到了解决问题的办法

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using System.Threading.Tasks;
using System.Threading;

namespace chart
{
    public partial class Form1 : Form
    {
        string s;
        int InputData = 0;
        private delegate void CanIJust();
        Series series = new Series();
        private List<int> _valuelist;
        private Thread _thread;
        private CanIJust _DoIt;
        private Random _ran;
        private int _interval;
        private List<double> _timelist;
        private List<int> _customValueList;
        SerialPort ComPort = new SerialPort();
        int sfs = 0;
        string temp = "";
        string temp1 = "";

        public Form1()
        {
            InitializeComponent();
            chart1.ChartAreas[0].AxisX.IsStartedFromZero = true;
            chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = false;
            chart1.Series[0].XValueType = ChartValueType.Time;
            chart1.ChartAreas[0].AxisX.ScaleView.SizeType = DateTimeIntervalType.Seconds;
            chart1.ChartAreas[0].AxisX.IntervalAutoMode = IntervalAutoMode.FixedCount;
            chart1.ChartAreas[0].AxisX.IntervalType = DateTimeIntervalType.Seconds;
            chart1.ChartAreas[0].AxisX.Interval = 0;
            _valuelist = new List<int>();
            _ran = new Random();
            _interval = 500;
            tbupdateinterval.Text = "500";
            GoBoy();
            _timelist = new List<double>();
            _customValueList = new List<int>();
        }



        private void GetInfoPorts()
        {
            try
            {
                string[] ArrayComPortsNames = null;
                int index = -1;
                string ComPortName = null;
                cboPorts.Items.Clear();
                cboBaudRate.Items.Clear();
                cboStopBits.Items.Clear();
                cboParity.Items.Clear();
                cboHandShaking.Items.Clear();
                //Com Ports
                ArrayComPortsNames = SerialPort.GetPortNames();
                do
                {
                    index += 1;
                    cboPorts.Items.Add(ArrayComPortsNames[index]);


                } while (!((ArrayComPortsNames[index] == ComPortName) || (index == ArrayComPortsNames.GetUpperBound(0))));
                Array.Sort(ArrayComPortsNames);

                if (index == ArrayComPortsNames.GetUpperBound(0))
                {
                    ComPortName = ArrayComPortsNames[0];
                }
                //get first item print in text
                cboPorts.Text = ArrayComPortsNames[0];
                //Baud Rate
                cboBaudRate.Items.Add(115200);
                cboBaudRate.Items.Add(300);
                cboBaudRate.Items.Add(600);
                cboBaudRate.Items.Add(1200);
                cboBaudRate.Items.Add(2400);
                cboBaudRate.Items.Add(9600);
                cboBaudRate.Items.Add(14400);
                cboBaudRate.Items.Add(19200);
                cboBaudRate.Items.Add(38400);
                cboBaudRate.Items.Add(57600);
                cboBaudRate.Items.ToString();
                //get first item print in text
                cboBaudRate.Text = cboBaudRate.Items[0].ToString();
                //Data Bits
                cboDataBits.Items.Add(8);
                cboDataBits.Items.Add(7);
                //get the first item print it in the text 
                cboDataBits.Text = cboDataBits.Items[0].ToString();

                //Stop Bits
                cboStopBits.Items.Add("One");
                cboStopBits.Items.Add("OnePointFive");
                cboStopBits.Items.Add("Two");
                //get the first item print in the text
                cboStopBits.Text = cboStopBits.Items[0].ToString();
                //Parity 
                cboParity.Items.Add("None");
                cboParity.Items.Add("Even");
                cboParity.Items.Add("Mark");
                cboParity.Items.Add("Odd");
                cboParity.Items.Add("Space");
                //get the first item print in the text
                cboParity.Text = cboParity.Items[0].ToString();
                //Handshake
                cboHandShaking.Items.Add("XOnXOff");
                cboHandShaking.Items.Add("None");
                cboHandShaking.Items.Add("RequestToSend");
                cboHandShaking.Items.Add("RequestToSendXOnXOff");
                //get the first item print it in the text 
                cboHandShaking.Text = cboHandShaking.Items[0].ToString();


            }
            catch
            {
                MessageBox.Show("خطا در گرفتن اطلاعات پورت");
            }
        }
        private void GoBoy()
        {
            _DoIt += new CanIJust(AddData);
            DateTime now = DateTime.Now;
            chart1.ChartAreas[0].AxisX.Minimum = now.ToOADate();
            chart1.ChartAreas[0].AxisX.Maximum = now.AddSeconds(10).ToOADate();
            _thread = new Thread(new ThreadStart(ComeOnYouThread));
            _thread.Start();

        }
        private void ComeOnYouThread()
        {
            while (true)
                try
                {
                    chart1.Invoke(_DoIt);
                    Thread.Sleep(_interval);
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("Exception:" + e.ToString());
                }
        }
        private void AddData()
        {
            DateTime now = DateTime.Now;
            InputData = ComPort.ReadByte();


            object firstByte = InputData;

            if (ComPort.IsOpen == true)
            {


                s = Convert.ToString(Convert.ToChar(firstByte));
                temp1 += s;
                lock (firstByte)
                {
                    if (Convert.ToInt32(firstByte) == 13)
                    {

                        temp = temp1;
                        temp1 = "";
                        ComPort.DiscardInBuffer();
                        ComPort.DiscardOutBuffer();
                        _valuelist.Add(Convert.ToInt32(temp));
                        chart1.ResetAutoValues();
                        if (chart1.Series[0].Points.Count > 0)
                        {
                            while (chart1.Series[0].Points[0].XValue < now.AddSeconds(-5).ToOADate())
                            {
                                chart1.Series[0].Points.RemoveAt(0);
                                chart1.ChartAreas[0].AxisX.Minimum = chart1.Series[0].Points[0].XValue;
                                chart1.ChartAreas[0].AxisX.Maximum = now.AddSeconds(5).ToOADate();
                            }
                        }
                        chart1.Series[0].Points.AddXY(now.ToOADate(), _valuelist[_valuelist.Count - 1]);
                        chart1.Invalidate();
                    }
                }

            }
        }
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            if (_thread != null)
                _thread.Abort();
        }


        private void btn_2D_Click_1(object sender, EventArgs e)
        {
            btn_2D.Enabled = false;
            btn_3D.Enabled = true;
            chart1.ChartAreas[0].Area3DStyle.Enable3D = false;
        }

        private void btn_3D_Click_1(object sender, EventArgs e)
        {
            btn_2D.Enabled = true;
            btn_3D.Enabled = false;
            chart1.ChartAreas[0].Area3DStyle.Enable3D = true;
        }

        private void btn_add_Click(object sender, EventArgs e)
        {
            _customValueList.Add(_ran.Next(0, 100));
            _timelist.Add(DateTime.Now.ToOADate());
            updatesecondChart();
        }
        private void updatesecondChart()
        {
            chart2.Series[0].Points.AddXY(_timelist[_timelist.Count - 1], _customValueList[_customValueList.Count-1]);
            chart2.Invalidate();
        }

        private void btn_serialize_Click(object sender, EventArgs e)
        {

        }

        private void btn_updateInterval_Click(object sender, EventArgs e)
        {
            int interval = 0;
            if (int.TryParse(tbupdateinterval.Text, out interval))
            {
                if (interval > 0)
                    _interval = interval;
                else
                    MessageBox.Show("بازه زمانی باید بیشتر از 0 باشند");
            }
            else
            {
                MessageBox.Show("I nappropriate Data.");
            }
        }

        private void btnGetSerialPorts_Click(object sender, EventArgs e)
        {
            GetInfoPorts();
        }

        private void btnPortState_Click(object sender, EventArgs e)
        {
            //if (sfs == 1)
            //{
                try
                {
                    if (btnPortState.Text == "ارتباط با دستگاه")
                    {
                        temp1 = "";
                        temp = "";
                        btnPortState.Text = "قطع ارتباط با دستگاه";
                        ComPort.PortName = Convert.ToString(cboPorts.Text);
                        ComPort.BaudRate = Convert.ToInt32(cboBaudRate.Text);
                        ComPort.DataBits = Convert.ToInt16(cboDataBits.Text);
                        ComPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), cboStopBits.Text);
                        ComPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), cboHandShaking.Text);
                        ComPort.Parity = (Parity)Enum.Parse(typeof(Parity), cboParity.Text);
                        ComPort.Open();
                        AddData();

                    }
                    else if (btnPortState.Text == "قطع ارتباط با دستگاه")
                    {
                        btnPortState.Text = "ارتباط با دستگاه";
                        ComPort.Close();

                    }
                }
                catch
                {
                    btnPortState.Text = "ارتباط با دستگاه";
                    ComPort.Close();
                    MessageBox.Show("خطا در انجام عملیات");
                }
            }
            //else
            //{
            //    MessageBox.Show("برای ذخیزه فایل محلی را انتخاب کنید");
            //}
        //}

        private void CmbPalette_SelectedIndexChanged_1(object sender, EventArgs e)
        {
            chart1.Palette = (ChartColorPalette)CmbPalette.SelectedIndex;
        }

        private void CmbChartType_SelectedIndexChanged(object sender, EventArgs e)
        {
             series.ChartType = (SeriesChartType)CmbChartType.SelectedIndex;
        }
    }
}