【问题标题】:Averaging serial data stream values平均串行数据流值
【发布时间】:2013-06-16 07:56:30
【问题描述】:

我大约有一个数据流。 500 Hz 来自串行端口。数据由控制机器的微处理器发送。数据被一个类过滤掉并显示在不同的文本框中,该类去除了传输协议使用的标题字符。 这是将我得到的四个变量分配给不同文本框的代码。

private void SetText(string text)
    {
        if (this.txtOutput.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            this.BeginInvoke(d, new object[] { text });
        }
        else
        {
            txtOutput.AppendText(text + "\r\n");
            string a = "", b = "", c = "", d="";
            string invia = text.ToString();
            Stripper strp = new Stripper();
            strp.Distri(invia, out a, out b, out c, out d);
            if (a != "")
            {
                textBox7.Text = a; //currentRes
            }
            if (b != "")
            {
                textBox2.Text = b; //temperature
            }

            if (d != "" )
            {
             textBox3.Text = d; //motor current
            }

            if (c == "1\r") //motor RPM
            {
                timer3.Start();
            }
        }
    }

我面临的问题是我每秒获得数百个值“a”、“b”和“d”,显然相关的文本框正在闪烁。此外,我想平均每个变量的值,每个变量取 100 个样本,然后在相关文本框中显示它们。这样可以避免闪烁并提供更准确的读数。

如何在不冻结同时必须为其他功能提供控制的应用程序的情况下将每个变量“a”、“b”和“d”平均到 x 个样本? 示例代码将不胜感激。

【问题讨论】:

    标签: c# stream serial-port buffer average


    【解决方案1】:

    每个变量取 100 个样本的平均值 ... 会给出更准确的读数

    那么这个数字 100 是从哪里来的,只是来自 GUI 设计还是与数据有某种关系?

    您是要平均独立(相邻)块还是需要移动平均?

    一个简单的方法:

    class Accum
    {
        private int sum, count;
    
        public event AverageChanged; 
    
        public void Add(int value)
        {
           sum += value;
           count += 1;
           if (count >= 100)
           {
               OnAvarerageChanged(sum/count);
               sum = 0;
               count = 0;
           }
        }
    
        ....
    
    }
    

    您需要在表单上创建 3 个此实例。由于所有 SerialPort 数据都将发生在同一个线程上,因此您只需在处理事件时进行同步。

    更新:

    最简单但不太通用的方法:

    class Accum
    {
        private int sum, count;
    
        //public event AverageChanged; 
    
        public void Add(int value)
        {
           sum += value;
           count += 1;
           if (count >= 100)
           {
               OnAvarerageChanged(sum/count);
               sum = 0;
               count = 0;
           }
        }
    
        public Label MyLabel { get; set; }
    
        private void OnAvarerageChanged(int av)
        {
            SetTextCallback d = new SetTextCallback(SetText);
            string text = av.ToString();
            MyLabel.BeginInvoke(d, new object[] { text });
        }
    
        private void SetText(string text)
        {
            this.MyLabel.Text = text;
        }
    
    }
    

    【讨论】:

    • 感谢您的建议。 100 只是一个数字,我坚持认为平均 100 个样本可以提供更准确的测量值和足够的时间来停止文本框闪烁,但显然它甚至可以是 1000。平均 x 值的独立块很好,我不需要更复杂的计算。我担心的是,如果我让 3 个类对这些值进行平均,应用程序会冻结。可能是我错了吗?
    • 不,如果你只是调用这个Add()方法,你只会更新1/100次,不会冻结。
    • 谢谢你。我现在要测试。
    • 您可以找到引发事件here 的代码,但您也可以稍作修改,并将对您的窗口(或标签)的引用传递给 Accum 类。
    • 这个类应该减轻负载(/ 100)。线程无济于事。但我看到这条线:txtOutput.AppendText(text + "\r\n");,摆脱它。
    猜你喜欢
    • 1970-01-01
    • 2013-05-03
    • 2021-12-22
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多