啊~我的天!好久没更新这个系列了,主要是在琢磨怎么彻底的消除数据不连续的问题。
这个星期从硬件到软件到通讯协议,试过了很多方法来解决数据,不连续的问题。光通讯协议就用了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来提高数据的准确度。