MicroPython的午睡(40) まずはネット接続してntp、M5ATOM Lite

Joseph Halfmoon

超小型デバイスM5 ATOM Liteに、MicroPythonのESP32向けgenericポートを書き込んで動かしております。ESP32系のデバイスの売りといえば何といってもイージーなネット接続であります。まずはWiFiアクセスポイントに接続。最初はntpサーバにお願いしてRTCに時刻を設定してみます。

※「MicroPython的午睡」投稿順 Indexはこちら

前回ことさら “generic port” と書きましたが、genericでもESP32向けの機能は充実しております。以下の日本語文書をみると各種機能に「さらっと」触れているので、これ読めば何とかなりそうな気がします。

ESP32用クイックリファレンス

今回は充実のそれら機能の中から、networkモジュール、 ntptimeモジュール、そして machineモジュールからRTCクラスについて勉強してみたいと思います。MicroPythonのドキュメントをあさってみると、ESP32向けの記述は「さらっと」「そっけなく」完結している感じ。それに対して1世代前の兄弟機種ESP8266向けの文書の方が詳しく感じます。ESP32はESP8266との互換性が高いようなので、今回実験してみるネットワーク関係については、ESP8266向けのドキュメントも参照しておくと分かり易いです。

ネットワークの基礎 (ESP8266)

ただ、微妙に違いがあることも事実です。例えばRTCについては、ESP8266のリアルタイムクロック(RTC)という項には、「標準」MicroPythonではサポートされる関数のうち、

esp8266では now(), irq(), init(), deinit()はサポートされていない

という趣旨の記述があります。しかし、インストールしたESP32 generic上で調べてみると以下のようにinit()が存在したりします。

>>> help(machine.RTC)
object <class 'RTC'> is of type type
init -- <function>
datetime -- <function>
memory -- <function>

結局のところ、init()もnow()もdatetime()で兼用できるので、ESP32の実装で不便はないのですが、スクリプトの記述にあたっては処理系ごとの凸凹の確認は常に必要と思われます。

今回の実験

今回はベーシック、通り一遍、必ずやることの復習、という感じです。

    • WiFiアクセスポイントに接続
    • ネットワークに接続できたら何処かのntpサーバに接続して時刻をGETしてRTCに設定
    • 念のため、現在時刻(JSTで)をREPL画面に表示

上述のドキュメントの中にWiFi接続のための雛形コードがあります。それを使えば接続は簡単(以下の実装では、雛形コードよりことさら重くなってますが、実験用ということで。)また、ネットワークに接続してありさえすれば ntp でRTCに現在時刻を設定するのは簡単です。実験に使用したコード全文は以下に。

import network, ntptime, machine, time

def do_connect(ssid, pw, timeout, opt=True):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect(ssid,pw)
        while (not wlan.isconnected()) and (timeout > 0):
            start = time.ticks_ms()
            while time.ticks_diff(time.ticks_ms(), start) < 1000:
                pass
            timeout -= 1
    if opt:
        print('timeout: ', timeout)
        print('network config: ', wlan.ifconfig())
    return wlan.isconnected()

def initRTC(timZone, opt=True):
    ntptime.host = "YOUR_NTP_SERVER address"
    ntptime.settime()
    t0 = machine.RTC().datetime()
    if opt:
        print("{0}/{1:02d}/{2:02d} {3:02d}:{4:02d}:{5:02d}".format(t0[0],t0[1],t0[2],t0[4]+timZone,t0[5],t0[6]))
 
def main():
    if do_connect('YOUR_SSID','YOUR_PASSKEY', 10):
        initRTC(9)

if __name__ == "__main__":
    main()

なお、YOUR_などと書かれている文字列部分には、適切なアドレスやSSID等を書き入れないとなりませぬ。

実験結果

やはりESP32は楽。MicroPythonでさらにお手軽。結果はこんな感じです。

connecting to network...
timeout: 8
network config: ('YOUR IP ADDRESS', 'YOUR_NET_MASK', 'YOUR_GATEWAY', 'YOUR_DNS')
2021/08/26 12:03:23

勿論、YOUR_の部分には環境依存のアドレス等が入っています。

なお、上記のコードを見るとわかりますが、

    • ntpはUTC(協定世界時)である
    • RTCに設定する時刻はntpから返ってきた時刻そのものなのでUTC
    • RTCから読み出した値を表示するときに hourに+9して、JSTに変換している

です。OSのある環境と違って TimeZone 設定が見当たらなかったので、そういう単刀直入な(誤魔化し?)方法で始末してしまいました。Python書いている人が分かっていればいいんだ。。。

MicroPython的午睡(39) “generic”ポートで見るATOM Lite へ戻る

MicroPython的午睡(41) MQTTでPublish、M5ATOM Lite へ進む