だいぶ一般的になっているBLEについて。すごく概念的なことはあちこちに書いてある。が、下から上まで(むしろ下だけ)知りたいのに、資料少なすぎ。なので自力で調べる無茶な挑戦。第7回=(続)デバイス名称の取得について
もうよくわからんので、Seeed XIAO BLE nRF52840からではなく、Adalm-plutoからアドバタイズを撃ってみて、そしてSCAN_REQを取れないかどうか試してみる。これの何がいいかって、ADV_INDのチャンネルを固定してしまうので、SCAN_REQも固定されるってこと。
いつも通りいきなりな感じで、
-
import matplotlib.pyplot as plt -
import numpy as np -
import scipy.signal as signal -
import adi -
# import time -
-
# https://jp.mathworks.com/help/signal/examples/fir-gaussian-pulse-shaping-filter-design.html -
def gaussdesign(bt,nsymbol_in_filter=3,nsample_per_symbol=2): -
t_normalized=np.linspace(-nsymbol_in_filter/2,nsymbol_in_filter/2,nsymbol_in_filter*nsample_per_symbol+1) -
a=np.sqrt(np.log(2)/2)/bt -
expindex=-(np.pi*t_normalized/a)**2 -
h=np.sqrt(np.pi/a)*np.exp(expindex) -
h=h/np.sum(h) -
return h -
-
# シンボル列を引き延ばす -
def extend_symbol_to_simulation_sampling_rate(symbols,t_symbol,t_simulation_sampling): -
# シンボル数 -
size_of_symbols=symbols.size -
# 最後のシンボルが終わる時間 -
end_time=size_of_symbols*t_symbol -
# 計算タイミング -
t=np.arange(0,end_time,t_simulation_sampling) -
# 各シンボルの開始(終了)時間 -
t_periods_of_symbols=np.append(0,np.arange(1,size_of_symbols,1)*t_symbol) -
# 結果データ領域確保 -
ex_symbols=np.zeros_like(t) -
# 先頭データは入れておく -
ex_symbols[0]=symbols[0] -
# 各シンボルについて、その期間のインデックスを取得し、データを入れ込む -
for i in range(0,size_of_symbols): -
ex_symbols[np.where(t>t_periods_of_symbols[i])]=symbols[i] -
return ex_symbols,end_time -
-
# よく使う変数 -
pi=np.pi -
deg2rad=pi/180.0 -
twopi=2*pi -
-
# 設定 -
f_carrier=2402e6 # 搬送波周波数 in Hz -
f_sym=1e6 # シンボルレート in Hz -
m=0.5 # 変調指数 -
f_samp_simulation=f_sym*8 # 計算のサンプリングレート in Hz -
thetaIB=0*deg2rad # 搬送波の初期位相(何でもいい) in rad -
f_deviation=(m*f_sym)/2 # 周波数偏差 in Hz -
n_symbol_preamble=16 -
-
# ガウスフィルタ設定 -
n_sample_per_symbol=f_samp_simulation/f_sym -
BT=0.5 -
n_symbol_in_filter=float(6) -
filter_length=n_symbol_in_filter*n_sample_per_symbol+1 -
h=gaussdesign(BT,int(n_symbol_in_filter),int(n_sample_per_symbol)) -
symbols_gf_in_base=np.zeros(int(np.ceil(n_symbol_in_filter/2))) -
-
# シンボル列生成 -
symbols_in_base=np.array([0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1,1,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,1,1,0,0,1,1,1,0,1,0,0,0,0,1,0,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,1,0,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,0,1,0,1,0,0,0,0,1,0,1,1,1,1,0,0,1,1,1,0,1,1,1,0,0,1,1,1,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,0,0,1,0,1,0,0,1,1,0,1,1,1,1,1,1,0,1,0,1,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,1,1,1,1,0,0,0,1,1,1,1,0,1,1,1,0,0,1,1,0,1,1,1,1,0,1,0,0,0,1,0,0,0,1,1,1,1,0,0,1,1,1,0,0,1,0,1,0,0,1,0,1,0,1,0,0,0,0,0,1,1,1,1,1,0,1,1,0,1,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,1,1,0,1,0,1,1,0,0,1,0,0,0,0,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0]) -
symbols_in_base=symbols_in_base*(2)-1 # -1 or +1 にする -
-
# 後で使う変数 -
t_sym=1/f_sym -
t_samp_simulation=1/f_samp_simulation -
omega_deviation=twopi*f_deviation -
-
# シンボルを計算用に拡張 -
symbols,t_end=extend_symbol_to_simulation_sampling_rate(symbols_in_base,t_sym,t_samp_simulation) -
-
# ガウスフィルタ設定 -
n_sample_per_symbol=f_samp_simulation/f_sym -
BT=0.5 -
n_symbol_in_filter=float(6) -
filter_length=n_symbol_in_filter*n_sample_per_symbol+1 -
h=gaussdesign(BT,int(n_symbol_in_filter),int(n_sample_per_symbol)) -
symbols_gf_in_base=np.zeros(int(np.ceil(n_symbol_in_filter/2))) -
symbols_gf_in_base=symbols_gf_in_base*(2)-1 # -1 or +1 にする -
-
symbols_gf,t_end_gf=extend_symbol_to_simulation_sampling_rate(symbols_gf_in_base,t_sym,t_samp_simulation) -
-
# ガウスフィルタ適用 -
symbols_gf=signal.lfilter(h,1,np.append(symbols,symbols_gf)) -
symbols=symbols_gf[symbols_gf.size-symbols.size::1] -
-
# 計算するタイミング -
t=np.arange(0,t_end,t_samp_simulation) -
-
# 全計算タイミングにおける瞬間的な角速度 -
omega_in_moment=omega_deviation*symbols -
-
# 全計算タイミングにおける瞬間的な位相変化量 -
phase_change_in_moment=omega_in_moment*t_samp_simulation -
-
# 全計算タイミングでの位相 -
phiIB_t=np.cumsum(phase_change_in_moment)+thetaIB -
-
# 送信波形生成 -
xITX_t=np.exp(1j*phiIB_t) -
xITX_t=np.append(xITX_t,np.zeros(600000)) -
-
n_samples_rx=xITX_t.size*4 -
-
# ADALM-PLUTOの設定 -
sdr = adi.Pluto("ip:192.168.2.1") -
sdr.tx_lo=int(f_carrier) -
sdr.tx_rf_bandwidth=int(f_deviation*8) -
sdr.tx_hardwaregain_chan0=0 -
# 繰り返し送信を有効にする -
sdr.tx_cyclic_buffer=1 -
-
sdr.rx_lo=int(f_carrier) -
sdr.rx_rf_bandwidth=int(f_deviation*8) -
sdr.gain_control_mode_chan0='manual' -
sdr.rx_hardwaregain_chan0=6 -
sdr.rx_buffer_size=n_samples_rx -
-
sdr.sample_rate=int(f_samp_simulation) -
-
sdr.tx(xITX_t*16384) -
# 受信 -
xIRX_t = sdr.rx() -
print(sdr) -
-
#sdr.tx_destroy_buffer() -
#sdr.tx_cyclic_buffer=0 -
## オブジェクト解放 -
#sdr=None -
-
# 復調 -
xIRX_t0=xIRX_t[:-1:] -
xIRX_t1=xIRX_t[1::] -
symbols_rx=1*np.angle(xIRX_t1/xIRX_t0) -
symbols_rx=np.append(0,symbols_rx) -
-
# 規格化 -
symbols_rx=symbols_rx/(f_sym/f_samp_simulation*pi*m) -
-
# プロット -
fig = plt.figure(figsize=(8.0, 8.0)) -
plt.subplot(4,1,1) -
plt.plot(xITX_t.real) -
plt.plot(xITX_t.imag) -
plt.subplot(4,1,2) -
plt.plot(symbols) -
plt.subplot(4,1,3) -
plt.plot(xIRX_t.real) -
plt.plot(xIRX_t.imag) -
plt.subplot(4,1,4) -
plt.plot(symbols_rx) -
plt.show() -
-
sdr.tx_destroy_buffer() -
sdr.tx_cyclic_buffer=0 -
# オブジェクト解放 -
sdr=None -
np.save('o_t',t) -
np.save('o_rx_t',xIRX_t)
上2つが送信波形とそれを作ったベースバンドで、下2つが受信波形と復調結果(それらしく見える範囲を拡大している)。
で、
Wiresharkで読み取れたデータがこちら。BeaconになってもらっていたSeeed XIAO BLE nRF52840はUSBケーブルを抜いてあるので、これがAdalm-plutoから送信されたものであるはず。でちゃんと読み取れている。で、スマホでnRF Connectを起動してSCAN状態でやってみると、
拡大してみると、
それらしいのがいる。左(先のタイミング)がAdalm-plutoからのADV_INDで右(後のタイミング)がスマホからのSCAN_REQと思われる。
これがスマホが出しているSCAN_REQっぽい。で、Adalm-pluto波形を解析してみる、、、で、解析するコードに間違いを発見。Preamble+Access Addressをパタン検索する際に、いきなりマッチしてカウント0で戻る場合があるのに、0より大きい場合に見つかったものとしていたorzので修正。ついでに電波を送受するPythonコードで、tについて、Tx側のtを保存してしまっていたので、受信データに合わせて再生成するようにパッチあてした。
-
import numpy as np -
import matplotlib.pyplot as plt -
from scipy import signal -
-
def search_index_by_pattern(data,pattern): -
ds=data.size -
ps=pattern.size -
cyc=ds-ps+1 -
ret=-1 -
if cyc>0: -
for i in range(cyc): -
data_part=data[i:i+ps] -
if np.all(data_part==pattern): -
ret=i -
break -
return ret -
-
f_sym=1e6 # -
rx_all=np.load('o_rx_t.npy') -
t_all=np.load('o_t.npy') -
t_all=t_all-t_all[0] -
t_all_0=t_all[:-1:] -
t_all_1=t_all[1::] -
t_samp=np.mean(t_all_1-t_all_0) -
f_samp=1/t_samp -
print(f_samp/1e6) # should be 8MHz -
t_all=np.linspace(0,t_samp*rx_all.size,rx_all.size) #tの保存がイマイチだったので再生成する -
# フィルター係数生成 -
freq_cutoff=f_sym*2 -
w_cutoff=freq_cutoff/(f_samp/2) -
b,a=signal.butter(1,w_cutoff,'lowpass') -
-
# フィルター適用 -
rx_all=signal.lfilter(b,a,rx_all) -
-
rx_all_amp=np.abs(rx_all) -
rx_all_amp_dig=np.where(rx_all_amp>5,1,0) -
rx_all_amp_dig_0=rx_all_amp_dig[:-1:] -
rx_all_amp_dig_1=rx_all_amp_dig[1::] -
rx_all_amp_dig_10=np.append(rx_all_amp_dig_1-rx_all_amp_dig_0,0) -
rx_all_amp_dig_rising_edge=np.where(rx_all_amp_dig_10>0)[0] -
rx_all_amp_dig_falling_edge=np.where(rx_all_amp_dig_10<0)[0] -
print(rx_all_amp_dig_rising_edge.size) -
print(rx_all_amp_dig_falling_edge.size) -
-
pa_and_aa=np.array([0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,1]) -
pnum=0 -
-
for i in range(rx_all_amp_dig_rising_edge.size): -
if rx_all_amp_dig_falling_edge[i]-rx_all_amp_dig_rising_edge[i]>40: -
rx=rx_all[rx_all_amp_dig_rising_edge[i]:rx_all_amp_dig_falling_edge[i]] -
t=t_all[rx_all_amp_dig_rising_edge[i]:rx_all_amp_dig_falling_edge[i]] -
# demod -
rx_t0=rx[:-1:] -
rx_t1=rx[1::] -
rx_dem=-1*np.angle(rx_t1/rx_t0) -
rx_dem=np.append(0,rx_dem) -
# normalization -
rx_dem=rx_dem/(f_sym/f_samp*np.pi*1) -
# digitization -
rx_dig=np.where(rx_dem>0,0,1) -
# counter top value -
counter_top=8-1 -
counter_half=int(counter_top/2) -
cnt_list=[] -
cnt_list.append(int(0)) -
for i in range(rx_dig.size-1): -
dig_pres=rx_dig[i+1] -
dig_prev=rx_dig[i] -
if (dig_pres!=dig_prev): -
cnt_list.append(int(0)) -
else: -
if (cnt_list[i]<counter_top): -
cnt_list.append(cnt_list[i]+int(1)) -
else: -
cnt_list.append(int(0)) -
cnt=np.array(cnt_list) -
smp_pos=np.where(cnt==counter_half)[0] -
rd_dig_smp=rx_dig[smp_pos] -
fig=plt.figure() -
fig.add_subplot(3,1,1) -
plt.plot(t,np.real(rx)) -
plt.plot(t,np.imag(rx)) -
fig.add_subplot(3,1,2) -
plt.plot(t,rx_dem) -
plt.ylim(-1,1) -
fig.add_subplot(3,1,3) -
plt.plot(rx_dig) -
plt.plot(smp_pos,rd_dig_smp,linestyle='',marker='.') -
plt.ylim(-0.5,1.5) -
fig.tight_layout() -
plt.savefig('pic'+str(pnum)+'.png') -
pnum=pnum+1 -
#plt.show() -
pp_and_aa_pos=search_index_by_pattern(rd_dig_smp,pa_and_aa) -
if(pp_and_aa_pos>=0): #間違ってた -
print("t_start=",end="") -
print(t[0]) -
print("t_end=",end="") -
print(t[-1]) -
print(pp_and_aa_pos) -
rd_dig_smp=rd_dig_smp[pp_and_aa_pos:] -
pos=0 -
while pos<rd_dig_smp.size: -
for n in range(8): -
print(rd_dig_smp[pos],end='') -
pos=pos+1 -
if pos==rd_dig_smp.size: -
break -
print("") -
fig=plt.figure() -
fig.add_subplot(1,1,1) -
plt.plot(t_all,np.real(rx_all)) -
plt.plot(t_all,np.imag(rx_all)) -
plt.show()
6024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E
と、
C30C6EB7A13FEA5BDE30CD58ABDF6458BD
が得られる。
前者はよく見たパタン(Adalm-plutoで送信したやつ)。で、後者の方、
Header : C3 (SCAN_REQ, TxAdd: Random, RxAdd: Random)
PDU Length : 0C (12bytes)
AdvA : 6EB7A13FEA5B (5B:EA:3F:A1:B7:6E)
ScanAdr : DE30CD58ABDF (DF:AB:58:CD:30:DE)
CRC : 6458BD
って読み解ける。Adalm-plutoが出したADV_INDに対してSCAN_REQを出していることがわかる(AdvAがWiresharkのデータと違うのはAdalm-plutoでうまく受信させるために何度もやり直した(スマホのSCANボタンを押した)、で、TxAddがRandomだからだと思う)。
ではnRF52840でやってみる。が、3つのアドバタイズチャンネルをAdalm-plutoで同時に受信できないので、やっぱり固定にしたい。で、
~/.arduino15/packages/Seeeduino/hardware/nrf52/1.1.8/libraries/Bluefruit52Lib/src/BLEAdvertising.cpp
をいじる。349行目にある(バージョンによって違うかも)、
.channel_mask = { 0, 0, 0, 0, 0} , // 40 channel, set 1 to disable
を
.channel_mask = { 0, 0, 0, 0, 0xC0 } , // 40 channel, set 1 to disable
にすれば、Channel37だけになるっぽい。この設定がChannel indexなのかRF channelなのか正直わからんのだけど、どうやらChannel indexなんやないかな?知らんけど。Wiresharkによると、実際のところこれでChannel Index : 37だらけになる。
で、さらに、
Bluefruit.Advertising.setInterval(160, 160); // in unit of 0.625 ms
の部分も
Bluefruit.Advertising.setInterval(64, 64); // in unit of 0.625 ms
ってすることで、Adalm-plutoでnRF52840が出したものなのかどうかをわかりやすくしてみる(高頻度で出しているやつがこいつだってわかる)。で、Adalm-plutoで受信すると、こうなる。
で、こいつを解析するんだが、ビットで出してLibreOfficeCalcで結果を算出するのがめんどくさくなってきたので、もうここまで解析用のPythonでやってしまう。で、こんなコードで、
-
import numpy as np -
import matplotlib.pyplot as plt -
from scipy import signal -
-
def byte_invert_order(src:np.uint8): -
a=((src>>4)&0x0F)|((0xF0)&(src<<4)) -
b=((a>>2)&0x33)|((a<<2)&0xCC) -
return ((b>>1)&0x55)|((b<<1)&0xAA) -
-
def search_index_by_pattern(data,pattern): -
ds=data.size -
ps=pattern.size -
cyc=ds-ps+1 -
ret=-1 -
if cyc>0: -
for i in range(cyc): -
data_part=data[i:i+ps] -
if np.all(data_part==pattern): -
ret=i -
break -
return ret -
-
ch37whiten=np.array([ -
0xB1,0x4B,0xEA,0x85,0xBC,0xE5,0x66,0x0D, -
0xAE,0x8C,0x88,0x12,0x69,0xEE,0x1F,0xC7, -
0x62,0x97,0xD5,0x0B,0x79,0xCA,0xCC,0x1B, -
0x5D,0x19,0x10,0x24,0xD3,0xDC,0x3F,0x8E, -
0xC5,0x2F,0xAA,0x16,0xF3,0x95,0x98,0x36, -
0xBA,0x32,0x20,0x49,0xA7,0xB8,0x7F,0x1D, -
0x8A,0x5F,0x54,0x2D,0xE7,0x2B,0x30,0x6D, -
0x74,0x64,0x40,0x93,0x4F,0x70,0xFE,0x3B, -
0x14,0xBE,0xA8,0x5B,0xCE,0x56,0x60,0xDA, -
0xE8,0xC8,0x81,0x26,0x9E,0xE1,0xFC,0x76, -
0x29,0x7D,0x50,0xB7,0x9C,0xAC,0xC1,0xB5, -
0xD1,0x91,0x02,0x4D,0x3D,0xC3,0xF8,0xEC, -
0x52,0xFA,0xA1,0x6F,0x39,0x59,0x83,0x6B, -
0xA3,0x22,0x04,0x9A,0x7B,0x87,0xF1,0xD8, -
0xA5,0xF5,0x42,0xDE,0x72,0xB3,0x06,0xD7, -
0x46,0x44,0x09,0x34,0xF7,0x0F,0xE3,0xB1 -
]) -
f_sym=1e6 # -
rx_all=np.load('o_rx_t.npy') -
t_all=np.load('o_t.npy') -
t_all=t_all-t_all[0] -
t_all_0=t_all[:-1:] -
t_all_1=t_all[1::] -
t_samp=np.mean(t_all_1-t_all_0) -
f_samp=1/t_samp -
print(f_samp/1e6) # should be 8MHz -
#t_all=np.linspace(0,t_samp*rx_all.size,rx_all.size) -
# フィルター係数生成 -
freq_cutoff=f_sym*2 -
w_cutoff=freq_cutoff/(f_samp/2) -
b,a=signal.butter(1,w_cutoff,'lowpass') -
-
# フィルター適用 -
rx_all=signal.lfilter(b,a,rx_all) -
-
rx_all_amp=np.abs(rx_all) -
rx_all_amp_dig=np.where(rx_all_amp>5,1,0) -
rx_all_amp_dig_0=rx_all_amp_dig[:-1:] -
rx_all_amp_dig_1=rx_all_amp_dig[1::] -
rx_all_amp_dig_10=np.append(rx_all_amp_dig_1-rx_all_amp_dig_0,0) -
rx_all_amp_dig_rising_edge=np.where(rx_all_amp_dig_10>0)[0] -
rx_all_amp_dig_falling_edge=np.where(rx_all_amp_dig_10<0)[0] -
print(rx_all_amp_dig_rising_edge.size) -
print(rx_all_amp_dig_falling_edge.size) -
-
pa_and_aa=np.array([0,1,0,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,1]) -
pnum=0 -
-
for i in range(rx_all_amp_dig_rising_edge.size): -
if rx_all_amp_dig_falling_edge[i]-rx_all_amp_dig_rising_edge[i]>40: -
rx=rx_all[rx_all_amp_dig_rising_edge[i]:rx_all_amp_dig_falling_edge[i]] -
t=t_all[rx_all_amp_dig_rising_edge[i]:rx_all_amp_dig_falling_edge[i]] -
# demod -
rx_t0=rx[:-1:] -
rx_t1=rx[1::] -
rx_dem=-1*np.angle(rx_t1/rx_t0) -
rx_dem=np.append(0,rx_dem) -
# normalization -
rx_dem=rx_dem/(f_sym/f_samp*np.pi*1) -
# digitization -
rx_dig=np.where(rx_dem>0,0,1) -
# counter top value -
counter_top=8-1 -
counter_half=int(counter_top/2) -
cnt_list=[] -
cnt_list.append(int(0)) -
for i in range(rx_dig.size-1): -
dig_pres=rx_dig[i+1] -
dig_prev=rx_dig[i] -
if (dig_pres!=dig_prev): -
cnt_list.append(int(0)) -
else: -
if (cnt_list[i]<counter_top): -
cnt_list.append(cnt_list[i]+int(1)) -
else: -
cnt_list.append(int(0)) -
cnt=np.array(cnt_list) -
smp_pos=np.where(cnt==counter_half)[0] -
rd_dig_smp=rx_dig[smp_pos] -
fig=plt.figure() -
fig.add_subplot(3,1,1) -
plt.plot(t,np.real(rx)) -
plt.plot(t,np.imag(rx)) -
fig.add_subplot(3,1,2) -
plt.plot(t,rx_dem) -
plt.ylim(-1,1) -
fig.add_subplot(3,1,3) -
plt.plot(rx_dig) -
plt.plot(smp_pos,rd_dig_smp,linestyle='',marker='.') -
plt.ylim(-0.5,1.5) -
fig.tight_layout() -
plt.savefig('pic'+str(pnum)+'.png') -
pnum=pnum+1 -
#plt.show() -
pp_and_aa_pos=search_index_by_pattern(rd_dig_smp,pa_and_aa) -
if(pp_and_aa_pos>=0): -
print(f"t_start={t[0]}({pp_and_aa_pos}):",end="") -
rd_dig_smp=rd_dig_smp[pp_and_aa_pos:] -
pos=0 -
bpos=0 -
barray_str='' -
while pos<rd_dig_smp.size: -
bdata=0 -
for n in range(8): -
bdata=bdata*2+rd_dig_smp[pos] -
pos=pos+1 -
if pos==rd_dig_smp.size: -
break -
if bpos>4: -
bdata=byte_invert_order(bdata^ch37whiten[bpos-5]) -
barray_str=barray_str+format(bdata,'02X') -
bpos=bpos+1 -
print(barray_str) -
-
fig=plt.figure() -
fig.add_subplot(1,1,1) -
plt.plot(t_all,np.real(rx_all)) -
plt.plot(t_all,np.imag(rx_all)) -
#plt.show()
-
7.9999991999999995 -
159 -
159 -
t_start=0.0017272501727250173(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.002253000225300023(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AF -
t_start=0.002572250257225026(14):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.05169388016938802(14):556B7D91716024DE30CD58ABDF0201061AFF5900029539D837CB7EF9A63FBB2C3B24D7B94D04A0A5C58E6F831C5B4C -
t_start=0.05222013022201302(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AFE9 -
t_start=0.05253975525397553(13):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.09338825933882594(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.14026701402670141(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.18584964358496436(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.23199227319922733(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.2763419026341903(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.2771869027186903(14):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.3170135317013532(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.3644361614436162(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.40646579064657906(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.4069920406992041(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AF -
t_start=0.40731091573109157(15):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.4502735450273545(12):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.45079929507992955(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AF -
t_start=0.45111829511182955(14):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.4925281742528175(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.5345579284557929(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.5801895580189559(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.6218823121882312(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.6649379414937941(15):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.6654641915464192(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AFE9 -
t_start=0.6657830665783067(13):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.7054006955400696(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.749431449943145(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.7499568249956825(8):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AF -
t_start=0.7502764500276451(14):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.7965969546596955(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.8286788328678834(7):556B7D9171C30CA7B8B5EAC25BBBAF54C78D7358B503E9 -
t_start=0.8424845842484585(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.8898920889892089(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.890417839041784(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AF -
t_start=0.890737089073709(15):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=0.939841468984147(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=0.9841122234112224(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=1.0294228529422853(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=1.0758213575821358(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=1.1229389872938988(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=1.1234643623464362(7):556B7D9171C30CA7B8B5EAC25BDE30CD58ABDFFD21AF -
t_start=1.1237839873783988(14):556B7D91714415DE30CD58ABDF0E095849414F206E524635323834308B3BB308 -
t_start=1.1657067415706743(13):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C -
t_start=1.2126012462601248(14):556B7D91716024DE30CD58ABDF0201061AFF590002150112233445566778899AABBCCDDEEFF0DEADBEEFCA54545E4C
45,46,47行に着目すると
[45行目]
60 : ADV_SCAN_IND
24 : 36byte
DE30CD58ABDF : AdvAdr=DF:AB:58:CD:30:DE
(...省略)
[46行目]
C3 : SCA_REQ, TxAdd=Random, RxAdd=Random
0C : 12byte
A7B8B5EAC25B : ScanAdr=5B:C2:EA:B5:B8:A7
DE30CD58ABDF : AdvAdr=DF:AB:58:CD:30:DE
[47行目]
44 : SCAN_RESP, TxAdd=Random
15 : 21byte
DE30CD58ABDF : AdvAdr=DF:AB:58:CD:30:DE
0E : 14Byte
09 : Complete Local Name
5849414F206E52463532383430 : XIAO nRF52840
よし、できた。
いちおうWiresharkによると、
、じゃぁWiresharkでいいやん、、、あ、そす、、、無線の波形からデータにしてみたかっただけです。こんなの知らんでもいいんやろうけど、モノ作りでは、うまくいかないことも多くて、そういう時に、自分で手を動かした、自分の目で見た経験が活きると思ってる。最近できてないなーーー
そういえばVSCodeのArduino拡張機能が廃止になったらしい。で、ArduinoIDEを使えって書いてある。Arduino IDEは1系だと変数や関数をたどるのがメンドクサイ、2系だと、、、思い出せないけど1度移行してみたもののたしか嫌な点があってやめたんだったと思う。が、実際問題、2系を使っていくしかないかな。













コメントをお書きください