UMEHOSHI ITA TOP PAGE
COMPUTER SHIEN LAB
「UMEHOSHI ITA」にESP32-WROOM-32E-N16を、「UMEHOSHI ITA」へ取り付ける例を示しています。
(「UMEHOSHI ITA」は一部の端子だけをCN11とCN12を介して引き出し、そこに別途の自作基板を取り付けて、少しだけ利用することを想定しています。)
ESP32-WROOM-32E-N16を付けての実験
ESP32-WROOM-32E-N16の取り付け例
ESP32-WROOM-32E-N16dは起動時に、GPIO0、GPIO12、GPIO15に与える電圧レベルで挙動が次のように変化するので注意が必要です。
- GPIO0は起動時にHIGHで通常起動、LOWでプログラムを書き込み用の待機状態。
(新たに追加したSW3で、手動で自動時の切り替えができる)
- GPIO12は起動時のLOWでSPIフラッシュメモリへの電圧を正しい3.3Vにする。
(既存SW2の操作で、起動時は必ず押す必要がある)
- GPIO15は起動時のHIGHブートローダのログ出力を有効にします。
(開放状態で、必ずUART0にログが出力される。)
UMEHOSHI ITA にESP32-WROOM-32E-N16を取り付けた場合、GPIO15端子は開放状態なので、必ずUARTへのブートローダのログ表示状態ですが、
(UMEHOSHI ITAのUART通信はPIC32が受け持ちますが、起動時の1秒間程度の受信を無視するのでこの表示は見えません。)
ESP32-WROOM-32EのGPIO12端子は起動時にLowにして内部SPIフラッシュメモリへ正しい電圧を設定しなければならない。
これは、下記イメージのようにESP32のIO12に繋がるSW2端子とGND間にコンデンサー(0.1u)を付けて、起動時でLowになるようにしました。
(一時的に起動時だけPIC32でRB7を出力モードでLowにしてみたが、これではESP32側でLowと判断してくれないかったの採用しませんでした。)
GPIO12はPIC32のRB7やSW2に繋がっており、SW2を押しながら起動すれば良のですが、UMEHOSHI ITAでもSW2を押しながらの起動モードが存在します。
そしてESP32-WROOM-32Eの取り付けによってUMEHOSHI ITA内のPIC32のRB7入力端子がSW2のOFF時で1.8Vしか得られない問題が発覚しました。
それに対応するためにPIC32のRB7をプルアップ指定に変更し、これでSW2のOFFレベルが2.0VになってギリでPIC32がHiと判断できるようにしました。
(将来的には、SW2とRB7にあるR5の1Kを300Ω程度する方法が良いと考える)
ESP32をプログラム書き込みの「UART Download Mode」にするためには起動時にIO0端子をLOWにするため切り替えが必要です。
([UMEHOSHI ITA]において、ESP32のIO0端子はどこにも繋がっていません。DTR/RTS制御は対応していません)
そのためには、
「IO0」を引き出して空いているCN12-5とジャンパーで配線し、ここに繋がるスイッチを付けたボードを別途に作成する必要があります。
そのため[UMEHOSHI ITA]基板の裏で「IO0:(U19-25)に繋がっているT6スルーホール」からジャンパー線で引き出して、
コネクタCN12-5と接続させるため、次のように半田付けしました。
上記は半田面で、下記がESP32-WROOM-32E-N16を取り付けた時の部品面と別途のSW3(黄色)を付けた基板とその配置兼回路図です。
MicroPythonファームウェアをESP32-WROOM-32E-N16を書き込むためには、上記で示す別途のIO0端子に繋がるSW3(黄)を付けた基板を付けて、
SW1(赤)リセットと、SW2(白)と、SW3(黄)を押して、SW1(赤)だけ離した後に3秒待ってLEDが消えた後に、残りスイッチ(SW2とSW3)を離します。
このSW3(黄)を付けた基板は、上記の配置兼回路に従って両面スルーホール2.54mm×2mmピッチ基板にCN11とCN12の2mmピッチソケットを付けて、
接続できるような基板(上記写真)を作成して取り付けます。
このCN11とCN12の繋がりの関係を以下に表で示します。(この部分的な回路図)
| CN12 | ESP32-WROOM-32D端子名 | PIC32MX端子No:名 | - | CN11 | ESP32-WROOM-32D端子名 | PIC32MX端子No:名 |
| CN12-1 | 2: 3V3 | 13: VDD | | CN11-10 | 11: IO26 | |
| CN12-2 | 35:TXD0 出力 | 12: RX (RA4) 入力 | | CN11-9 | 10: IO25 | |
| CN12-3 | 34:RXD0 入力 | 11: TX (RB4) 出力 | | CN11-8 | 37: IO23 | |
| CN12-4 | 6: IO34 | | | CN11-7 | 36: IO22(SCL)(RTS) | |
| CN12-5 | ジャンパー配線でSW3へ | | | CN11-6 | JMP10-OPEN-U19-23: IO15 | 18: RTS (RB9) 出力 |
| CN12-6 | 7: IO35 | | | CN11-5 | 33:IO21 (SDA) | |
| CN12-7 | 8: IO32 | | | CN11-4 | 5: SENSOR_VN | |
| CN12-8 | 9: IO33 | | | CN11-3 | 4: SENSER_VP | |
| CN12-9 | 12: IO27 | | | CN11-2 | JUM11-OPEN-16: IO13 | 17: CTS (RB8) 入力 |
| CN12-10 | GND | 19: Vss | | CN11-1 | 31: IO19(CTS) | |
MicroPythonファームウェアの書き込み
MicroPython公式サイトのESP32専用ダウンロードページから、
Releases版を取得して操作します。
以下は、ESP32_GENERIC-20260406-v1.28.0.bin のMicroPythonファームウェアを取得(20260808)した場合の例で示しています。
このMicroPythonファームウェアの書き込みには、esptoolツールを使います。
(esptoolツールは、pip install esptoolでインストールします。3.3.3バージョンを使った例です。)
同様にadafruit-ampyやmpremoteもインストールすると良いでしょう。
esptoolツールを使ったMicroPythonファームウェア書き込み
PCとUMEHOSHI ITAをUSBケーブルで接続し、
SW1(赤)リセットと、
SW2(白)と SW3(黄)を押して、
SW1(赤)だけ離した後に3秒待ってLEDが消えた後に、残りスイッチ(SW2とSW3)を離します。
(この操作で、ESP32-WROOM-32E-N16は書き込みの「UART Download Mode」になります。
そしてUMEHOSHI ITAはスルーモード(UART CDCブリッジ)になります。)
そして、次のように操作しました。(デバイスマネージャでUSBシリアライズのCOMが3の場合の例です。)
R:\drone>esptool --before no_reset --port COM3 --baud 115200 flash_id
esptool.py v3.3.3
Serial port COM3
WARNING: Pre-connection option "no_reset" was selected. Connection may fail if the chip is not in bootloader or flasher stub mode.
Connecting.....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting....
Detecting chip type... ESP32
Chip is ESP32-D0WD-V3 (revision v3.1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
WARNING: Detected crystal freq 41.47MHz is quite different to normalized freq 40MHz. Unsupported crystal in use?
Crystal is 40MHz
MAC: 38:18:2b:34:09:c0
Uploading stub...
Running stub...
Stub running...
Manufacturer: a1
Device: 4018
Detected flash size: 16MB
Hard resetting via RTS pin...
R:\drone>esptool --before no_reset --port COM3 --baud 115200 erase_flash
esptool.py v3.3.3
Serial port COM3
WARNING: Pre-connection option "no_reset" was selected. Connection may fail if the chip is not in bootloader or flasher stub mode.
Connecting...
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting...
Detecting chip type... ESP32
Chip is ESP32-D0WD-V3 (revision v3.1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
WARNING: Detected crystal freq 41.47MHz is quite different to normalized freq 40MHz. Unsupported crystal in use?
Crystal is 40MHz
MAC: 38:18:2b:34:09:c0
Stub is already running. No upload is necessary.
Erasing flash (this may take a while)...
Chip erase completed successfully in 9.6s
Hard resetting via RTS pin...
R:\drone>esptool --before no_reset --chip esp32 --port COM3 --baud 115200 write_flash -z 0x1000 ESP32_GENERIC-20260406-v1.28.0.bin
esptool.py v3.3.3
Serial port COM3
WARNING: Pre-connection option "no_reset" was selected. Connection may fail if the chip is not in bootloader or flasher stub mode.
Connecting...
Chip is ESP32-D0WD-V3 (revision v3.1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
WARNING: Detected crystal freq 41.47MHz is quite different to normalized freq 40MHz. Unsupported crystal in use?
Crystal is 40MHz
MAC: 38:18:2b:34:09:c0
Stub is already running. No upload is necessary.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x001aefff...
Compressed 1760192 bytes to 1152806...
Wrote 1760192 bytes (1152806 compressed) at 0x00001000 in 103.5 seconds (effective 136.0 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
R:\drone>
上記で実行している全てのesptoolのオプションで、--before no_reset を行っています。
これはDTR/RTS制御を行わない指定です。
同時に --port COM3 --baud 115200 でポート名と速度を指定しています。
最初の実行で「flash_id」を指定して「Chip is ESP32-D0WD-V3 (revision v3.1)」のチップ情報が得られています。
次の実行で、チップのラッシュメモリを完全にクリア(消去)しています。
最後の実行で、ESP32_GENERIC-20260406-v1.28.0.binのファームウェアを書き込んでいます。
MicroPythonの実行やファイル操作
PCとUMEHOSHI ITAをUSBケーブルで接続し、
SW1(赤)リセットと、
SW2(白)を押して、
SW1(赤)だけ離した後に3秒待ってLEDが消えた後に、SW2(白)スイッチを離します。
(この操作で、そしてUMEHOSHI ITAはスルーモード(UART CDCブリッジ)になります。
SW3(黄)の基板は付けなくても動作します。)
ここでPC側で「Tera Term」を起動すると、会話モードのMicroPython実行ができます。
以下では、リセットを実行させている例です。
>>>
>>> import machine
>>> machine.reset()
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:4200
load:0x40078000,len:15236
load:0x40080400,len:3332
entry 0x400805a8
MicroPython v1.28.0 on 2026-04-06; Generic ESP32 module with ESP32
Type "help()" for more information.
>>>
続けて「Tera Term」を終了し、pipでインストールしたampyの確認例を示します。
ampy:Adafruit MicroPython Tool はコマンドプロンプトでファイル操作ができます。
R:\drone>ampy -p COM3 -b 115200 ls
/boot.py
R:\drone>ampy -p COM3 -b 115200 get boot.py
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()
R:\drone>
上記では、lsオプションでESP32側のファイルリストを確認にて、boot.pyの存在を確認しています。
そして、getオプションでboot.pyの内容を表示しています。使用したa,pyのバージョンは 1.1.0です。
ampy はかつての定番ツールでしたが、現在は開発がほぼ止まっています。
対して近年(2026年)の標準ツールは mpremote 「MicroPython Remote Control(マイクロパイソン・リモート・コントロール)」になっています。
これもpipでインストールでき、下記は1.25.0バージョンのを使ったmpremoteの実行例です。
R:\drone>mpremote connect COM3 fs ls
ls :
139 boot.py
R:\drone>mpremote connect COM3 fs rm :boot.py
rm :boot.py
R:\drone>mpremote connect COM3 reset
R:\drone>mpremote connect COM3 run serverall.py
上記では、ESP32内のファイルリストを確認し、次にそのファイルを削除しています。
(ESP32内のファイルを指定する場合、「:」のファイル名の前に付けます。)
そして、リセット操作後に、PC上のファイルserverall.pyをESP32内で一時実行させています。
serverall.pyのファイルは後述するファイルで、内部でループなどあり、プログラムを終了しないと、プロンプトに戻りません。
boot.pyファイルが起動用に使われるファイルですが、
while True: などの無限ループが書かれていたり、重い初期化処理が走っていたりすると、
マイコンの制御権(REPL)を mpremote が奪えずにコマンドがタイムアウト、または拒否される場合があります。
ESP32-WROOM-32E-N16をWifiのアクセスポイントにして、USBでは電源供給だけにして遠隔操作する。
ESP32に「自身をアクセスポイントにし、ESP32を遠隔操作用TCPサーバーとして働く」機能のファイルをboot.pyで記憶して置きます。
(ESP32のルートにboot.pyのファイルがあると、起動時にそれを実行します。)
操作対象のPC側で、対応するクライアント用を起動して、このサーバーに接続して、遠隔用もデータをこのサーバーに送信して遠隔操作します。
「自身をアクセスポイントにし、ESP32を遠隔操作用サーバーTCPサーバーとして働く」機能の次の内容ファイルをserverall.pyの名前で作成します。
import network
ap = network.WLAN(network.AP_IF) # create access-point interface
ap.config(essid='ESP32E00-AP') # set the ESSID of the access point
ap.config(max_clients=10) # set how many clients can connect to the network
ap.ifconfig(('192.168.130.1', '255.255.255.0', '192.168.130.1', '8.8.8.8'))
# set (ip address, subnet mast, default gateway, dns ip address)
ap.active(True) # activate the interface
import ubinascii
b=ap.config('mac')
#print("mac address:", ubinascii.hexlify(b))
conf=ap.ifconfig() # get various interface addresses
#print("IP,netmask,gw,DNS:", conf)
# ------------------------------------------------------------------------------
import os # server
import sys
import socket
import _thread
import time
#import esp
path_datas = "./"
flag_listen_loop=True
sock2=None # TCPクライアントと通信するソケット
def tcp_send_message(sock,msg): # sockのクライアント側にメッセージ送信
bin=('M'+msg+"\r\n").encode("utf-8")
if sock : sock.sendall(bin)
def send(msg):# sock2のクライアント側にメッセージ送信
msg=f"{msg}" # 文字列へ変換
if sock2 is None: return
a=msg.split("\n")
for s in a:
tcp_send_message(sock2,s)
def ls_filelist(sock,path): # ファイルリストの文字列をクライアントに送信
tcp_send_message(sock,"ls_filelist:" + path)
if path == "": path="."
try:
for f_name in os.listdir(path) :
file_info = os.stat(f_name)
file_size = file_info[6]
d_inf = 'dir' if (file_info[0] & 0x4000 ) else ' ' # ディレクトリ判定
msg = f"{d_inf} {file_size:7} {f_name}"
tcp_send_message(sock, msg)
except Exception as e:
tcp_send_message(sock,"ls_filelist Error:" + str(e))
def cat_filepath(sock, filepath): # filepathのテキスト内容をクライアントに送信
tcp_send_message(sock, "cat_filepath:" + filepath)
try:
with open(filepath) as fr:
ss = fr.readlines()
for s in ss:
if s[-1] == '\n' : s=s[:-1] # 改行を除く
tcp_send_message(sock, s)
except Exception as e:
tcp_send_message(sock,"cat_filepath Error:"+ str(e))
def del_filepath(sock, filepath): # filepathのファイルを削除
tcp_send_message(sock, "del_filepath:" + filepath)
try:
os.remove(filepath)
except Exception as e:
tcp_send_message(sock,"del_filepath Error:"+ str(e))
def import_name(sock, name):# nameのモジュールのPythonソースを実行
tcp_send_message(sock, "import_name:" + name)
try:
mod=__import__(name) # 動的なインポートで実行
del sys.modules[name] # 再度インポートできるように開放
except Exception as e:
tcp_send_message(sock,"import_name Error:"+ str(e))
def send_file(sock, filepath):# filepathのファイルをクライアントに送信
try:
idx_last_sep = filepath.rfind('\\')
filename = filepath if idx_last_sep == -1 else filepath[idx_last_sep+1:]
file_info = os.stat(filepath)
filesize = file_info[6]
s = "f{} {}".format(filename, filesize)
bin=(s+"\r\n").encode("utf-8")
sock.sendall(bin) #send filename filesize
if filesize > 0:
with open(filepath, "rb") as f:
bin = f.read(filesize)
sock.sendall(bin) # send binary file
#
tcp_send_message(sock,"server:send_file:"+ filepath)
except Exception as e:
tcp_send_message(sock,"server:send_file Error:"+ str(e))
def recieve_file(sock):# TCPでファイルを受信(1byte受信の繰り返し)
buf=b""
while True:
bin = sock.recv(1)
if bin == b'': break
buf += bin
if buf[-2:] == b"\r\n":
s = buf[0:-2].decode('utf-8')
a=s.split(' ')
filename, filesize = a[0], int(a[1])
f=open( path_datas + filename, "wb") # 受信ファイルの保存
n=0
tcp_send_message(sock,f"Starting to receive {filename}:size={filesize} Please wait.")
while n < filesize:
bin = sock.recv(1)
if bin == b'': break
f.write(bin)
n += 1
if n % 10000 == 0: tcp_send_message(sock,f"\n{n}bytes were received.")
#
f.close()
tcp_send_message(sock,f"\n{filename} size:{filesize}, {n}bytes receive end.")
if filename.endswith(".umh"):
send_cmdfile(sock,filename) # ファイルのコマンド内容をUMEHOSHI ITAへ送信
break
#
#print(filename + ":size=" + str(filesize)) # debug ---------------
def recieve_file_Max(sock):# TCPでファイルを受信(バッファを最大して受信)
buf=b""
while True:
bin = sock.recv(1)
if len(bin) != 1: break
buf += bin
if buf[-2:] == b"\r\n":
s = buf[0:-2].decode('utf-8')
a=s.split(' ')
filename, filesize = a[0], int(a[1])
bin=b""
while len(bin) < filesize:
bin += sock.recv(filesize-len(bin))
with open( path_datas + filename, "wb") as f: # 受信ファイルの保存
f.write(bin)
tcp_send_message(sock,f"Server:'{filename}' {len(bin)}bytes received.")
if filename.endswith(".umh"):
send_cmdfile(sock,filename) # ファイルのコマンド内容をUMEHOSHI ITAへ送信
break
#
#print(filename + ":size=" + str(filesize)) # debug ---------------
def recieve_message(sock): # 受信メッセージに対する処理
global flag_listen_loop
buf=b""
while True:
bin = sock.recv(1)
if len(bin) != 1:
flag_listen_loop = False
return False
#
buf += bin
if buf[-2:] == b"\r\n":
s = buf[0:-2].decode('utf-8').strip()
if s == "end_listen_loop": # 受信文字列がこれと一致するなら終了
flag_listen_loop = False
return False
#
if s.startswith("ls -l"): # ファイルリスト要求に対する送信処理
ls_filelist(sock, s[5:].strip() )
return True
#
if s.startswith("cat "):# ファイル内容表示要求に対する送信処理
cat_filepath(sock, s[4:] )
return True
#
if s.startswith("del "):# ファイル削除要求に対する処理
del_filepath(sock, s[4:] )
return True
#
if s.startswith("import "):# Pythonファイルの実行要求に対する処理
import_name(sock, s[7:] )
return True
#
if s.startswith("get "): # ファイル要求に対するファイル送信
send_file(sock, s[4:] )
return True
#
if s.startswith("exc "): # .umhファイルの内容で、[UMEHOSHI ITA]のUART1に出力する。
send_cmdfile(sock, s[4:] )
return True
#
if len(s)>1 and s[0] in "SRG":
print( s ) # 受信文字列を、UME専用Hexコマンドと判断して、UMEHOSHI ITAへ送信
else:
tcp_send_message(sock,s) # 受信文字列を、TCPクライアントへECHO送信
#
return True
def receiveData(sock): # 受信処理ループ
# tcp_send_message(sock,"start sever receiveData" )
while True:
bin = sock.recv(1)#1byte recieve
if len(bin) != 1: break
if bin == b"f" : recieve_file(sock)
elif bin == b"F" : recieve_file_Max(sock)
elif bin == b"M" : recieve_message(sock)
else:
tcp_send_message(sock,"server receive error:" + str(bin) )
#
# ------------- UART -------------------
flag_input_loop=False
log_fw=open( "log.txt", "a") # TCP通信ができない時のesp32への入力状態を記録するログ
#
def input_loop(): # UMEHOSHI ITA のUART1出力を読み取ってTCPクライアントに送信するループ
global flag_input_loop
try:
flag_input_loop = True
s=""
while flag_input_loop:
c = sys.stdin.read(1) # ESP32の出力を受信
s += c
if c != '\n': continue
if sock2 is None:
log_fw.write(s)
time.sleep(0.1)
s=""
continue
s = s[:-1:] # 最後の改行を除く
if s.strip() != '' : # Response message from ume received by esp32
tcp_send_message(sock2, s + ":Response")
#
time.sleep(0.001)
if s == "end_input_loop": break
s=""
#
tcp_send_message(sock2, "End! input_loop\r\n")
except Exception as e:
# print("Error :" , e) # debug ---------------
tcp_send_message(sock2,"input_loop Error:"+ str(e))
log_fw.write("input_loop Error:"+ str(e) + "\n")
log_fw.close()
# ss のUME専用Hexコマンドを[UMEHOSHI ITA]のUART1に出力する。
def send_cmd( ss, cmdchar="SRG"):# example ss=[S048000800000FFAF000086]
a = ss.split('\n')
for s in a:
s=s.strip()
if s == "" or not s[0] in cmdchar : continue
print( s ) # Command string sent from esp32 to ume
tcp_send_message(sock2, s + ":Command" )
time.sleep(0.1)
# .umhファイルの内容で、[UMEHOSHI ITA]のUART1に出力する。
def send_cmdfile(sock,filepath, cmdchar="SRG"):
try:
with open(filepath , "r", encoding="utf-8") as f:
ss = f.readlines()
if filepath.endswith(".umh") : ss = ss[1:]
ss="".join(ss)
send_cmd( ss, cmdchar) # ss のUME専用Hexコマンドを[UMEHOSHI ITA]のUART1に出力
except Exception as e:
# print("Error :" , e) # debug ---------------
tcp_send_message(sock,"send_cmdfile Error:"+ str(e))
# ------------- Main -------------------
portnumber=59154
ip = "192.168.130.1"
server_addr =(ip, portnumber)
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.bind(server_addr)
time.sleep(3.1) # 3.1秒待機 ([UMEHOSHI ITA]の初期を待つため)
thread_id = _thread.start_new_thread(input_loop, ()) # 入力用スレッド起動
serversock.listen(1) # TCPサーバ受け入れ待機
while flag_listen_loop:
#
sock2, address = serversock.accept() # クライアントの接続許可
serversock.close()
tcp_send_message(sock2, "\nConnect!") # TCPクライアントへのメッセージ
try:
receiveData( sock2 ) # 受信応答処理のループ
except: pass
sock2.close()
そしてPC側で上記のserverall.pyファイルを、ESP32内にboot.pyの名前でコピーします。それを次のコマンド操作です。
(SW1(赤)リセットと、
SW2(白)を押して、SW1(赤)だけ離した後に3秒待ってLEDが消えた後に、SW2(白)スイッチを離したスルーモードで行います)
R:\drone>mpremote connect COM3 fs cp serverall.py :boot.py
cp serverall.py :boot.py
R:\drone>
以上で、電源を供給すれば(起動時にGPIO0をLowにしない条件あり)、boot.pyの「自身をアクセスポイントにし、
ESP32を遠隔操作用TCPサーバー」が起動します。
このサーバー内には受信スレッドや接続許可ループがあり、このプログラムが終了するまではmpremoteによるファイル操作ができません。
それで、遠隔操作でこのサーバー終了させるコマンド("end_listen_loop"のメッセージ文字列)を用意しています。
後述しているclient_ume_esp32.pyでは、このメッセージ文字列で終了操作ができるように作っています。
Wifiの遠隔操作の起動とクライアント側操作
PCとUMEHOSHI ITAをUSBケーブルで接続し、
SW1(赤)リセットと、
SW2(白)を押して、
SW1(赤)だけ離した後にLEDが消えたて再び点灯した後に、SW2(白)のスイッチを離します。
(SW1(赤)だけ離したに約4秒ほどSW2(白)を押します。)
これでUMEHOSHI ITAはUART1コマンドモードになります。
これを実現するため、[UMEHOSHI IT] 基板のテスト用プログラム(「テスト・ウメ・フラッシュ」)の例外として、
以下の変更が必要でした。
- my_sys.cのvoid core_timer_sub_1()関数定義内のif(core_once_count4_val==1 && _RB7 == 0){のUART1コマンドモード指定で、
下記ように対応する2行をコメント化する。
// U1MODEbits.RTSMD = 0; // UxRTS ピンモード選択をフロー制御モード
// U1MODEbits.UEN = 2;//UxTX、UxRX、UxCTS、UxRTS ピンを有効にして使う
代わりに、次の2行を使う。
U1MODEbits.RTSMD = 1; // UxRTS ピンモード選択を片方向モード(フロー制御しない).
U1MODEbits.UEN = 0; //UxTX、UxRXをピンを有効, UxCTS、UxRTSはPORTxレジスタで指定
- my_uart.cのvoid uart_cmd_mode_polling() 関数内で、次のように対応行をコメント化する。
//if (_reply_boot_message() == 0) return; これで最初の1byte読み取りミスを無くす。
上記で示した遠隔操作用TCPサーバーのソースがESP32で動いていれば、
PC側で'ESP32E00-AP'のからWifiアクセスポイント(パスフレーズ無し)に接続できるはずです。
'ESP32E00-AP'のアクセスポイントに接続できれば、"192.168.130.0"のネットワークに属したことになります。
この時、ESP32は192.168.130.1のIPアドレスになっています。
そして、59154のポート番号で、次のクライアントプログラムを接続して制御できます。
import os # client_ume_esp32.py
import socket
import sys
import time
import threading
path_datas="./"
# ----- 受信関連 ---------------------------------
def recieve_file(sock):
buf=b""
while True:
bin = sock.recv(1)
if len(bin) != 1: break
buf += bin
if buf[-2:] == b"\r\n":
s = buf[0:-2].decode('utf-8')
a=s.split(' ')
filename, filesize = a[0], int(a[1])
bin=b""
while len(bin) < filesize:
bin += sock.recv(filesize-len(bin))
with open( path_datas + filename, "wb") as f:
f.write(bin)
#tcp_send_message(sock,filename + ":size=" + str(len(bin)))
break
print(filename + ":size=" + str(filesize)) # debug ---------------
def recieve_message(sock): # TCP文字列メッセージ受信
buf=b""
while True:
bin = sock.recv(1)#1byte受信
if len(bin) != 1: break
buf += bin
if buf[-2:] == b"\r\n":# 1行の文字列受信終了?
s = buf[0:-2].decode('utf-8')#バイナリから
print(s)
break
def receiveData(sock): # 全てのTCP受信のスレッド用関数
#print( "start receiveData" )
while True:
bin = sock.recv(1)#1byte受信
if len(bin) != 1: break
if bin == b"f" : recieve_file(sock)
elif bin == b"M" : recieve_message(sock)
else: print(bin , end="")
#
print( "receiveData ended." )
# ----- 送信関連 ---------------------------------
def send_file(sock, filepath):
try:
filesize = os.path.getsize(filepath)
filename = os.path.basename(filepath)
s = "f{} {}".format(filename, filesize)
bin=(s+"\r\n").encode("utf-8")#binaryへ変換
# print(bin, end=" ")
sock.sendall(bin) #filename filesize 送信
with open(filepath, "rb") as f:
bin = f.read(filesize)
# print("送信data:" , bin )
sock.sendall(bin) # ファイル内容一括送信
print("送信byte:" , len(bin) )
except Exception as e:
print( "send_file error:" + str(e))
def send_file_Max(sock, filepath):
try:
filesize = os.path.getsize(filepath)
filename = os.path.basename(filepath)
s = "F{} {}".format(filename, filesize)
bin=(s+"\r\n").encode("utf-8")#binaryへ変換
# print(bin, end=" ")
sock.sendall(bin) #filename filesize 送信
with open(filepath, "rb") as f:
bin = f.read(filesize)
# print("送信data:" , bin )
sock.sendall(bin) # ファイル内容一括送信
#print("送信byte:" , len(bin) )
except Exception as e:
print( "send_file_Max error:" + str(e))
def send_message(sock,msg):
bin=('M'+msg+"\r\n").encode("utf-8")#binaryへ変換
sock.sendall(bin)#一括送信
print(f"Send:{msg}")
# ----- メイン ---------------------------------
portnumber=59154
ip="192.168.130.1"
s = input(f"IP (defualt:{ip})Address>")
if s != "": ip = s
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, portnumber))
#print("接続成功")
t_id = threading.Thread(target=receiveData, args=(sock,) )
t_id.start()
time.sleep(1.0)
loopFlag = True
cmd=""
while loopFlag:
s = input("入力:M/F/'quit'/?>")
if s != "": cmd = s
if cmd == 'M':
msg = input("UME HEX Command /exc /ls -l/cat /get /del /import >")
send_message(sock,msg)
cmd=' '
elif cmd == 'f' or cmd == 'F':
s='F'
print(os.listdir(path_datas))
filename = input("送信したいファイル名入力>")
if not os.path.isfile(path_datas + "/" + filename):
print( filename, "no exist")
continue
if cmd == 'f' : send_file(sock, path_datas + "/" + filename)
if cmd == 'F' : send_file_Max(sock, path_datas + "/" + filename)
cmd=' '
elif cmd == 'quit':
send_message(sock,'end_listen_loop')
loopFlag=False
else:
pass
#
time.sleep(1.0)
sock.close()
sys.exit(0)
上記ソースを、client_ume_esp32.pyの名前で作成したファイルがある場合、例えば次のように実行できます。
R:\drone>python client_ume_esp32.py
IP (defualt:192.168.130.1)Address>
Connect!
入力:M/F/'quit'/?>M
UME HEX Command /exc /ls -l/cat /get /del /import >ls -l
Send:ls -l
ls_filelist:
11211 boot.py
36 log.txt
1427 test01.umh
23 test02.umh
入力:M/F/'quit'/?>
上記で最初のプロンプト入力:M/F/'quit'/?>で、
Mの入力でESP32内のファイル操作メッセージ入力モードへ進む、Fの入力でESP32へのファイル送信、quit入力でサーバー終了を選択します。
上記ではMを入力して、UME HEX Command /exc /ls -l/cat /get /del /import >のプロンプトへ進めている。
ここでは以下の入力が可能で、上記ではディレクトリー表示させている例です。
- .umhファイル実行
- ディレクトリー表示
- ファイル内容表示
- ファイルのダウンロード
- ファイル削除
- pythonモジュール実行