Skip to main content
Firmware Stable

LYNX: the motor does not run or does not react to the throttle

Applies to

Motor controllers running the LYNX application: the swid from list_devices contains _LYNX_. Builds (mods) differ in features, so a path that does not exist may belong to another build - see LYNX mods. Other applications (OPHION, FALCON, ...) use the same variable names and numbers with other meanings: do not apply this playbook to them; use the general method and search_docs with the application name.

Before you start

Follow the general method: read-only tools, exact case-sensitive paths, quote values, name the device by name and serial number. Ask the user what exactly happens (no sound at all, a beep, the motor twitches, nothing when the throttle is pressed). Never write, save, reboot or run a motor command unless the user asks for that exact action and the operator has raised emGUI's level.

Read in this order: /mode, then the error words, then /disarm_reason. /mode 100 does not mean the device is armed.

Steps

1. Find the device

emgui_status, then list_devices; pick the node whose swid contains _LYNX_. Empty list: Could not discover any nodes.

2. Read /mode

read_variable /mode. Meanings: LYNX mode table; a lower number has priority.

  • 0 - driver or common-block error: step 3.
  • 2 - invalid input readings: read /common/stat (value 1 set = inputs not valid, see common state) and the GPIO voltages, then step 5.
  • 6, 65, 68 - BMS error or BMS reports charging: BMS setup and bmsopts. 65 needs a power cycle after charging; 68 clears when charging ends.
  • 9 - motor identification running: wait for it to finish.
  • 10 - initialisation after power-up, lasts /best/reset_time. If it never leaves 10, collect a report (step 10).
  • 20 - the CAN control message is missing: control message 0x5FF and the 0x5FF bits of safetyopts.
  • 30 - welding builds only: the controller works as a welder (welding).
  • 70 - step-up charging (special hardware): wait for charging to end.
  • 79 - slave in a multi-controller setup; the master decides: multi-controller setup.
  • 80 - driver override, typically from the stop command; run without arguments releases it (stop). Tell the user; do not run it yourself.
  • 90 - locked: lock (lock at start-up, lock input mapping).
  • 95 - seat switch: seat switch.
  • 100 to 110 (standby, braking, accelerating, kickback, assist, cruise) - no blocking condition: step 3, then step 4.
  • 120 - permanently disarmed until reboot (/disarm_reason negative, typically -18: the accelerator): find the cause with steps 3-5, fix it, then the user power-cycles.
  • Any other value - read its row in the linked table and say so.

3. Read /driver/error and /common/error

4. Read /disarm_reason

Meanings: disarm reasons. What a disarm blocks: disarming block. A negative value stays until reboot; fix the cause first.

LYNX arms only when the accelerator is valid and released for a moment. /disarm_reason keeps the reason that started the disarm while the device waits to arm. Also read /safetyopts (safetyopts): with value 1 (ACC NaN disarms forever) set, the stock setting, an invalid accelerator shows -18 and /mode 120 instead of 21.

  • 0 - armed. If the throttle still does nothing, step 5 (is /sig_acc following the throttle?) and step 6.
  • 1 or 21 - not armed since power-up or since a blocking mode (21: /mode was in a mode that blocks driving - error, power-up initialisation, BMS error or charging, invalid inputs, CAN timeout, identification). /mode still blocking: step 2 for that mode. /mode 100 or another normal mode: the device is waiting to arm, step 5. With safetyopts value 1 clear, an accelerator invalid from power-up leaves 21 with mode 100 indefinitely.
  • 2 - the accelerator signal became invalid while the device was armed (seen only with safetyopts value 1 clear); it re-arms once the signal is valid and released: step 5.
  • -18 (with /mode 120) - the accelerator signal was invalid at some point since power-up, including from power-up, and safetyopts value 1 makes that permanent: step 5, fix, then the user power-cycles.
  • 10 seat switch; 11, 12 reverse or map change (map options); 13, 14, 15 BMS (see mode 6 above); 16 shutdown in progress; 17 identification running (wait); 19, 20 geofencing; 23 step-up charging (mode 70 above); 24 slave; 25, 26, 27 brake (static brake, drvopts, safetyopts); 28 driver override (mode 80 above); 29 locked (mode 90 above). Any other value: read its row in the table.

5. Check the accelerator input chain

Read the parameters with list_variables (kind: param, path: /io, then path: /acc/asc); read everything else, the states and the /common/ioconfN parameter, with read_variable.

  1. /io/IN_acc - two values: the physical input and its options. 8-12 = GPIO0-4 (input IDs, pin assignment). An input taken from CAN is described under special input values.
  2. /common/gpioN for that GPIO, in mV (GPIO readings); /acc/asc/in shows the same input.
  3. Compare it with /acc/asc absmin, min, max, absmax (ASC safety settings, ASC variables). Below absmin or above absmax (0 = that limit is not set) the output is invalid, which disarms: typically a disconnected wire, connector or throttle.
  4. /acc/asc/out - NaN confirms an invalid accelerator.
  5. /acc/csc/out, once /acc/asc/out is a number - the accelerator after the dead zones (CSC states); it must be 0 with the throttle released. Not 0 at rest means the device sees the throttle as pressed and will not arm: the released voltage is above min (or away from center when center is set) by more than the dead zone (ASC tuning, CSC dead zones). /sig_acc is 0 whenever the device is disarmed and shows the throttle only once armed: use it only with /disarm_reason 0 (sig_acc).
  6. /common/ioconfN for that GPIO - an analogue throttle wants 0, floating (GPIO configuration). With 2 (pull-down) an open wire reads near 0 mV, which is below absmin.
  7. /common/iovolt, if the device has it - the sensor supply the controller gives the throttle; near 0 means that supply is missing. A low supply also sets a /common/error bit.
  8. Redundant throttle, only when dual_err is not 0 (dual throttle error; find its path with list_variables pattern: dual_err): /acc/acc_err; /acc/asc_2/out matters only then.

Voltage at the rail or near 0 mV: wiring, connector or throttle - ask the user to check it. Voltage in range but IN_acc points to the wrong GPIO, or the limits do not fit the throttle: a configuration change (step 8).

6. Context reads

  • /driver/stat - active warnings (over-current, under-voltage, temperature ...): driver state.
  • /driver/limit - active limiters: limiter word. Bit 14 alone (16384) follows the map's torque level and is not a fault (map settings).
  • /driver/enable - 0 at standstill is normal (enable).
  • /driver/supply/voltage - the battery voltage (supply); compare it with the controller's range in its hardware documentation.

7. History

execute_command log (it can return -1 while printing entries - use the output). Compare each entry's run with the current run permanent (read_variable /permanents/run): a smaller run is an earlier power-up, history rather than the present cause; a larger one means the counter was reset since, so the entry is older still (error log format). pmlog is optional.

8. Fix, one change at a time

Propose a single change, cite the page, say which variable goes from what to what. Parameter writes and save need the operator to raise emGUI's level to write; a negative disarm reason, mode 120, /driver/error and /common/error also need a power cycle after the fix. Read the chain again afterwards.

9. Report

  1. Device: name, serial number, swid.
  2. /mode, /driver/error, /common/error, /disarm_reason, quoted.
  3. Cause, with the values that show it (for the throttle: IN_acc -> GPIO mV -> limits -> asc/out -> csc/out).
  4. Fix, and which part needs a write.
  5. URLs used; old log entries named as history.

10. Escalate

Cause not found, a driver error that returns after a reboot, or suspected hardware: ask for a diagnostic report.

Worked example

Example unit (LYNX), reported "does not run":

  • /mode = 100: no blocking mode. /driver/error = 0, /common/error = 0.
  • /disarm_reason = 21 with a normal mode: waiting to arm, go to the accelerator.
  • /io/IN_acc = 11,0: GPIO3. /common/gpio3 = 7 mV, /acc/asc/absmin = 500 mV: below the limit, so /acc/asc/out and /acc/csc/out = NaN and the device never arms. /sig_acc = 0 only because the device is disarmed.
  • /common/ioconf3 = 2 (pull-down): an open wire reads about 0 mV, which fits. /common/iovolt = 11.1 V: the throttle supply is present.
  • log: two "phase A/C CM diff" entries from runs 903 and 980; the run permanent is 1432, so they are history, not the cause.
  • /safetyopts = 0 on this unit, so it shows 21 rather than -18.

Diagnosis: no throttle signal on GPIO3 - wire, connector or throttle. Fix the connection; then GPIO3 reads within min...max, /acc/asc/out becomes a number, /acc/csc/out is 0 with the throttle released, and the device arms. Setting ioconf3 to 0 is the recommended setting for an analogue throttle but does not replace the missing signal.