這讓我想到 Watchdog 功能, 程式須週期性地在 Watchdog 計時器時限內重設旗標, 否則系統就會被 Watchdog 重新啟動, 這樣系統當機時就會自動重啟, 不至於當在那邊不動. 我查詢 MicroPython 文件, 發現 pyboard 文件裡的 machine 模組有一個 WDT 看們狗物件, 參考 :
# class WDT – watchdog timer
只要呼叫 WDT() 建構式即可建立一個 WDT 物件, 可傳入 timeout 參數指定看門狗計時器時限 (最低為 1 秒) :
from machine import WDT
wdt=WDT(timeout=2000) #計時器時限 2 秒 (timeout 參數單位 ms)
然後在程式的無限迴圈中必須在看門狗計時器時限內呼叫 WDT 物件的 feed() 方法重設旗標, 讓看門狗知道系統正常運作, 才能避免系統被它重置 :
wdt.feed() #重設 WDT 旗標
但很可惜地, 我在 ESP8266 模組上測試, 用 dir(machine) 可以看到 WDT 模組, 但是無法傳入 timeout 參數設定計時器時限, 會出現 "does not take keword arguments", 如果不傳入參數則可以順利建立 WDT 物件與呼叫 feed(), 只是看起來沒作用而已 :
>>> import machine
>>> dir(machine)
['__name__', 'mem8', 'mem16', 'mem32', 'freq', 'reset', 'reset_cause', 'unique_id', 'idle', 'sleep', 'deepsleep', 'disable_irq', 'enable_irq', 'time_pulse_us', 'RTC', 'Timer', 'WDT', 'Pin', 'Signal', 'PWM', 'ADC', 'UART', 'I2C', 'SPI', 'DEEPSLEEP', 'PWRON_RESET', 'HARD_RESET', 'DEEPSLEEP_RESET', 'WDT_RESET', 'SOFT_RESET']
>>> from machine import WDT
>>> wdt=WDT(timeout=2000) Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function does not take keyword arguments
>>> wdt=WDT(2000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError:
>>> wdt=WDT() #不傳參數可建立物件
>>> wdt.feed() #也可呼叫 feed(), 但沒作用
>>> wdt.timeout=2000
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'WDT' object has no attribute 'timeout'
後來在下面這篇文章看到, 原來可設參數的 WDT 目前僅支援 WiPy 而已, 參考 :
"The docs show a WDT but that's only implemented for the WiPy (cc3200 port). In 64c5a94 I added a note to this effect."
# WDT support #esp8266 #2154
後來我在下面這篇文章看到有人問為何在呼叫 machine.time_pulse_us() 時傳入參數 2 秒沒問題, 但傳入 3 秒卻會導致系統重啟? 參考 :
# ESP8266 - Board auto-reset when using overlong delay machine.time_pulse_us() #2775
此函數以前沒用過, 測試我的 ESP-01 模組確實如此. 這函數是用來測量指定的 GPIO 輸入脈波的寬度用的, 咦, 這不就是之前測試超音波時想找的跟 Arduino 的 pulseIn() 一樣功能的函數嗎? 當時因為找不到, 所以只好自己寫一個來用. 參考 :
# machine.time_pulse_us()
除了回過頭去用 time_pulse_us() 改寫超音波程式外, 這裡我關心的是 time_pulse_us() 的重啟現象是否可用在 WDT 上呢? 仔細測試結果發現, time_pulse_us() 的重啟界線似乎不穩定, 有時 2.52 秒就重啟, 有時卻超過 3 秒也沒問題, 所以沒辦法用.
後來我在下面這篇文章讀到, 原來 machine 模組本身就有一個 reset() 函數可用來在程式中透過控制來重啟系統, 參考 :
# How can I reset ESP8266 MicroPython after main.py crashes?
這給了我一個靈感, time_pulse_us() 的重啟現象雖然不能用, 但是不是可用它的傳回值來控制 machine.reset() 重啟系統呢? 另一個想法是用 IRQ 來控制旗標, 根據旗標狀態來決定是否要重啟. 可行與否還要再測試看看, 這樣做與 WDT 是否意義不同呢? 等我幫二哥整理完 C 語言再回頭研究看看.
參考 :
# Crash recovery, stack usage & watchdog #264
# ESP8266 - Board auto-reset when using overlong delay machine.time_pulse_us() #2775
2018-04-26 補充 :
其實 ESP8266 也支持 WDT 才對, 我找到其說明文檔如下 :
# class WDT – watchdog timer
有空再來試試.
2018-05-14 補充 :
有一個模擬 WDT 的方法如下 :
# How can I reset ESP8266 MicroPython after main.py crashes?
2019-07-13 補充 :
MicroPython on ESP8266/ESP32 已於 v1.10 版韌體開始支援 WDT 功能了, 參考 :
# MicroPython on ESP32 學習筆記 (六) : 看門狗 WDT
沒有留言:
張貼留言