Safeties and Protections — Xregulator¶
What the firmware does when voltage, current, temperature, or RPM exceeds safe limits. Each protection lists its trigger, the action it takes, the variable names you can grep for, whether each variable is user-settable (persisted in Flash via LittleFS) or hardcoded, and the modes where it is active.
The system uses several shared mechanisms (ramp paths, immediate cuts, cooldown lockout). These are defined once below, then referenced by name in each protection.
Notation and Shared Mechanisms¶
Voltage sensors¶
Two physical sensors:
- BatteryV — ADS1115 channel 0. Used only for the cross-sensor disagreement check.
- IBV — INA228 bus voltage. The signal used by all software protections.
getBatteryVoltage()returnsIBV.
The INA228 hardware ALERT pin operates on the chip's own internal averaged value (not visible to firmware).
Three shutdown paths¶
| Path | Phases | When used |
|---|---|---|
| Immediate cut | applyImmediateCut() — GPIO4 LOW within one loop tick, PWM zeroed, PID reset, sysMode = FAULT. No cooldown. |
INA228 hardware OV, hard overcurrent, temp critical, RPM below minimum |
Warning ramp (MODE_WARNING_RAMP_AND_LOCKOUT) |
Phase 1: slew duty down to rpmMinDuty at DutyRampRate (50 %/s default). Phase 2: hold for ShutdownPhase2HoldMs (0 = skip). Phase 3: slew to 0 at DutySlowRampRate (1 %/s default). Phase 4: hold at 0 for SettleTimeBeforeCut, then GPIO4 LOW. Then FIELD_COLLAPSE_DELAY cooldown lockout. |
Alternator hard-shutdown, voltage disagreement warning, temp warning/sustained |
Critical ramp (MODE_CRITICAL_RAMP) |
Same as Warning ramp but skips Phases 1 and 3 entirely — jumps directly to Phase 4. Slew limiter forced off. Same cooldown after Phase 4. | Voltage disagreement critical, voltage implausible, temp data stale, current data stale |
All ramp parameters (DutyRampRate, DutySlowRampRate, SettleTimeBeforeCut, ShutdownPhase2HoldMs) are user-settable.
Cooldown lockout¶
FIELD_COLLAPSE_DELAY (user-settable, default 30 s) — held after every Warning- or Critical-ramp shutdown. While held, MODE_LOCKOUT_RAMP is active and no charging attempts. After it elapses the system retries; if the fault is still active a new lockout begins. Not applied to immediate-cut faults.
nearBulk arming gate¶
All voltage OV throttling protections (Groups 1, 2, 3) and load-dump detection arm only when the active charging target is within ProtectionProxGateV of BulkVoltage:
nearBulk = (ProtectionProxGateV <= 0) OR (ChargingVoltageTarget >= BulkVoltage − ProtectionProxGateV)
User-settable: ProtectionProxGateV (default 0.5 V). Set to 0 to arm always.
Voltage Overvoltage Protections¶
Eight distinct mechanisms. Group 1/2/3 are throttling protections that keep charging while trimming current. Load dump and Alternator Hard Shutdown ramp the field down. The INA228 hardware ALERT is the final hardware backup. The three voltage-sensor failure protections handle the case where a sensor itself is broken.
Group 1 — Prediction-Based Cap¶
Predicts where voltage will be TdPred seconds from now and trims the current cap if the prediction overshoots.
- Trigger:
Vpred > ChargingVoltageTarget + OvPredMarginV, whereVpred = IBV + TdPred × max(0, dvdt)anddvdtis EMA-smoothed atDvdtAlpha. - Arming guard:
IBV > ChargingVoltageTarget − 0.06 V(PRED_GUARD, hardcoded). Prevents firing during ramp-up. - Action:
fastOvCurrentCap = min(fastOvCurrentCap, setpointLimited − KHard × (Vpred − V_HARD)). SetsfastOvClampActivewhich forcesGOV_BYPASS_SLEW(the duty slew limiter is removed so the output current loop can collapse the field at full speed). - dvdt sample window: 1–100 ms between INA samples. Fast mode (~4.3 ms, field on) passes; slow mode (~1054 ms, field off) rejected — dvdt holds last value. Safe because the group only arms while the field is on.
- User-settable:
OvGroup1Enable,TdPred(0.045 s),OvPredMarginV(0.15 V),DvdtAlpha(0.08),KHard(35 A/V — shared with Group 2). - Hardcoded:
PRED_GUARD= 0.06 V. - Active: AUTO,
voltageControlActive && nearBulk.
Group 2 — Measured Voltage Threshold¶
Fires on present measured voltage, no prediction.
- Trigger:
IBV > ChargingVoltageTarget + OvMeasMarginV. - Action:
fastOvCurrentCap = min(fastOvCurrentCap, setpointLimited − KHard × (IBV − target − OvMeasMarginV)). SameGOV_BYPASS_SLEWside effect. - User-settable:
OvGroup2Enable,OvMeasMarginV(0.10 V),KHard(35 A/V). - Active: AUTO,
voltageControlActive && nearBulk.
Group 3 — Current-Based (iExcess Supervisor)¶
Catches OV before it appears in voltage by watching for excess alternator current at the moment the CV loop should be trimming back.
- Trigger: measured alternator current exceeds
setpointLimited + IExcessKforIExcessNconsecutive control ticks (each ~5 ms). - Signal source: selected by
IExcessSigSrc— MA(N) (default), EMA(TC), or raw. MA window isIExcessMA_N; EMA TC isInputFilterTC(Plant Delay tab). - Voltage arming sub-gate:
IBV > ChargingVoltageTarget − OvMeasMarginV. Symmetric counterpart to Group 2 — "how close to target before overshoots become serious." One knob (OvMeasMarginV) controls both. - Hysteresis on release: stays latched until current falls back to
setpointLimited + IExcessK − 2.0 A(IEXCESS_HYST, hardcoded). Prevents on/off chatter. - Action on fire: snap
cv_Ito 0 (default) or proportional bleed atIExcessKBleed × excessA/s.fastOvCurrentCap = max(0, fastOvBaseCap − 1.0 × excess)(cap slopeK_IE, hardcoded). SetsfastOvClampActive. - Recovery seed:
cv_I = preEventCvI × IExcessReseedFracon release. Prevents bouncing straight back through setpoint. - Post-fastOV mismatch gate: after any fastOV event, Group 3 is suppressed until measured current actually falls back to within
IExcessKof setpoint — prevents firing on field wind-down current already handled by Group 1/2. - User-settable:
IExcessK(5 A),IExcessN(3 ticks),IExcessKBleed(0 = snap),IExcessReseedFrac(0.5),IExcessSigSrc(MA(N)),IExcessMA_N. - Hardcoded:
IEXCESS_HYST= 2.0 A,K_IE= 1.0 A/A. - Active: AUTO,
voltageControlActive && nearBulk.
Load Dump Detection¶
Three-tier rate-of-change detection on battery current — catches the upward dBcur/dt spike when loads are switched off.
| Tier | Threshold | Persistence | Catches |
|---|---|---|---|
| 1 | LoadDumpDtThresh1 (4000 A/s) |
1 sample | Hard-switched FET disconnects |
| 2 | LoadDumpDtThresh (1500 A/s) |
2 consecutive | Standard relay openings |
| 3 | LoadDumpDtThresh3 (1000 A/s) |
3 consecutive | Slow relay-contact disconnects |
- Gate:
voltageControlActive && nearBulk && inaFastModeActive(field on, INA fast mode). - Action on fire:
cv_I = 0,setpointLimited = 0,fastOvCurrentCap = 0,fastOvClampActiveset. AW bleed drives recovery. - All three thresholds user-settable.
- Active: AUTO with
voltageControlActive.
Alternator Hard Shutdown (absolute)¶
Software absolute trip on IBV. The only software-layer hard OV shutdown.
- Trigger:
IBV > AlternatorHardShutdownV. - Action:
MODE_WARNING_RAMP_AND_LOCKOUT. Phase 1 → 3 → 4 ramp, GPIO4 LOW,FIELD_COLLAPSE_DELAYcooldown. - Slew-bypass accelerator: if
IBV > AlternatorHardShutdownV + 0.5 V(hardcoded),govMode = GOV_BYPASS_SLEW— Phase 1 becomes instant instead of slewing atDutyRampRate. - User-settable:
AlternatorHardShutdownV. First-boot default auto-scales toBulkVoltage + 0.3 V(12 V system → 14.8 V, 24 V → 29.1 V, 48 V → 57.9 V). Once saved, the value is absolute and never auto-adjusts — re-set manually if you change BulkVoltage system class. - Hardcoded: +0.5 V slew-bypass offset.
- Active: AUTO only. Bypassed in MANUAL and LIMP HOME.
INA228 Hardware ALERT (hardware backup)¶
The fastest and most direct protection. Operates entirely in hardware — the firmware doesn't need to run.
- Trigger: INA228 internal averaged bus voltage exceeds
VoltageHardwareLimit = BulkVoltage + 0.3 V(auto-tracked; recomputed on everyBulkVoltagechange). - Action: INA228 ALERT pin asserts (active LOW, open-drain) → pulls GPIO4 LOW physically → gate driver loses power → field collapses.
- Filter: chip is configured
SLOW_ALERT. Average length depends on conversion config — fast mode (inaFastModeActive, field on) gives ~4.3 ms cycle; slow mode (field off) gives ~1054 ms. So the hardware is fast when it needs to be and slow when the field is off (where noise margin is irrelevant). - Software latch:
inaOvervoltageLatchedis set byCheckAlarms()(runs every 250 ms; polls for new events every 5 s). Latch is held; release check at 3 s, definitive recheck every 10 s. While latched,selectFieldEventReason()returnsREASON_INA_OVERVOLTAGEat Priority 1 andapplyImmediateCut()runs every control tick. - Post-clear suppression: for
INA_OV_DISAGREE_SUPPRESS_MS(10 s, hardcoded) after the latch clears, the voltage-disagreement check is suppressed (sensors diverge naturally as the field collapses). - User-settable: indirectly via
BulkVoltage. The +0.3 V offset is hardcoded. - Hardcoded: +0.3 V offset,
INA_OV_DISAGREE_SUPPRESS_MS= 10 s, latch recheck cadences. - Active: ALL modes including MANUAL and LIMP HOME. Disabled only when
INADisconnected = 1.
Voltage Sensor Failure Protections¶
These do not detect overvoltage on the battery — they detect that the voltage sensors themselves are giving inconsistent or impossible readings.
Disagreement Warning¶
- Trigger:
|BatteryV − IBV| > VoltageDisagreeThresholdsustained forVoltageDisagreeTimeout. - Action: Warning ramp + 30 s lockout.
- Suppressed during INA OV latch and for 10 s after clearing.
- User-settable:
VoltageDisagreeThreshold(0.15 V),VoltageDisagreeTimeout(10 s). - Active: AUTO only.
Disagreement Critical¶
- Trigger:
|BatteryV − IBV| > critical_thresholdsustained forVoltageDisagreeCriticalTimeoutMs(3 s, hardcoded), or either sensor returns NaN, or either sensor reads < 0.1 V. The NaN/<0.1 V cases fire immediately with no debounce. - Critical threshold auto-scales by system class: 1.0 V (12 V), 2.0 V (24 V), 4.0 V (48 V).
- Action: Critical ramp (Phase 4 direct) + 30 s lockout.
- User-settable: none — the threshold is auto-scaled, the timeout is hardcoded.
- Active: AUTO only.
Implausibility¶
- Trigger: both BatteryV and IBV are outside the plausible voltage range for the system class (single-sensor implausibility passes — needs both bad).
- Auto-scaled ranges (0.5 V buffer hardcoded): 12 V → 4.5–15.5 V; 24 V → 9.0–30.5 V; 48 V → 18.0–60.5 V.
- Action: Critical ramp (Phase 4 direct) + 30 s lockout.
- Fires immediately — no debounce.
- User-settable: none. The ranges are auto-derived from
BulkVoltage. - Active: AUTO only.
Voltage OV — Threshold Cascade (Default 12 V Settings)¶
What fires when, in order of voltage threshold:
IBV |
Protection | Action |
|---|---|---|
| target + 100 mV | Group 2 | Trim current cap |
| target + 150 mV predicted | Group 1 | Trim current cap |
| target − 100 mV (and current excess) | Group 3 (iExcess) | Snap cv_I, trim cap |
14.8 V (BulkVoltage + 0.3) |
Alternator Hard Shutdown | Warning ramp + 30 s lockout |
14.8 V averaged (VoltageHardwareLimit) |
INA228 hardware ALERT | Physical GPIO4 cut (backup; same threshold but uses chip's averaged value) |
15.3 V (AlternatorHardShutdownV + 0.5) |
Slew-bypass accelerator | Phase 1 becomes instant |
| Both sensors > 15.5 V (or < 4.5 V) | Implausibility | Critical ramp + 30 s lockout |
Note: Group 1/2/3 thresholds are relative to ChargingVoltageTarget (which is bulk in bulk, absorption in absorption, etc.), while the hard-shutdown thresholds are absolute and reference BulkVoltage directly.
Co-firing behavior¶
The hardware ALERT and software hard-shutdown reach the same nominal threshold by design (both BulkVoltage + 0.3 V). The software uses raw IBV; the hardware uses the chip's averaged value. On a fast transient the software fires first; on a slow ramp the hardware catches up. When both fire on the same event, applyImmediateCut() detects gpio4IsLow already, suppresses redundant logging, and only sets the software latch state.
Temperature Protections¶
All temperature protections use TempToUse (mirrored from AlternatorTemperatureF if TempSource = 0, otherwise temperatureThermistor). Setting IgnoreTemperature = 1 disables T0–T3 below. T4 (TempTask hang) and T5 (data stale) are unaffected.
T0 — Thermal PID (continuous derate)¶
Subtracts a penalty from the RPM-table current ceiling before the output current loop sees it. Not a fault response — normal steady-state thermal management.
- PID setpoint:
TemperatureLimitF(the actual damage limit). - Process variable:
projectedTempF = tempFiltered + thermalSlopeFPerSec × ThermalLookaheadSec. Predictive — starts derating before temperature reaches the limit, based on how fast it is rising. - Output:
thermalPenaltyAmps, asymmetrically slew-limited (ThermalPenaltyRiseRateup,ThermalPenaltyFallRatedown). Subtracted fromgetCapCurrentForRPM(RPM)before clamping toMaxTableValue. - Stale-temp safety: if temp is NaN or out of range, the PID halts and holds the last penalty rather than zeroing it. T5 cuts the field if the data stays stale for 20 s.
- User-settable:
TemperatureLimitF(150 °F),ThermalLookaheadSec(90 s),TempPIDKp(3.0 A/°F),TempPIDKi(0.025 A/°F/s),TempPIDFilterAlpha(0.2),TempPIDIntervalMs(5000 ms),ThermalPenaltyRiseRate(60 A/s),ThermalPenaltyFallRate(20 A/s). - Active: AUTO only.
T1 — Warning Ramp¶
- Trigger:
TempToUse > TemperatureLimitF + TempWarnExcess(default 150 + 2 = 152 °F). - Action: Warning ramp + 30 s lockout.
- User-settable:
TempWarnExcess(2 °F). - Active: AUTO only.
T2 — Sustained Warning¶
- Trigger: T1 condition sustained continuously for
TempSustainedTimeout(default 120 s). Timer resets when temp drops below the warning threshold. - Action: GPIO4 cut after Phase 4 settle. No auto-restart — field stays off until manual re-enable or reboot.
- User-settable:
TempSustainedTimeout(120 s). - Active: AUTO only.
T3 — Critical (immediate cut)¶
- Trigger:
TempToUse > TemperatureLimitF + TempCritExcess(default 150 + 10 = 160 °F). - Action: Immediate cut via
applyImmediateCut(). No ramp, no cooldown timer. - User-settable:
TempCritExcess(10 °F). - Active: ALL modes including MANUAL. T3 sits at Priority 1 in
selectFieldEventReason(), evaluated before the manual-mode check at Priority 2. Manual does not bypass this.
T4 — TempTask Hang¶
Heartbeat monitor for the OneWire task running on Core 0. Triggers the buzzer unconditionally; field cut is handled by T5 (which fires at the same 20 s threshold when the task hangs).
- Trigger:
millis() − lastTempTaskHeartbeat > TEMP_TASK_TIMEOUT(20 s, hardcoded). - Action:
tempTaskAlarm = true→ GPIO21 buzzer fires regardless ofAlarmActivate. Field cut comes from T5 sinceMARK_FRESHstops being called when the task hangs. - Hardcoded:
TEMP_TASK_TIMEOUT= 20 s. - Active: ALL modes when
IgnoreTemperature = 0. Independent ofselectFieldEventReason().
T5 — Temperature Data Stale¶
The primary field-cut for any temperature monitoring failure. Detects 20 s with no validated reading. Handles read errors (CRC fails, sensor disconnects, bad data) and hung-task scenarios.
- Trigger: any of:
dataTimestamps[IDX_ALTERNATOR_TEMP] == 0 && millis() > 60 s; ormillis() − tempTimestamp > 20 s; or value is NaN, < −50 °F, or > 400 °F. - Action: Critical ramp + 30 s lockout.
- Recovery: automatic on first valid read after lockout clears.
- Hardcoded: 20 s staleness window.
- Active: AUTO only.
Overcurrent Protections¶
Hard Overcurrent (electronic fuse)¶
- Trigger:
MeasuredAmps > HardOCTripAmpsforHardOCDebounceMs. - Action: Immediate cut via
applyImmediateCut(). No ramp, no cooldown timer. - User-settable:
HardOCDebounceMs(20 ms). - Auto-derived:
HardOCTripAmps = MaxTableValue + 10 A(recomputed whenMaxTableValuechanges; not persisted). - Active: ALL modes including MANUAL. Priority 1 in
selectFieldEventReason().
Current Alarms (buzzer only)¶
Two thresholds that drive the buzzer but never touch the field:
- Alternator current alarm:
MeasuredAmps > CurrentAlarmHigh. User-settable, default 100 A. - Battery current alarm:
|Bcur| > MaximumAllowedBatteryAmps. User-settable, default 150 A.Bcuris INA228 net battery current, not alternator output.
Both fire via CheckAlarms() if AlarmActivate = 1. Throttled to one console message per 30 s.
Note: The Group 3 iExcess supervisor (under Voltage OV above) is also current-based, but it functions as an OV protection — it fires when current is excessive given the voltage situation. The hard OC trip here fires on absolute current regardless of voltage.
RPM Gate¶
- Trigger:
RPM < MinRPMForField(whenIgnoreRPM = 0). - Action: Immediate cut via
applyImmediateCut(). No ramp, no cooldown timer. - User-settable:
MinRPMForField(200 RPM),IgnoreRPM(off by default). - Active: ALL modes. Priority 3 in
selectFieldControlMode().
System-Level Safeties¶
Hardware Watchdog¶
- Timeout: 16 s (hardcoded in setup via
esp_task_wdt_init). - Feeds:
esp_task_wdt_reset()at the start of everyloop()iteration and during long operations (OTA, cloud upload). - On timeout:
trigger_panic = true→ full system reboot. On reboot, all GPIO pins reset LOW, which cuts the field driver. - Monitors: Core 1 (main task) only.
Alarm Buzzer (GPIO21)¶
Driven by CheckAlarms() every 250 ms. Aggregates all alarm conditions into one GPIO. Independent of field control — the buzzer has no authority over GPIO4.
| Condition | Threshold | Gated by AlarmActivate? |
|---|---|---|
| High alternator temperature | TempAlarm (190 °F) |
Yes |
| Low alternator temperature | TempAlarmLow (32 °F, 0 = off) |
Yes |
| High battery voltage | VoltageAlarmHigh (15 V) |
Yes |
| Low battery voltage | VoltageAlarmLow (11 V, > 8 V floor) |
Yes |
| High alternator current | CurrentAlarmHigh (100 A) |
Yes |
| High battery current | MaximumAllowedBatteryAmps (150 A) |
Yes |
| INA228 hardware OV latch | Any INA OV event | Yes |
| Temp sensor not responding | No valid read for > 20 s | Yes |
| Efficiency anomaly | effAnomalyAlarmActive |
Yes |
| TempTask hung | TempTask heartbeat > 20 s | No — always fires |
AlarmLatchEnabled — if set, buzzer stays on after the condition clears until ResetAlarmLatch.
Quick Reference — User-Settable Parameters¶
Voltage OV throttling (Voltage tab):
| Parameter | Default | Purpose |
|---|---|---|
OvGroup1Enable / OvGroup2Enable |
on / on | Per-group enables |
OvPredMarginV |
0.150 V | Group 1 trigger |
OvMeasMarginV |
0.100 V | Group 2 trigger + Group 3 voltage gate |
KHard |
35 A/V | Group 1+2 cap slope |
TdPred |
0.045 s | Group 1 prediction horizon |
DvdtAlpha |
0.08 | Group 1 dvdt EMA alpha |
IExcessK |
5 A | Group 3 current threshold above setpoint |
IExcessN |
3 ticks | Group 3 persistence |
IExcessKBleed |
0 (snap) | Group 3 integrator response |
IExcessReseedFrac |
0.5 | Group 3 recovery seed |
IExcessSigSrc / IExcessMA_N |
MA(N) / — | Group 3 signal filter |
LoadDumpDtThresh1/2/3 |
4000 / 1500 / 1000 A/s | Load dump three-tier |
ProtectionProxGateV |
0.5 V | nearBulk gate width |
AwBleedRate / AwRecoverRate / AwSeedProtectMs |
2.0 / 0.1 / 150 ms | AW integrator behavior |
SlopeBleedThresh / SlopeBleedK / SlopeBleedProxV |
0.5 V/s / 50 / 0.5 V | Slope-bleed integrator drain |
Voltage shutdown / sensor health (Battery tab → Safety):
| Parameter | Default | Purpose |
|---|---|---|
AlternatorHardShutdownV |
BulkVoltage + 0.3 V on first boot |
Software absolute trip |
VoltageDisagreeThreshold |
0.15 V | Warning trigger |
VoltageDisagreeTimeout |
10 s | Warning debounce |
FIELD_COLLAPSE_DELAY |
30 s | Cooldown lockout |
SettleTimeBeforeCut |
1000 ms | Phase 4 settle |
Shutdown ramp shape (Tuning → Current → Rate Limiting):
| Parameter | Default | Purpose |
|---|---|---|
DutyRampRate |
50 %/s | Phase 1 duty slew |
DutySlowRampRate |
1 %/s | Phase 3 duty slew |
ShutdownPhase2HoldMs |
0 (skip) | Phase 2 hold |
Temperature (Temperature tab):
| Parameter | Default | Purpose |
|---|---|---|
TemperatureLimitF |
150 °F | PID setpoint and base for all thresholds |
TempWarnExcess |
2 °F | T1 warning (152 °F) |
TempCritExcess |
10 °F | T3 immediate cut (160 °F) |
TempSustainedTimeout |
120 s | T2 escalation timer |
TempAlarm / TempAlarmLow |
190 °F / 32 °F | Buzzer thresholds |
ThermalLookaheadSec |
90 s | Predictive PID horizon |
TempPIDKp / TempPIDKi |
3.0 / 0.025 | Temperature PID gains |
TempPIDFilterAlpha |
0.2 | Temp input EMA |
TempPIDIntervalMs |
5000 ms | Temp PID compute period |
ThermalPenaltyRiseRate / FallRate |
60 / 20 A/s | Penalty slew limits |
IgnoreTemperature |
0 | Disable T0–T3, T5 |
Overcurrent / RPM:
| Parameter | Default | Purpose |
|---|---|---|
HardOCDebounceMs |
20 ms | Hard OC debounce |
CurrentAlarmHigh |
100 A | Alternator current alarm |
MaximumAllowedBatteryAmps |
150 A | Battery current alarm |
MinRPMForField |
200 RPM | RPM gate |
IgnoreRPM |
0 | Disable RPM gate |
Quick Reference — Hardcoded Constants¶
| Constant | Value | Where |
|---|---|---|
PRED_GUARD |
0.06 V | Group 1 arming dead-band |
IEXCESS_HYST |
2.0 A | Group 3 release hysteresis |
K_IE |
1.0 A/A | Group 3 cap slope |
| AlternatorHardShutdownV slew-bypass | +0.5 V | Phase 1 instant when this far above threshold |
| INA228 hardware OV offset | +0.3 V above BulkVoltage |
VoltageHardwareLimit |
INA_OV_DISAGREE_SUPPRESS_MS |
10 s | Disagreement check suppress after INA OV clears |
| INA228 latch recheck cadences | 3 s / 10 s / 5 s | Early/definitive/new-event poll |
VoltageDisagreeCriticalTimeoutMs |
3 s | Critical disagreement debounce |
| Critical disagreement threshold | 1 / 2 / 4 V | Auto-scaled by system class |
| Implausibility plausible range buffer | 0.5 V | Buffer around system class min/max |
TEMP_TASK_TIMEOUT |
20 s | Heartbeat deadline |
| Temp staleness window | 20 s | T5 trigger |
HardOCTripAmps offset |
+10 A above MaxTableValue |
Auto-derived |
| Watchdog timeout | 16 s | Hardware reset on hang |
BULK_V_BAND |
50 mV below BulkVoltage |
Bulk→Absorption arming band |
KiDown multiplier |
7 × VoltageKi |
CV PI asymmetric unwind |
CV_HIGH_DEADBAND_V |
25 mV | CV tuning HIGH-phase overshoot dead-band |
Mode-by-Mode Active Protections¶
| Protection | AUTO | MANUAL | LIMP HOME |
|---|---|---|---|
| Group 1 / 2 / 3 (Voltage OV throttling) | Active (CV stages, nearBulk) |
— | — |
| Load Dump | Active | — | — |
| Alternator Hard Shutdown | Active | — | — |
| INA228 hardware ALERT (physical) | Active | Active | Active |
| INA228 software latch | Active | Active (Priority 1) | Active (pre-gate, before LIMP path) |
| Voltage disagreement (warning + critical) | Active | — | — |
| Voltage implausible | Active | — | — |
| T0 thermal PID derate | Active | — | — |
| T1 / T2 warning + sustained | Active | — | — |
| T3 critical immediate cut | Active | Active (Priority 1) | — |
| T4 TempTask hang alarm | Active | Active | Active |
| T5 temp data stale | Active | — | — |
| Hard overcurrent | Active | Active (Priority 1) | — |
| RPM gate | Active | Active | — |
| Watchdog reboot | Active | Active | Active |
| Buzzer | If AlarmActivate = 1 (TempTask hang always) |
Same | Same |
"—" means the priority hierarchy in selectFieldControlMode() returns MODE_NORMAL_MANUAL (Priority 2) or LIMP HOME bypasses the protection chain entirely, before the listed protection is evaluated.