[備忘録]ESP32 MicroPythonサンプルコード

# はじめに

ESP32のコーディングをMicroPythonで行うことができます。
自身の備忘録として、コードメモを残します。

環境の構築は、下記の記事を参考にしてください。
[[備忘録]ESP32-VSCode-microPythonでの開発環境の構築](https://qiita.com/kotaproj/items/b53006aef9d04053a5ee)

# 注意事項
　動く程度のものなので、書き方として間違っている場合があります。


# 確認環境

- ホストPC
  - windows10 64bit Home
  - VSCode - 1.41.1
     - Pymakr 1.1.5
  - NodeJS - 12.14.1 LTS
- ターゲット
    - MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32


# GPIO関連


## Lチカ(GPIO-OUTPUT)

27番PINにLEDを接続するのを前提に記載しています。

```
from machine import Pin

led = Pin(27, Pin.OUT)

# LED ON
led.value(1)
# LED OFF
led.value(0)

# 別の書き方
# LED ON
led.on()
# LED OFF
led.off()
```

## GPIO-INPUT

27番PINにタクトスイッチを接続するのを前提に記載しています。

```
from machine import Pin

# GPIO INPUT
btn = Pin(27, Pin.IN)

# GPIO INPUT - プルアップ
btn = Pin(27, Pin.IN, Pin.PULL_UP)

# GPIO INPUT - プルダウン
btn = Pin(27, Pin.IN, Pin.PULL_DOWN)

# 状態の取得
btn.value()
# -> 0 or 1
```


## GPIO-IRQ割り込み

27番PINの変化を検出ことを前提に記載しています。


```
from machine import Pin

irq_count = 0

# 割り込み発生時にコールされる
# 引数のpinにて、設定したピンの状態取得可能
def irq_callback(p):
    global irq_count
    irq_count += 1

# pin27をinput設定
btn = Pin(27, Pin.IN, Pin.PULL_UP)

# pin27に対し、立ち上がりに検出時irq_callback()がコールされる
btn.irq(trigger=Pin.IRQ_RISING, handler=irq_callback)
```

立下りや両方を取得したい場合は、

```
# pin27に対し、立ち下がり検出時
btn.irq(trigger=Pin.IRQ_FALLING, handler=irq_callback)

# pin27に対し、立ち上がり or 立ち下がり検出時
btn.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=irq_callback)
```


# タイマー関連

## タイマー ONESHOT, 定期処理

```
import machine
import time

TIMER_ID = 0


def tmr_callbak(t):
    print("call tmr_callbak")

tmr = machine.Timer(TIMER_ID)


# 3秒後(3000msec)、1回だけtmr_callbak()がコールされる
tmr.init(period=3000, mode=machine.Timer.ONE_SHOT, callback=tmr_callbak)

# このスリープの間にコールされる
time.sleep(5)
# ->"call tmr_callbak"


# 3秒毎(3000msec)に、tmr_callbak()がコールされる
tmr.init(period=3000, mode=machine.Timer.PERIODIC, callback=tmr_callbak)

# このスリープの間にコールされる
time.sleep(10)
# ->"call tmr_callbak"
# ->"call tmr_callbak"
# ->"call tmr_callbak"
```

## タイマーを停止する

```
tmr.deinit()
```


# ストリーム関連(テキストIO)

## テキストファイルの書き込み

```
import uio as io

SETTINGS_TXT = "settings.txt"
mojiretu = "0123456789abcdef"

f = io.open(SETTINGS_TXT, "w")
f.write(mojiretu)
# ->16
f.close()

```

## テキストファイルの読み込み

```
import uio as io

SETTINGS_TXT = "settings.txt"

f = io.open(SETTINGS_TXT, "r")
yomidasi = f.read()
f.close()

print(yomidasi)
# ->"0123456789abcdef"

```


## テキストファイルのjsonと組み合わせ

```
import uio as io
import ujson as json

SETTINGS_TXT = "settings.txt"
wt_dict = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}

f = io.open(SETTINGS_TXT, "w")
f.write(json.dumps(wt_dict))
f.close()

f = io.open(SETTINGS_TXT, "r")
rd_dict = json.loads( f.read() )
f.close()
print(rd_dict)
# ->{'key2': 'value2', 'key3': 'value3', 'key1': 'value1'}

```


## テキストファイルのseek

```
import uio as io

SETTINGS_TXT = "settings.txt"

f = io.open(SETTINGS_TXT, "r")
yomidasi = f.read()
print(yomidasi)
# ->"0123456789abcdef"
yomidasi = f.read()
# ->""
f.seek(0)
yomidasi = f.read()
print(yomidasi)
# ->"0123456789abcdef"

f.close()
```

## 1行単位でリストにする

```
f.readlines()
['line1', 'line2', 'line3']

```

# 並行処理(スレッド)

MicroPythonには、threadingはありません。
低水準APIの_threadを使用します。

## 簡単な例

```
import _thread
import time

def dummy_func():
    count = 0
    while True:
        print("call dummy_func", count)
        count += 1
        time.sleep(1)


_thread.start_new_thread(dummy_func, ())

# ->call dummy_func 0
# ->call dummy_func 1
# ->call dummy_func 2
# ->call dummy_func 3

```

## スレッド間通信(socket通信)

Queueが存在しないので、socket通信を使用しています。

ファイル名：thread_socket.py

```
import _thread
from usocket import socket, AF_INET, SOCK_DGRAM
import time

HOST = ""
ADDR = '127.0.0.1'
PORT = 50001
RCV_BUF_SIZE = 1024

def rcv_func():
    s = socket(AF_INET, SOCK_DGRAM)
    s.bind((HOST, PORT))

    while True:
        msg, address = s.recvfrom(RCV_BUF_SIZE)
        print("rcv_func : ", msg, address)

    s.close()


def snd_func():
    s = socket(AF_INET, SOCK_DGRAM)

    for i in range(3):
        send_data = "send " + str(i)
        s.sendto(send_data.encode(), (ADDR, PORT))
        time.sleep(1)

    s.close()

_thread.start_new_thread(rcv_func, ())
time.sleep(1)
_thread.start_new_thread(snd_func, ())

```

実行結果

```

>>> import thread_socket
I (7310) modsocket: Initializing
>>> rcv_func :  b'send 0' ('127.0.0.1', 61289)
rcv_func :  b'send 1' ('127.0.0.1', 61289)
rcv_func :  b'send 2' ('127.0.0.1', 61289)

```


# Wifi関連

## アクセスポイントへの接続

ファイル名：sample_wifi000.py
※SSID, PASSは各自の環境に合わせ変更が必要です

```
import network
import time

# 接続するアクセスポイント情報
SSID = "XXXXXXXXXXXXX"
PASS = "XXXXXXXXXXXXX"

def do_connect():

    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect(SSID, PASS)
        while not wlan.isconnected():
            time.sleep(1)
    print('network config:', wlan.ifconfig())

    return


do_connect()
```

実行結果：

```
>>> import sample_wifi000
I (18060) wifi: wifi driver task: 3ffd2bcc, prio:23, stack:3584, core=0
略
I (36952) wifi: STA_START
connecting to network...
I (37072) wifi: new:<1,0>, old:<1,0>, ap:<255,255>, sta:<1,0>, prof:1
略

I (37962) network: CONNECTED
I (38742) tcpip_adapter: sta ip: 192.168.11.26, mask: 255.255.255.0, gw: 192.168.11.1
I (38742) network: GOT_IP
network config: ('192.168.11.26', '255.255.255.0', '192.168.11.1', '192.168.11.1')
>>>
```

# HTTP通信(urequests)

urequestモジュールを使用します。
※WiFiに接続している前提で記載します。

## HTTP GETメソッド

ファイル名：sample_urequests.py

```
import urequests as requests

url = "https://www.example.com/"

response = requests.get(url)
print(response.text)
response.close()
```

実行結果：

```
>>> import sample_wifi000
略

>>> import sample_urequests000
<!doctype html>
<html>
略
</html>
```


# さいごに

定期的に更新する予定です。


# 参考

[microPython ESP32 用クイックリファレンス](https://micropython-docs-ja.readthedocs.io/ja/latest/esp32/quickref.html)