Bluetoothモジュールの製造テストと量産キャリブレーション
出荷されるすべてのBluetoothモジュールは製造テストラインを通過します。「だいたい動く」モジュールと、温度・電圧・アンテナ不整合の全条件下で仕様を満たすモジュールの差はファームウェアではなく、テストプロセスにあります。本記事では、ステーションごとのワークフロー、主要なキャリブレーションパラメータ、スループットとカバレッジの経済性を解説します。
4ステーションの製造ライン
標準的なBLEモジュール製造ラインには4つの必須ステーションがあります。いずれかを省略すると、保証返品によって露呈する盲点が生まれます:
| ステーション | 機能 | サイクルタイム | 検出不良モード |
|---|---|---|---|
| 1. ICT / 外観検査 | オープン/ショート、部品配置、はんだ品質 | 約8秒 | ツームストン、ブリッジ、パッシブ部品欠落 |
| 2. ファームウェア書込 | アプリ+ブートローダー書込、MAC・XTALトリム値書込 | 約15秒 | フラッシュ破損、誤バリアント、ブランクチップ |
| 3. RFキャリブレーション | 周波数オフセット、TXパワー、RSSIオフセット、水晶トリム | 約25秒 | ±40kHzオフセット、3dBパワー誤差、感度低下 |
| 4. 機能テスト | アドバタイズ、接続、GATT Read/Write、GPIO、ADC、消費電流 | 約20秒 | IOリーク、スリープ電流異常、不安定リンク |
総ラインサイクルタイム:約68秒/モジュール。並列ステーションとマルチアップ治具により、単一ラインで200〜400個/時のスループットを達成します。
水晶周波数キャリブレーション — 最も重要な25秒
32MHz水晶はすべてのBLE接続の心臓部です。キャリブレーションなしでは±40ppmの初期公差は2.402GHzで±96kHzのキャリアオフセットに相当し、温度と経年変化を加えるとBLE仕様(最大±150kHz)を超過します。キャリブレーションにより±10ppm以下に調整します。
nRF52/nRF53シリーズのキャリブレーション手順:
// Step 1: DUTをチャネル0(2402 MHz)で連続キャリアTXに設定
// Step 2: スペクトラムアナライザで実際の周波数 f_meas を測定
// Step 3: トリム値を計算
// f_target = 2402.000 MHz, f_meas はSAから取得
int32_t offset_hz = f_meas - 2402000000; // 符号付きオフセット(Hz)
int32_t trim_ppb = (offset_hz * 1000) / 2402; // ppbに変換
// nRF52 XTALトリムレジスタ:16ビット2の補数、LSB = 0.5 ppm
// 32 MHzで0.5 ppm = 16 Hz
int16_t trim_value = (int16_t)(offset_hz / 16);
if (trim_value > 32767) trim_value = 32767;
if (trim_value < -32768) trim_value = -32768;
// UICRに永続保存
NRF_UICR->XTALFREQ = (uint16_t)trim_value;
// Step 4: 再測定で f_error < ±2 kHz を確認
スリープクロックに標準32.768kHz水晶を使用するモジュールでは、同じ原理を適用しますが、GPS規律参照に対して32MHzクロックを測定し、その比率から32kHzトリム値を導出します。
TXパワーキャリブレーション:オートチューンだけでは不十分
ほとんどのチップセットSDKは整数レジスタ値としてdBm単位のTXパワー設定を提供します。しかし実際の放射電力はPCBレイアウト、整合回路の公差、アンテナ効率、さらにはプラスチック筐体にも依存します。「0 dBm」に設定されたモジュールでも、製造バッチ全体では-2〜+3 dBmの範囲でばらつきます。
| 目標TXパワー | レジスタ値範囲 | 測定出力 | キャリブレーション後レジスタ |
|---|---|---|---|
| +4 dBm | 0x04〜0x0C | +2.1〜+5.8 dBm | 個体別ルックアップ |
| 0 dBm | 0x00〜0x04 | -1.5〜+1.9 dBm | 個体別ルックアップ |
| -8 dBm | 0xFFF8〜0xFFFC | -9.2〜-6.7 dBm | 個体別ルックアップ |
| -20 dBm | 0xFFEC〜0xFFF0 | -22.1〜-18.3 dBm | 個体別ルックアップ |
キャリブレーションホストはTXパワーレジスタを4〜5段階でスイープし、各値をパワーメータまたはスペクトラムアナライザで測定、線形補間テーブルを構築し、レジスタ対dBmのマッピングをモジュール内部フラッシュに保存します。実行時にはアプリケーションファームウェアがこのテーブルを読み取り正確な電力目標を達成します。これはアンテナ経路間の電力差が0.5dB未満でなければならないAoA/AoD方向探知で特に重要です。
製造経済性:テストカバレッジ vs コスト
テスト時間の1秒ごとにコストがかかります。EMSはライン時間1秒あたり$0.02〜$0.05を請求します。BOMが$3.50のモジュールでは、68秒のテストで$1.36〜$3.40が追加され、単価が倍になる可能性があります。線引きがエンジニアリング判断の核心です。
| テスト項目 | 追加時間 | カバレッジ | スキップリスク |
|---|---|---|---|
| 3チャネル完全RFキャル | +8秒 | チャネル間電力平坦度 | 低 — 通常0.5dB以内 |
| RSSIオフセットキャリブレーション | +5秒 | ±1 dB RSSI精度 | 中 — 距離推定に影響 |
| スリープ電流測定 | +4秒 | リーク、不良パッシブ | 高 — スリープ電流異常は電池を消耗 |
| アンテナVSWRチェック | +3秒 | アンテナ離調、組立不良 | 高 — 3dB効率低下は機能テストで検出不可 |
| 温度サイクル | +120秒 | 水晶ドリフト、はんだ疲労 | サンプリングのみ — 全数非対象 |
製造テストの鉄則:スリープ電流とアンテナVSWRは絶対に省略しないこと。これらは機能的なアドバタイズテストでは検出できない物理的欠陥(水晶負荷コンデンサのはんだブリッジ、PCB位置ずれによるアンテナ不整合)を捕捉します。アドバタイズは正常でもスリープ時に2µAではなく800µAを消費するモジュールは、節約したテスト時間の10倍のコストがかかる保証返品を生み出します。
自動化:手動から完全自動化へ
完全自動化テストセルの構成:
- テスト治具:電源・UART/SWD・RF用ポゴピンベッド(同軸スイッチ→SMA)
- 計測器:スペクトラムアナライザ(Rigol RSA3030N相当)、µA読み取り対応プログラマブル電源(Keithley 2280S相当)
- シールド筐体:2.4GHzで>60dBアイソレーション(JRE 0806またはカスタム)
- ホストPC:SCPI/VISA経由で計測器、シリアル経由でDUTを制御するPythonテストスクリプト
- MESデータベース:全シリアル番号と全測定値をトレーサビリティ用に記録
Pythonテストオーケストレータ — 骨格:
import pyvisa, serial, sqlite3, time
class ModuleTester:
def __init__(self, sn):
self.sn = sn
self.rm = pyvisa.ResourceManager()
self.sa = self.rm.open_resource('TCPIP::192.168.1.100::INSTR')
self.psu = self.rm.open_resource('USB0::0x05E6::0x2280::12345::INSTR')
self.dut = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
self.db = sqlite3.connect('production.db')
def measure_frequency_offset(self, channel=0):
freq = 2402 + channel * 2 # MHz
self.dut.write(b'AT+CWTX=%d\r\n' % channel)
time.sleep(0.1)
self.sa.write(f'FREQ:CENT {freq}MHZ')
self.sa.write('INIT:IMM')
offset = float(self.sa.query('CALC:MARK:X?')) - freq * 1e6
return int(offset)
def measure_sleep_current(self):
self.dut.write(b'AT+SLEEP\r\n')
time.sleep(0.5)
current = float(self.psu.query('MEAS:CURR?'))
return current * 1e6 # µA
def calibrate_and_store(self):
offset = self.measure_frequency_offset()
trim = offset // 16
self.dut.write(f'AT+XTALTRIM={trim}\r\n'.encode())
offset2 = self.measure_frequency_offset()
if abs(offset2) > 2000:
raise Exception(f"XTAL cal failed: {offset2} Hz offset")
i_sleep = self.measure_sleep_current()
if i_sleep > 5.0:
raise Exception(f"Sleep current {i_sleep:.1f} µA exceeds 5 µA limit")
self.db.execute(
'INSERT INTO test_results VALUES (?, ?, ?, ?)',
(self.sn, offset2, trim, i_sleep)
)
self.db.commit()
return True
歩留まり最適化:データ駆動トリミング
10,000個のモジュール後、製造データベースがパターンを明らかにします。XTALトリム値のヒストグラムは水晶の製造公差分布を示します。平均トリムが-8(すなわち水晶が一貫して128Hz速い)の場合、PCBレイアウトに水晶ピンの過剰な寄生容量がある可能性があり、外部負荷コンデンサを12pFから10pFに減らせば分布は中心にシフトします。このようなクローズドループフィードバックが92%の歩留まりと98.5%の歩留まりを分け、月産10万個では6.5%の差が6,500個の不良削減につながります。
結論
製造テストはコストセンターではなく、モジュールが顧客に届く前に受ける最後のエンジニアリングレビューです。適切に設計されたテストステーションは、水晶オフセットを接続断になる前に捕捉し、スリープ電流をバッテリー寿命クレームになる前に測定し、RF出力を距離問題になる前に検証します。68秒を投資してください。代替案は、数日間のデバッグ、ライン停止、そしていかなるキャリブレーションでも修復できない評判の損失です。
Bluetoothモジュールは、出荷するプロセスと同等の信頼性しか持ちません。徹底的にテストし、精密にキャリブレーションし、すべてを記録してください。