DEV Community

codemee
codemee

Posted on

不需網路就可以自動對時的神奇 ESP8266

在 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)
>>>
Enter fullscreen mode Exit fullscreen mode

你可以看到一連接上 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
...
Enter fullscreen mode Exit fullscreen mode

注意到這個設定必須在 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.
>>>
Enter fullscreen mode Exit fullscreen mode

如果取得控制板的時間, 就會看到接近以下尚未對時過的時間:

>>> import time
>>> time.localtime()
(2000, 1, 1, 0, 0, 38, 5, 1)
>>>
Enter fullscreen mode Exit fullscreen mode

我們可以讓控制板連上網路, 再利用 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)
>>>
Enter fullscreen mode Exit fullscreen mode

這樣就可以取得正確的時間了。

不連網也能對時?

如果將控制板拔掉後再重新接上, 讓 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)
Enter fullscreen mode Exit fullscreen mode

既然時間不準, 我們就利用網路對時吧:

>>> import ntptime
>>> ntptime.settime()
>>> time.localtime()
(2022, 2, 22, 1, 45, 52, 1, 53)
>>>
Enter fullscreen mode Exit fullscreen mode

ESP8266 的自動連網

時間正確了, 咦, 你有注意到我們沒有連網嗎?沒有連網怎麼可能可以網路對時呢?來確認一下:

>>> import network
>>> sta = network.WLAN(network.STA_IF)
>>> sta.isconnected()
True
>>>
Enter fullscreen mode Exit fullscreen mode

咦, 我們已經連上網了!原來 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
>>
Enter fullscreen mode Exit fullscreen mode

再想進行網路對時就會發生錯誤, 循錯誤訊息指示, 在 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
>>>
Enter fullscreen mode Exit fullscreen mode

在 ESP32 的 MicroPython 上, 並不會有自動重新連線的問題, 控制板重啟後網路介面都是關閉的。

小結

本文說明的雖然是個小問題, 不過常常就是因為這樣的小問題導致耗費大量時間除錯。我個人建議不要太依賴預設的自動行為, 不論 Thonny 是否會幫控制板對時, 若需要正確的時間, 就明確在程式中對時;同樣地, 也明確在程式中連接無線網路, 這樣, 若是無線網路有問題, 也會在連結時看到錯誤訊息, 不會默默不語, 可以及早發現問題。

Top comments (0)