diff --git a/app/simulation/modules/engine.py b/app/simulation/modules/engine.py index 4359dbf..6b17821 100644 --- a/app/simulation/modules/engine.py +++ b/app/simulation/modules/engine.py @@ -171,38 +171,43 @@ class EngineModule(Module): # Hilfsfunktionen def visco(temp_c: float) -> float: - # -10°C -> 0.6, 20°C -> 0.8, 90°C -> 1.0 + # -10°C -> 0.6, 20°C -> 0.8, 90°C -> 1.0 (linear segmentiert) if temp_c <= -10: return 0.6 if temp_c >= 90: return 1.0 - return 0.6 + (temp_c + 10.0) * 0.004 + if temp_c <= 20: + # -10..20°C: 0.6 -> 0.8 (30 K Schritt → +0.2 => +0.006666.. pro K) + return 0.6 + (temp_c + 10.0) * (0.2 / 30.0) + # 20..90°C: 0.8 -> 1.0 (70 K Schritt → +0.2) + return 0.8 + (temp_c - 20.0) * (0.2 / 70.0) # Spannungsfaktor: unter vmin kein Crank, bei 12.6V ~1.0 vfac = 0.0 if elx_v <= starter_vmin else min(1.2, (elx_v - starter_vmin) / max(0.3, (12.6 - starter_vmin))) crank_rpm = starter_nom * vfac * visco(oil) - # effektive Start-Schwelle: nie unter Stall+50 und nicht „unplausibel“ hoch - start_rpm_th_eff = max(stall_rpm + 50.0, min(start_rpm_th, 0.35 * idle)) + # sinnvolle effektive Startschwelle (unabhängig von stall) + start_rpm_min = 0.15 * idle # 15 % vom Idle + start_rpm_max = 0.45 * idle # 45 % vom Idle + start_rpm_th_eff = max(start_rpm_min, min(start_rpm_th, start_rpm_max)) - # --- Ziel-RPM bestimmen (ohne Jitter) --- + # --- Ziel-RPM bestimmen --- if ign in ("OFF", "ACC"): self._running = False target_rpm = 0.0 + elif ign == "START": - # deterministisches Cranken - target_rpm = crank_rpm - # zünde/greife, sobald die effektive Schwelle erreicht ist + target_rpm = crank_rpm # wie gehabt + # Greifen, sobald Schwelle erreicht und Spannung reicht if not self._running and target_rpm >= start_rpm_th_eff and elx_v > starter_vmin: self._running = True else: # ON - # „Catch on ON“: wenn beim Umschalten genug Restdrehzahl da ist, gilt er als angesprungen - if not self._running and rpm >= max(stall_rpm + 50.0, 0.20 * idle): + # Catch-on-ON: wenn beim Umschalten noch genug Drehzahl anliegt + if not self._running and rpm >= max(0.15 * idle, start_rpm_th_eff * 0.9): self._running = True if self._running: cold_add = max(0.0, min(cold_gain_max, (90.0 - cool) * cold_gain_per_deg)) idle_eff = idle + cold_add - # Pedal/PI-Logik bleibt wie gehabt, target_rpm wird weiter unten aus net_torque bestimmt target_rpm = max(idle_eff, min(maxr, rpm)) else: target_rpm = 0.0