同一個(gè)外部中斷的Arduino隨機睡眠與喚醒
摘要:為了控制Arduino的隨機睡眠與喚醒,不采用“預定睡眠-隨機喚醒”的常規設計模式,而是通過(guò)一個(gè)外部中斷隨機使Arduino進(jìn)入睡眠,并且通過(guò)同一個(gè)外部中斷隨機喚醒Arduino。首先使用開(kāi)源Enerlib和LowPower庫對ArduinoPro Mini進(jìn)行實(shí)驗,然后應用于實(shí)際的工程設計中,取得了很好的效果。該方法可以作為成熟的方案推廣到工程設計的實(shí)際應用當中。
本文引用地址:http://dyxdggzs.com/article/201610/306868.htm引言
“預定睡眠-隨機喚醒”是嵌入式系統設計中常用的方法。例如,在完成規定的數據發(fā)送或接收任務(wù)后,MCU立即進(jìn)入休眠以節約電力,這就是“預定睡眠”的含義;當有新的數據發(fā)送和接收任務(wù)時(shí),通過(guò)各種方式喚醒MCU執行前述任務(wù),這就是“隨機喚醒”的含義。在實(shí)際工程中,完成該功能主要使用軟件,首先整合系統功能,執行完功能模塊后馬上執行預定的睡眠指令,而喚醒功能則直接在中斷服務(wù)程序中體現。很多教科書(shū)、論壇中廣泛介紹的也都是這種方法,該方法能夠滿(mǎn)足一般工程設計的需要。但“預定睡眠”在某些工程中并不適合使用,例如在無(wú)線(xiàn)傳感網(wǎng)絡(luò )構成的系統中,某個(gè)節點(diǎn)或分系統的睡眠時(shí)機不是由自己決定的,而是遠程隨機控制的。在這種情況下,睡眠指令在節點(diǎn)或分系統執行自己任務(wù)的過(guò)程中隨機發(fā)生,同樣,喚醒指令發(fā)出也是隨機的,通常為節省系統的硬件開(kāi)支并提高其可靠性,發(fā)出睡眠和喚醒指令使用同一個(gè)信號,所以系統軟件的睡眠指令就不能固定在系統功能程序的預定位置,甚至不能在功能主程序及其調用的函數中出現。
1 目前Arduino睡眠與喚醒的方法
在A(yíng)rduino IDE中控制Arduino睡眠的工具主要有Enerlib和LowPower兩種開(kāi)源類(lèi)庫,前一種已被Arduino開(kāi)源庫收錄,這兩種類(lèi)庫專(zhuān)門(mén)完成 Arduino的睡眠控制。Arduino的睡眠效果和典型應用在參考文獻中有詳細的介紹,但也未涉及到隨機進(jìn)入睡眠的方法。
1.1 使用Enerlib類(lèi)庫的實(shí)現方法
Enerlib類(lèi)庫提供的Example代碼說(shuō)明了如何使用該類(lèi)庫的功能函數,為閱讀方便起見(jiàn),筆者添加了行號標識和中文注釋?zhuān)缦滤校?/p>
可以看出,進(jìn)入睡眠的代碼在僅執行一次的初始化模塊void setup()中,表明系統啟動(dòng)后做完初始化工作即進(jìn)入睡眠。代碼的19~23行給出了5種睡眠方式,在實(shí)際應用中選擇一種適合的方式即可。系統的喚醒在 Int0外部中斷服務(wù)程序中,Enerlib類(lèi)庫提供了一個(gè)只能在中斷服務(wù)程序中使用的WasSleeping()函數,以判定系統目前的“睡眠/醒著(zhù)” 的狀態(tài),該程序執行一次睡眠,然后隨機喚醒后不能再次進(jìn)入睡眠狀態(tài)。這是一個(gè)典型的“預定睡眠一隨機喚醒”實(shí)例。
1.2 使用LowPower類(lèi)庫的實(shí)現方法
LowPower類(lèi)庫提供的實(shí)例代碼如下(行號和中文注釋由筆者添加):
可以看出,進(jìn)入睡眠的代碼在主程序循環(huán)體void loop()內,系統啟動(dòng)后即進(jìn)入休眠狀態(tài),一旦有外部中斷即喚醒,喚醒后執行完主程序功能后再次進(jìn)入睡眠,這也是典型的“預定睡眠-隨機喚醒”實(shí)例。
因ATMega單片機在外部中斷模式下會(huì )忽略引起中斷引腳的數據方向,所以該例程第10行“pinMode(wake UpPin,INPUT);”沒(méi)有必要。
以上兩種睡眠與喚醒實(shí)例均實(shí)現不了隨機進(jìn)入睡眠的功能要求。
2 隨機睡眠與喚醒的方法
如果可以實(shí)現在系統工作過(guò)程中隨時(shí)中止工作進(jìn)入睡眠(如為了節省電力而遠程控制終止節點(diǎn)的監測),然后在適當的時(shí)機再喚醒系統繼續工作,就是典型的“隨機睡
眠-隨機喚醒”功能。
2.1 隨機進(jìn)入睡眠與喚醒的方法
在以上兩個(gè)實(shí)例中,一個(gè)是將睡眠指令放于初始化模塊,實(shí)現一次性主動(dòng)睡眠;另一個(gè)是將睡眠指令放在主程序循環(huán)體中,在執行完預定功能后主動(dòng)進(jìn)入睡眠,二者均有外部隨機喚醒。如果要實(shí)現通過(guò)外部指令(中斷)隨機進(jìn)入睡眠,睡眠指令首先不能放在初始化模塊void setup()中,因為這樣僅會(huì )引起一次睡眠;如果放到主程序循環(huán)體void loop()中,則必須在由“睡眠/喚醒”指令引起的中斷服務(wù)程序中放置相應的標志,然后再在主程序中判斷這個(gè)標志,勢必增加相應的軟件開(kāi)支,而且程序的結構也不明晰。
因此,實(shí)現隨機進(jìn)入睡眠的最簡(jiǎn)單的方法就是將睡眠指令直接置于中斷服務(wù)程序當中,當睡眠指令發(fā)出后,執行中斷服務(wù)程序進(jìn)入睡眠;當喚醒指令發(fā)出后,只要進(jìn)入了中斷服務(wù)程序即可喚醒。但是在同一個(gè)中斷服務(wù)程序中實(shí)現該功能,需要透徹地了解相應單片機的中斷處理機制以及所用的庫函數對中斷的處理方法。
2.2 Arduino的外部中斷
構成Arduino的核心處理器主要是Atmel的AVR ATmega系列MCU(如ATmega328),常用的實(shí)驗平臺有UNO、NANO、Pro、Pro Mini、Micro、Lilypad、Leonardo、Duemilanove等,因此Arduino的睡眠與喚醒的控制實(shí)質(zhì)是對MCU的控制,也就是控制ATnaega328睡眠與喚醒。
實(shí)現隨機睡眠與喚醒的實(shí)驗平臺是Arduino Pro Mini3.3 V、8 MHz/ATInega328,ATrnega328的外部中斷機制主要有:①RESET具有最高的優(yōu)先級,第二個(gè)為INT0;②任一中斷發(fā)生時(shí)全局中斷使能位被清零,從而禁止了所有其他的中斷;③退出中斷后,總是回到主程序并至少執行一條指令才可以去執行其他被掛起的中斷;④如果選擇了邊沿觸發(fā)方式或電平變化觸發(fā)方式,那么持續時(shí)間大于一個(gè)時(shí)鐘周期的脈沖將觸發(fā)中斷,過(guò)短的脈沖則不能保證觸發(fā)中斷,如果選擇低電平觸發(fā)方式,那么低電平必須保持到當前指令執行完成;⑤外部中斷通過(guò)引腳INT0、INT1與INT2觸發(fā),只要使能中斷且電平發(fā)生了合適的變化,即使引腳INT0~2配置為輸出,中斷也會(huì )觸發(fā);⑥若要求INT0與INT1在信號下降沿或上升沿觸發(fā),則I/O時(shí)鐘必須工作;⑦通過(guò)電平方式觸發(fā)中斷,在將MCU從掉電模式喚醒時(shí),要保證電平保持一定的時(shí)間,以降低MCU對噪聲的敏感程度;⑧中斷響應時(shí)間最少為4個(gè)時(shí)鐘周期,若中斷發(fā)生時(shí)MCU處于休眠模式,中斷響應時(shí)間還需增加4個(gè)時(shí)鐘周期,此外還要考慮到不同的休眠模式所需要的啟動(dòng)時(shí)間。
2.3 Enerlib和LowPower類(lèi)庫的中斷處理方式
兩個(gè)類(lèi)庫中,Enerlib的5種睡眠指令為PowerDown()、Standby()、PowerSave()、SleepADC()、Idle(),LowPower的5種睡眠方式為ADC_OFF、BOD_OFF、IDLE_OFF、STANDBY EXT_STANDBY,除了對各種不同設備進(jìn)行關(guān)斷外,對系統中斷的處理方式均相同,即睡眠前后均不對中斷的使能進(jìn)行處理,而且均提供了打開(kāi)和關(guān)閉終端使能的函數。這樣,打開(kāi)和關(guān)閉中斷的時(shí)機就完全交給了開(kāi)發(fā)者。
3 隨機睡眠與喚醒的實(shí)現與結果
使用Arduino自帶的LED(Pin13驅動(dòng))來(lái)檢驗隨機睡眠與喚醒,睡眠發(fā)生時(shí)LED閃爍0.1 s,表示接收到睡眠命令,然后熄滅LED進(jìn)入睡眠;喚醒發(fā)生時(shí)LED閃爍0.1 s,表示接收到喚醒命令,然后LED以1 Hz頻率閃爍工作。以下代碼筆者添加了行號標識和中文注釋。
將Arduino Pro Mini的Pin2(D2)通過(guò)一個(gè)10 KΩ電阻連接到Vcc,然后在Pin2對地連接一個(gè)按鍵開(kāi)關(guān),下載完程序后上電,系統LED進(jìn)入1 Hz閃亮模式,按一下按鍵,LED閃爍0.1 s,然后進(jìn)入睡眠;再按一下按鍵,LED閃爍0.1 s,然后系統LED進(jìn)入1 Hz閃爍模式,如此重復。
結語(yǔ)
Arduino的核心--ATmega系列單片機,以其RISC的可靠結構、主控板、外圍模塊等硬件的規范設計,具有較高的可靠性。Arduino之所以風(fēng)靡全球,除了開(kāi)源的硬件之外,更重要的是配套了開(kāi)發(fā)軟件的IDE以及眾多的類(lèi)庫,同時(shí)IDE集成、定義了編程方法,底層的Bootloader就像是個(gè)微型操作系統,而不像使用Keil C開(kāi)發(fā)單片機軟件那樣自己來(lái)組織程序的結構、編寫(xiě)驅動(dòng)程序,Arduino的軟件和硬件設計使得編程、供電、下載一體化。由于其遵循開(kāi)源共享的宗旨,相關(guān)類(lèi)庫會(huì )越來(lái)越豐富,也正是這個(gè)IDE將軟件開(kāi)發(fā)工具和實(shí)際硬件隔離,使得軟件開(kāi)發(fā)變得簡(jiǎn)單、快速,開(kāi)發(fā)者可以專(zhuān)注于方案的實(shí)施。當然也由于軟件底層與功能模塊硬件的隔離,使得開(kāi)發(fā)者越來(lái)越依賴(lài)類(lèi)庫,這一循環(huán)導致開(kāi)發(fā)者過(guò)分依賴(lài)類(lèi)庫而不去探究問(wèn)題的實(shí)質(zhì),最后導致問(wèn)題得不到解決或者退而更換主控系統硬件,從而妨礙了Arduino更大范圍的應用。本文所敘述的例程可以根據實(shí)際工程要求做適當修改而直接應用,具有一定的參考價(jià)值。
評論