前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#实例(经典):四路光电开关&激光雷达数据采集和波形图绘制

C#实例(经典):四路光电开关&激光雷达数据采集和波形图绘制

作者头像
zls365
发布2020-10-30 11:18:10
1.6K0
发布2020-10-30 11:18:10
举报
文章被收录于专栏:CSharp编程大全CSharp编程大全

前言:本文全部纯手工打造,如有疏漏之处,还请谅解!

这篇文章涉及较多C#重要知识点,如果都能看懂,你至少可以算得上入门了!有兴趣的同志可以下载源码调试.

开始吧:

-》指令格式介绍

激光测距模块

UDP: 192.168.1.200 8008发往8010;192.168.1.201 8008发往8011;

协议:C3 00为195cm

光电开关模块

UDP:192.168.1.202 8008发往8012

帧头59 59

数据 01 01 01 01 为4个光电开关状态,依次为安检通道入口光电开关、安检门光电开关1、安检门光电开关2,安检通道出口光电开关。其中1为无人遮挡状态,0为有人遮挡状态

填充 44 55 66 77 88 99 00 12 23 34 45 56 67 ee

4个光电开关均无人

1、2、3光电开关有人 4光电开关无人

开发软硬件环境:

硬件:1. 4路光电开关,4路测距雷达,数据通过udp发送到主机192.168.1.119

软件:1. vs2017 + win10

-》重要知识点:

1. 多线程操作:thread和task的使用

2. winform的chart控件使用

3.队列Queue和list使用

4.双缓冲用法

5.定时器操作

6.线程中操作主窗体控件:

this.Invoke((EventHandler)delegate

{

richTextBoxEx1.Text += stringData + "\r\n";

}):

7.通过循环的方式遍历操作控件

8.数据类型转换:

Byte[] recv = client.Receive(ref endpoint);

string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();

-》开发难点:

1. chart需要绘制所有采集上来的数据点,光电开关1毫秒就一组数据,绘图时间得跟得上

2. 多线程的灵活使用

全部代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace lidarTest
{
    public partial class mainForm : DevComponents.DotNetBar.Office2007Form
    {
        public mainForm()
{
            this.DoubleBuffered = true;//设置本窗体
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲

            this.EnableGlass = false;
            InitializeComponent();
            InitChart();
            checkBox2.Checked = false;
            checkBox1.Checked = false;
        }
        private Queue<int>[] dataQueue = new Queue<int>[8];//把Queue<double>看成一个类型 int[] a=new int [8]
        private List<int>[] dataList = new List<int>[8];
        private Queue<string> dQueue = new Queue<string>();
        bool isStart = false;
        int count = 0;
        private static readonly object Lock = new object();
        Stopwatch elapsetime = new Stopwatch();
        private void mainForm_Load(object sender, EventArgs e)
{
            dataQueue[0] = new Queue<int>();
            dataQueue[1] = new Queue<int>();
            dataQueue[2] = new Queue<int>();
            dataQueue[3] = new Queue<int>();
            dataQueue[4] = new Queue<int>();
            dataQueue[5] = new Queue<int>();
            dataQueue[6] = new Queue<int>();
            dataQueue[7] = new Queue<int>();

            dataList[0] = new List<int>();
            dataList[1] = new List<int>();
            dataList[2] = new List<int>();
            dataList[3] = new List<int>();
            dataList[4] = new List<int>();
            dataList[5] = new List<int>();
            dataList[6] = new List<int>();
            dataList[7] = new List<int>();

            this.WindowState = FormWindowState.Normal;
            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.Top = 0;
            this.Left = 0;
            this.Width = Screen.PrimaryScreen.WorkingArea.Width;
            this.Height = Screen.PrimaryScreen.WorkingArea.Height;
            Start();

            //MessageBox.Show( DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_fff"));
        }
        // 防止闪屏        
        //protected override CreateParams CreateParams
        //{
        //    get
        //    {
        //        CreateParams cp = base.CreateParams;
        //        cp.ExStyle |= 0x02000000;
        //        return cp;
        //    }
        //}

        public void Start()
{
            Thread t1 = new Thread(StartDataRevThread1); //第一路激光雷达数据接收线程
            t1.Start();
            t1.IsBackground = true;

            Thread t2 = new Thread(StartDataRevThread2); //第二路激光雷达数据接收线程
            t2.Start();
            t2.IsBackground = true;

            Thread t3 = new Thread(StartDataRevThread3);//第三路激光雷达数据接收线程
            t3.Start();
            t3.IsBackground = true;

            Thread t4 = new Thread(StartDataRevThread4);////第四路激光雷达数据接收线程
            t4.Start();
            t4.IsBackground = true;

            Thread t5 = new Thread(StartDataRevThread5);//四个广电开关数据接受线程
            t5.Start();
            t5.IsBackground = true;

            Thread t6 = new Thread(dataSaveThread6);//数据写入线程
            t6.Start();
            t6.IsBackground = true;
        }
        private void StartDataRevThread1()
{
            try
            {
                UdpClient client = new UdpClient(8021);
                //IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);//
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.30"), 8008);
                //client.Client.ReceiveBufferSize = 40960;//40960 默认值是8192
                while (true)
                {
                    Byte[] recv = client.Receive(ref endpoint);
                    string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
                    this.Invoke((EventHandler)delegate
                        {
                            //richTextBoxEx1.Text += stringData + "\r\n";
                            chartShow( recv[2] + (recv[3]<<8),1);
                        }
                        );
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace) ;
            }
        }
        private void StartDataRevThread2()
{
            try
            {
                UdpClient client = new UdpClient(8022);
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.40"), 8008);
                while (true)
                {
                    Byte[] recv = client.Receive(ref endpoint);
                    string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
                    this.Invoke((EventHandler)delegate
                    {
                        //richTextBoxEx2.Text += stringData + "\r\n";
                        chartShow(recv[2] + (recv[3] << 8),2);
                    }
                      );
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
            }
        }
        private void StartDataRevThread3()
{
            try
            {
                UdpClient client = new UdpClient(8023);
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.100"), 8008);
                while (true)
                {
                    Byte[] recv = client.Receive(ref endpoint);
                    string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
                    this.Invoke((EventHandler)delegate
                    {
                        //richTextBoxEx3.Text += stringData + "\r\n";
                        chartShow( recv[2] + (recv[3] << 8),3);
                    }
                      );
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
            }
        }
        private void StartDataRevThread4()
{
            try
            {
                UdpClient client = new UdpClient(8024);
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.200"), 8008);
                while (true)
                {
                    Byte[] recv = client.Receive(ref endpoint);
                    string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
                    this.Invoke((EventHandler)delegate
                    {
                        //richTextBoxEx4.Text += stringData + "\r\n";
                        chartShow( recv[2] + (recv[3] << 8),4);
                    }
                      );
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
            }
        }

        private void StartDataRevThread5()
{
            try
            {
                UdpClient client = new UdpClient(8012);
                IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.202"), 8008);
                client.Client.ReceiveBufferSize = 1024*1024;//默认值是8192
                while (true)
                {
                    Byte[] recv = client.Receive(ref endpoint);
                    elapsetime.Restart();//计时开始
                    this.Invoke((EventHandler)delegate
                    {
                        //if (count >= 100)
                        {
                            count = 0;
                            Task.Run(() =>
                            {
                                chartShow(recv[2], 5);
                            }
                            );
                            Task.Run(() =>
                            {
                                chartShow(recv[3], 6);
                            }
                            );
                            Task.Run(() =>
                            {
                                chartShow(recv[4], 7);
                            }
                           );
                            Task.Run(() =>
                            {
                                chartShow(recv[5], 8);
                            }
                          );
                            //chartShow(recv[2], 5);
                            //chartShow(recv[3], 6);
                            //chartShow(recv[4], 7);
                            //chartShow(recv[5], 8);

                            if (checkBox2.Checked == true)
                            {
                                string stringData = "0x" + BitConverter.ToString(recv).Replace("-", " 0x").ToLower();
                                dQueue.Enqueue(DateTime.Now.ToString("yyyy-MM-dd_HH:mm:ss:fff") + "  " + stringData);
                            }
                         

                        }
                        count++;

                    } );
                    elapsetime.Stop();//计时结束
                    this.Invoke((EventHandler)delegate
                    {
                        label1.Text = "接收数据耗时:"+ elapsetime.ElapsedMilliseconds.ToString("0000");
                    });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
            }
        }
        private void dataSaveThread6()
{
            while (true)
            {
                if (checkBox2.Checked == true)
                {
                    String LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log");
                    if (dQueue.Count() > 0)
                        strWrite(dQueue.Dequeue(), LogPath, "log.txt");
                }
            }
        }
        private void InitChart()
{
            Chart[] ch = new Chart[12] { chart1, chart2, chart3, chart4,chart5, chart6, chart7, chart8 , chart_1, chart_2, chart_3, chart_4 };
            for (int i = 0; i < 4 ; i++)
            {
                ch[i].ChartAreas.Clear();
                ChartArea chartArea1 = new ChartArea("C1");
                ch[i].ChartAreas.Add(chartArea1);
                //定义存储和显示点的容器
                ch[i].Series.Clear();
                Series series1 = new Series("S1");
                series1.ChartArea = "C1";
                ch[i].Series.Add(series1);

                ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false;
                ch[i].Legends[0].Enabled = false;

                ch[i].ChartAreas[0].AxisX.Interval = 100;
                ch[i].ChartAreas[0].AxisX.Maximum = 1000;
                //ch[i].ChartAreas[0].AxisX.ScaleView.Size = 8;//设置图表可视区域数据点数,说白了一次可以看到多少个X轴区域

                ch[i].ChartAreas[0].Axes[0].MajorGrid.Enabled = false;
                ch[i].ChartAreas[0].Axes[1].MajorGrid.Enabled = false;
                //y轴上网格
                //ct.ChartAreas[0].Axes[1].MajorGrid.Enabled = false;  
                //ch[i].ChartAreas[0].AxisX.IsStartedFromZero = false;
                //ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
                //ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
                //设置标题
                ch[i].Titles.Clear();
                //ch[i].Titles.Add("S01");
                //ch[i].Titles[0].Text = "通道" + (i + 1) + " 折线图显示";
                //ch[i].Titles[0].ForeColor = Color.RoyalBlue;
                //ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
                //设置图表显示样式
                ch[i].Series[0].Color = Color.Red;
                //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", );
                ch[i].Series[0].ChartType = SeriesChartType.FastLine;
                ch[i].Series[0].Points.Clear();
            }
            for (int i = 4; i < 12; i++)
            {
                ch[i].ChartAreas.Clear();
                ChartArea chartArea1 = new ChartArea("C1");
                ch[i].ChartAreas.Add(chartArea1);
                //定义存储和显示点的容器
                ch[i].Series.Clear();
                Series series1 = new Series("S1");
                series1.ChartArea = "C1";
                ch[i].Series.Add(series1);

                ch[i].ChartAreas[0].AxisY.IsStartedFromZero = false;
                ch[i].Legends[0].Enabled = false;

                //ch[i].ChartAreas[0].AxisX.Interval = 100;
                //ch[i].ChartAreas[0].AxisX.Maximum = 10000;
                //ch[i].ChartAreas[0].AxisX.ScaleView.Size = 8;//设置图表可视区域数据点数,说白了一次可以看到多少个X轴区域

                ch[i].ChartAreas[0].Axes[0].MajorGrid.Enabled = false;
                ch[i].ChartAreas[0].Axes[1].MajorGrid.Enabled = false;
                //y轴上网格
                //ct.ChartAreas[0].Axes[1].MajorGrid.Enabled = false;  
                //ch[i].ChartAreas[0].AxisX.IsStartedFromZero = false;
                //ch[i].ChartAreas[0].AxisX.MajorGrid.LineColor = System.Drawing.Color.Silver;
                //ch[i].ChartAreas[0].AxisY.MajorGrid.LineColor = System.Drawing.Color.Silver;
                //设置标题
                ch[i].Titles.Clear();
                //ch[i].Titles.Add("S01");
                //ch[i].Titles[0].Text = "通道" + (i + 1) + " 折线图显示";
                //ch[i].Titles[0].ForeColor = Color.RoyalBlue;
                //ch[i].Titles[0].Font = new System.Drawing.Font("Microsoft Sans Serif", 12F);
                //设置图表显示样式
                ch[i].Series[0].Color = Color.Red;
                //this.chart1.Titles[0].Text = string.Format("{0}折线图显示", );
                ch[i].Series[0].ChartType = SeriesChartType.FastLine;
                ch[i].Series[0].Points.Clear();
            }
        }

        public void chartShow(int y, int ch)
{

            Chart[] chNum = new Chart[8] { chart_1, chart_2, chart_3, chart_4, chart5, chart6, chart7, chart8 };
            if (ch <= 8)
                chartDisplay(chNum[ch - 1], ch, y);

        }
        delegate void ChartDelegate(Chart chart, int ch, int y);
        private void chartDisplay(Chart chart, int ch, int y)
{

            if (chart.InvokeRequired)
            {
                ChartDelegate chartDelegate = chartDisplay;
                chart.Invoke(chartDelegate, new object[] { chart, ch, y });
            }
            else
            {
                lock (Lock)
                {
                    if (isStart == true)
                        UpdateQueueValue(ch, y);//点击开启按钮后,开始采集收集数据,并更新到队列或列表中
                   
                }
            }
        }
        private void UpdateQueueValue(int ch, int y)
{
            lock (Lock)
            {
                if (dataQueue[ch - 1].Count > 1000)
                    //先出列
                    dataQueue[ch - 1].Dequeue();
                dataQueue[ch - 1].Enqueue(y);
                //方法二 用list
                //if (dataList[ch - 1].Count > 20000)
               //     dataList[ch - 1].RemoveAt(0);
               
                //dataList[ch - 1-4].Add(2);
                dataList[ch - 1].Add(y);
            }
        }
        private void btnStart_Click(object sender, EventArgs e)
{

            if (!isStart)
            {
               dataQueue[0] = new Queue<int>();
               dataQueue[1] = new Queue<int>();
               dataQueue[2] = new Queue<int>();
               dataQueue[3] = new Queue<int>();
               dataQueue[4] = new Queue<int>();
               dataQueue[5] = new Queue<int>();
               dataQueue[6] = new Queue<int>();
               dataQueue[7] = new Queue<int>();

                dataList[0] = new List<int>();
                dataList[1] = new List<int>();
                dataList[2] = new List<int>();
                dataList[3] = new List<int>();
                dataList[4] = new List<int>();
                dataList[5] = new List<int>();
                dataList[6] = new List<int>();
                dataList[7] = new List<int>();

                chart_1.Series[0].Points.Clear();
                chart_2.Series[0].Points.Clear();
                chart_3.Series[0].Points.Clear();
                chart_4.Series[0].Points.Clear();
                chart5.Series[0].Points.Clear();
                chart6.Series[0].Points.Clear();
                chart7.Series[0].Points.Clear();
                chart8.Series[0].Points.Clear();

                btnStart.Text = @"停止采集";
                btnStart.DisabledImage = btnStart.Image;
                btnStart.Image = (Image)btnStart.PressedImage.Clone();
                isStart = !isStart;

            }
            else
            {
                btnStart.Text = @"开始采集";
                btnStart.Image = btnStart.DisabledImage;
                isStart = !isStart;
            }
        }
        /*************文件写入函数**************/
        private void strWrite(string str, string filePath, string fileName)
{
            lock (Lock)
            {
                if (!Directory.Exists(filePath))
                    Directory.CreateDirectory(filePath);
                if (!File.Exists(filePath + "\\" + fileName))
                    File.Create(filePath + "\\" + fileName).Close(); //.Close 很关键,不然会有问题

                StreamWriter sw = new StreamWriter(filePath + "\\" + fileName, true);//true 追加数据
                sw.WriteLine(str);
                sw.Close();
            }         
        }
        /*************chart图片保存函数**************/
        private void imageSave( Chart chart, string filePath, string fileName)
{
            lock (Lock)
            {
                if (!Directory.Exists(filePath))
                    Directory.CreateDirectory(filePath);
                chart.SaveImage(filePath +"\\" + fileName, ChartImageFormat.Png);
            }
        }

        /*************定时器中更新chart**************/
        private void timer1_Tick(object sender, EventArgs e)
{

            Chart[] ch = new Chart[8] { chart1, chart2, chart3, chart4, chart5, chart6, chart7, chart8 };
            Chart[] cha = new Chart[4] { chart_1, chart_2, chart_3, chart_4 };
            string[] str = new string[8] { "chart1", "chart2", "chart3", "chart4", "chart5", "chart6", "chart7", "chart8" };
            string[] stri = new string[4] { "chart_1", "chart_2", "chart_3", "chart_4",  };
            Label[] lb = new Label[4] { label2, label3, label4, label5 };

            
            for (int j = 4; j < 8; j++)
            {
                Stopwatch sw = new Stopwatch();
                var k = j;//参数需要传入task中,不然j一直是7
                Task.Run(() =>
            {

                sw.Start();
                this.Invoke((EventHandler)delegate
                {
                    //chart5.Series[0].Points.Clear();
                    for (int i = 0; i < dataList[k].Count; i++)
                        ch[k].Series[0].Points.AddY(dataList[k][i]);//光电开关波形图-所有点
                    dataList[k].Clear();

                    ch[k-4].Series[0].Points.Clear();
                    for (int i = 0; i < dataQueue[k].Count; i++)
                        ch[k - 4].Series[0].Points.AddY(dataQueue[k].ElementAt(i));//光电开关波形图-最近1000个点


                    for (int i = 0; i < dataList[k-4].Count; i++)
                        cha[k - 4].Series[0].Points.AddY(dataList[k-4][i]);//激光测距雷达波形图--所有点
                    dataList[k-4].Clear();

                    if (checkBox1.Checked == true)
                    {
                        //保存曲线图片
                        String imagePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "image//" + str[k]);
                        imageSave(ch[k], imagePath, DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss_fff") + ".png");
                    }
                    sw.Stop();
                    lb[k - 4].Text = sw.ElapsedMilliseconds.ToString(str[k] + "耗时:" + "0000");//记录chart绘制的好事呢
                });

            });
            }


        }
  
    }
}

运行结果:

项目源码下载地址:

链接:https://pan.baidu.com/s/1QfoIVNarj-rgK449JM40yQ

提取码:v2nu

------------------------------------------------------------------------

如果这篇文章对你有帮助,就请多多点击在看,让更多朋友看到,需要进C#交流群群的请加,备注进群

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CSharp编程大全 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档