ESP32にSPI to Ethernet モジュール USR-ES1を接続した話

ESP32 + USR-ES1から同一LAN内のPCにTCPでデータ転送を行ったとき、どれくらいの性能が出るのかを調べるのに使ったプログラムやスケッチと、測定時の画面コピーなどを掲載した。ブログとしての本文はこちら。USR-ES1(W5500)のコントロールには、Arduino IDEで容易にインストールできるEthernet2ライブラリをそのまま使っている。

本文側にも書いたが、有線LANで接続する際には送信側と受信側は同じスイッチングハブ(1000BASE-T) に接続している。受信(TCPのaccept() )側は、同じWindows 7 のノートPCを使っていて tcp/8888 でlisten() している。

Windows用プログラム

Windowsでは送信側と受信側双方とも同じプログラムを使う。以下のソースをVisual Studio 2017 (Community版)を使ってビルドした。再現する際には、WIN32コンソールアプリケーションとしてプロジェクトを新規作成し、好みの名前でC++ソースを新規追加して以下を貼り付けて保存すればよいはず。

使い方および動作

Windowsのコマンドプロンプトを開き、実行ファイル名とオプションを指定して実行する。
オプション -B でバッファサイズをバイト単位で、-M で1回ごとの転送バイト数をメガバイト単位で指定する。バッファサイズは256の整数倍(256, 512, 1024, 2048, 4096, …) を指定すること。
オプション文字無しの引数があった場合、送信先IPアドレスとして使う。送信先IPアドレスがあれば送信側、なければ受信側として動作する。

送信側と受信側とでバッファサイズや転送バイト数は同じにしておく。送信側は-Mオプションで指定する転送バイト数の送信を10回繰り返し転送レートの平均値を表示する。受信側は転送バイト数を受信するごとに転送レートを表示し実行を続ける。

送信側の転送バッファには、setup_buffer() によって先頭から順に0から255 までの値が繰り返して格納されており、受信側はバッファサイズ分受信するたびごとにcheck_buffer() によって内容をチェックする。そのとき想定していないバイトが見つかれば、その時点でプログラムを終了する。

例えば実行ファイル名が SockTest.exe、受信側が 192.168.1.100 、バッファサイズ2048バイト、転送バイト数を100(メガバイト)とするときには以下のように実行する。

コマンドの実行やESP32のリセットによって新規に送信を開始するときには、あらかじめ受信側プログラムを起動し直しておく必要がある。受信側を停止するためには、コマンドプロンプトに対してCtrl+C を打ち込む。

WindowsPC – ノートPC間の実行時表示(送信側)

送信側にはWindows 10のデスクトップPCを使った。

転送レートは毎秒106メガバイトといったところだった。毎回の転送レートにばらつきがあるのは、送信側のWindows PCで山のようにプロセスが動いているためと思われる。まあ、1秒間に100メガバイトも転送できていればいいだろう。

ESP32 + USR-ES1用テストスケッチ(有線接続)

ESP32 + USR-ES1の調査には送信側として以下のスケッチを使った。受信側は上と同じWindows用のプログラムを利用。Windows PC間の転送に比べるととても遅くて時間がかかるので、転送バイト数は10メガバイトとした。

Ethernet.init(SPI_SS); によりスレーブセレクトにSPI_SS ( == 5) を使っていることを教えている。GPIO10を使うならば省略可能なのだが、ESP-WROOM-32ではGPIO10は内蔵フラッシュに接続されているので使えない。

Ethernet2ライブラリに含まれている EthernetClientクラスの write() メソッドを使って送信バッファの内容を送り出しているが、このメソッドに対してW5500の送信バッファの最大値(2048バイト)を超えるバイト数を指定した場合、先頭の2048バイトしか送信されず、実行上はエラーにもならないことに注意が必要だろう。
2048バイト以下の場合、send() の引数として指定したバイト数はすべて送信できますよ、というコードになっているので戻り値の評価はエラーの有無のみとしている。

そのあたりの実装は、Ethernet2ライブラリのutility/socket.cppのsend() を参照。

ESP32 + USR-ES1 – ノートPC間の実行時表示

リセットボタン(EN-SW)を押すとシリアルモニタには以下のように表示された。

転送レートは毎秒0.45メガバイトといったところだった。シリアル通信よりは格段に高速なことは間違いないが、ちょっと物足りないから、ライブラリを書き換えて高速化を試みてみた。それについては本文側で触れている。

ESP32 WiFi使用時のテストスケッチ

参考用にESP32をWIFI_STAとして使った場合の転送レートを得てみた。受信側ノートPCは、WiFiルーターのローカル側ハブと2台のスイッチングハブを介してLANケーブルで接続されている。なお、うちのWiFiルーターは古いので有線側リンク速度は100Mbpsである。

以下のようなスケッチを使った。

いつも書いているような典型的なWIFI_STAスケッチである。

WiFiClientwrite(); の実装では、指定の転送バイト数を10回まわるループ内で送信し終わらなければ、送信できたバイト数を返すようになっている(これが普通だと思うが)。そのため、一度に送信できなかった残りについても考慮している。

ESP32 WiFi-ノートPC間の実行結果

転送レートは毎秒約1.23メガバイトだった。なんか遅い気もするが、USR-ES1での有線接続よりは速かった。