Developed by Control Operations & Relay Engineering (CORE), this engine controller is a compact, reliable, and fully state-driven system designed for smooth starts, stable idling, smart throttle behavior, and automatic stall/overheat management. Built for creators who want realistic engine logic without the complexity.
Special thanks to Uran_Wind — creator of the ZE Modular Engine Controller — whose guidance made perfect stoichiometric control possible. His work and support were instrumental in bringing this controller to life.
========================================
ENGINE CONTROLLER – STATE MACHINE
========================================
STATES:
- OFF
- CRANK
- RUN
- STALL
- OVERHEAT
State debug output:
OFF = 0
CRANK = 1
RUN = 2
STALL = -1
OVERHEAT = -2
========================================
SECTION 1 – WHAT EACH STATE DOES
========================================
OFF
---
• Throttle Out = 0.
• Starter = OFF.
• PID and timers are idle (nothing running here).
• Engine is considered fully off.
CRANK (Starting)
-----------------
• Resets the Engine PID when entering.
• Runs the StartTimer (counts how long we've been cranking).
• Starter = ON while RPS ≤ Max Starter RPS.
• Tracks how stable the RPS is:
- If RPS changes a lot or is still very low → RpsStableTimer is reset.
- If RPS is steady and above Stall RPS → RpsStableTimer counts up.
• Throttle Out = PID aiming at Idle RPS (tries to spin engine to idle speed).
RUN (Normal running)
---------------------
• Normal “engine is running” state.
If Throttle Mode = 1 (PID throttle):
• Target RPS = Idle RPS + Throttle In * (Max RPS - Idle RPS).
• Throttle Out = PID that tries to reach that target RPS.
If Throttle Mode = 0 (Raw Input):
• If Throttle In = 0 OR RPS is below (Idle RPS - margin):
- PID tries to hold Idle RPS.
- Throttle Out = whatever PID says (idle throttle).
- idle_throttle is updated here.
• Else (player is on throttle and engine is healthy):
- Uses previously learned idle_throttle.
- Throttle Out = idle_throttle + Throttle In * (1 - idle_throttle)
(blends from “just enough to idle” up to full power).
- If RPS ≥ Max RPS → Throttle Out = 0 (over-speed cut).
STALL (Engine stalled / failed start)
--------------------------------------
• Throttle Out = 0.
• Runs StallDebounceTimer (short delay before auto-restart).
• No starter here by default; this state just marks “the engine is dead”
and prepares for possible auto-crank.
OVERHEAT (Too hot)
-------------------
• Active only if Overheat Protection is not “NONE”.
• Calculates an overheat_factor (1 at 100°C, goes down as temp rises).
• Two modes:
1) Protection = REDUCE:
• Throttle is reduced based on overheat_factor.
• Same logic as RUN, but scaled down:
- In PID throttle mode: target power is reduced.
- In Blend mode: final output is multiplied by overheat_factor.
• If Temp ≥ 110°C → internally upgrades protection to SHUTOFF.
2) Protection = SHUTOFF:
• Throttle Out = 0 (kills engine power).
• On leaving OVERHEAT, protection mode is reset to the configured setting
from the property (NONE / REDUCE / SHUTOFF).
========================================
SECTION 2 – TRANSITION LOGIC ONLY
========================================
Legend:
Power = On/Off input (bool)
RPS = Engine speed
Temp = Engine temperature
Stall RPS = Stall_RPS value
StartTimer = “how long we tried to start”
RpsStableTimer = “how long RPS has been stable above stall”
StallDebounceTimer = short delay before auto-restart
Start If Stall = auto restart enabled?
Protection Type = NONE / REDUCE / SHUTOFF
Overheat Prot = property that sets the base protection type
FROM OFF
--------
IF Power == TRUE
→ CRANK
(OFF has no other outgoing transitions)
FROM CRANK
----------
IF Power == FALSE
→ OFF
IF RpsStableTimer is done
(RPS has been steady and above Stall RPS for enough time)
→ RUN
IF StartTimer is done
(cranking too long without success)
→ STALL
FROM RUN
--------
IF Power == FALSE
→ OFF
IF RPS ≤ Stall RPS
(engine bogged down / died)
→ STALL
IF Temp ≥ 100
AND Protection Type ≠ "NONE"
(engine too hot and protection enabled)
→ OVERHEAT
FROM STALL
----------
IF Power == FALSE
→ OFF
IF Start If Stall == TRUE
AND StallDebounceTimer is done
(auto-restart enabled and debounce time passed)
→ CRANK
FROM OVERHEAT
-------------
IF Power == FALSE
→ OFF
IF Protection Type ≠ "SHUTOFF"
AND Temp is back below the protection threshold
AND RPS < Stall RPS
(cooled, engine basically not spinning)
→ CRANK (try to start again)
IF Protection Type ≠ "SHUTOFF"
AND Temp is back below the protection threshold
AND RPS > Stall RPS
(cooled, engine still running)
→ RUN (go back to normal running)
(Note: If Protection Type ESCALATES to or was already "SHUTOFF" then it will transition out of the OVERHEAT State when temperature is below 90C to avoid repeated Crank attempts.)
========================================
SUPER SHORT FLOW SUMMARY
========================================
OFF --Power ON--> CRANK --stable RPS--> RUN
RUN --stall--> STALL --auto restart--> CRANK
ANY --Power OFF--> OFF
RUN --overheat--> OVERHEAT --cooled--> RUN or CRANK (depending on RPS)
STALL --auto restart disabled--> stays STALL until Power OFF
If you have any issues let me know in the discussion page!