題:
減少arduino和我的計算機上的處理草圖之間的延遲
Kenneth .J
2014-06-04 17:27:35 UTC
view on stackexchange narkive permalink

我目前正在Arduino項目書的項目14中。

我正在嘗試使用Arduino控製筆記本電腦上的處理草圖。這可以通過使用電位器控製圖像的背景來實現。

Arduino代碼:

  void setup(){} Serial.begin(9600);} void循環(){Serial.write(analogRead(A0)/ 4);}  

處理:

  //導入串行庫導入processing.serial。*; //設置串行objectSerial myPort; //為imagePImage徽標創建一個對象; //變量以存儲背景colorint bgcolor = 0; void setup(){``colorMode(HSB,255);徽標= loadImage(“ http://arduino.cc/logo.png”);大小(logo.width,logo.height); println(“可用的串行端口”); println(Serial.list()); myPort = new Serial(this,Serial.list()[0],9600);} //等效於arduino的循環函數void draw(){if(myPort.available()> 0){bgcolor = myPort.read(); println(bgcolor); } background(bgcolor,255,255); image(logo,0,0);}  

現在,雖然該代碼有效,但隨著我轉動電位計,背景顏色發生了變化,但很大轉動電位器和看到背景改變顏色之間的時間差,以及Arduino /電位器的值在處理的串行監視器上改變。

我嘗試過的事情:

  • 更改串行通訊速度

我注意到,當我降低串行通訊速度時,例如大約100左右,從打開電位器到在筆記本電腦上看到電位器變化之間的延遲減少到大約1秒。但是,當我進一步降低串行通信速度時,例如值為1時,延遲再次增加。

在另一方面,在9600的標準速度下,延遲非常大,大約5秒++,然後電位計的變化才會出現在筆記本電腦/處理。

為什麼降低通訊速度(達到特定點)會減少時間延遲,而增加通訊時間會增加時間延遲?而且,無論如何,我可以使它接近瞬時嗎?

您每一次都在Arduino`loop()`周圍輸出讀數。您的Processing程序很有可能運行得不夠快,無法跟上它的步伐。嘗試在Arduino代碼的`loop()`中添加一個延遲,以減慢它的速度;例如延遲(50)。
嗨,彼得,謝謝您的及時回答,增加一點延遲確實可以解決我的問題。不過,這只是一個小問題,有什麼辦法可以確定將來我的處理程序的速度,以防止再次發生這種情況,或者獲得更好的筆記本電腦/處理速度是否可以解決問題?另外,為什麼輸入250或300的通訊速度會弄亂arduino的讀數?(我得到的讀數在讀數和零之間交替顯示,例如147,0,147,0)
五 答案:
Tom
2014-06-06 17:32:36 UTC
view on stackexchange narkive permalink

正如已經指出的那樣,您的Arduino說得太快了。添加 delay()會減慢它的速度,但是仍然對處理感到大吼。理想情況下,您希望Processing在方便時詢問該值,然後從Arduino收到一個答案。

輸入 SerialEvent()

與Arduino上的 loop()和Processing中的 draw()相對, serialEvent()內部的所有內容僅在串行緩衝區。因此,與其處理盡可能快的問題而不是讓Arduino更快地大喊大叫,不如讓他們進行愉快,禮貌的(異步)對話。

Processing和Arduino都有一個serialEvent。 這是Arduino上的serialEvent()這是Processing中的serialEvent()。雙方都使用serialEvent,會發生以下情況:

  1. 處理將字符發送到串行連接。這可以是任何字符,但是如果我們預先確定一個字符,我們可以過濾掉例如嘈雜的信號。對於此示例,讓我們每次想要重新讀取電位計時都發送 V 。發送角色後,我們將照常繼續我們的業務。不在這裡等待答案!

  2. 在Arduino方面,什麼也沒有發生,直到它在串行緩衝區中接收到數據為止。它檢查傳入的字符是否是 V ,幸運的是,它是。 Arduino一次讀取電位計的值,一次將該值輸出到串行,然後返回冷卻狀態,最大程度地放鬆所有冷卻。提示:以字符(在本例中為 * )終止該值。這將幫助您進行下一步。

  3. 當串行緩衝區中的新數據突然出現干擾 strike>時,處理過程將進行常規的界面像素處理。它切換到 serialEvent(),並開始讀取串行數據,直到遇到終止的 * 。知道這是值得閱讀的最後一個字符後,我們現在可以將輸入值存儲在存儲Arduino讀數的變量中。

  4. 就是這樣。現在,處理過程知道新的傳感器值,並繼續執行我們告訴它的所有操作。同時,您的Arduino正在享受天氣或考慮天氣的存在,直到收到串行數據為止。

  5. ol>
在使用時,將一個電容器與電位計並聯。這樣可以消除DAC輸入的微小變化,從而可以防止處理中的抖動動作。
謝謝您這個不錯的(也是有點擬人化的)答案!
實際上,通過USB提出問題可以是一個主意。這是因為USB比串行端口具有更多的“延遲”,因此與其他方式相比,提問和等待響應的操作耗時更多,特別是與以高波特率進行的操作相比。讓Arduino運行得更快一點是可以的(儘管它不應使鏈接的串行部分飽和)。不足之處在於,處理草圖應在可用的Arduino數據耗盡時將其耗盡,並保留需要時使用的最後一個完整值。
Peter Bloomfield
2014-06-04 19:25:42 UTC
view on stackexchange narkive permalink

您每次在Arduino loop()周圍都會輸出一個讀數,因此您的Processing程序運行速度似乎不足以跟上它的運行速度。嘗試在您的Arduino代碼中的 loop()中添加延遲以減慢它的速度,例如:

  void loop(){Serial.write(analogRead(A0) / 4); delay(50);}  

據我所知,Processing旨在以一致的幀速率運行,您可以使用 frameRate() code進行修改>功能。默認情況下,它為每秒60幀,儘管在較舊的系統(或運行密集型程序的位置)上運行速度可能較慢。您可以通過讀取 frameRate 變量來檢查其運行速度。

在Arduino循環中引入50毫秒的延遲意味著它將稍作更新每秒低於20次。這意味著它應該足夠快以達到用戶界面的目的,但也應該在處理程序的能力之內。

就波特率(通信速度)而言,可以任意調整它可能會產生不可預測的結果。這是因為硬件僅支持特定的速度,而嘗試使用其他任何速度都可能導致另一端的數據出現亂碼。 Serial.begin()文檔提供了有關支持的波特率的更多信息。

Volker Siegel
2014-06-04 23:09:00 UTC
view on stackexchange narkive permalink

您的輪詢循環將以處理器的全速運行,並在每一輪中寫入串行端口。

這樣,您向串行端口寫入的方式比其處理的更多。

端口會以您配置的速度快寫出數據,並以太快的速度從程序中傳入緩衝數據以將其寫出

這裡重要的是它將保持值的順序:這是一個 FIFO緩衝區 ,以先進先出順序工作。

發生的事情是:
該循環將填充端口緩衝區,並使其保持100%充滿。
如果轉動電位計,則更改後的值如果將其寫入緩衝區的末尾,則該端口將以最快的速度寫入緩衝區中仍具有舊值的所有元素。

最後是您感興趣的值。我們想立即看到的最新值是在FIFO的末尾,先進先出也意味著後進/後出。與我們想要的相反。

讀取數據有意義的最大頻率是可以寫入數據的頻率,因此您至少應使用足夠長的延遲來寫入數據。


另一種獨立的措施通常可以防止這種延遲,
您還可以將端口的寫緩衝區設置為最小。


p>

這將導致數據刪除得更早,而不是先緩衝很多數據。

當然,在許多應用程序中,這並不是您所需要的;運氣不好,它一開始可能仍然可以工作,並且在某些情況下,由於處理器負載等因素導致時序變化時,它會變得不穩定,並且只會丟失一些隨機數據樣本。通常,大緩衝區的行為更具確定性,因此默認情況下使用大緩衝區

正確的主意,但聲明“緩衝區已滿,只會丟棄新數據”,這不太正確。一旦緩衝區被填滿,數據就不會被丟棄,而是寫入塊,直到傳出緩衝區中有空間為止。這意味著輸入和輸出很快就會以相同的平均速率流過,但是在它們之間存在一定的緩衝區等待時間。
Daniel Eisterhold
2014-06-05 07:50:26 UTC
view on stackexchange narkive permalink

僅在電位計的值變化超過某個閾值時才發送數據,而不是不斷發送串行數據。

  int oldValue = 0; const int threshold = 5; void setup( ){Serial.begin(9600); pinMode(A0,INPUT)} void loop(){if(oldValue > = AnalogRead(A0)+ threshold || oldValue < = AnalogRead(A0)-threshold){Serial.println(analogRead(A0)); oldValue = AnalogRead(A0); }}  
那個“ loop()”沒有用相等的樣本填充輸出緩衝區,這很好。但是它仍然以處理器的全速運行,這可能是所需速度的100倍。這意味著如果輸入頻繁變化,例如由於“閾值”以上的噪聲或高分辨率的連續變化(在此處的示例應用程序中不是這種情況),它仍然可以快速將緩衝區填充到極限。
Rishi Swethan
2017-06-03 03:35:34 UTC
view on stackexchange narkive permalink

有兩種簡單的解決方案可確保仍在尋找的人都可以使用:-

  1. 將延遲增加到50到100毫秒。

  2. setup()中的 Serial.begin(9600)之後添加它;

      Serial.setTimeout(50) ;  
  3. ol>

    第二步是最重要的。只有添加以上代碼後,它才對我有用。當我遇到完全相同的問題時,我在很多其他論壇中都很少提及這一點。

這有些誤解。 setTimeout()方法適用於輸入,而不適用於輸出-請參閱https://www.arduino.cc/en/Serial/SetTimeout上的文檔


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