MIL, SIL et HIL sont trois niveaux de test hardware-in-the-loop qui échangent coût et vitesse contre fidélité. Utilisez le MIL pendant le développement d'algorithmes, le SIL pour valider le code compilé, et le HIL pour vérifier le comportement sur du matériel réel avant la production.
Ce que signifient MIL, SIL et HIL
Model-in-the-Loop (MIL) exécute votre algorithme de contrôle sous forme de modèle de simulation contre une plante simulée. Aucun matériel impliqué. Itération rapide, faible coût, mais fidélité la plus basse.
Software-in-the-Loop (SIL) compile votre code de production et l'exécute sur une machine hôte contre un environnement simulé. Même binaire, pas de matériel. Détecte les bugs de génération de code que le MIL manque.
Hardware-in-the-Loop (HIL) exécute votre code de production sur l'ECU ou le microcontrôleur cible, connecté à un simulateur temps réel qui émule l'environnement physique. Fidélité la plus élevée, coût le plus élevé.
Matrice de comparaison
| Dimension | MIL | SIL | HIL |
|---|---|---|---|
| Coût | Faible | Faible à moyen | Élevé |
| Vitesse | Rapide (secondes) | Moyenne (minutes) | Lente (minutes à heures) |
| Fidélité | Faible | Moyenne | Élevée |
| Matériel requis | Aucun | Aucun | ECU cible + rack simulateur |
| Usage typique | Conception d'algorithmes | Vérification du code | Validation système |
| Compatible CI | Oui | Oui | Non (banc dédié) |
| Découverte de bugs | Erreurs de conception | Erreurs de codegen | Intégration, timing |
Quand utiliser chaque approche
MIL : développement précoce d'algorithmes
Utilisez le MIL quand l'algorithme change encore, que vous avez besoin d'itérations rapides, que le matériel n'est pas encore disponible, ou que vous effectuez des balayages paramétriques. Le MIL n'est pas adapté quand vous devez valider le comportement temporel, la latence d'interruption ou la communication sur bus.
SIL : vérification du code avant le matériel
Utilisez le SIL quand la génération de code est terminée, que vous voulez détecter les régressions en CI, que vous validez l'équivalence numérique entre le modèle et le code généré, ou que les créneaux sur le banc matériel sont rares. Le SIL manque les défauts de timing temps réel et le comportement des périphériques spécifiques au matériel.
HIL : validation système pré-production
Utilisez le HIL quand le firmware de l'ECU est figé, que vous devez valider le timing et le comportement du bus, que la certification exige des preuves matérielles, ou que vous exécutez des suites de régression de nuit. Le HIL est coûteux à mettre en place et lent à itérer.
Exemple : test de limite de tension à chaque niveau
La même logique de test s'exécute aux trois niveaux. Seul le plug change.
MIL : capteur simulé
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
class SimulatedVoltageSensor(htf.plugs.BasePlug):
"""Retourne une valeur déterministe depuis un modèle de simulation."""
def setUp(self):
pass
def read_voltage(self) -> float:
return 11.8
def tearDown(self):
pass
@htf.plug(sensor=SimulatedVoltageSensor)
@htf.measures(
htf.Measurement("battery_voltage")
.in_range(minimum=10.0, maximum=14.5)
.with_units(units.VOLT),
)
def measure_battery_voltage(test, sensor):
test.measurements.battery_voltage = sensor.read_voltage()
def main():
test = htf.Test(measure_battery_voltage, test_name="battery-voltage-mil")
with TofuPilot(test):
test.execute(test_start=lambda: "UNIT-MIL-001")
if __name__ == "__main__":
main()SIL : code compilé contre un bus simulé
import ctypes
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
class SILVoltageSensor(htf.plugs.BasePlug):
"""Appelle la bibliothèque C de production compilée via ctypes."""
LIB_PATH = "./build/battery_monitor.so"
def setUp(self):
self._lib = ctypes.CDLL(self.LIB_PATH)
self._lib.get_battery_voltage.restype = ctypes.c_float
def read_voltage(self) -> float:
return float(self._lib.get_battery_voltage())
def tearDown(self):
pass
@htf.plug(sensor=SILVoltageSensor)
@htf.measures(
htf.Measurement("battery_voltage")
.in_range(minimum=10.0, maximum=14.5)
.with_units(units.VOLT),
)
def measure_battery_voltage(test, sensor):
test.measurements.battery_voltage = sensor.read_voltage()
def main():
test = htf.Test(measure_battery_voltage, test_name="battery-voltage-sil")
with TofuPilot(test):
test.execute(test_start=lambda: "UNIT-SIL-001")
if __name__ == "__main__":
main()HIL : ECU réel sur banc matériel
import can
import openhtf as htf
from openhtf.util import units
from tofupilot.openhtf import TofuPilot
class HILVoltageSensor(htf.plugs.BasePlug):
"""Lit la tension depuis l'ECU réel via le bus CAN."""
CHANNEL = "can0"
BUSTYPE = "socketcan"
def setUp(self):
self._bus = can.interface.Bus(channel=self.CHANNEL, bustype=self.BUSTYPE)
def read_voltage(self) -> float:
msg = self._bus.recv(timeout=1.0)
raw = msg.data[2]
return raw * 0.1
def tearDown(self):
self._bus.shutdown()
@htf.plug(sensor=HILVoltageSensor)
@htf.measures(
htf.Measurement("battery_voltage")
.in_range(minimum=10.0, maximum=14.5)
.with_units(units.VOLT),
)
def measure_battery_voltage(test, sensor):
test.measurements.battery_voltage = sensor.read_voltage()
def main():
test = htf.Test(measure_battery_voltage, test_name="battery-voltage-hil")
with TofuPilot(test):
test.execute(test_start=lambda: "UNIT-HIL-001")
if __name__ == "__main__":
main()Comment TofuPilot suit les résultats à tous les niveaux
Chaque exécution de test est envoyée à TofuPilot avec le même nom de mesure (battery_voltage) quel que soit le niveau. Le champ test_name distingue l'environnement.
| test_name | Niveau | Traçabilité |
|---|---|---|
battery-voltage-mil | MIL | Référence algorithme |
battery-voltage-sil | SIL | Régression codegen |
battery-voltage-hil | HIL | Validation matérielle |
Une unité qui passe le MIL mais échoue au SIL indique un problème de génération de code. Une unité qui passe le SIL mais échoue au HIL indique un problème d'intégration matérielle.
Cadre de décision
| Activité | Niveau recommandé |
|---|---|
| Réglage des gains de contrôle | MIL |
| Tests de régression en CI | SIL |
| Vérification de la sortie de génération de code | SIL |
| Validation du comportement bus CAN/LIN | HIL |
| Vérification des interruptions et du timing | HIL |
| Suite d'injection de fautes de nuit | HIL |
| Balayage paramétrique (100+ cas) | MIL ou SIL |
| Validation pré-release | HIL |
| Analyse de cause racine d'un problème terrain | HIL |