Arduino ESP8266编程深入要点
生活随笔
收集整理的這篇文章主要介紹了
Arduino ESP8266编程深入要点
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??????? 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中再騰出幾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語言之間的這點點執行差別,我們根本就很難體現得出來的!
轉載于:https://www.cnblogs.com/lanzhi/p/6467331.html
總結
以上是生活随笔為你收集整理的Arduino ESP8266编程深入要点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos6.5 做路由器
- 下一篇: poj3342Party at Hali