ESP32のUDP通信のベンチマーク
- 試験環境
- 試験内容(ソースコードは記事巻末参照。前回SPP通信同様手順とした)
- 通信手順
- ASCIIコードを用い、LFで送受信における完了トリガーとする。
- 通信サイクル
- ラズパイよりデータを送信し、ESP32が受信データと同一データを送信。
- ラズパイ上で送受信データの一致確認をもってサイクル完了とした。
- 測定方法
- PC側でtime関数を使用し、上記サイクル時間を計測。
- 1サイクル内の各種オーバーヘッドは含む。但しloopのオーバーヘッドは除く。
- シリアルポートopen後の初回通信は評価対象としない。(時間が長い為)
- 通信レートは1000サイクルにおける1サイクル平均値にて算出
- 通信手順
- 試験結果
- 各送受信データ量における、N=1000の試験結果を示す。
- 表1:試験結果概要
- 各転送データ量における通信時間の分布は以下の通り。
- 図1:1~10byte時の分布
- 図2:10~100byte時の分布
- 図3:100~500byte時の分布
- 図4:500~900byte時の分布
- 各送受信データ量における、N=1000の試験結果を示す。
表1:試験結果一覧
送受信データ(byte) | 通信時間AVE(s) | 通信時間MAX(s) | 通信時間MIN(s) | 通信時間3σ(s) | 通信時間6σ(s) | 実効通信レート(bps) |
---|---|---|---|---|---|---|
1 | 0.006728 | 0.037318 | 0.002986 | 0.011635 | 0.02327 | 2378 |
2 | 0.006747 | 0.036077 | 0.002707 | 0.011704 | 0.023407 | 4743 |
3 | 0.006944 | 0.050978 | 0.002646 | 0.012661 | 0.025323 | 6912 |
4 | 0.00681 | 0.035284 | 0.002574 | 0.011763 | 0.023526 | 9398 |
5 | 0.007037 | 0.029986 | 0.002837 | 0.012069 | 0.024138 | 11368 |
10 | 0.006832 | 0.030259 | 0.002804 | 0.011145 | 0.022291 | 23419 |
20 | 0.006815 | 0.039036 | 0.00283 | 0.011928 | 0.023855 | 46955 |
30 | 0.00695 | 0.039083 | 0.002977 | 0.010938 | 0.021876 | 69065 |
40 | 0.00701 | 0.031827 | 0.002954 | 0.0109 | 0.0218 | 91298 |
50 | 0.006951 | 0.034668 | 0.002869 | 0.011069 | 0.022138 | 115091 |
100 | 0.007374 | 0.037092 | 0.003061 | 0.012287 | 0.024574 | 216979 |
150 | 0.007757 | 0.043328 | 0.003128 | 0.013567 | 0.027133 | 309398 |
200 | 0.007795 | 0.037367 | 0.00368 | 0.01239 | 0.024781 | 410520 |
250 | 0.007967 | 0.030451 | 0.00363 | 0.011485 | 0.02297 | 502071 |
300 | 0.008077 | 0.043682 | 0.004004 | 0.01274 | 0.025481 | 594280 |
350 | 0.008221 | 0.038176 | 0.00398 | 0.012072 | 0.024143 | 681182 |
400 | 0.008623 | 0.041072 | 0.004008 | 0.012782 | 0.025565 | 742201 |
450 | 0.009021 | 0.063308 | 0.00419 | 0.014533 | 0.029065 | 798138 |
500 | 0.009058 | 0.040857 | 0.004214 | 0.013759 | 0.027518 | 883197 |
600 | 0.009419 | 0.038899 | 0.004465 | 0.01333 | 0.026661 | 1019216 |
700 | 0.010279 | 0.083165 | 0.004678 | 0.017752 | 0.035503 | 1089600 |
800 | 0.011781 | 0.080902 | 0.004999 | 0.022093 | 0.044186 | 1086495 |
900 | 0.011107 | 0.061182 | 0.005582 | 0.018299 | 0.036598 | 1296480 |
- 考察
- 通信時間のバラつき
- 綺麗な1山で正規分布
- 通信自体のオーバーヘッド(1byte送信時)
- ワースト29.7.3ms(ave:6.7ms 6σ:23ms) 但し、頻度としては10ms以内が多い。
- ESP32高温時の動作異常について(温度はtemperatureRead()関数で観測)
- CPU温度が49℃を超えた際に以下現象が発生した。ESP32側はパケット送信を実施しているが、クライアント側が受信できない。この時CPUはフリーズやシャットダウンは起きていない。クライアント側からのパケット受信はできている。温度が下がれば動作は再度安定する。
- ESP32のSoftAPモードについて
- 上記高温時の不具合内容が、温度との依存関係なく頻発した。電圧ドロップ等も確認したが、3.3~3.4Vは維持出来ており、原因は不明。
- 通信時間のバラつき
- 結論
- 制御指令に対する遅延:1指令が100byte以内であれば、ワースト32ms
- 通信速度:1Mbps以上出る
- ESP32ソース
void wifi_info(){ uint8_t wifiMac[6]; esp_read_mac(wifiMac, ESP_MAC_WIFI_STA); char wifiMacChar[18] = {0}; sprintf(wifiMacChar,"%02X:%02X:%02X:%02X:%02X:%02X", wifiMac[0],wifiMac[1],wifiMac[2],wifiMac[3],wifiMac[4],wifiMac[5]); Serial.printf("MAC:%s\n",wifiMacChar); Serial.print("ip:"); Serial.println(WiFi.localIP()); Serial.print("subnet:"); Serial.println(WiFi.subnetMask()); Serial.printf("wifiTxPower:%d\n",WiFi.getTxPower()); } void wifiNonAP_setup(){ const char ssid[]= "ssid"; const char pass[]= "sspass"; WiFi.begin(ssid,pass); while (WiFi.status() != WL_CONNECTED);{ delay(500); Serial.println("wifi_connect_ok"); } void udp_setup(){ const int localport = 10000; WiFi.setTxPower(WIFI_POWER_19_5dBm); wifiNonAP_setup(); esp_wifi_set_ps(WIFI_PS_NONE); wifi_info(); udp.begin(localport); } void setup() { Serial.begin(115200); Serial.printf("cpuFreq(Mhz):%d\n",ets_get_cpu_frequency()); Serial.printf("cputemp:%f\n",temperatureRead()); udp_setup(); Serial.println("bootUpFin"); } void loop() { const char *remoteIp = "xxx.xxx.xxx.xxx"; const int remoteUdpPort = 10001; String btRxBuff; String udpRxBuff; while(true){ if (udp.parsePacket()){ udpRxBuff = udp.readStringUntil('\n'); udp.beginPacket(remoteIp, remoteUdpPort); udp.print(udpRxBuff + '\n'); udp.endPacket(); } } }
- ラズパイ
import time import socket import csv serv_ip = ("xxx.xxx.xxx.xxx", 10000) local_ip = ("xxx.xxx.xxx.xxx", 10001) tx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) rx_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) rx_sock.bind(local_ip) def udp_tx(tx_data="", chk=1): tx_data = tx_data + '\n' tx_data_b = tx_data.encode('utf-8') tx_sock.sendto(tx_data_b, serv_ip) if chk == 1: rx_data_b, add = rx_sock.recvfrom(1024) rx_data = rx_data_b.decode('utf-8') if tx_data_b == rx_data_b: return True else: print('err') return None else: return True def udp_benchmark(loop=10, byte=1): result_ls = [byte] data = 0 send_data = "" for n in range(byte): send_data += str(data) data += 1 if data >= 9: data = 0 tx_result = udp_tx(tx_data=send_data) for n in range(loop): start = time.time() tx_result = udp_tx(tx_data=send_data) ct = time.time() - start if tx_result is None: result_ls.append(-1) else: result_ls.append(round(ct, 6)) return result_ls for n in [1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 600, 700, 800, 900, 1000]: result_ls = udp_benchmark(loop=1000, byte=n) print(result_ls) with open('udp_benchmark_pc.csv', 'a', newline='') as f: writer = csv.writer(f) writer.writerow(result_ls) f.close() tx_sock.close() rx_sock.close()