极客秀
搜索

基于C#和ESP32的远程示波器(6)—— 合理的利用数据缓存区来消除数据丢失

啊~我的天!好久没更新这个系列了,主要是在琢磨怎么彻底的消除数据不连续的问题。

这个星期从硬件到软件到通讯协议,试过了很多方法来解决数据,不连续的问题。光通讯协议就用了HTTP,UDP,WebSockerts以及TCP还为每一个通讯协议专门写了数据处理的代码和示波器(每天写到吐了、无数的BUG和Error)

最后我们解决的方法还是:定时器控制采样率、HTTP将数据打包上传、利用标志位来交替写入缓存区。 ** 上期问题阐述与解决 **
我简单的阐述一下上一期的代码出现的问题:

首先是我们在任务中运行ADC采集,这样子会导致我们无法控制我们的采样率,这样子对于信号采集来说是不应该出现的。 其次我们的数据在Data =
PostData中会有一个数据传递的过程,又可以造成不必要的耗时。 因此我们选择的方法是使用定时器来定时触发我们的ADC采样。
并且使用两个数据缓存区PostData1和PostData2,定时器交替向这两个缓存区写入数据。
** 主要代码 ** 我们首先加入定时器的头文件(利用的也是FreeRTOS)以及声明其句柄。

#include <freertos/timers.h>TimerHandle_t timer;

接着在主函数中加入定时器的配置

timer = xTimerCreate("DataTimer", pdMS_TO_TICKS(2), pdTRUE, NULL, onTimer);xTimerStart(timer, 0);

该定时器的名字命名为:DataTimer,2ms触发一次,自动装填,回调函数为onTimer 接着我们定义我们的回调函数的内容。


int QueueFlag = 1;void IRAM_ATTR onTimer(TimerHandle_t xTimer) {  static int j = 0;  int ADCVlaue[4];  for (int i = 0; i < 4; i++) {      ADCVlaue[i] = analogRead(32 + i);            if(QueueFlag)      {        switch(i)      {        case 0:PostData1+="IO0:"+String(ADCVlaue[i])+"n";break;        case 1:PostData1+="IO1:"+String(ADCVlaue[i])+"n";break;        case 2:PostData1+="IO2:"+String(ADCVlaue[i])+"n";break;        case 3:PostData1+="IO3:"+String(ADCVlaue[i])+"n";break;      }      }      else      {        switch(i)      {        case 0:PostData2+="IO0:"+String(ADCVlaue[i])+"n";break;        case 1:PostData2+="IO1:"+String(ADCVlaue[i])+"n";break;        case 2:PostData2+="IO2:"+String(ADCVlaue[i])+"n";break;        case 3:PostData2+="IO3:"+String(ADCVlaue[i])+"n";break;      }      }  }  j++;  if(j == 500)  {    j = 0;    if(QueueFlag == 1)    {      QueueFlag = 0;    }    else    {      QueueFlag = 1;    }    xSemaphoreGiveFromISR(dataSemaphore, NULL);  }}

我们设置缓存区PostData 1和PostData2, 接着定义一个QueueFlag用来决定我们写入的缓存区,并且设置好我们的数据形式。
当定时器触发500次后,改变这个标志位改变ADC所写入的缓存区。
这样子的好处是我们可以减小数据处理的频率,减少CPU的负荷以及使用环形缓存区可以避免我们发送数据的时候导致数据的丢失。
等到采样到500次后我们释放信号量,指示HTTP可以上传数据了。


void Task2Code(void *parameter) {  for (;;) {   if (xSemaphoreTake(dataSemaphore, portMAX_DELAY) == pdPASS) {    int number = 0;    HTTPClient http;    http.begin(serverUrl);    http.addHeader("Content-Type", "text/plain");    if(QueueFlag == 0)    {      int httpResponseCode = http.POST(PostData1);      PostData1 = "";    }    else    {      int httpResponseCode = http.POST(PostData2);      PostData2 = "";    }        http.end(); // 关闭HTTP连接      }  }  }

这样子就构成了我们的主要代码。
** 效果展示 ** 我们来看看运行效果。

这里有2000个点,4次的数据上传,可以看到几乎没有数据丢失的现象。

虽然在8157左右出现了一个数据异常,但是看来像是因为数据丢失/异常导致的结果,我们可以在上位机软件中想办法去除。
如果有机会后续可能会更新利用DMA来提高采样率以及设置外部ADC和DAC来提高数据的准确度。

1.转载请保留原文链接谢谢!
2.本站所有资源文章出自互联网收集整理,本站不参与制作,如果侵犯了您的合法权益,请联系本站我们会及时删除。
3.本站发布资源来源于互联网,可能存在水印或者引流等信息,请用户擦亮眼睛自行鉴别,做一个有主见和判断力的用户。
4.本站资源仅供研究、学习交流之用,若使用商业用途,请购买正版授权,否则产生的一切后果将由下载用户自行承担。
5.联系方式(#替换成@):pm#vimge.com

  相关内容