概要
HIL(Hardware-in-the-Loop:ハードウェア・イン・ザ・ループ)とは、実際のコントローラハードウェア(ECUや組み込み機器)をテスト対象として、その周囲の物理環境(エンジン、センサー、アクチュエータ等)をリアルタイムシミュレーターで模擬してテストする手法です。
通常のソフトウェアシミュレーションと異なり、「実際のハードウェア」がテストに参加するため、ファームウェアの実機動作・タイミング特性・入出力インターフェースの正確な検証が可能です。一方で、物理的なプラントに接続するリスク(壊れた制御コードが実車や機械を破壊する等)を排除して安全にテストできます。
自動車・航空宇宙・鉄道・産業機器などの安全クリティカルな分野では、HILテストは開発の標準プロセスに組み込まれており、規格(ISO 26262、DO-178C等)でも要求される場合があります。
歴史・背景
1980年代:航空宇宙産業でHILシミュレーションの概念が体系化されました。フライトシミュレータの制御系テストで、実際のフライトコンピュータを模擬された航空機ダイナミクスに接続してテストする手法が開発されました。
1990年代:自動車産業でエンジン制御(ECU)の複雑化に伴い、HILテストが普及しました。dSPACEやNational Instrumentsが自動車向けHILシステムを製品化。Bosch・BMW・トヨタ等のOEMが開発プロセスに採用しました。
2000年代:AUTOSAR(AUTomotive Open System ARchitecture)の普及とともに、HILテストがソフトウェア開発プロセスに標準統合されました。MATLAB/Simulinkによるモデルベース開発からHILシステムへの自動コード生成が一般化しました。
2010年代以降:HILシステムの低コスト化が進み、Raspberry PiやSpeedgoatなどのオープン/セミオープンシステムが登場。ArduinoやESP32等の小型組み込み機器向けのミニHIL環境も作れるようになりました。また電気自動車・自動運転の普及により、バッテリーシステム・センサーフュージョンのHILテストが重要性を増しています。
技術仕様
HILシステムの構成要素
+------------------------+ +------------------------+
| リアルタイムシミュレータ | | ターゲットECU / 組込機器 |
| |◄──────►| |
| プラントモデル | | ファームウェア |
| (エンジン/モータ等) | | (制御アルゴリズム) |
| | | |
| I/O ボード: | | 実際のI/O: |
| ・アナログ出力 → ADC |──────►| ・センサー入力 |
| ・PWM入力 ← GPIO |◄──────| ・アクチュエータ出力 |
| ・CAN バス |◄──────►| ・CAN通信 |
| ・デジタルI/O |◄──────►| ・GPIO |
+------------------------+ +------------------------+
HILシステムの分類
| 種類 | 説明 | 用途 |
|---|---|---|
| 信号レベルHIL | センサー/アクチュエータ信号を電気的に模擬 | 自動車ECU、航空機制御 |
| 機能HIL | ネットワーク通信(CAN/Ethernet等)を模擬 | 通信プロトコルテスト |
| パワーHIL | 実際の電力を模擬(モータドライバ等) | 電力電子、EV |
| ソフトウェアHIL(SIL) | 全てソフトウェアで模擬(実HWなし) | 開発初期 |
| プロセッサHIL(PIL) | ターゲットプロセッサ上でシミュレーション | コードの実機検証 |
HILの主要プラットフォーム
| プラットフォーム | メーカー | 特徴 | 価格帯 |
|---|---|---|---|
| DS1007 PPC Board | dSPACE | 自動車標準、MATLAB連携 | 高価(数百万〜) |
| PXI/CompactRIO | NI(VeriStand) | モジュール式、柔軟 | 中〜高価 |
| Speedgoat Target | Speedgoat | Simulink Real-Time直接対応 | 中〜高価 |
| ETAS LABCAR | ETAS | AUTOSAR対応 | 高価 |
| OSS HIL(自作) | オープンソース | 低コスト、柔軟 | 低〜中 |
リアルタイム要件
HILシステムのリアルタイム性能は非常に重要です。制御系の更新レートに合わせてシミュレーションを実行する必要があります:
| 制御系 | 典型的なサイクル時間 | シミュレーション要件 |
|---|---|---|
| 自動車エンジン制御 | 1〜10ms | 1ms以下 |
| 電力変換器(インバータ) | 10〜100μs | 10μs以下 |
| 航空機フライト制御 | 10〜40ms | ジッタ < 1μs |
| 産業ロボット制御 | 1〜10ms | 1ms以下 |
動作原理
信号のモデリングと I/O の対応
# Pythonによるシンプルなモータモデル例(実際のHILはC/Simulinkが多い)
import time
import numpy as np
class DCMotorModel:
"""DCモータの簡易モデル(HILシミュレーション用)"""
def __init__(self, R=1.0, L=0.01, Ke=0.1, Kt=0.1, J=0.01, B=0.001):
self.R = R # 抵抗 [Ohm]
self.L = L # インダクタンス [H]
self.Ke = Ke # 逆起電力定数 [V/(rad/s)]
self.Kt = Kt # トルク定数 [Nm/A]
self.J = J # 慣性モーメント [kg*m^2]
self.B = B # 粘性摩擦係数
self.omega = 0.0 # 角速度 [rad/s]
self.i = 0.0 # 電流 [A]
def step(self, voltage, dt):
"""1ステップ(dt秒)のシミュレーション"""
# 電気系モデル: L*di/dt = V - R*i - Ke*omega
di = (voltage - self.R * self.i - self.Ke * self.omega) / self.L
self.i += di * dt
# 機械系モデル: J*domega/dt = Kt*i - B*omega
domega = (self.Kt * self.i - self.B * self.omega) / self.J
self.omega += domega * dt
return self.omega, self.i # ← HIL I/OボードのAO/AIとして出力/入力
class HILSimulator:
"""HILシミュレータのコアループ"""
def __init__(self, target_cycle_s=0.001):
self.motor = DCMotorModel()
self.cycle_s = target_cycle_s
def run(self, io_interface):
"""リアルタイムシミュレーションループ"""
while True:
t_start = time.perf_counter()
# ECUからPWMデューティを読み取り電圧に変換
pwm_duty = io_interface.read_pwm_duty()
voltage = pwm_duty * 24.0 # 24V電源想定
# モデルを1ステップ進める
omega, current = self.motor.step(voltage, self.cycle_s)
# 速度センサー(エンコーダ模擬)をECUに出力
io_interface.write_encoder_speed(omega)
# 電流センサー模擬
io_interface.write_current_sense(current)
# 残り時間までスリープ(リアルタイム制約)
elapsed = time.perf_counter() - t_start
sleep_time = self.cycle_s - elapsed
if sleep_time > 0:
time.sleep(sleep_time)
CAN バスを使ったHIL例
// 自動車ECU向け: CANでHILシステムと通信するテスト
// ターゲットECU(実ハード)がCANメッセージを送受信
// HILシステムがエンジン状態を模擬して返す
// ECU側: エンジン回転数要求メッセージ送信
typedef struct {
uint16_t target_rpm; // 目標回転数
uint8_t throttle_pct; // スロットル開度 [%]
} EngineControlMsg;
void send_engine_control(EngineControlMsg *msg) {
CAN_TxHeaderTypeDef header = {
.StdId = 0x100, // ECU制御メッセージID
.DLC = sizeof(EngineControlMsg),
.IDE = CAN_ID_STD,
.RTR = CAN_RTR_DATA,
};
HAL_CAN_AddTxMessage(&hcan1, &header, (uint8_t*)msg, &mailbox);
}
// HILシステム側(dSPACEやカスタムRTシステム):
// 0x100 を受信 → エンジンモデルに入力 → 0x200 で現在のRPM/トルクを返す
用途・ユースケース
自動車ECUの開発
BMW、トヨタ、BoschなどのOEM・Tier1サプライヤーでは全てのECU開発にHILが必須です:
- エンジン制御ECU:燃料噴射・点火タイミングの制御をエンジンモデルに対して検証
- トランスミッションECU:変速制御ロジックをトランスミッションモデルで検証
- ADAS(先進運転支援):カメラ・LiDAR・レーダーのセンサーモデルを使ったシステムテスト
産業機器・ロボット
PLCやモーションコントローラのHILテストは産業機器の開発を安全化します:
- ロボットアームの制御ループをリンク・ジョイントのダイナミクスモデルで検証
- コンベア制御システムを電子カムモデルで検証
宇宙・航空
ISS(国際宇宙ステーション)のソフトウェア更新テスト、人工衛星の姿勢制御システム検証など、実機での繰り返しテストが不可能または危険なケースでHILが必須です。
IoT・スマートビルディング
ビルの空調制御(BACnet/Modbus機器)をHVACモデルに接続してHILテストし、節電ロジックの安全性を確認します。
実装・開発のポイント
オープンソースでのミニHIL構築
小規模な組み込みシステム向けに低コストのHIL環境を作る例:
# Raspberry Pi + Python でミニHIL
# ターゲット: Arduino(モータ制御ファームウェア)
# HIL側: Raspberry Pi(モータモデル + センサー模擬)
import RPi.GPIO as GPIO
import spidev
class MiniHIL:
def __init__(self):
# DACでアナログセンサー信号を模擬
self.spi = spidev.SpiDev()
self.spi.open(0, 0) # SPI経由でDAC(MCP4921)制御
# GPIOでPWM信号を受信(ArduinoのPWM出力を読む)
GPIO.setup(17, GPIO.IN)
def write_dac_voltage(self, voltage, vref=3.3):
"""DACで電圧出力(センサー模擬)"""
value = int(voltage / vref * 4095)
self.spi.xfer2([0x70 | (value >> 8), value & 0xFF])
def read_pwm_duty(self, pin=17, timeout=0.01):
"""GPIOでPWM計測"""
# 立ち上がりエッジから次の立ち上がりまでの周期と
# Hiの期間からデューティ比を計算
...
テスト自動化とCI/CD統合
# GitHub Actions でのHILテスト自動化(自社HILサーバーとの連携例)
name: HIL Test
on:
push:
branches: [main]
jobs:
hil-test:
runs-on: self-hosted # HILサーバー上のランナー
steps:
- uses: actions/checkout@v3
- name: Build Firmware
run: make build
- name: Flash to DUT
run: openocd -f flash.cfg -c "program firmware.elf verify reset exit"
- name: Run HIL Test Suite
run: python3 hil_test_suite.py --report junit-report.xml
- name: Upload Test Results
uses: actions/upload-artifact@v3
with:
name: hil-results
path: junit-report.xml
他技術との比較
| 比較項目 | HIL | MIL(Model-in-Loop) | SIL(Software-in-Loop) | 実機テスト |
|---|---|---|---|---|
| 実ハード | 使用 | 不使用 | 不使用 | 使用 |
| プラント | シミュレーション | シミュレーション | シミュレーション | 実物 |
| ファームウェア検証 | 完全 | 不可 | 部分的 | 完全 |
| リスク | 低(実機保護) | なし | なし | 高 |
| テスト網羅性 | 高(異常系も容易) | 高 | 高 | 低(異常系困難) |
| コスト | 中〜高 | 低 | 低 | 低〜高 |
| 開発フェーズ | 後期(プロト以降) | 初期 | 中期 | 最終 |