matlab-generate-ble-waveform について
Bluetooth Low EnergyのPHY波形を生成、シミュレーション、解析するMATLABスキルです。BLEの物理層を扱うユーザー向けに、PHYモードの選択から方向検出、適合性試験、受信機シミュレーション、共存解析、送信測定まで案内します。
主な機能
- 014種類のBLE PHYモード波形を生成
- 02マルチパケットバーストとPDU波形を構成
- 03CTEと方向検出の手順に対応
- 04BERと劣化受信機のシミュレーションを案内
- 05RF-PHY試験と送信測定を扱う
活用シーン
- 01BLE PHYモードの比較
- 02CTEによる角度推定の試験
- 03帯域幅、PAPR、信号電力の測定
- 04ノイズやWLAN干渉下のBERシミュレーション
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ matlab/ matlab-agentic-toolkit --skill matlab-generate-ble-waveformインストール後、Claude Code で/matlab-generate-ble-waveformを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
manifest.yamlreferences/cte-direction-finding.mddata-whitening.mddirection-finding.mdfunctionalAPI.mdphy-modes-and-timing.mdpractical-receiver-simulation.mdrfphy-compliance-testing.mdrssi-localization.mdtransmitter-measurements.mdwlan-coexistence.md詳細
BLE 波形生成
ルーティング
| インテント | 手がかり | パターン |
|---|---|---|
| 基本的な生成 | 「生成」、「波形」 | 単一モード |
| モードの比較 | 「比較」、「すべてのモード」 | 全モード |
| 方向検出 | 「CTE」、「AoA」、「AoD」 | CTE |
| RF-PHY 適合性 | 「適合性」、「RF-PHY」 | RF-PHY テスト |
| 共存 | 「WLAN」、「干渉」 | WLAN 共存 |
| TX 測定 | 「PAPR」、「OBW」、「電力」 | TX 測定 |
| 位置特定 | 「RSSI」、「ビーコン」、「距離」 | RSSI 位置特定 |
| BER/受信機 | 「BER」、「ノイズ」、「感度」 | BER シミュレーション |
| 複数パケット | 「バースト」、「IFS」 | 複数パケット |
| スペクトラム | 「スペクトラム」、「スペクトルマスク」 | スペクトル解析 |
| ホワイトニング | 「ホワイトニング」、「スクランブル」 | ホワイトニング比較 |
| 劣化要因 | 「CFO」、「実用的」、「現実的」 | エンドツーエンド |
デフォルト(曖昧なリクエストの場合):LE1M、37 バイトのペイロード、チャネル 37。
使用する場合
ユーザーが BLE PHY 層の波形の生成、シミュレーション、または解析を依頼した場合に、このスキルを使用します。モード比較、CTE/方向検出、RF-PHY 適合性テスト、BER シミュレーション、TX 測定、WLAN 共存、RSSI 位置特定などが含まれます。bleWaveformGenerator、bleIdealReceiver、bleCTEIQSample、bleAngleEstimate、または bluetoothTestWaveform を扱うあらゆるタスクに適用されます。
使用しない場合
- BR/EDR(クラシック Bluetooth)→
bluetoothWaveformGeneratorを使用します(別の BR/EDR スキルで扱います) - Channel Sounding(CS)→
bleCSWaveform(bleCSConfig)を使用します(R2024b 以降)。CS には独自の測距/距離測定パイプラインがあり、PHY 波形生成には含まれません - ネットワークレベルのシミュレーション → リンク層/ネットワークのモデリングには
bluetoothLENodeを使用します - 経路損失のモデリング → 伝搬/チャネルのモデリングには
bluetoothPathLossを使用します
PHY モード
| モード | symbolRate | データレート | 符号化 | 時間(37 B) |
|---|---|---|---|---|
"LE1M" | 1e6 | 1 Mbps | なし | 約336 us |
"LE2M" | 2e6 | 2 Mbps | なし | 約172 us |
"LE500K" | 1e6 | 500 kbps | FEC S=2 | 約974 us |
"LE125K" | 1e6 | 125 kbps | FEC S=8 | 約2768 us |
参考資料
このファイルの内容を超える詳細なガイダンスについては、以下を参照してください。
- functionalAPI.md — bleWaveformGenerator の Name-Value ペアに関する API リファレンス全体
- phy-modes-and-timing.md — PHY モードごとの詳細な時間計算
- cte-direction-finding.md — CTE パイプライン:生成、IQ サンプリング、制約
- direction-finding.md — bleAngleEstimate による AoA/AoD 角度推定
- rfphy-compliance-testing.md — RF-PHY テスト波形のパターンと設定
- transmitter-measurements.md — OBW、PAPR、電力測定のパターン
- practical-receiver-simulation.md — BER シミュレーションと劣化を考慮した受信機
- wlan-coexistence.md — WLAN 干渉と共存のシナリオ
- rssi-localization.md — RSSI ビーコンと距離推定のパターン
- data-whitening.md — ホワイトニングのオン/オフ比較と内部処理
パラメーター(bleWaveformGenerator)
| パラメーター | デフォルト | 範囲 |
|---|---|---|
Mode | "LE1M" | LE1M、LE2M、LE500K、LE125K |
ChannelIndex | 37 | 0-39 |
SamplesPerSymbol | 8 | >=1(プロットには >=4 を使用) |
WhitenStatus | "On" | On、Off |
DFPacketType | "Disabled" | Disabled、ConnectionCTE、ConnectionlessCTE |
AccessAddress | 広告用のデフォルト値 | 32 ビットのバイナリ列ベクトル |
ModulationIndex | 0.5 | [0.45, 0.55] |
PulseLength | 1 | [1, 4] |
基本レシピ
messageBits = randi([0 1], payloadLenBytes*8, 1);
waveform = bleWaveformGenerator(messageBits, ...
Mode=phyMode, SamplesPerSymbol=sps, ...
ChannelIndex=ch, WhitenStatus="On");
symbolRate = 1e6 + 1e6*(phyMode=="LE2M");
fs = symbolRate * sps;
パターン
全モードの比較
phyModes = ["LE1M","LE2M","LE500K","LE125K"];
sps = 8;
messageBits = randi([0 1], 37*8, 1);
figure; tl = tiledlayout(4,2,TileSpacing="compact",Padding="compact");
title(tl,"BLE - All PHY Modes")
for idx = 1:4
wf = bleWaveformGenerator(messageBits, ...
Mode=phyModes(idx), SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
sr = 1e6 + 1e6*(phyModes(idx)=="LE2M");
fs = sr*sps; t = (0:length(wf)-1)/fs*1e6;
nexttile; plot(t,real(wf),t,imag(wf))
xlabel("Time (\mus)"); ylabel("Amplitude"); title(phyModes(idx)+" - IQ")
legend("I","Q"); grid on; xlim([0 min(80,t(end))])
nexttile; N=length(wf); f=(-N/2:N/2-1)*(fs/N)/1e6;
plot(f, 20*log10(abs(fftshift(fft(wf)))/N+eps))
xlabel("Frequency (MHz)"); ylabel("dB"); title(phyModes(idx)+" - Spectrum")
grid on; xlim([-3 3]); ylim([-80 0])
end
複数パケットのバースト(T_IFS = 150 us)
sps = 8; fs = 1e6*sps;
messageBits = randi([0 1], 37*8, 1);
ifsGap = complex(zeros(round(150e-6*fs), 1));
burst = complex(zeros(0,1));
for pkt = 1:3
wf = bleWaveformGenerator(messageBits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37);
burst = [burst; wf; ifsGap]; %#ok<AGROW>
end
往復デコード
messageBits = randi([0 1], 37*8, 1); sps = 8;
wf = bleWaveformGenerator(messageBits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
rxBits = bleIdealReceiver(wf, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
assert(isequal(rxBits, messageBits))
データチャネル+カスタムアクセスアドレス
accessAddr = randi([0 1], 32, 1);
wf = bleWaveformGenerator(randi([0 1],27*8,1), ...
Mode="LE2M", SamplesPerSymbol=8, ChannelIndex=9, ...
AccessAddress=accessAddr, WhitenStatus="On");
fs = 2e6 * 8;
CTE の生成
messageBits = randi([0 1], 20*8, 1); sps = 8; fs = 1e6*sps;
wf_noCTE = bleWaveformGenerator(messageBits, Mode="LE1M", ...
SamplesPerSymbol=sps, ChannelIndex=10, WhitenStatus="On");
wf_conn = bleWaveformGenerator(messageBits, Mode="LE1M", ...
SamplesPerSymbol=sps, ChannelIndex=10, WhitenStatus="On", DFPacketType="ConnectionCTE");
wf_cless = bleWaveformGenerator(messageBits, Mode="LE1M", ...
SamplesPerSymbol=sps, ChannelIndex=10, WhitenStatus="On", DFPacketType="ConnectionlessCTE");
% CTE appends unmodulated constant tone for antenna switching (typ. 72-216 us)
cteDelta_conn_us = (length(wf_conn) - length(wf_noCTE)) / fs * 1e6;
cteDelta_cless_us = (length(wf_cless) - length(wf_noCTE)) / fs * 1e6;
CTE フルパイプライン(Tx → Rx → Angle)
pduHex = '02049B03270102030405'; % 10-byte PDU (>=6 bytes needed for >=11 IQ samples)
pdu = int2bit(hex2dec(reshape(pduHex, 2, [])'), 8, false);
pdu = pdu(:);
cfgCRC = crcConfig(Polynomial="z^24+z^10+z^9+z^6+z^4+z^3+z+1", ...
InitialConditions=int2bit(hex2dec('555551'),24), DirectMethod=true);
pduCRC = crcGenerate(pdu, cfgCRC);
txWf = bleWaveformGenerator(pduCRC, ChannelIndex=36, DFPacketType="ConnectionlessCTE");
[~, ~, iqSamples] = bleIdealReceiver(txWf, ChannelIndex=36, ...
DFPacketType="ConnectionlessCTE", SlotDuration=2);
cfgAngle = bleAngleEstimateConfig;
cfgAngle.ArraySize = 4; cfgAngle.SlotDuration = 2; cfgAngle.SwitchingPattern = [1 2 3 4];
angle = bleAngleEstimate(iqSamples, cfgAngle);
別の方法(R2022a 以降):iqSamples = bleCTEIQSample(cteSamples, Mode="LE1M", SlotDuration=2);
BER シミュレーション
messageBits = randi([0 1], 100*8, 1); sps = 8; phyMode = "LE1M";
snrValues = 0:4:20; berResults = zeros(size(snrValues));
for idx = 1:length(snrValues)
wf = bleWaveformGenerator(messageBits, Mode=phyMode, SamplesPerSymbol=sps, ChannelIndex=5, WhitenStatus="On");
sigPower = mean(abs(wf).^2);
rxWf = awgn(wf, snrValues(idx), 10*log10(sigPower));
rxBits = bleIdealReceiver(rxWf, Mode=phyMode, SamplesPerSymbol=sps, ChannelIndex=5, WhitenStatus="On");
n = min(length(messageBits), length(rxBits));
berResults(idx) = sum(messageBits(1:n) ~= double(rxBits(1:n))) / n;
end
semilogy(snrValues, berResults, "-o"); xlabel("SNR (dB)"); ylabel("BER"); grid on
bleIdealReceiver は int8 を返すため、double() でキャストします。Eb/No を変換するには、snr = convertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps) を使用します。
RF-PHY テスト波形
cfg = bluetoothTestWaveformConfig;
cfg.Mode = "LE1M"; cfg.PayloadLength = 37;
cfg.PacketType = "Disabled"; cfg.ModulationIndex = 0.5;
testWf = bluetoothTestWaveform(cfg);
rfCfg = bluetoothRFPHYTestConfig;
rfCfg.Test = "Output power"; rfCfg.Mode = "LE1M";
rfCfg.PayloadLength = 37; rfCfg.OutputPower = 0; rfCfg.CenterFrequency = "Mid";
WLAN 共存
sps = 8; fs = 1e6*sps;
bleWf = bleWaveformGenerator(randi([0 1],37*8,1), Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
t = (0:length(bleWf)-1)'/fs;
wlanInterferer = 0.1*complex(randn(length(bleWf),1),randn(length(bleWf),1)) .* exp(1j*2*pi*3e6*t);
combined = bleWf + wlanInterferer;
CIR_dB = 10*log10(mean(abs(bleWf).^2) / mean(abs(wlanInterferer).^2));
TX 測定(電力、OBW、PAPR)
sps = 8; wf = bleWaveformGenerator(randi([0 1],255*8,1), Mode="LE1M", ...
SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On", ModulationIndex=0.5);
fs = 1e6*sps; N = length(wf);
avgPower_dBm = 10*log10(mean(abs(wf).^2)) + 30;
spec = abs(fftshift(fft(wf))).^2; cumP = cumsum(spec)/sum(spec);
f = (-N/2:N/2-1)*(fs/N);
occBW_MHz = (f(find(cumP>=0.995,1)) - f(find(cumP>=0.005,1))) / 1e6;
papr_dB = 10*log10(max(abs(wf).^2) / mean(abs(wf).^2));
ホワイトニングの比較
bits = randi([0 1], 37*8, 1); sps = 8;
wfOn = bleWaveformGenerator(bits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="On");
wfOff = bleWaveformGenerator(bits, Mode="LE1M", SamplesPerSymbol=sps, ChannelIndex=37, WhitenStatus="Off");
アドバタイジング PDU(ADV_IND)
cfgAdv = bleLLAdvertisingChannelPDUConfig;
cfgAdv.PDUType = "Advertising indication";
cfgAdv.AdvertiserAddress = "A1B2C3D4E5F6";
cfgAdv.AdvertiserAddressType = "Random";
cfgAdv.AdvertisingData = "0201060709546573744245020A00";
pduBits = bleLLAdvertisingChannelPDU(cfgAdv);
wf = bleWaveformGenerator(pduBits, Mode="LE1M", SamplesPerSymbol=8, ChannelIndex=37);
PDUType の値:"Advertising indication"、"Scan request"、"Scan response"、"Connection indication"、"Advertising direct indication"、"Advertising non connectable indication"。
アドレス:12 文字の 16 進数文字列(コロンなし)。AdvertisingData:16 進数文字列(長さ・タイプ・値の AD 構造体)。
データチャネル PDU
cfgData = bleLLDataChannelPDUConfig;
cfgData.LLID = "Data (start fragment/complete)";
cfgData.SequenceNumber = 1;
cfgData.NESN = 0;
cfgData.MoreData = false;
payload = dec2hex(randi([0 255], 50, 1))'; % 50-byte hex payload
payload = reshape(payload', 1, []);
pduBits = bleLLDataChannelPDU(cfgData, payload);
wf = bleWaveformGenerator(pduBits, Mode="LE2M", SamplesPerSymbol=8, ChannelIndex=15);
LLID の値:"Data (continuation fragment/empty)"、"Data (start fragment/complete)"、"Control"。
SequenceNumber(SN ではありません)。ペイロード:16 進数文字列、数値ベクトル [0,255]、または n×2 の char 配列。
エンドツーエンド(実用的な受信機)
helperBLEPracticalReceiver(AGC + CFO + タイミングリカバリー)を使用します。次が必要です:openExample('bluetooth/BLEPracticalReceiverExample')。符号化モードの SNR 変換:SNR = EbNo + 10*log10(codeRate) - 10*log10(sps)。
CTE の互換性
| モード | ConnectionCTE | ConnectionlessCTE |
|---|---|---|
| LE1M | はい | はい |
| LE2M | はい | いいえ |
| LE500K | いいえ | いいえ |
| LE125K | いいえ | いいえ |
CTE にはデータチャネル(0-36)が必要です。 DFPacketType≠"Disabled" の場合、ChannelIndex 37/38/39 は絶対に使用しないでください。CTE はデータチャネル専用の機能です。
仕様上の制約
- Ch 37/38/39(アドバタイジング): LE1M または LE Coded のみ。LE2M は不可です。
- CTE: データチャネル(0-36)での LE1M/LE2M のみ。コーデッド PHY は不可です。
- アクセスアドレス: アドバタイジング =
'8E89BED6'(固定)、データ = ランダム。 - ホワイトニング初期値: ChannelIndex から自動設定されます。設定できません。
- T_IFS: 150 us。TX 電力: 最大 +20 dBm。変調指数: 0.45-0.55。
bleIdealReceiver: ハード判定のみで、int8を返します。- 「スロット」(1 スロット、3 スロット、5 スロット): BR/EDR の概念のみです。BLE にはスロットベースのパケットはありません。
- ISO ストリーム:
BN × IRC × Sub_Interval <= ISO_Intervalを検証してください。計算結果が上限を超える場合は、要求を拒否してください。
無効な組み合わせ(これらの要求は拒否してください)
| 要求 | 無効な理由 |
|---|---|
| LE2M + FEC 符号化 | FEC はコーデッド PHY(LE500K/LE125K)でのみ使用されます |
| Ch 37/38/39 での LE2M | プライマリアドバタイジングは LE1M または Coded のみです |
| CTE + LE500K/LE125K | BLE 5.1 仕様により、CTE は LE1M/LE2M に制限されています |
| ConnectionlessCTE + LE2M | ConnectionlessCTE は LE1M のみです |
| 「3 スロット」または「5 スロット」の BLE | スロットベースなのは BR/EDR です。BLE では単一パケットを使用します |
| Ch 37/38/39 での CTE | CTE はデータチャネル(0-36)のみです |
| BN×IRC×Sub_Int > ISO_Interval となる ISO パラメーター | サブイベントがインターバルを超えるため、スケジューリングできません |
規約
fs = (1e6 + 1e6*(mode=="LE2M")) * sps— ハードコードしないでください- 軸:us(時間)、MHz(周波数)、dB(電力)
tiledlayout/nexttile(subplotではありません)- スペクトル:常に
20*log10(abs(fftshift(fft(wf)))/N + eps)を使用してください — BLE のスペクトルプロットにはperiodogram、pspectrum、pwelchを使用しないでください - コーデッドモードでは
xlim([0 min(80,t(end))]) - I と Q の両方をプロットします:
plot(t, real(wf), t, imag(wf)) - IFS ギャップ:
complex(zeros(N,1))(出力は複素数です) - スペクトルプロットでは
SamplesPerSymbol>=4を指定してください。SPS=1 は波形生成には有効ですが、ナイキスト限界のため、可視化や正確なスペクトル解析には不十分です
コードスタイル
生成するスクリプトは、MathWorks の例の規約に従う必要があります。%% セクションヘッダーを使用し、すべてのパラメーターをソフトコード化して、分かりにくいロジックにはコメントを付けてください。
構成とソフトコード化
スクリプトを %% ヘッダーで区切ります:設定 → 波形生成 → 処理 → 解析 → 可視化。ユーザーが設定できる値はすべて先頭で名前付き変数として定義し、処理ロジックにマジックナンバーを使用しないでください。
%% Configuration
% Specify BLE waveform generation parameters.
phyMode = "LE1M"; % PHY transmission mode
payloadLength = 37; % Payload length in bytes
sps = 8; % Samples per symbol
channelIndex = 37; % BLE channel index (0-39)
% Derived parameters
symbolRate = 1e6 + 1e6*(phyMode=="LE2M"); % 2 Msym/s for LE2M, 1 Msym/s otherwise
fs = sps * symbolRate; % Sample rate in Hz
numBits = payloadLength * 8; % Payload length in bits
%% Waveform Generation
% Generate BLE waveform from random payload bits.
messageBits = randi([0 1], numBits, 1);
waveform = bleWaveformGenerator(messageBits, ...
Mode=phyMode, SamplesPerSymbol=sps, ChannelIndex=channelIndex);
コメント
- インライン(右揃え): 単位、範囲、または簡潔な目的 —
% Eb/No in dB - ブロック(2〜5 行の上に配置): 意図または なぜ —
% IFS gap must be complex (bleWaveformGenerator output is complex) - 制約事項: 仕様の参照 —
% LE2M uses 2 Msym/s (only mode with 2x symbol rate) - コメントしないこと: 自明な行、機械的にすべての行、または閉じる
endステートメント
命名
- camelCase:
messageBits、txWaveform、symbolRate、channelIndex - 説明的なループカウンター:
countMode、pktIdx(i、jではない) - 名前付き定数:
bitsPerByte = 8、tIFS = 150e-6 - 複数初期化:
[numErrors, perCount] = deal(0, 0)
注意点
| 間違い | 修正 |
|---|---|
bleWaveformConfig(...) | 存在しません。bleWaveformGenerator(bits, NV...) を直接使用してください |
BLE に対する bluetoothWaveformGenerator | BR/EDR のみ。bleWaveformGenerator を使用してください |
comm.BLEReceiver | 存在しません。bleIdealReceiver を使用してください |
LE2M に対する symbolRate=1e6 | LE2M = 2e6 |
パラメーター名としての 'PHYMode' | 'Mode' を使用してください |
モードとしての 'LECODED' | "LE500K" または "LE125K" を使用してください |
| 第 1 引数としての設定オブジェクト | バイナリ列ベクトル randi([0 1],N,1) でなければなりません |
空の [] ビット | 最小 1 バイト |
IFS に対する実数の zeros() | complex(zeros(N,1)) を使用してください |
| CTE + コーディングモード | CTE は LE1M/LE2M のみ |
ConnectionlessCTE + LE2M | LE1M のみ |
| チャネル 37/38/39 での LE2M | 仕様違反。LE1M または Coded を使用してください |
NV 引数としての CTELength/CTEType | 有効ではありません。DFPacketType を使用してください |
bleAngleEstimate(wf, NV...) | bleAngleEstimate(iqSamples, bleAngleEstimateConfig) を使用してください |
RF-PHY に対する bleWaveformGenerator | bluetoothTestWaveformConfig + bluetoothTestWaveform を使用してください |
| オーバーサンプリング補正なしの AWGN | convertSNR(EbNo,"ebno","snr",SamplesPerSymbol=sps) を使用してください。awgn に明示的な電力を渡してください("measured" は決して使用しないでください) |
劣化を伴う bleIdealReceiver | helperBLEPracticalReceiver を使用してください |
| 符号化レートなしのコーディングモードに対する Eb/No | SNR = EbNo + 10*log10(codeRate) - 10*log10(sps) |
| 警告なしの SPS=1 | SPS=1 はナイキスト限界です — ユーザーに警告してください: スペクトル解析なし、デコード性能は限界的 |
resample なしのタイミング ppm オフセット | resample(wf, 1e6+ppm, 1e6) または分数遅延フィルターを介してクロックドリフトを適用してください |
| PRBS9 なしの適合性 Df1/Df2 | TP/TRM/CA/BV-05-C には comm.PNSequence(z^9+z^5+1)を使用してください。安定ビット(Df1)と交互ビット(Df2)パターンを分離してください |
BLE スペクトルに対する periodogram/pwelch | 手動の fftshift(fft(wf)) を使用してください — スキルの慣例 |
プロパティ名としての SN | bleLLDataChannelPDUConfig の SequenceNumber を使用してください |
コロン付きアドレス "A1:B2:..." | コロンなしの 12 文字の 16 進文字列を使用してください: "A1B2C3D4E5F6" |
PDUType="ADV_IND" | 完全な文字列を使用してください: "Advertising indication" |
| AdvertisingData としてのバイナリベクトル | 16 進文字列を使用してください: "0201060709..."(長さ-タイプ-値) |
Copyright 2026 The MathWorks, Inc.