MicroPython v1.8.7-7-gb5a1a20a3 on 2017-01-09; ESP module with ESP8266
Type "help()" for more information.
>>> import time #有支援 time 模組
Traceback (most recent call last):
File "
>>> import calendar #未支援 calendar 模組
Traceback (most recent call last):
File "
>>> time.time() #傳回開機後秒數
4561
>>> time.time()
4564
>>> time.time()
4589
>>> time.time()
4729
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import time
>>> now=time.time() #傳回 UTC 的 epoch 秒數
>>> now
1495270100.4163206
>>> time.ctime(now) #將 epoch 秒數轉成時間字串
>>> time.ctime(time.time()) #MicroPython 沒有實作 ctime()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ctime'
不過 MicroPython 的 time 模組倒是實作了 localtime() 函數, 它會傳回從 2000 年 1 月 1 日 0 時 0 分 0 秒起算的時間字串, 例如 :
>>> now=time.time()
>>> now #自 2000/1/1 起之秒數
23093
(2000, 1, 1, 6, 24, 53, 5, 1)
# https://docs.micropython.org/en/latest/pyboard/library/utime.html#utime.localtime
要如何才能讓 ESP8266 顯示正確時間呢? 如果使用 Pyboard 等板子可以採用 RTC 來提供目前時間, 但對於只拉出兩個 I/O 埠的 ESP-01 就太麻煩了, 最方便的方法是利用 ESP8266 本身自有的 WiFi 連網功能從 NTP 伺服器取得同步時間, 而且 MicroPython 有實作 ntptime 模組, 其 settime() 函數會以從 NTP 伺服器取得的 UTC 時間去設定 ESP8266 內的 RTC :
參考 :
# Setting RTC From Internet?
但是存取 NTP 伺服器須先讓 ESP8266 連上網路, 參考本系列測試中的 WiFi 測試 :
# MicroPython on ESP8266 (二) : 數值型別測試
# MicroPython on ESP8266 (三) : 序列型別測試
# MicroPython on ESP8266 (四) : 字典與集合型別測試
# MicroPython on ESP8266 (五) : WiFi 連線與 WebREPL 測試
# MicroPython on ESP8266 (六) : 檔案系統測試
MicroPython 文件參考 :
# MicroPython tutorial for ESP8266 (官方教學)
# http://docs.micropython.org/en/latest/micropython-esp8266.pdf
# http://docs.micropython.org/en/latest/pyboard/library/usocket.html#class-socket
# http://docs.micropython.org/en/v1.8.7/esp8266/library/usocket.html#module-usocket
# https://gist.github.com/xyb/9a4c8d7fba92e6e3761a (驅動程式)
>>> import network #匯入 NETWORK 模組
>>> sta_if = network.WLAN(network.STA_IF) #取得 STA 介面物件
>>> sta_if.connect('EDIMAX-tony', '1234567890') #連線 AP
>>> sta_if.ifconfig() #檢視 STA 設定
('192.168.2.122', '255.255.255.0', '192.168.2.2', '192.168.2.2') #取得 IP 192.168.2.122
取得 IP 表示已連線至 AP, 接下來便可以透過 Internet 連線從 NTP 伺服器取得 UTC 時間了. MicroPython 有實作了 ntptime 模組, 其中的 settime() 方法可用來設定 ESP8266 內部時鐘, 然後再用 time 模組的 localtime() 方法即可取得目前的 UTC 時間, 例如 :
>>> from ntptime import settime #從 ntptime 模組匯入 settime()
>>> settime() #以自 NTP 伺服器取得之 UTC 時間設定 RTC
(2017, 5, 20, 7, 19, 40, 5, 140)
>>> time.localtime() #顯示目前之 UTC 時間
(2017, 5, 20, 7, 21, 19, 5, 140)
但是由於 MicroPython 未實作 locale 模組, 因此無法藉此設定時區來取得台灣時間 :
>>> import locale
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: no module named 'locale'
如果要取得本地而非 UTC 時間, 必須自行換算, 例如台灣時間為 UTC+8, 我們可以將 time.localtime() 傳回的 tuple 傳給 time.mktime(), 它會將此 tuple 轉成 Epoch 秒數, 將其加上 28800 秒 (= 8 小時) 便是台灣時間的 Epoch 秒數, 最後再傳給 time.localtime() 即可得到台灣時間的 tuple, 例如 :
>>> time.mktime(time.localtime()) #將 RTC 時間轉成 UTC 之 Epoch
548580535
>>>
>>> time.localtime(time.mktime(time.localtime())+28800) #UTC 加 8 小時
(2017, 5, 20, 15, 38, 26, 5, 140) #為台灣時間
這樣要製作我慣用的 YYYY-MM-DD HH:mm:SS 時間格式字串就很容易啦, 例如 :
測試 1 : 從 NTP 伺服器取得 UTC 時間並轉為台灣時間
import time
from ntptime import settime
settime()
utc_epoch=time.mktime(time.localtime())
Y,M,D,H,m,S,ms,W=time.localtime(utc_epoch + 28800)
t=str(Y) + '-'
if M<10:
t += '0' + str(M)
else:
t += str(M)
t += '-'
if D<10:
t += '0' + str(D)
else:
t += str(D)
t += ' '
if H<10:
t += '0' + str(H)
else:
t += str(H)
t += ':'
if m<10:
t += '0' + str(m)
else:
t += str(m)
t += ':'
if S<10:
t += '0' + str(S)
else:
t += str(S)
print(t)
測試 1 : 從 NTP 伺服器取得 UTC 時間並轉為台灣時間
import time
from ntptime import settime
settime()
utc_epoch=time.mktime(time.localtime())
Y,M,D,H,m,S,ms,W=time.localtime(utc_epoch + 28800)
t=str(Y) + '-'
if M<10:
t += '0' + str(M)
else:
t += str(M)
t += '-'
if D<10:
t += '0' + str(D)
else:
t += str(D)
t += ' '
if H<10:
t += '0' + str(H)
else:
t += str(H)
t += ':'
if m<10:
t += '0' + str(m)
else:
t += str(m)
t += ':'
if S<10:
t += '0' + str(S)
else:
t += str(S)
print(t)
將上面程式存成 t.py 用 ampy 上傳 ESP8266 後執行結果如下 :
D:\test>ampy --port COM4 put t.py #上傳 RSP8266
D:\test>ampy --port COM4 run t.py #執行程式
(2017, 5, 20, 15, 28, 3, 5, 140)
2017-05-20 23:28:03
注意, 下面這篇文件提到, ESP8266 內建 RTC 每 7 個小時 45 分會溢位, 因此最好 7 個小時內要呼叫 time() 或 localtime() 函數一次, 這樣 MicroPython 才能處理溢位問題, 參考 :
# http://docs.micropython.org/en/v1.8.7/esp8266/esp8266/general.html#real-time-clock
"Due to limitations of the ESP8266 chip the internal real-time clock (RTC) will overflow every 7:45h. If a long-term working RTC time is required then time() or localtime() must be called at least once within 7 hours. MicroPython will then handle the overflow."
# https://docs.micropython.org/en/latest/pyboard/library/utime.html
# Timezone support for "time" module #2130
# Date/Time management
# 15.3. time — Time access and conversions (Python 標準函式庫)
# MicroPython标准库函数utime
# NTP update micropython time
2017-07-05 補充 :
上面的程式可以寫個 fill_zero() 函數來簡化 :
測試 2 : 從 NTP 伺服器取得 UTC 時間並轉為台灣時間-簡化版
def fill_zero(n):
if n<10:
return '0' + str(n)
else:
return str(n)
import time
import ntptime
ntptime.settime()
while True:
utc_epoch=time.mktime(time.localtime())
Y,M,D,H,m,S,ms,W=time.localtime(utc_epoch + 28800)
t='%s-%s-%s %s:%s:%s' % (str(Y),fill_zero(M),fill_zero(D),\
fill_zero(H),fill_zero(m),fill_zero(S))
print(t)
time.sleep(1)
此程式使用 time.sleep() 每秒讀取 ESP8266 內建時鐘後轉成台灣時間, 然後使用字串格式化技巧產生時間字串, REPL 介面輸出如下 :
2017-07-05 20:03:37
2017-07-05 20:03:38
2017-07-05 20:03:39
2017-07-05 20:03:40
2017-07-05 20:03:41
2017-07-05 20:03:42
2017-07-05 20:03:43
2017-07-05 20:03:44
2017-07-05 20:03:45
2017-07-05 20:03:46
2017-07-05 20:03:47
2017-07-05 20:03:48
2017-07-05 20:03:49
2017-08-29 補充 :
由於 MicroPython 尚未支援 datetime, 所以無法使用 datetime.strftime() 將時戳依照指定格式轉成如 "2017-08-29 12:34:21" 的字串. 如果要將特定日期時間字串轉成其他時區, 必須自行進行字串處理, 將其轉成 8 元素的串列或元組傳給 time.maketime() 轉成時戳才能進行整數計算, 最後將時戳傳給 time.localtime() 轉回串列.
例如 "2017-08-29 12:34:12" 這個字串用空格, '-' 與 ':' 以 split() 拆開後只能得到 6 個元素, 必須在拆開前在後面補上 '0:0' 變成 "2017-08-29 12:34:12:0:0" 再拆才不會出錯. 實際範例參考下列文章的測試 4 :
# MicroPython on ESP8266 (二十) : 從 ThingSpeak 讀取資料
參考 :
# [Python] 時間格式轉換(strtime & strftime)
# Converting UTC in utime.localtime giving wrong date
# micropython/micropython-lib (支援 strftime)
# How to convert python timestamp string to epoch?
4 則留言 :
老師您好 又來請教非常基本的問題了
pin.value(0)的問題解決後
想隨便寫個for之類的小程式在8266上面跑
但不管如何都會出現
Traceback (most recent call last):
File "", line 1
SyntaxError: invalid syntax
而同樣的code如
print ("Hello, Python")
寫成hello.py 在Linux上執行都是正常的
請問這是路徑問題嗎?
我用os.listdir()是能直接看到的
我比較熟悉Linux上的指令 不太了解esp8266
您的程式碼長怎樣呢?
老師您好 我截圖比較容易閱讀
http://imgur.com/a/OdP9D
像這樣的python檔我放在樹莓派上都能正常運作
但用Webrepl放到esp上執行就是無法
REPL 介面跟 Python IDLE 介面一樣直接輸入 Python 指令, 而 python hi.py 並非 Python 指令, 而是作業系統命令, REPL 當然不認得. 給 MicroPython 跑的 Python 程式要存成 main.py 利用 ampy 等工具上傳到 ESP8266 的 MicroPython 檔案系統跟目錄下, 在 REPL 按 Ctrl+D 才會執行, 參考 :
http://yhhuang1966.blogspot.tw/2017/05/micropython-on-esp8266_18.html
張貼留言