題:
如何在Arduino Uno上同時運行兩個循環?
Daniel T.
2014-09-29 02:54:06 UTC
view on stackexchange narkive permalink

我是Arduino的新手,我想控制兩個設備:

  1. 可以改變顏色的RGB LED燈條
  2. 一盞燈可以檢測環境光水平的傳感器
  3. ol>

    我想做的是讓LED燈條連續不斷地循環通過彩虹的顏色,並且光傳感器將調整LED的亮度根據環境光線水平這是我自己單獨測試的兩段代碼,並確認它們可以正常工作:

    LED燈條:

      j =(j + 1 )%256; //當前光週期的迭代// //設置條帶顏色for(int i = 0; i< strip.numPixels(); i ++){strip.setPixelColor(i,Wheel((((i * 256 / strip.numPixels()) + j)& 255));} //顯示新的顏色,並在下一個周轉之前等待20ms。show(); delay(20);  

    光傳感器:

      sensors_event_t事件; tsl.getEvent(&event); //獲得光照測量值trip.setBrightness(event.light); //設置LED燈條的亮度 

    問題是光傳感器需要100ms到600ms的時間來獲取讀數,並且 tsl.getEvent(&event)是一個阻塞的調用,因此最終結果是LED燈帶的更新速度太慢。我需要將兩者並排運行,以便光傳感器讀取不會阻止LED燈條更新。知道我怎麼能做到嗎?

“ tsl”來自哪個庫?
100至600ms過多。是否僅將LDR連接到模擬輸入?
@BrettM我認為他正在使用TSL2561 I2C光傳感器。
六 答案:
Gerben
2014-09-29 18:02:07 UTC
view on stackexchange narkive permalink

可以通過降低準確性來使傳感器更快地返回數據。

  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS); / *快速但分辨率低* /  

您還可以修改庫以在每次讀取後不關閉傳感器電源。只需打開 TSL2561.cpp ,找到 getFullLuminosity 函數,然後註釋讀取 disable(); 的行和讀取的12行切換(_integration){...}

另一種解決方法是使用計時器每20ms更新一次像素。您可以使用計時器,每20毫秒中斷一次主循環並更新像素值。

(我無法真正為您提供計時器方面的幫助,因為我本人可以直接為我的計時器和ISR設置寄存器,這不適合初學者。但是可能有用於它的庫更加用戶友好。)

http://playground.arduino.cc/code/timer1此庫應有助於簡化計時器
始終將tsl2561保持打開狀態,以查看我上面的編輯是否需要任何延遲。
Duncan C
2014-09-29 04:42:33 UTC
view on stackexchange narkive permalink

arduino不是多線程或多任務設備。您必須編寫不同的函數以彼此“玩得開心”。對於這種多任務處理來說,阻塞代碼是致命的。您可能需要重寫讀取光傳感器的代碼,使其無阻塞。

如果您可以使該代碼成為非阻塞代碼,那麼Visual Micro的發布就是路要走。

Visual Micro
2014-09-29 04:30:45 UTC
view on stackexchange narkive permalink

在loop()中設置一個“狀態服務器”。簡單地說,這意味著跟踪每個任務的下一個命令,然後每個loop()在每個任務中執行一項操作。

如果一個任務需要比另一個任務更快地運行,則可以使用

如果任務需要暫停,則將“ Last Run” millis()保存到全局變量,並忽略該任務,直到經過正確的時間量為止。不要使用delay(),始終讓loop()運行。

想法是loop()盡可能頻繁地運行,但是每次運行時您都要做一件事。

花點時間才能擺脫這種工作方式,但它使Arduino處理器可以自由地均勻處理所有作業。

  int task1Status = 0; int task2Status = 0; void loop(){doOneThingOfTask1(); doOneThingOfTask2();} // 10可以點亮LED,但只能避免doOneThingOfTask1(){如果(task1Status == 10)task1Status = 0; switch(task1Status){情況0://開始執行新流程情況1://做某事情況9://做最後一件事}}  
我打算發布類似的內容,然後我注意到OP表示進行光測量的代碼是阻塞代碼。
@Duncan C哦!好點子。我將留下答案,因為我認為它描述了一種避免在代碼中其他地方出現相同問題的工作方式。也可能是通過檢查對getEvent()的庫調用,可以應用相同的解決方案來減少延遲。顯然,這意味著更改庫代碼,但是可以將庫複製到草圖文件夾中並作為本地源進行修改。更改Lib當然會有所幫助,但是本地資源和一些黑客攻擊可能會產生解決方案。謝謝 :)
JRobert
2014-09-29 22:10:02 UTC
view on stackexchange narkive permalink

您的第一個最大的問題是

光傳感器需要100毫秒至600毫秒的時間來獲取讀數,而tsl.getEvent(&event)是一個阻塞調用,

您需要無障礙訪問光傳感器。查看庫代碼以查看其阻塞時正在做什麼。它有可能等待傳感器設置“完成”位。如果是這樣,您將需要修改庫,方法是

  1. 添加一個布爾值的 .isDone()函數來測試完成的位,並且不要讓您的主程序需要讀取直到isDone()== TRUE;或
  2. 將.getEvent()設置為非阻塞狀態,以使其立即返回明顯無效的讀數(例如-1),而不是在傳感器尚未準備就緒時阻塞。
  3. ol>

    這使您的主程序可以自由地服務於任何需要做的事情,並且隨時可以做,而不必為慢速傳感器付出任何代價。

ForestPhoenix
2014-10-24 18:46:08 UTC
view on stackexchange narkive permalink

有些庫允許多任務處理,例如我的庫 arduOS

這應該可以工作:

  #include <arduos16.h># include<arduos_core.h>#include <roundscheduler.h>SYS_enable_preemptive; //不要忘記!!! void setup(){auto sched = new SYS :: RoundScheduler(2); sched->add(&loop1); //這兩個是函數。 sched->add(&loop2); SYS :: start();}  

但請記住,實際的多任務處理可能會非常棘手,並帶有非常模糊的錯誤。 (但是您可以找到它們)。

該操作系統看起來比普通的arduino操作系統更易於使用
lxx
2015-01-01 13:34:27 UTC
view on stackexchange narkive permalink

1。使用兩個arduino,通過串行或i2c相互通信,這可能是最簡單的選擇(但不是最便宜的-儘管您可以從4美元獲得克隆的arduinos)。

2。尋找更新更快的光傳感器。嘗試了一個LDR(光敏電阻)/光電管?然後可以使用模擬讀取。

也可以從使用arduino切換到c,但這需要做更多的工作,並且您仍然會遇到類似的問題。

對於這個問題,切換到C確實不起作用。


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