CircuitPythonで測定器Keysightのディジタルマルチメータ34461Aの電圧をひろう

#CircuitPythonのWi-Fi接続
　
　マイコンボードはAdafruit Metro M4 Express AirLift (WiFi)を使います。主な特徴です。
>
*CPU　120MHz Cortex M4 ATSAMD51（浮動小数点、DSP、フラッシュ・メモリ512Kバイト、RAM 192Kバイト）
*外付けEEPROM　2Mバイト
*動作電圧　3.3V（DCジャック7～9V入力、MicroUSBの5V入力）
*無線　ESP32-WROOM-32　SPI接続
*アナログ（D-Aコンバータ）出力　A0とA1ピン
*インターフェース・バス　I2C　SPI

![IMG_3038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/52eb5617-e53e-80fa-cd0e-ec5d73107495.png)


　CircuitPythonは5.0.0 Beta 0（　https://github.com/adafruit/circuitpython/tags
　）
を使います。インストールは省略します。Wi-Fiを使うとき、ESP32-WROOM-32のファームウェアは1.3.0以上が必要です。Adafruitの解説に従って1.4.0もしくは1.5.0に上げます。
　こちらの記事を参照してください。
https://www.denshi.club/pc/python/circuitpython/circuitpython-10-step3-1.html

　Muエディタに、examplesにあるesp32spi_simpletest.pyを読み込み、40行にあるWi-Fiルータの接続個所の2か所（ルータ名とパスワード）を修正します。

```esp.connect_AP(b'MY_SSID_NAME', b'MY_SSID_PASSWORD')
```
　main.pyで保存します。メニューにあるシリアルを開きます。画面下部に実行の様子が表示されます。

![wifi01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/c4b8ce1e-de98-df44-3416-bcfc9a84b6e0.png)

#CircuitPython のソケット（BSD）はMicroPythonベース
　Docs » ESP8266 用クイックリファレンス » ESP8266用 MicroPythonチュートリアル » 5. ネットワーク - TCPソケット
　https://micropython-docs-ja.readthedocs.io/ja/latest/esp8266/tutorial/network_tcp.html
の解説記事を見ると、通常のPythonのsocketプログラムとは異なります。

 ```import socket```

は、同じですが、

　```addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)```

getaddrinfo()関数で接続をします。そして、不要な部分を破棄し、

　```addr = addr_info[0][-1]```

そのaddrでconnectします。

```s = socket.socket()
s.connect(addr)```

　サンプルのなかで、必要な部分を抜き出しました。

```python
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as sockets
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
import time

esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

requests.set_socket(sockets, esp)

if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(b'Buffalo-G-20EA', b'ｘｘｘｘｘｘ')
    except RuntimeError as e:
        print("could not connect to AP, retrying: ",e)
        continue
print("Connected to", str(esp.ssid, 'utf-8'), "\tRSSI:", esp.rssi)
print("My IP address is", esp.pretty_ip(esp.ip_address))
```

　つづいてソケットの接続方法を記述します。Windowsやラズパイでは、.localが使えます（mDNSやavahi）が、CircuitPythonではサポートされていないので、IPアドレスを直接記述します。

```python
host = "K-34461A-16054.local"
ipAddr = "192.168.111.111"
ports = 5025
addr_info = sockets.getaddrinfo(ipAddr, ports)
print(addr_info)
addr = addr_info[0][-1]
print(addr)
skt = sockets.socket()
print("connect to")
skt.connect(addr)
print("connect'd")

print("send to")
skt.send("*IDN?\n") 
print("received")

data = skt.recv(64).decode()
print(data)
skt.close()
print("Done")
```

　受信するrecv()関数は、処理系によっては、送られてくる文字数がバッファより少ないと終了しません。CircuitPythonでもそういう仕様のようです。機器名の問い合わせの*IDN?に対して、このDMMは約70文字を返してきます。recv(256)では、受け取りが終了しませんでした。

　実行結果です。
![wifi02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/0041f4ee-88c5-727b-aab2-be3320bfbfac.png)

#電圧を測る

```python
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as sockets
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
import time

# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

requests.set_socket(sockets, esp)

if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(b'Buffalo-G-20EA', b'ｘｘｘｘｘｘｘ')
    except RuntimeError as e:
        print("could not connect to AP, retrying: ",e)
        continue
print("Connected to", str(esp.ssid, 'utf-8'), "\tRSSI:", esp.rssi)
print("My IP address is", esp.pretty_ip(esp.ip_address))

ipAddr = "192.168.111.111"
ports = 5025
addr = sockets.getaddrinfo(ipAddr, ports)[0][-1]

skt = sockets.socket()
skt.connect(addr)

skt.send("*IDN?\n")
print(skt.recv(71).decode())

skt.send('CONF:VOLT:DC 10,0.001\n') 
skt.send('READ?\n') 
print('DC: ' + skt.recv(17).decode())
skt.close()
print("Done")
```
　実行結果です。DMMの測定端子には、実験用電圧源TL431の出力をつないでいます。

![wifi04a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/445fa189-2e2b-59d4-ac34-0a84fd683651.png)