Arduino for ESP8266的話,若是不修改代碼,默認沒有辦法進入輕睡眠的省電模式,只能進入Modem Sleep,也就是說Wifi能夠暫時睡眠可是CPU無法睡,Modem Sleep最低功耗在15mA-16mA,輕睡眠的最低功耗在1mA-2mA左右
若是要在Arduino中再騰出幾KB內存的話,我這晨還有一個方法,就是去到esp8266 arduino的開發包中,找到一個叫"cont.h"的頭文件,裏邊有一個棧大小的宏定義常量叫「CONT_STACKSIZE",他的值默認是4096,我試着將他改爲1024,這樣就省了3KB內存,具體穩定的話,我用一個程序目前測試了一下,仍是能夠順利騰出3KB的內存的,由於恰好我應要用把這將近50K的內存用完,因此特此貢獻這個方法
我先看看他的調度的彙編來肯定一下是否有其餘的隱患,目前是測得能夠正常工做的
若是你用過SDK就會發現,有將近50K的內存,你用Arduino會少了幾K,很差奇是去了哪裏嗎?有4K至少,是被用來作保存是上下文用的,什麼是上下文?就是內核調度器的一個概念,你能夠理解爲,一個MCU要實現不一樣的線程,他就要爲單個線程保存單獨的現場環境,而這個現場環境就用掉了4K多一點的內存了
若是有空能夠將試着去官網下載一個最新版的SDK文件夾,而後將"lib"中的文件替換至如今的2.0.0版的"lib"文件夾中,這樣的話,可使用一些SDK1.5.0的一些最新的特性(不知道的能夠暫時不升級),記得替換前要進行好備份原來的文件夾,若是替換後編譯時出錯,則能夠在這個舊的文件夾中找至具體出錯的文件進行找舊版的覆蓋上去用,目前我大部份測試Arduino 2.0.0將SDK 1.3.0替換成SDK1.5.0(最新版的)也是能夠正常工做的
另外發現Arduino的一個問題就是在使用TCP(注意僅是TCP)發送一個內存緩衝區(大小是1450左右)函數的時候速度很慢(表現爲TCP這個write函數執行時間較久),暫時我尚未辦法找到內部的緣由,可是使用SDK就沒有這個問題,可是爲了使用Arduino良好的編譯環境,以及一堆的函數庫(好比SD卡庫),我在Ardiuno中使用了SDK的代碼(能夠直接編譯成功,改動不大)
我查看過這個write函數內部的源代碼,發現裏邊有進行調度的跡象,所以有多是由於這個Arduino內部的調度所產生的問題,這樣的話好比你要作一個實時性要求很高的串口透傳就會有受影響
但若是對這個實時性要求不高的話,暫時Arduino也能夠知足要求,個人話,是在Arduino上採用SDK編程的方法,使用異步回調的接口(而不是像Arduino同樣必須在一個大循環裏執行全部的邏輯)
同時也要注意,因爲esp8266的省電模式中,有三種,其中有一種是叫Modem Sleep,這種是默認開啓的(你可能在一買回來就ping這個esp8266會以爲慢,其實不是他慢,根據個人測試,只要關掉這個默認的省電模式,esp8266的響應很是快,能夠達到小於1毫秒的時間)理論分析也是能夠作到小於1毫秒的,實測也能夠。這種模式對於Arduino來說是能夠輕易進入的,他的功耗大概是省電模式進入後是15mA左右,可是對於第二種比較好用的更省電的模式,大概是1mA左右,是15分之一
可是這種模式,你首先要理解爲何省電能再省14mA?緣由是這個CPU能夠被暫停!但因爲是由系統本身判斷如何進入省電模式的,其中有一個重要的條件,則是,CPU要保持空閒,纔會被檢測到,這是系統內部的邏輯來實現的,其中有一點重要的條件就是,CPU上的程序不能有一個循環定時,它的間隔是不能小於路由器上的兩個DITM Beacon幀中設定的間隔的,一般咱們家用的通常是100毫秒,你能夠抓包看看便知具體數值,通常是這個
若是有一個定時他老是小於100毫秒去執行的
那麼CPU便不能被斷定爲空閒狀態,換言之,他省電也只能作到15mA了,即便你調用了API將系統設定爲輕睡眠模式
用Arduino的結論就是默認不能進入輕睡眠模式,那就是說默認狀況下你用Arduino作的東西的最低的功耗可能只能到15mA了,一個1500mAh的電池,能夠跑80個小時,由於中間還會醒來接收一下是否有數據要發給本身的,因此不會跑足100個小時的,而接收時的平均電流通常是60-70mA左右,這是比15mA還要大幾倍的
好了,那是否是就完全沒辦法了?
有的
那就是想辦法將這個阻礙系統斷定Arduino進入省電模式的東西去掉
core_esp8266_main.cpp
在這個核心的文件中,你打開就會發現剛纔我講的,那個「Arduino利用SDK的函數來建立一個SDK上的任務(注意不是RTOS)」的函數
我如今的推測就是多是這個建立的任務致使Arduino不能進入輕睡模式的,由於他這個任務的時間片可能就是15mS左右,15mS固然是小了100mS的了!因此這又怎麼會能進入輕睡眠模式呢?CPU怎麼可能知道他啥時候要睡呢?一睡要是影響了你的15mS的時間片,人家罪就大了不是?
15mS這個時間值是經詳細研讀樂鑫的esp8266手冊推測得出的,官方特麼的沒有任何說法給出來這些重要的數值
因此啊,要讓Arduino不要被阻礙進入輕睡眠模式,從而讓CPU能夠順利被暫停的關鍵就在於要去掉這個建立的任務了
着重來看這個函數
core_esp8266_main.cpp中的"loop_wraper()"
static void loop_wrapper() {
static bool setup_done = false;
if(!setup_done) {
setup();
setup_done = true;
}
preloop_update_frequency();
loop();
esp_schedule();
}
他就是Arduino中的loop函數那個大循環的「包在外邊」的代碼了
一者是setup(),一者是loop(),setup使用了一個靜態變量來判斷爲只執行一次
loop()則是你實際的loop函數的代碼,在編譯時,這個函數會和在ino文件中的loop函數對應連接起來
因此有了這個不斷在執行的循環啊
系統不能讓它睡這個也徹底能夠理解了吧?
那麼問題來了,是否是隻要簡單的不要建立這幾個任務就好了呢?
是的,若是你不使用Serial等內部封裝了Arduino自己的這套調度系統的話,是沒有大問題的
可是啊,問題是這些平時用得很爽的封裝過的類啊,他內部或多或少都是使用了Arduino的這套調度系統的
你不相信能夠本身使用VS的跳轉功能來查看這些函數的源代碼,就知道了
因此啊,換言之啊,能夠總結爲
若是你想在Arduino中找到一些不使用這些調度系統的函數的話, 那用之,則沒問題
可是很惋惜不少都不行
要用輕睡眠省電模式就最好不要用Arduino
不要以爲奇怪,看起來低效的東西,邏輯上每每很好理解!
這就是Arduino的封裝者爲何必定要強行加一個setup和loop的緣由,內部的邏輯就是爲了簡化入門者的門檻,同時引導你快速造成一種編程的思想習慣,也就是西鄉同樣所強調的「編程框架」
雖然它不是異步的,但顯然是簡單而又可讓你動腦筋去實現複雜的結構的一種好的切入點
只要咱們不知足於這種編程的方式,咱們總能找到更有效的異步回調的方式的,但,那時的你也不是一個新手級別的人了
天然而言掌握回調這樣的方法來解決業務邏輯,這是垂手可得的事
因此Arduino他並非低效(雖然我本人也比較喜歡用異步的方式,看起來比較「高效」)
好了,只要注重幾個重要的點,其實Arduino也沒啥的,他的執行速度就是SDK的執行速度,C++和C語言之間的這點點執行差異,咱們根本就很難體現得出來的!編程