題:
Arduino使用millis()的計時不正確或不正確?
user3284376
2014-03-10 04:28:49 UTC
view on stackexchange narkive permalink

我一直在使用Arduino來記錄一些數據。在我的Arduino草圖中,我還使用了 millis()函數,因此我可以跟踪所測量的每個值的獲取時間。但是,我注意到時間不正確。例如,在現實生活中,30秒只能顯示為10秒(虛構示例)。

我是否正確地說,Arduino延遲功能會影響使用 millis()的時間?換句話說,假設我有一個50ms的延遲,這是否意味著 millis()函數在該持續時間內也停止,然後在連接持續時間內繼續等等?當我嘗試繪製一些數據並發現經過一定時間後,我的數據中峰的頻率過於頻繁時,我注意到了這一點。因此,我想知道這是否是時間不匹配的原因,如果是,那麼如何解決這個問題,以便保持每個樣本出現的時間? :

  #include <eHealth.h>長時間未簽名; //當按下reset時,安裝例程運行一次:void setup(){Serial.begin(9600); } //循環例程永遠反復運行:void loop(){float ECG = eHealth.getECG();時間= millis(); Serial.print(時間); Serial.print(“”); Serial.print(ECG,5); Serial.println(“”); delay(50);}  
您是否正在使用官方的Uno板之一?
實際定時而不是虛假值(帶有時間戳記的串行監控器是理想的選擇)可能會幫助您了解發生了什麼。
“ millis()”的計算是由中斷驅動的,因此“ delay()”不應影響它。
我有同樣的問題,但僅當我將其(millis())集成到復雜代碼中時才有。我猜想代碼的複雜性會隨著代碼的複雜性越來越延遲而影響其準確性。有什麼辦法可以避免這種情況?也許使用單獨的RTC模塊?
三 答案:
Cybergibbons
2014-03-10 14:15:13 UTC
view on stackexchange narkive permalink

millis()是中斷驅動的,因此 delay()不會對其產生影響,至少不會在基於ATmega的板上。

並不是說 millis()也是完全準確的。計時器的每個刻度不完全是1毫秒,而是1.024毫秒。該錯誤會逐漸累積,直到進行校正為止。這可以在TIMER0_OVF(定時器0溢出)中斷處理程序的實現中看到。

另一個不准確的原因是振盪器/晶體本身,它不完全是16MHz。不過,它非常接近,並且只要溫度變化不大,就相對穩定。

上面的意思是,使用 millis()。這聽起來像不是您的問題。

另一個潛在的問題是 getECG()在做什麼-這可能很慢。

  float eHealthClass :: getECG(void){float類似物0; //從模擬輸入讀取。Analog0 = analogRead(0); //二進製到電壓的轉換返回Analog0 =(float)analog0 * 5 / 1023.0; }  

analogRead()很慢,但並不慢,不會影響這樣的循環。

我見過的另一個問題是人們當他們更改時鐘速度但沒有正確更改boards.txt時。這意味著 millis()實現中使用的常量是錯誤的,並且時間是錯誤的。這是要執行以下操作

 靜態長號lastUpdate; if(millis()-lastUpdate > 50){lastUpdate = millis(); //做事情}  

我們真的需要查看您得到的時間戳。如果您實際上看到30s顯示為10s,那麼還有其他工作。

請注意,對於Uno,時鐘不是由晶體驅動的,而是僅使用比晶體精度低的陶瓷諧振器。
@jfpoilpret很好知道。 [查看原理圖](http://arduino.cc/zh/uploads/Main/Arduino_Uno_Rev3-schematic.pdf),這將是CSTCE16M0V53-R0 [Murata CERALOCK器件](http://www.mouser.com / ProductDetail /村田電子/ CSTCE16M0V53-R0 /?qs = HPA2Xx%252bU0WhPWbRcNuzhZw ==)。
諧振器的初始容差(通常為0.5-2%)和溫度穩定性很差,但是如果您在使用諧振器時校准定時環,只要溫度不動,它們就可以了。
Millis()仍在每1.024ms滴答的計時器上工作,但它們添加了錯誤補償,以每當誤差表變量變高時遞增的形式進行。我認為這實際上是Roman Black的算法。因此時序應該準確地更接近1ms。https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring.c
對於那些仍然有興趣的人,請參閱我在JRobert的答案上發表的評論,由於沒有答案,我不想回答自己的答案,我只是改寫了這個問題。
更優化的`getECG`:`float eHealthClass :: getECG(void){return AnalogRead(0)* 5 / 1023.0; }`
JRobert
2014-03-11 21:08:00 UTC
view on stackexchange narkive permalink

如果在很大的時間段 eHealth.getECG()調用持續時間內關閉了中斷,則 millis()的計數可能會落後。否則, millis()返回的時間應該比您描述的3x錯誤要準確得多。

您說採樣信號的頻率似乎比預期的要高,如果採樣率低於預期,則可能會發生這種情況。您是否假設採樣率為20Hz?您的循環可能會花費比50ms更長的時間,您會在打印時間中看到該時間,但這些時間仍應跟踪時鐘時間。如果您沒有考慮到這一點,但假設每次採樣為50ms,則會看到數據的明顯加速。

如果這不是問題,那麼下一步就是切換一個在 loop()時輸出,並用頻率計(某些便宜的DVM可以做到)或'示波器'測量所得方波的頻率。用空的 loop()做同樣的事情。第一個實驗將是您的實際採樣率或間隔;第二個將告訴您 millis()(即timer0頻率)是否符合您的期望。

我一直在研究它,並逐漸意識到問題並不在Arduino上,在大多數情況下,millis()函數運行得很好,其中一些值之間的間隔不完全是8ms(延遲)您已經說出了預期。我描述的3x錯誤是我用來接收數據的Python方面的錯誤。不知道可能是什麼結果,我使用的是python的pyserial,它運行緩慢。
我對您的實現不太了解,無法給您帶來1 / 2@'d的猜測,但是Python方面的速度足夠慢,無法刪除示例嗎?
user48711
2015-09-04 01:29:18 UTC
view on stackexchange narkive permalink

這裡也一樣。我可以補充一點,如果中斷被關閉,則測量的時間為“實時”。無論如何,我不明白為什麼會出現這種延遲,因為如果循環花費的時間太長,無論如何,millis()應該返回實時值(每個值之間只有更大的距離)

“這里相同”指的是什麼?答案應該獨立存在,因為StackExchange可以對事物進行重新排序(與論壇不同)。因此,“在此相同”可能意味著任何含義,具體取決於您的答案顯示在下面。
儘管(公認地)您缺乏足夠的聲譽,但該帖子更適合作為評論。
抱歉,我雖然回答您的問題,但顯然是指主要帖子,否則會是評論


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...