ESP32とラズパイでBluetoothによるSPP通信のベンチマーク
- 目的
- ESP32とラズパイでBluetoothのSPP通信を行った場合遅延と実効通信レートがどの程度になるか調査をする。
- 試験環境
- 試験内容(ソースコードは記事巻末参照)
- 通信手順
- ASCIIコードを用い、LFで送受信における完了トリガーとする。
- 通信サイクル
- ラズパイよりデータを送信し、ESP32が受信データと同一データを送信。
- ラズパイ上で送受信データの一致確認をもってサイクル完了とした。
- 測定方法
- ラズパイ側で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.013288 | 0.071321 | 0.006205 | 0.032500 | 0.065000 | 1204 |
2 | 0.013523 | 0.081167 | 0.006226 | 0.033617 | 0.067233 | 2366 |
3 | 0.013145 | 0.058818 | 0.007148 | 0.032047 | 0.064094 | 3652 |
4 | 0.01379 | 0.063877 | 0.006835 | 0.033823 | 0.067645 | 4641 |
5 | 0.013136 | 0.057554 | 0.006931 | 0.031898 | 0.063795 | 6090 |
10 | 0.013178 | 0.057569 | 0.007301 | 0.031447 | 0.062894 | 12141 |
20 | 0.015249 | 0.065444 | 0.008145 | 0.033261 | 0.066522 | 20985 |
30 | 0.017178 | 0.066215 | 0.008599 | 0.035967 | 0.071934 | 27943 |
40 | 0.017413 | 0.090023 | 0.009469 | 0.035429 | 0.070858 | 36754 |
50 | 0.019243 | 0.08304 | 0.009867 | 0.035136 | 0.070273 | 41574 |
100 | 0.033166 | 0.085077 | 0.014676 | 0.036745 | 0.073490 | 48242 |
150 | 0.036418 | 0.096614 | 0.015962 | 0.032540 | 0.065080 | 65901 |
200 | 0.036001 | 0.082626 | 0.018734 | 0.031361 | 0.062723 | 88886 |
250 | 0.037932 | 0.087403 | 0.022059 | 0.027688 | 0.055376 | 105452 |
300 | 0.039324 | 0.093719 | 0.024318 | 0.025414 | 0.050828 | 122063 |
350 | 0.041409 | 0.076375 | 0.026813 | 0.024264 | 0.048528 | 135236 |
400 | 0.044113 | 0.086197 | 0.028701 | 0.028282 | 0.056563 | 145082 |
450 | 0.057283 | 0.098023 | 0.032105 | 0.038603 | 0.077206 | 125692 |
500 | 0.063707 | 0.110676 | 0.034387 | 0.034159 | 0.068317 | 125575 |
600 | 0.067726 | 0.137092 | 0.040482 | 0.032502 | 0.065004 | 141748 |
700 | 0.075531 | 0.173518 | 0.044626 | 0.033677 | 0.067354 | 148283 |
800 | 0.079246 | 0.128892 | 0.049892 | 0.030826 | 0.061653 | 161522 |
900 | 0.095119 | 0.166947 | 0.056227 | 0.037209 | 0.074418 | 151389 |
- 考察
- 通信時間のバラつき
- 正規分布ではなく、2山になっている。6σでの想定が妥当である。
- 通信自体のオーバーヘッド(1byte送信時)
- ワースト78.3ms(ave:13.3ms 6σ:65ms) 但し、頻度としては10msが多い。
- 通信時間のバラつき
- 結論(一回辺り100byte以内の送受信による制御を想定)
- 制御指令に対する遅延:ワースト106ms
- ESP32ソース
#include <Arduino.h> #include <BluetoothSerial.h> BluetoothSerial SerialBT; String btrx_buff; void spp_setup(){ uint8_t macBT[6]; char btname[11]; esp_read_mac(macBT, ESP_MAC_BT); sprintf(btname, "ESP32-%02X%02X", macBT[4], macBT[5]); if (SerialBT.begin(btname)) { Serial.println("start_spp"); } } void setup() { Serial.begin(115200); spp_setup(); } void loop() { btrx_buff = SerialBT.readStringUntil('\n'); SerialBT.print(btrx_buff + '\n'); //Serial.println(btrx_buff); }
- ラズパイ
import serial import time import csv bt_spp = serial.Serial(port='/dev/rfcomm0', baudrate=115200, timeout=None) def spp_tx(tx_buff=None,chk=1): tx_buff = tx_buff + '\n' tx_buff_b = tx_buff.encode('utf-8') bt_spp.write(tx_buff_b) if chk == 1: rx_data_b = bt_spp.readline() rx_data = rx_data_b.decode('utf-8') if tx_buff == rx_data: return True else: return None elif chk == 2: rx_data_b = bt_spp.readline() rx_data = rx_data_b.decode('utf-8') if rx_data == '\n': return True else: return None else: return True def spp_benchimark(loop=10,byte=1): ct = 0 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 = spp_tx(tx_buff=send_data) for n in range(loop): start = time.time() tx_result = spp_tx(tx_buff=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]: result_ls = spp_benchimark(loop=1000,byte=n) with open('data.csv','a') as f: writer = csv.writer(f) writer.writerow(result_ls) bt_spp.close()