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

 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で保存します。メニューにあるシリアルを開きます。画面下部に実行の様子が表示されます。

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)

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

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'xxxxxx')
    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アドレスを直接記述します。

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)では、受け取りが終了しませんでした。

 実行結果です。

電圧を測る

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'xxxxxxx')
    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の出力をつないでいます。