arduino多任務庫processSchedule在線程中設置延遲的方法

processSchedule是一個可以應用于Arduino平臺的多任務庫,這是個開源項目,項目地址:https://github.com/wizard97/ArduinoProcessScheduler在我剛開始使用這個庫的時候碰到了一點小問題,我相信很多第一次使用這個庫的人都會碰到我這個問題:“就是在使用這個庫的時候有沒有一種像在loop方法里面使用delay設置延遲的方式?”,答案是否定的,但是有變通的方式,本篇文章就是向大家介紹這種方式的。

我為什么選擇使用processSchedule

我先引用一下這個項目介紹的部分內容,然后再來說我選擇的理由

Basic

  • Control Over How Often a Process Runs (Periodically, Iterations, or as Often as Possible)
  • Process Priority Levels (Easily make custom levels as well)
  • Dynamically Add/Remove and Enable/Disable Processes
  • Interrupt safe (add, disable, destroy, etc.. processes from interrupt routines)
  • Process concurrency protection (Process will always be in a valid state)

Advanced

  • Spawn new processes from within running processes
  • Automatic Process Monitoring Statistics (calculates % CPU time for process)
  • Truly object oriented (a Process is its own object)
  • Exception Handling (wait what?!)
  • Scheduler can automatically interrupt stuck processes

上述引用是這個多任務庫的一些特點,我把每條都翻譯一下 基本的

  • 控制Process如何運行(定期,迭代或盡可能多的)
  • 支持定義Process優先級(輕松創建自定義級別)
  • 動態的添加/刪除和允許/禁止一個Process
  • 中斷安全的(從中斷程序增加,禁止,銷毀Process等等)
  • Process并發保護(Process總是處于有效狀態) 高級的
  • 允許從運行的Process中產生新的Process
  • 自動統計監測Process(每個Process使用的CPU時間的百分比)
  • 真正的面向對象(一個Process就是一個對象)
  • 異常處理(等什么?!)
  • 調度程序可以自動中斷卡住的Process 上述的特點是我選擇使用這個多任務庫的一個原因,最主要的原因就是他是使用面向對象的方式開發,這是一種比較友好的方式,使用更簡單。

怎么做?

在開始描述怎么做之前,我默認正在讀這篇文章的人都是對這個多任務庫有過初步了解通讀過這個項目的wiki頁面的。如果你還沒有進入這個開源項目了解過,可以先去這個項目的主頁了解后再回來讀這篇文章。

現在開始正式介紹在Process是怎么實現延遲,其實方法也很簡單,就是在你想要設置延遲之前先記錄一下你當前Process的運行狀態,然后調用Process對象的setPeriod(delay_ms)方法重新設置當前Process對象的循環周期,然后return等待下次循環。如果我的描述無法讓你理解,那么下面的一個小例子應該能幫助你。

virtual void service()
    {

        int lengh=sizeof(tune)/sizeof(tune[0]);
        noTone(_tonePin);
        for(int i=state;i<lengh;i++){
            tone(_tonePin,tune[i]);
            state=x+1;
            /**設置該Process對象新的執行周期,
            這樣在設置的這個新周期時間之后都會再次調用該對象的service()方法**/
            setPeriod(400*durations[i]);  
            return;
        }
        state=0;
        setPeriod(5000);
    }

對于這種所有過程代碼都寫在service()方法的案例應該比較容易理解,然而我在實際的應用中可能 會在service()方法中順序執行多個方法,這些被調用的方法可能會有不同的延遲需要,這樣想保存運行狀態就會比較復雜了,我們需要給不同的方法定義一種狀態,這樣當service()方法再次被調用的時候我就能知道該從哪個方法開始執行了,就像下面這個例子一樣處理:

//可以先定義一個狀態的枚舉類,定義出所有的狀態
typedef enum processState
{
    STATE_F1,
    STATE_F2,
    STATE_F3,
...etc
} processState_t;

class toneProcess : public process
{
        toneProcess(Scheduler &manager, ProcPriority pr, unsigned int period)
        :  Process(manager, pr, period)
        {
            state = STATE_F1; //initialize the current state
        }
        
        //在每次進入到service()方法的時候都檢查一下運行狀態,確定本次需要執行哪個方法
        virtual void service() override {
            switch(state) {
                case STATE_F1:
                    function1();
                    break;
               case STATE_F2:
                    function2();
                    break;
        
               case STATE_F3:
                    function3();
                    break;
        }
        
        void function1(){
            Serial.println("this is function1");
            //start delay
            setPeriod(500); // Will resume at function 2 in 500ms
            state = STATE_F2; //state transition to state 2
        }
}

private:
processState_t state;
};

好了,本文到這里也就可以結束了,以上內容如果有什么說得不清楚或者有錯誤的地方請大家一定要留言告訴我,我會及時修正。

前幾天看到有很多人,特別是程序員們使用github的Issues寫博客,這讓我也很想試一下,所以我也在github上建了一個我的博客項目,項目地址是:https://github.com/asymt/Blog/issues

發表評論

電子郵件地址不會被公開。 必填項已用*標注