codemee
Posted on February 22, 2022
在 ESP8266 上使用 MicroPython 時發生了一件神奇的事, 我拿了一個剛剛燒錄好 MicroPython 韌體的 ESP8266 控制板, 居然不需設定 ESP8266 的時間, 就可以取得正確的時間, 例如:
MicroPython v1.17 on 2021-09-02; ESP module with ESP8266
Type "help()" for more information.
>>> import time
>>> time.localtime()
(2022, 2, 22, 9, 31, 0, 1, 53)
>>>
你可以看到一連接上 ESP8266, 取得的就是正確時間, 神奇吧?
Thonny 開發環境的自動對時
不過後來發現, 這是因為我使用的 Thonny 開發環境預設會在連結上控制板時, 自動依照電腦上的時間設定控制板, 所以控制板不需要校正時間也能取得正確的時間。
這個功能立意良好, 不過若沒有注意, 可能會因為實際部署裝置時並不會跟 Thonny 連接對時, 導致時間錯誤。
Thonny 的進階設定
如果要取消 Thonny 的自動對時功能, 要修改進階設定檔, 檔案的位置可透過『工具/開啟 Thonny 資料夾』開啟資料夾, 然後開啟 configuration.ini 檔, 在檔案中找到或是如下建立 ESP8266 專屬的區塊 (ESP32 專屬區塊的名稱就是 'ESP32'), 加上 sync_time = False
的設定:
...
[ESP8266]
port = COM4
used_vidpids = {(6790, 29987)}
sync_time = False
...
注意到這個設定必須在 Thonny 關閉時修改才能生效, 重新開啟 Thonny 後, 連結上 ESP8266 控制板, 會先看到 Thonny 提醒你控制板上的時鐘慢了 xxxxx 秒, 這就是因為取消 Thonny 自動對時的關係:
WARNING: Device's real-time clock seems to be off by 698838035 seconds
MicroPython v1.17 on 2021-09-02; ESP module with ESP8266
Type "help()" for more information.
>>>
如果取得控制板的時間, 就會看到接近以下尚未對時過的時間:
>>> import time
>>> time.localtime()
(2000, 1, 1, 0, 0, 38, 5, 1)
>>>
我們可以讓控制板連上網路, 再利用 ntptime
模組透過網路對時:
>>> import network
>>> sta = network.WLAN(network.STA_IF)
>>> sta.active(True)
#7 ets_task(4020ee68, 28, 3fff9ea0, 10)
>>> sta.connect('FLAG-SCHOOL', '12345678')
>>> import ntptime
>>> ntptime.settime()
>>> time.localtime()
(2022, 2, 22, 1, 43, 31, 1, 53)
>>>
這樣就可以取得正確的時間了。
不連網也能對時?
如果將控制板拔掉後再重新接上, 讓 Thonny 再連結上控制板, 因為剛剛已經斷電了, 所以時間又回到未對時的狀況:
>>>
Backend terminated or disconnected. Use 'Stop/Restart' to restart.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
WARNING: Device's real-time clock seems to be off by 698838263 seconds
MicroPython v1.17 on 2021-09-02; ESP module with ESP8266
Type "help()" for more information.
>>> import time
>>> time.localtime()
(2000, 1, 1, 0, 0, 19, 5, 1)
既然時間不準, 我們就利用網路對時吧:
>>> import ntptime
>>> ntptime.settime()
>>> time.localtime()
(2022, 2, 22, 1, 45, 52, 1, 53)
>>>
ESP8266 的自動連網
時間正確了, 咦, 你有注意到我們沒有連網嗎?沒有連網怎麼可能可以網路對時呢?來確認一下:
>>> import network
>>> sta = network.WLAN(network.STA_IF)
>>> sta.isconnected()
True
>>>
咦, 我們已經連上網了!原來 ESP8266 會將網路狀態記錄在快閃記憶體, 重新啟動時會嘗試連上網路, 因此就可以很神奇地進行網路對時。如果我們將網路關閉:
>>> sta.active(False)
>>> ntptime.settime()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ntptime.py", line 34, in settime
File "ntptime.py", line 20, in time
OSError: -2
>>
再想進行網路對時就會發生錯誤, 循錯誤訊息指示, 在 MicroPython 的原始檔中可以看到這是在向 DNS 伺服器查詢 NTP 伺服器 IP 位址時因為網路不通而發生錯誤。由於網路介面已經關閉, 即使重新啟動控制板, 也不會自動連上無線網路, 當然就無法網路對時:
>>>
Backend terminated or disconnected. Use 'Stop/Restart' to restart.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
WARNING: Device's real-time clock seems to be off by 698838813 seconds
MicroPython v1.17 on 2021-09-02; ESP module with ESP8266
Type "help()" for more information.
>>> import ntptime
>>> ntptime.settime()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ntptime.py", line 34, in settime
File "ntptime.py", line 20, in time
OSError: -2
>>>
在 ESP32 的 MicroPython 上, 並不會有自動重新連線的問題, 控制板重啟後網路介面都是關閉的。
小結
本文說明的雖然是個小問題, 不過常常就是因為這樣的小問題導致耗費大量時間除錯。我個人建議不要太依賴預設的自動行為, 不論 Thonny 是否會幫控制板對時, 若需要正確的時間, 就明確在程式中對時;同樣地, 也明確在程式中連接無線網路, 這樣, 若是無線網路有問題, 也會在連結時看到錯誤訊息, 不會默默不語, 可以及早發現問題。
Posted on February 22, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.