だいぶ一般的になっているBLEについて。すごく概念的なことはあちこちに書いてある。が、下から上まで(むしろ下だけ)知りたいのに、資料少なすぎ。なので自力で調べる無茶な挑戦。第1回=アドバタイズを出して、それを観測する。
本当はありとあらゆる資料を読むのが正解だとはわかっている。が、手を動かさないとぜんっぜん頭に入らない初老のおじさんなのです(ていうか、だいたいの資料が英語で、で、英語がわからんだけ๐·°(৹˃̵﹏˂̵৹)°·๐)。
まずは、WeMos D1R32を使ってアドバタイズを出してみる。WeMos D1R32については、こちら(https://sunday-engineer.jimdofree.com/2023/09/03/wemos-d1r32%E3%83%A1%E3%83%A2/)に取り上げている。で、Exampleからこいつ
まずは、WeMos D1R32を使ってアドバタイズを出してみる。WeMos D1R32については、こちら(https://sunday-engineer.jimdofree.com/2023/09/03/wemos-d1r32%E3%83%A1%E3%83%A2/)に取り上げている。で、Exampleからこいつ
を開いて書き込む。
そすっと、
そすっと、
こんな感じで、なにかペリフェラルとして動作していそうな感じがする。で、どんなのを出しているのかをAdalm-Plutoで観測する。Adalm-Plutoについては以前に触れてみたことがある(
ADALM-PLUTO(購入からセットアップまで)
ADALM-PLUTO(pythonで)(1)
ADALM-PLUTO(MATLABで動作確認)
ADALM-PLUTO(pythonで)(2)
ADALM-PLUTO(pythonで)(3)
)
で、まぁ気持ちを新たに、うちはLinuxなので、こちら(https://pysdr.org/content/pluto.html)を参考にしてインストール。Windowsだとこのへん(https://wiki.analog.com/resources/tools-software/linux-software/pyadi-iio)かな。通常やるっぽいんだけど、SSHでAdalm-Plutoに入って対応周波数の拡大はやっておく。で、こんなコードで動かしてみる。
まぁ、ちょうど出しているところが引っかかってくれるかどうかで、何度かトライしてみて、こんな感じになる(見たいところを拡大済み)。
ADALM-PLUTO(pythonで)(1)
ADALM-PLUTO(MATLABで動作確認)
ADALM-PLUTO(pythonで)(2)
ADALM-PLUTO(pythonで)(3)
)
で、まぁ気持ちを新たに、うちはLinuxなので、こちら(https://pysdr.org/content/pluto.html)を参考にしてインストール。Windowsだとこのへん(https://wiki.analog.com/resources/tools-software/linux-software/pyadi-iio)かな。通常やるっぽいんだけど、SSHでAdalm-Plutoに入って対応周波数の拡大はやっておく。で、こんなコードで動かしてみる。
-
import numpy as np
-
import adi
-
import matplotlib.pyplot as plt
-
sample_rate = 56e6 # Hz
-
center_freq = 2402e6 # Hz
-
num_samps = 1000000 # number of samples per call to rx()
-
sdr = adi.Pluto("ip:192.168.2.1")
-
sdr.sample_rate = int(sample_rate)
-
# Config Rx
-
sdr.rx_lo = int(center_freq)
-
#sdr.rx_rf_bandwidth = int(sample_rate)
-
sdr.rx_rf_bandwidth = int(2e6)
-
sdr.rx_buffer_size = num_samps
-
sdr.gain_control_mode_chan0 = 'manual'
-
sdr.rx_hardwaregain_chan0 = 0.0 # dB, increase to increase the receive gain, but be careful not to saturate the ADC
-
# Clear buffer just to be safe
-
for i in range (0, 10):
-
raw_data = sdr.rx()
-
# Receive samples
-
rx_samples = sdr.rx()
-
print(rx_samples)
-
t=np.linspace(0,1/sample_rate*num_samps,num_samps)
-
np.save('o_t',t)
-
np.save('o_rx_t',rx_samples)
-
# Calculate power spectral density (frequency domain version of signal)
-
psd = np.abs(np.fft.fftshift(np.fft.fft(rx_samples)))**2
-
psd_dB = 10*np.log10(psd)
-
f = np.linspace(sample_rate/-2, sample_rate/2, len(psd))
-
# Plot time domain
-
plt.figure(0)
-
plt.plot(np.real(rx_samples))
-
plt.plot(np.imag(rx_samples))
-
plt.xlabel("Time")
-
# Plot freq domain
-
plt.figure(1)
-
plt.plot(f/1e6, psd_dB)
-
plt.xlabel("Frequency [MHz]")
-
plt.ylabel("PSD")
-
plt.show()
搬送波周波数+/-周波数変位幅にピークが出ないのはGFSKの性質なんだろう(局初周波数=搬送波周波数で直行復調済み波形での計算結果なので0が搬送波周波数)。
で、読み取ったデータを保存するようにしてあるので、これを解析してみる。
解析は、かつてFSKを調べるときに使ったコード(https://sunday-engineer.jimdofree.com/2020/07/22/%E3%83%91%E3%83%AB%E3%82%B9%E3%81%A7%E7%9B%B4%E4%BA%A4%E5%BE%A9%E8%AA%BF-5-numpy%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B/)を参考に、こんなかんじで、
ってすると、
はて、これがなんなのか、、、まず復調波形が見にくいので2値化する。
-
import numpy as np
-
import matplotlib.pyplot as plt
-
from scipy import signal
-
f_sym=1e6 #
-
rx=np.load('o_rx_t.npy')
-
t=np.load('o_t.npy')
-
rx=rx[208500:228500]
-
t=t[208500:228500]
-
t=t-t[0]
-
t_0=t[:-1:]
-
t_1=t[1::]
-
t_samp=np.mean(t_1-t_0)
-
f_samp=1/t_samp
-
print(f_samp/1e6) # should be 56MHz
-
# フィルター係数生成
-
freq_cutoff=f_sym*2
-
w_cutoff=freq_cutoff/(f_samp/2)
-
b,a=signal.butter(1,w_cutoff,'lowpass')
-
-
# フィルター適用
-
rx=signal.lfilter(b,a,rx)
-
# 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)
-
fig=plt.figure()
-
fig.add_subplot(2,1,1)
-
plt.plot(t*1e6,np.real(rx))
-
plt.plot(t*1e6,np.imag(rx))
-
fig.add_subplot(2,1,2)
-
plt.plot(rx_dem)
-
plt.ylim(-1,1)
-
plt.show()
# digitization
rx_dig=np.where(rx_dem>0,1,0)
ってのを追加してプロットするわけだ。すると
こうなる。これを拡大して波形からいってきっとNRZで読んでいけばいいんだろうとして読んでいく、、、が、何となく前から気にはなっていたけど、上のpythonコードで復調すると、正負が逆になっちゃうので、それも考慮してって、、、
ところで、いつもイラっとするアルファベット言語圏の省略造語について、Bluetooth Core Specificationに"LIST OF ACRONYMS AND ABBREVIATIONS"っていう項があるので、ギリ許すことにする。絶望的にたくさんあるがこいつらをおぼえておかんといかん。
ところで、この実験に使っているWeMos
D1R32はだいぶ古いものなので、最近のものをいくつか発注した。これ(https://akizukidenshi.com/catalog/g/g117454/)と、これ(https://akizukidenshi.com/catalog/g/g117341/)。どちらも大した値段ではないけど、無駄遣いになる可能性もあるっちゃーある。、、、投資ってそんなもんだよね。それほど大したことのない台風で秋月もお休みしたようで、まだぜんっぜん発送手配が進んでないっぽいけど。
しかし、BLEの通信を下から紐解いていくのはまぁまぁしんどい。このテーマの続編を書けるかどうか、挫折するかもしれないって心配。だいたいの人がスマホやらRaspberryPiとかで情報をとるってのはやってるんだけど、その情報がどうやって飛んできたのかってことまで掘っている記事はないんよね。今の世の中そんなものなのかな。
記事と全く関係ないけど、FusionPCBに発注したP板は昨夜OCSに持ち込まれたらしい。順調です。P板設計がごく一般的な大人のたしなみになる日も近い、、、なわけないか。
ところで、だいぶ前から気づいてはいたけど、最近はGoogle Bloggerで記事を書いて、そのソースをJimdoに貼り付けてるんだけど、改行がなぜか省略されちゃったりするんだよね。特にソースコード。メンドクサイのでJimdoように修正したりはしない。必要に応じてGoogle Bloggerで見る。
コメントをお書きください