【问题标题】:How to Plot Data Faster如何更快地绘制数据
【发布时间】:2021-03-13 12:27:15
【问题描述】:

我想绘制从 TCP 服务器获取的所有数据点。但我想不出一种方法来绘制所有数据点。相反,目前我将字符串打印到文本框中。从文本框中只打印第一行。 这是示波器 GUI 的实时数据绘图。 如何绘制所有值。

我用 I2S 麦克风对正弦波进行了测试,当使用以下代码绘制时,它给出了一个失真的信号。

int t;

private void Timer1_Tick(object sender, EventArgs e)
{
    one = new Thread(test);
    one.Start();
    t++;
}

public void test()
{
    byte[] bytes = new byte[client.ReceiveBufferSize];
    var readCount = stream.Read(bytes, 0, bytes.Length);

    string datastring = Encoding.UTF8.GetString(bytes);
    txtdata.Invoke((MethodInvoker)(() => txtdata.Text = datastring.Substring(0, 100)));
    
    txtno.Invoke((MethodInvoker)(() => 
        txtno.Text = ("\nnumber of bytes read: " + readCount)
    ));

    String ch1 = txtdata.Text; ;
    String[] ch1y = ch1.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

    for (int a = 1; a < ch1y.Length - 1; a++)
    {
        chart1.Invoke((MethodInvoker)(() =>
            chart1.Series[0].Points.AddXY(t, Convert.ToDouble(ch1y[a]))
        ));
    }

}

【问题讨论】:

  • 定时器的间隔是多少?
  • 1 毫秒 @ChrisSchaller。
  • 您的方法是否在该时间范围内完成,我怀疑您很容易获得竞争条件
  • client 到底是什么?
  • 客户端是PC,服务器是ESP32模块@ChrisSchaller

标签: c# winforms charts tcpclient


【解决方案1】:

这里的问题不在于您绘制数据的速度有多快,而是您尝试使用非均匀异步模式绘制实时模拟值。

听起来您正试图从 First Principals 的角度来解决这个问题,但您跳过了很多背景知识,而这是实现这一目标所必需的。

示波器具有许多功能,可让您专注于您在显示屏上看到的模拟样本的特定宽度或长度,这可能代表音频的微小样本,显示屏中线的幅度通常代表电脉冲在相对时间点的电压,而不是特定时间点。

如果您的 正弦波 表示恒定的 2KHz,并且您可以在屏幕上看到 2 个峰(和 2 个谷),那么您实际上是在查看在 1ms 间隔内捕获的数据,以绘制像图表中那样的波浪线需要很多点,因此您最初尝试将其绘制为单个 X、Y 纵坐标将需要超过 1 毫秒的多个、数百个离散点来渲染相同类型的线,但是您还必须特别小心,以确保 x 间隔代表确切的时间量,否则您绘制的点相对于采样值的时间将不在正确的位置。

这种处理频率不是你想用 C# 来实现的,它需要在硬件级别进行。

您用于 sample analogue 输入的 ESP32 将以特定的时间间隔捕获特定的数据包,您可能见过像 8 这样的短语-Bit 16Khz Mono 用于描述音频质量。

根据 ESP32 中正在进行的处理,您收到的字节通常代表总样本,然后我们需要使用 bitness 来确定如何将字节分解为 array 个值,它不是单个值。

所以 8-Bit Mono 意味着每 8 位将代表一个值,所以在这种情况下每个字节都是一个单独的值。 Mono 表示这是一个一维数组,在 Stereo 或 2 通道 interleaved 中,字节表示 2 个单独的数组,所以每个第二个字节实际上进入了第二个数组...

所以你不能简单地使用 UTF8 编码将字节转换为文本,你需要使用其他库,比如 NAudio 来解码,你可以手动尝试。

在简单的 c# 术语中,假设 8 位单声道,您可以使用数组索引为 X 和 x 索引处的字节值作为 Y 绘制整个样本,但这仍然不是匹配您在示波器中看到的内容。

请考虑一下您真正想在屏幕上看到的内容,对使用快速傅里叶变换计算 (FFT) 分析模拟读数进行一些研究,甚至可以直接在 ESP32 上执行此操作,这可能会减少您在 C# 代码中所做的处理。

【讨论】:

  • 我编辑了代码。我没有运行线程,而是在每个 timer.tick 事件中绘制图表。现在它有点好。但仍然不像正弦波。我认为这里的问题是在两个滴答点期间,无法绘制所有点以获得平滑的信号。我怎样才能以这种方式绘图@ChrisSchaller
  • 这不是String[] ch1y = ch1.Split(new char[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); for (int a = 1; a &lt; ch1y.Length - 1; a++) { chart1.Invoke((MethodInvoker)(() =&gt; chart1.Series[0].Points.AddXY(t, Convert.ToDouble(ch1y[a])) ));做的事
【解决方案2】:

我降低了波特率。此后,该波在 2kHz 波处几乎显示为纯正弦波。但只有 2kHz 波看起来像这样。不是运行线程,而是使用Add 命令为每个时钟滴答绘制图表。

【讨论】:

    猜你喜欢
    • 2017-05-14
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 2019-09-28
    • 2022-07-19
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多