Skip to main content
Firmware Stable

State machine

The BMS has a state machine that defines the behavior of the BMS.

The state is available as a variable:

  • /driver/state - string variable, the state name is printed
  • /driver/statemachine/state - integer variable, the state code is printed
ValueModePrinted nameDescriptionDSCCHG
0ERRERRORPermanent ERROROFFOFF
10FAILFAILFail (temporary) stateOFFOFF
20INITINITBMS is not set, minimum parametrization requiredOFFOFF
30PROTECTPROTTransient state, verifying that the error(s) has disappearedOFFOFF
40UNDERVOLTAGEUVUndervoltage of some battery cell detectedOFFOFF
60STORAGESTORBattery is being discharged to storage voltageOFFOFF
70STANDBYSTBYBMS switched OFF, no errorsOFFOFF
80PRECHARGINGPREStarting by prechargingPREOFF
90OVERVOLTAGEOVOvervoltage of some battery cell detectedONOFF
100IDLEIDLEIdle state - DSC port ON but no discharging or charging currentONOFF
110DISCHARGINGDISCHDischarging batteryONOFF
120REGENREGCharging battery by DSC from motorONOFF
124CHG_OVERTEMPCHOTCharger connected, but battery temperature is outside the charging limitsONOFF
125CHG_IDLECH_IDCharger connected but no chargingONOFF
130CHARGINGCHARCharging battery by CHG from chargerONON

The "Printed name" column shows the short state name printed by /driver/state and in the diagnostic logs.

How the state is evaluated

The state machine evaluates the conditions in a fixed priority order. The first matching condition wins:

  1. INIT — the cell count parameter /driver/balancing/Scount is 0 (the BMS is not configured yet)
  2. ERROR — any permanent error condition is active
  3. FAIL — any temporary fail condition is active
  4. PROTECT — any protect event is active, or the protect timer is still running
  5. UNDERVOLTAGE / OVERVOLTAGE — a cell voltage is out of the configured limits
  6. Runtime states — decided by the port command, current direction and charger detection:
    • Ports commanded OFF → STANDBY
    • DSC port is precharging → PRECHARGING (see precharging)
    • Current flowing from the battery → DISCHARGING
    • Current flowing into the battery → CHARGING (charger detected) or REGEN (no charger)
    • No significant current → CHG_IDLE (charger detected) or IDLE
    • Charger detected, but the battery temperature is outside the minChg/maxChg charging temperature limitsCHG_OVERTEMP (charging blocked, discharge stays available)

The current direction is detected with a time filter using the idle configuration (idle_current magnitude threshold and idle_timeout).

PROTECT state

The PROTECT state is entered when the BMS detects a condition that endangers the battery pack and the ports must be turned OFF. It is a transient state - the BMS stays in it for at least protect_timeout and until all protect conditions disappear. After that, the BMS returns to STANDBY, and the user must turn the ports back ON (using the sw command or over CAN).

If the BMS enters PROTECT state, the BMS will log the reason for entering the PROTECT state. The reason is available as a permanent variable protectLog. The permanent is an array of 20 logs. With a new log, the values are shifted to the right, and the oldest log is deleted. The newest log is always on the first position (most left). Use the wtf command to decode the log to human readable form - see diagnostic.

protectLog is a bitwise value - multiple reasons can be active at the same time (the values are OR-ed together).

ValueReasonCondition to enter
0x0000NoneNo protect reason active
0x0001Leave error stateLogged when the BMS is recovering from the FAIL state. The FAIL cause disappeared and the BMS passes through PROTECT back to normal operation.
0x0002ShortcutShort circuit detected on the DSC port - the current exceeded the short circuit threshold (idscShort for longer than idscDelay on BMS3, ishrt on BMS1). Increments the shortcut_counter permanent.
0x0004Shortcut on CHGShort circuit on the CHG port - current from the battery exceeded ichgshrt. Increments shortcut_counter. (BMS1 only)
0x0008Shortcut on CHG to batteryShort circuit on the CHG port - current into the battery exceeded ichgshrtp. Increments shortcut_counter. (BMS1 only)
0x0010DSC switch power overloadThe power dissipated in the DSC switch transistors was too high - the switch did not close properly, or it is heavily overloaded.
0x0020Shortcut of DSC transistorHardware failure of the DSC switch transistor. (legacy)
0x0040Current overload on DSCOvercurrent disconnect - the DSC current exceeded ocd_treshold for longer than ocd_delay. See pack current limiter.
0x0080Connected load on CHGA load was detected on the CHG port. (legacy)
0x0100Charger on DSC portA charger was detected on the DSC port. (legacy)
0x0200Overtemp of the switchA BMS internal temperature sensor of the switch (switchptc, mcu) exceeded its max threshold. See temperature limitation.
0x0400Overtemp on TS inputsA battery temperature sensor (TS input) reading is above max or below min (including the margin). See temperature limitation.
0x0800Bat voltage measurement errorThe battery voltage measurement does not match. (legacy)
0x1000Load on DSC during chargingA load current on the DSC port was detected while charging. (legacy)
0x2000Precharge failedThe DSC port voltage did not drop below prch_volt within precharge_time - the load capacitance is too big, or there is a short circuit on the output. See precharging.
0x4000Cell undervoltageThe lowest cell voltage was below cellMinVoltage for more than 1 s. See cell voltage limitation.
0x8000Cell overvoltageThe highest cell voltage was above cellMaxVoltage for more than 2 s. See cell voltage limitation.
note

Cell undervoltage (0x4000) and overvoltage (0x8000) alone do not hold the BMS in the PROTECT state - the BMS transitions to the dedicated UNDERVOLTAGE / OVERVOLTAGE states, where charging (UV) or discharging (OV) is still allowed.

note

Difference between PROTECT and FAIL/ERROR state:

  • PROTECT - protecting the battery pack
  • FAIL/ERROR - protecting the BMS (and pack)

FAIL/ERROR state

If the BMS enters FAIL/ERROR state, the BMS will log the reason for entering the FAIL/ERROR state in /permanents/errorLog. The permanent is an array of 20 logs. With a new log, the values are shifted to the right, and the oldest log is deleted. The newest log is always in the first position (most left). Use the wtf command to decode the log to human readable form - see diagnostic.

The only difference between FAIL and ERROR state is that the ERROR state is permanent, and the FAIL state is temporary. If you are in FAIL and the reason for entering the FAIL state is resolved, the BMS will automatically leave the FAIL state. If the BMS is in the FAIL for a longer time than the fail_timeout, the BMS will enter the ERROR state.

Values 100 and above are FAIL (recoverable) reasons, values below 100 are ERROR (permanent) reasons.

note

If the BMS is in the ERROR state, the BMS will disable wake from the CAN bus. Before communicating with the BMS, it is necessary to wake up the BMS by pressing the button.

ERROR reasons (permanent)

ValueReasonCondition to enter
0NoneNo error active
5Max fails reachedThe permanent fail_counter exceeded the max_fails parameter. The counter is incremented on every entry into the FAIL state.
6Max shortcuts reachedThe permanent shortcut_counter exceeded the max_shortcuts parameter. The counter is incremented on every short circuit event (any of the shortcut PROTECT reasons).
7Fail timerThe BMS stayed in the FAIL state for longer than the fail_timeout parameter without the fail reason disappearing.
10PanicThe battery was overcharged over the DSC port - cell overvoltage was active while charging current kept flowing into the battery for more than 20 s. The BMS cannot stop current flowing into the DSC port (it flows through the MOSFET body diodes), so it enters the permanent error as a last resort.
10Hardware errorThe hw_error state is non-zero - a hardware problem was detected during initialization or at runtime. See hardware status.
note

Panic and hardware error share the same log value 10.

FAIL reasons (temporary)

ValueReasonCondition to enter
101Heatsink isolationThe heatsink isolation voltage heatsink_isol left the allowed window - the heatsink is no longer isolated from the battery potential (e.g. moisture, mechanical damage). The behavior is configured by the htsIsolCfg parameter.
102Balancer errorThe balancer IC reports an error - the BMS cannot communicate with the balancer chip (communication problem), a parameter could not be written to the chip, or the chip reports an internal fault.
103Balancer failThe balancer IC stopped responding at runtime. The BMS retries the communication every 5 s. If the balancer does not recover within fail_timeout, the BMS enters the permanent ERROR state.
104Critical undervoltageA cell voltage was below the /driver/balancing/limiter/CritUnderVoltage parameter for more than 10 minutes. The battery is deeply discharged, and the BMS goes to sleep to prevent further discharge.
105Battery disbalancedCell undervoltage and overvoltage detected at the same time - the battery is heavily disbalanced.
106Cell check failThe cell connection check failed - some cells report an unexpected voltage (see badCells in balancing states), or the sum of all cell voltages differs from the measured pack voltage by more than 1 V. Typical cause: wrong Scount setting or a broken cell sense wire.

Recovering from the ERROR state

The ERROR state is permanent - the BMS will not leave it automatically. To recover:

  1. Wake the BMS by pressing the button (CAN wake is disabled in ERROR).
  2. Resolve the cause of the error (check errorLog with the wtf command).
  3. Use the clr_err shell command - it clears the error state and resets the fail_counter and shortcut_counter permanents.

State machine configuration

The state machine is configured in the /driver/stateMachine folder.

ParameterUnitDescription
fail_timeoutsIf the state is FAIL for longer time than the timeout, the BMS enter ERROR state
max_fails-Maximum number of fails before entering ERROR state
max_shortcuts-Maximum number of shortcuts before entering ERROR state
protect_timeoutsMinimum time in PROTECT state before recovering

State machine states

These read-only states are available in the /driver/stateMachine folder.

StateDescription
stateInternal state machine state code (see the state table above)
cmd_drvPending command for the ports: 0 = OFF, 1 = DSC on, 2 = CHG on, 3 = DSC+CHG on
fail_timerRemaining time in ms before the FAIL state becomes a permanent ERROR
protect_timerRemaining minimum time in ms in the PROTECT state

State machine permanents

PermanentDescription
fail_counterCount of FAIL state entries. When it exceeds max_fails, the BMS enters the ERROR state. Cleared by clr_err.
shortcut_counterCount of short circuit events. When it exceeds max_shortcuts, the BMS enters the ERROR state. Cleared by clr_err.