TCP 客户端中的 ESP32 实时数据图

物联网 ESP32
2021-06-09 14:44:59

我正在实现一个示波器 GUI 来可视化来自连接到 ESP32 的 I2S 麦克风的数据。数据通过 WiFi 传输到 ESP32,通过 TCP 套接字连接到制作 GUI 的 PC 客户端。

这是 ESP32,服务器端代码。

void setup() {

    const i2s_config_t i2s_config = {
      .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX), // Receive, not transfer
      .sample_rate = 16000,                         // 16KHz
      .bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT, // could only get it to work with 32bits
      .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, // although the SEL config should be left, it seems to transmit on right
      .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,     // Interrupt level 1
      .dma_buf_count = 4,                           // number of buffers
      .dma_buf_len = 8                              // 8 samples per buffer (minimum)
    };
};


void loop() {

  WiFiClient client = wifiServer.available();

  if (client) {

    while (client.connected()) {

      while (client.available()>0) {
        int32_t sample = 0;
        int bytes_read = i2s_pop_sample(I2S_PORT, (char *)&sample, portMAX_DELAY); // no timeout
        String samplestring = String(sample*0.00000059);
        client.println(samplestring);
     }

      delay(10);
   }
    client.stop();
    Serial.println("Client disconnected");
   }
}

我在 winform 的 GUI 上绘制它。但是当我绘制时它没有给出正确的波形格式(我尝试使用 1kHz 正弦波)。我正在将数据加载到文本框并转换double为绘制数据。

这里有什么问题?

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]))
        ));
    }
}

我像这样编辑了上面的代码

private void Timer1_Tick(object sender, EventArgs e)
    {
        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[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        double[] val = new double[ch1y.Length];

        for (int a = 1; a < ch1y.Length - 1; a++)
        {
            val[a] = double.Parse(ch1y[a]);


            chart1.Series[0].Points.Add(val[a]);
        }
        if (chart1.Series[0].Points.Count > 5)
            chart1.Series[0].Points.RemoveAt(0);
        chart1.ChartAreas[0].AxisX.Minimum = double.NaN;
        chart1.ChartAreas[0].AxisX.Maximum = double.NaN;
    }
1个回答

这里有几个想法:我和上面的 jcaron 一起说,你在跨边界分割数据时遇到了问题。此外,对于 1kHz 波,您以 16kHz 采样这一事实意味着该波将非常参差不齐。尝试输入 160Hz。所以,这里有一些可能效果更好的伪代码:试试看。如果它有效,你可以改进它,等等。它不是内存有效的,但你是在 PC 上运行的。

伪代码:有一个字符串,可以记住计时器滴答之间的内容。我称之为incoming_chars。为了快速尝试,将其设为全局(不寒而栗!)。以后再细化。

在您的计时器中打勾:

读取字节,转换为字符串并将其附加到incoming_chars,
而incoming_chars contans '\n'
..从incoming_chars
..获取第一个子字符串,包括'\n' ..将其解析为双精度并添加到图表中..切出第一个子字符串从incoming_chars
结束而
如果图表现在有太多点,请修剪旧的历史点。