2014年5月19日 星期一

[arduino]ArduinoThread分時多工

ArduinoThread



A simple way to run multiple stuff in Arduino.
一個簡單方式來使Arduino達到分時多工功能

NO, Arduino does not support “REAL” parallel tasks, but we can make use of this Class to improve our code, and easily schedule tasks with fixed (or variable) time between runs.
Arduino並非真的有平行運算功能,但我們能透過這個Class來改進程式碼,將工作做排程的動作,透過快速切換來個別執行,達到【類】多工現象。

Instalation


1、下載Library
2、放進Arduino libraries 資料夾


Getting Started

There are basicaly, two Classes included in this Library:
【Thread】 and 【ThreadController】 (that inherits from Thread).
這個Library有兩個Class【Thread】與【ThreadController】(繼承自Thread)



【Thread class】
This is the basic class, witch contains methods to set and run callbacks, check if the Thread should be runned, and also creates a unique ThreadID on the instantiation.
這是基本的Class,包含了方法去設定callbacks並執行,確認Thread 是否應該被啟動;
並且實作時創造一個獨有的ThreadID。



【ThreadController class】
Responsable for “holding” multiple Threads. Can also be called as “a group of Threads”, and is used to perform run in every Thread ONLY when needed.




  • 【The instantiation of a Thread class】

實作Thread 類別

Thread myThread = Thread();
// or, if initializing a pointer 初始化一個指標
Thread* myThread = new Thread();


  • 【Setting up a thread is essential. You can configure many things】:

設定 thread
myThread.enabled = true; 
// Default enabled value is true
//【.enabled】,是Thread開關
myThread.setInterval(10); 
// Setts the wanted interval to be 10ms
//用【setInterval(ms)】來設定間隔為10ms


myThread.ThreadName = "myThread tag";
/*
This is useful for debugging
(Thread Name is disabled by default, to use less memory)
(Enable it by definint USE_THREAD_NAMES on 'Thread.h')
         【.ThreadName】建立ThreadName可以方便Debugging,
         通常ThreadName被預設關閉,
         較不消耗記憶體
*/
myThread.onRun(callback_function); 
// This will set the callback of the Thread: "What should I run"?
//【.onRun(functionName)】來告訴Thread該執行哪個Callbackfunction




【using Thread and ThreadController】

Ok, creating Threads are not so hard. But what do we do with them now?
製造一個Thread 並不太難但我們該怎麼用她?
First, let’s see how Threads should work, to understand what a ThreadController is and does
首先,要了解ThreadController怎麼運作,從看Thread怎麼運作開始。

// First check if our Thread "should" be runned
//執行【.shouldRun()】來確認這個Thread是否該被啟動
if(myThread.shouldRun()){
  // Yes, the Thread should be runned, let's run it
  //用【.run()】來啟動Thread
  myThread.run();
}


Now that you got the idea, let’s think a little bit: What if i have 3, 5, 100 Threads. Do I need to check EACH one?!?
如果我有很多個Thread,那我得一個一個檢查嗎?
The answer is: NO. Create a ThreadController, and put all your boring-complex Threads inside it!
答案是NO,創造一個ThreadController來管理很多Thread,她像個箱子,將Thread丟進去。


// Instantiate a new ThreadController
//實作一個 ThreadController
ThreadController controller = ThreadController();
// Now, put a bunch of Threads inside it, FEED it!
//透過【.add(&Thread)】將Thread餵給ThreadController
// Notice the & before the thread, IF it's not instantied as a pointer.
//注意:如果Thread在實作時並"非"以指標形式時,應該前加上"&"
controller.add(&myThread); 
controller.add(&hisThread);
controller.add(&sensorReadings);


You have created, configured, grouped it. What is missing? Yes, whe should RUN it!
你已經將一群Thread群組化了,但你還得RUN ThreadController
controller.run();

TIPs and Warnings


  • ThreadController is not a LinkedList. It’s “MAXIMUM” size (the maximum Threads that it can store) is defined on ThreadController.h (default is 15)

ThreadController不是鏈結串列,她最大的size可以儲存15個Thread

  • !!!! VERY IMPORTANT !!!! When extending Thread class and implementing the function run(), always remember to put runned(); after all, otherwhise the Thread will ALWAYS run.
重要!當擴建Thread class 並 實作run() function時,記得放runned(),否則Thread一直處於Run狀態。


  • It’s a good idea, to create a Timer interrupt and call a ThreadController.run() there. That way, you don’t need to worry about reading sensors and doing time-sensitive stuff on your main code (loop). Check ControllerWithTimer example.

建立中斷計時器去呼叫ThreadController.run()。
這樣你的main loop可以專心處理讀取sensors數值或是處理即時性工作。


  • Inheriting from Thread or even ThreadController is always a good idea. For example, I always create base classes of sensors that extends Thread, so that I can “register” the sensors inside a ThreadController, and forget about really reading sensors, just getting theirs values within my main code. Checkout SensorThread example.




  • Remember that ThreadController is in fact, a Thread. If you want to enable or disable a GROUP of Threads, think about putting all of them inside a ThreadController, and adding this ThreadController to another ThreadController (YES! One ThreadController inside another). Check ControllerInController example.


  • Things must do stuff quickly. Waiting too loooong on a interrupt, means waiting too loooong on the main code (loop).

不能在interrupt callbackfunction 執行太久的工作,否則做到一半就又進入中斷,main code將一直不被執行,陷入無限迴圈。


Library Reference


【bool Thread::enabled】
Enables or disables the Thread. (do not stop it from running, but will return false 
when shouldRun() is called)
啟動/關閉Thread

【void Thread::setInterval()】
Setts the desired interval for the Thread (in Ms).
設定多久進入Thread callback

【bool Thread::shouldRun()】
Returns true, if the Thread should be runned. (Basicaly, the logic is: (reached time AND is enabled?).
Check Thread是否正在run

【void Thread::onRun(void (*callback)(void))】
The target callback function to be called.
設定Thread處理的callback function

【void Thread::run()】
This will run the Thread (call the callback function).
執行Thread

【int Thread::ThreadID】
Theoretically, it’s the address of memory. It’s unique, and can be used to compare if two threads are identical.
獨一的ID,用來比較Thread 是否相同。
【int Thread::ThreadName】
A human-redable thread name. Default is “Thread ThreadID” eg.: “Thread 141515”; Note that to enable this attribute, you must uncomment the line that disables it on ‘Thread.h’;
看不懂

【protected: void Thread::runned()】
Used to reset internal timer of the Thread. This is automaticaly called AFTER a call to run().
用來重設Thread 的間隔時間(重算),通常在執行完run()後,會自動執行

【void ThreadController::run()】
This will run the all Threads within the ThreadController, only if needed (if shouldRun returns true);
執行ThreadController 中所有Thread ,當Thread.shouldRun() returns true

【bool ThreadController::add(Thread* _thread)】
This will add a the thread to the ThreadController, and return true if suceeded (it the array is full, returns false).
將Thread 加入 ThreadController中

【void ThreadController::remove(Thread* _thread)】
This will remove the Thread from the ThreadController.
從ThreadController 中移除 某個Thread(透過名稱)

【void ThreadController::remove(int index)】
This will remove the thread on the position index.
從ThreadController 中移除 某個Thread(透過index)

【void ThreadController::clear()】
This will remove ALL threads from the ThreadController array.
移除所有Thread

【void ThreadController::size(bool cached = true)】
Returns how many Threads are allocated inside the ThreadController. If cached is false, will force the calculation of threads.
看ThreadController中有幾個Thread


【Thread* ThreadController::get(int index)】

Returns the Thread on the position index.
看Thread在ThreadController的哪個位置中





  • 參考來源:https://github.com/ivanseidel/ArduinoThread
















沒有留言:

張貼留言