繼續我的定期炸彈電子鐘研發,前後搞了快兩個多月,電池續航力不佳一事始終未見起色。最早的網路校時版可以撐 50-60 小時,之後加了光敏電阻改成浴室開燈才顯示卻只多撐半天。後來想說無線網路可能是耗電大戶,關掉網路改用 RTC 時鐘,不料使用時間反而更短。後來還試了便宜 3.7V 轉 5V 升壓板配三顆電池玩法,時間也沒變長倒是把我的 18650 鋰電池搞到過度放電

折騰一大圈全無進展,仔細想想,我這是在瞎試呀! 沒有數據佐證,單憑直覺判斷會省電就動手。處理電腦問題時我老愛挑戰別人「為什麼要改掉 XXX 寫法,你有證據或線索指出它是瓶頸?」「要取得數字或理論當依據再動手,不要胡亂試才能快速解決問題」,對映這陣子我處理耗電問題的表現,啪! 我被自己狠狠打臉。

痛定思痛,在三用電錶探針加裝一對公母杜邦接頭好串接測量電流大小;另外做了一條中間用杜邦接頭連接的 USB 電源線,以便測量 5V 的耗電量。測量工具跟基準數據是做好效能調校的第一步,回歸讓數字說話吧!

thumbnail

分別測試了 32x8 LED 矩陣顯示器、RTC 時鐘模組、光敏電阻模組的耗電量(測量 3.3V 接線電流量):

裝置名稱作用狀態電流閒置狀態電流
32x8 LED 點陣顯示模組顯示時間 19.5 mALED 全滅 11.4 mA
光敏電阻模組亮度超過設定值(LED 指示燈亮) 2.47 mA黑暗環境 1.48 mA
DS3231 I2C RTC 時鐘模組1.83 mAN/A

LED 點陣顯示器沒想像中耗電,清除文字熄滅所有 LED 只省了 8.1 mA,而加裝光敏電阻會多耗 2.47 mA,難怪浴室熄燈關閉版沒增加多少時間。

另外,我也試了 ESP8266 + RTC 時鐘版執行期間的 USB 5V 電流量,在 setup() 初始化階段約 100mA ~ 120mA,進入 loop() 顯示時鐘階段,電量則在 45 ~ 92 mA 間跳動,我的三用電錶一秒取樣一次,也無法記錄轉成線圖,只能用眼睛採樣自已抓範圍;當光線不足 LED 點陣不顯示文字,電流範圍下降到 35 ~ 85 mA,反覆試了幾次結果倒還一致,故這組數字應有參考價值。

下一個問題是,開無線網路版會比較耗電嗎?我將程式換回網路校時版,意外發現有沒有開無線網路的電流範圍跟 RTC 時鐘版幾乎一樣,採樣頻率更高並繪成線圖或許能看出差異,但以肉眼觀察看不出來有什麼不同。我推測無線網路耗電主要發生在收發資料時,電子鐘雖然有開網路,但大部分時間沒有資料傳輸,故耗電不如想像多。

有了這些數字,就能試著推估電池續航力。依前天文章國外網友的實測,假設 3.7V 轉 5V 電池座的轉換效率是 80%,2 顆 18650 2600 mAh (3.3V),約等於 2600 * 2 * 0.8 = 4160 mAh (5V)。若希望撐到 100 小時,平均耗電量要壓到 41.6 mA 以下;如果想一週換一次電池,耗電更要壓到 4160 / 24 / 7 = 24.76 mA 以下。

ESP8266 有個神奇的 Deep Sleep 功能,呼叫 ESP.deepSleep(毫秒數),程式會進入深層休眠模式一段指定時間,之後 RST PIN 腳會產生一個電壓降到 0 的短暫訊號;而 NodeMCU 開發板的 D0 PIN 腳與 RESET 鈕相連,D0 收到短暫低電壓訊息等同 RESET 按鈕會觸發重開機;於是乎只要將 RST PIN 腳接到 D0 PIN 腳,ESP 便能實現指定一段時間休眠,時間到再自己叫醒自己的神奇把戲。

我用 LCD 1602 液晶顯示器做一個簡單實驗:

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

/** 接線說明:
 * ESP8266 SCL->D1, SDA->D2, 電源要接 VU (5V),3V 不會動
*/

LiquidCrystal_I2C	lcd(0x27,2,1,0,4,5,6,7);

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  lcd.begin (16,2);
  lcd.setBacklightPin(3, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home();                   // go home
  lcd.print("Hello, World! ");  
  lcd.setCursor ( 0, 1 );        // go to the next line
  lcd.print("darkthread.net");
}

int count = 0;

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
  count++;
  lcd.home();
  lcd.print(String("* Loop Count=") + String(count));
  if (count > 5) {
    lcd.clear();
    ESP.deepSleep(5e6);
  }
}

程式運行邏輯為啟動後在 LCD 顯示文字,在 loop() 中讓 LED 燈一秒閃爍一次及在 LCD 顯示計次,閃爍五次後呼叫 ESP.deepSleep(5e6) 休眠 5 秒,周而復始。實測正常閃爍期間耗電約 125 mA,休眠時則為 38 mA,耗電降到 1/3,但發現一個問題,在休眠期間,5V、3.3V 仍會正常供電,故 LCD 背光是亮的,

LCD 顯示器有關閉背光 API,但想想並非所有裝置都能透過程式關閉省電,休眠期間停掉周邊設備供電才是治本之道。放連假在家腦波格外耗弱,我做了個越級打怪的決定 - 沒用現成的繼電器或 L298N 之類的現成模組,要自己用手邊現有零件做電晶體開關。(就這麼耗去了兩天的光陰,鳴...)

電子學只懂皮毛,這種題目對我來說太難,卡關卡到快吐了。

首先是零件問題,我手邊的電晶體幾乎全是 NPN 的,常見的 NPN 開關電路,是基極有電壓時導通過電;而 ESP 休眠時,PIN 腳會呈現 3V 以上的電壓,讓 NPN 開關成為通路。PNP 是 3V 以上斷路,程式執行時將 PIN 電壓改為 0 通電,休眠時電歷上升斷路,比較符合我的需要。

翻箱倒櫃挖到幾顆不知從哪裡拆下來的 A1015 PNP 電晶體,這才有辦法繼續玩下去。我成功用 E 極接 3V、B 極接 PIN 輸出,做到 PIN 腳 LOW 時通電、PIN 腳 HIGH 或休眠時斷電的效果。

但很快遇到下一個難題,LCD1602 顯示器要用 5V 驅動,PNP 是基極低電壓時導通,ESP 休眠時 PIN 腳電壓 3V,對 5V 形成順向偏壓,繼續導通。印象中可用電阻分壓搞定,書到用時方恨少,從沒想過看自己會有需要計算電晶電流大小、分壓的一天... (我居然在看電子學計算教學)

但我很便快放棄這條路,一來是電子學計算式一向讓我厭世,二來即使算得出正確答案,我手邊不一定湊得出所需電阻值,加上沒有知識經驗判斷差距是否可接受,能不能替換,估評將會困難重重。最後我選了另一條路,先用 PNP 做出休眠 0V、開機 3V 的開關,再用它當成 NPN 的基極輸入。噗,胡搞瞎搞,居然成功了! (順便試了線上晝電路圖的網站 - Visual Paradigm)

成功將斷電降到 13 mA,比官方文件 Deep Sleep 模式聲稱的耗電量 60 µA 高出非常多,在網路討論區有看到 20 μA 到 6 mA 不等的耗電值,我猜跟開發板設計、連接裝置有關聯,但這塊再次超出我的知識範圍,朕乏了,留待以後有機會來研究。

實測影片


Comments

# by 蛤仔

事實證明人只要脫離自己專業就會變得奇怪XD

# by JJC66601

光敏電阻模組 去除LED 指示燈(電源,與輸出狀態)還剩下多少耗電? 如果可以接受耗電量,用光敏電阻模組加繼電器控制剩下的電路,並用RTC方案 應該可以提升使用時間

# by Jeffrey

to JJC66601,光敏電阻模組指示燈亮滅差1mA,可視為指示燈及產生低電壓訊號的消耗,拆掉電源跟指示LED 估計平時可省 1mA,但涉及破壞模組硬體,打算留到後期再說。 至於沒考慮繼電器的原因有二:一是過去對繼電器的使用壽命有不好經驗,二是直覺繼電器靠電磁維持閉路狀態耗電應該不低(哈! 又是直覺)。這是個有趣議題,有時間來實測看看。

Post a comment


29 - 1 =