Reviewd and fixed deadman architecture

This commit is contained in:
2026-09-10 23:53:27 +02:00
parent 31b3595ac0
commit f8d111ef5c
15 changed files with 304 additions and 305 deletions
+27 -30
View File
@@ -19,7 +19,7 @@ temperature and pressure sensors, and an external starter switch.
| --- | ---: | --- | | --- | ---: | --- |
| Crank trigger input | 1 | 12 V active-low Hall, timer capture | | Crank trigger input | 1 | 12 V active-low Hall, timer capture |
| Cam trigger input | 1 | 12 V active-low Hall, timer capture | | Cam trigger input | 1 | 12 V active-low Hall, timer capture |
| Deadman inputs | 2 | Dedicated, independent 5 V vehicle-logic engine-permit inputs | | Deadman input | 1 | Shared 5 V signal from parallel steering-wheel switches; dedicated hardware engine-permit path |
| Thermistor inputs | 4 | Air, oil, water, and one spare temperature input | | Thermistor inputs | 4 | Air, oil, water, and one spare temperature input |
| General analogue inputs | 9 | Protected 0-5 V sensor channels | | General analogue inputs | 9 | Protected 0-5 V sensor channels |
| ADC rail-monitor channels | 3 | `VBAT_PROT`, `+5V_SENS`, and `+12V_SENS` | | ADC rail-monitor channels | 3 | `VBAT_PROT`, `+5V_SENS`, and `+12V_SENS` |
@@ -150,41 +150,38 @@ actual harness and input-function requirements.
## Deadman Engine-Permit Interlock ## Deadman Engine-Permit Interlock
The deadman uses two dedicated 5 V vehicle-logic inputs, not generic digital The steering wheel has two normally-open switches connected in parallel.
inputs. The steering-wheel switch provides two electrically independent, Holding either switch asserts one shared active-high 5 V `DEADMAN_IN` signal
normally-open contacts. Each contact has its own connector pin, protection, into the ECU; both must be released to deassert it. The ECU uses one dedicated
filtering, default-low bias, and conditioned logic path. This makes an open signal pin, protection/filter network, default-low bias and conditioning path,
circuit or a short to the 5 V source on one signal path non-permissive. separate from generic digital inputs.
The resulting 5 V `DEADMAN_OK` signal is high only when channel A reports The conditioned 5 V `DEADMAN_OK` signal feeds the hardware permission gate.
held and the independently conditioned, inverted channel B reports not One protected 3.3 V `DEADMAN_STATUS` input lets the MCU observe the same combined
released. It has two independent destinations: state. The MCU cannot identify which switch is held or compare their states.
- `DEADMAN_A_STATUS` and `DEADMAN_B_STATUS` enter MCU digital inputs so ![Parallel switches and single deadman input](diagrams/deadman-inputs.svg)
firmware can observe each contact, detect disagreement, disable scheduling,
and report the state.
- `DEADMAN_OK` is combined in hardware with the MCU's `MCU_RUN_PERMIT` output
to produce `ENGINE_PERMIT`.
![Deadman inputs](diagrams/deadman-inputs.svg) ![Single-input engine permission](diagrams/deadman-permit.svg)
![Deadman permit](diagrams/deadman-permit.svg) `ENGINE_PERMIT = DEADMAN_OK AND MCU_RUN_PERMIT`. The injector command is
`SAFE_INJECTOR_SIG = ENGINE_PERMIT AND MCU_INJECTOR_SIG`; the ignition driver
receives `SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT)`. These paths remove
permission in hardware when the shared input goes low, independently of
firmware response. Driver bias networks must establish off/inhibited states
through power loss and MCU reset.
`ENGINE_PERMIT` controls the enable inputs of the injector and ignition drivers Both switches released, an open shared signal or loss of switch supply removes
where those inputs are provided. If a selected driver has no suitable enable permission through the default-low input. An open individual switch branch
input, `ENGINE_PERMIT` is ANDed with that driver's MCU command signal using leaves the other switch usable. A stuck-closed switch or a shared signal shorted
logic that defaults to the disabled state on power-up or loss of power. to the asserted source can keep permission asserted; this single-input
arrangement cannot detect those faults or per-switch disagreement.
This hardware path ensures that releasing the deadman, an open circuit, or a Firmware clears pending injection and dwell schedules when `DEADMAN_STATUS`
single signal-path short to the 5 V source stops injector and ignition commands deasserts. A test mode may assert `MCU_RUN_PERMIT`, but cannot bypass a low
even if firmware or a timer output fails to respond. It does not claim to cover physical deadman input; bench operation requires a deliberate external test
a common-mode fault that energises both paths. Firmware must clear/disable arrangement asserting the single shared signal. The detailed interface and
pending injection and dwell schedules whenever `DEADMAN_OK` becomes invalid or fault behavior are defined in [DEAD_MAN.md](IO_MODULES/DEAD_MAN.md).
the two MCU status inputs disagree. A firmware test mode may assert
`MCU_RUN_PERMIT`, but it does not override the physical deadman inputs; bench
operation requires a deliberate external test arrangement that presents the
valid two-channel held state. The detailed signal and fault model is defined in
[DEAD_MAN.md](IO_MODULES/DEAD_MAN.md).
## Outputs ## Outputs
+88 -74
View File
@@ -3,106 +3,120 @@
## Purpose ## Purpose
This module provides the hardware run-permission path for the engine outputs. This module provides the hardware run-permission path for the engine outputs.
The steering-wheel dead-man switch must be held to assert permission. Two The steering wheel has two normally-open deadman switches wired in parallel.
electrically independent, normally-open switch contacts and two independent Holding either switch closes the circuit; holding both also closes it. Their
harness signal paths are required. Releasing the switch, an open circuit, outputs are tied together at the steering wheel and form **one shared deadman
one signal path shorted to the 5 V source, loss of a logic supply, or MCU reset signal entering the ECU**, not two independently monitored inputs.
must place the engine outputs in their non-energising state independently of
firmware.
This document defines the signal relationships and destinations only. Output The existing active-high 5 V interface is retained: either switch connects the
driver implementation is documented separately. protected 5 V source to `DEADMAN_IN`. Both switches must be released to remove
permission. The ECU conditions this one signal for hardware gating and MCU
observation. Output-driver implementation is documented separately.
## Logic domains ## Logic domains
| Signal | Domain | Active state | Default/fault state | | Signal | Domain | Meaning |
| --- | --- | --- | --- | | --- | --- | --- |
| `DEADMAN_A_HELD` | Protected 5 V logic | High: deadman channel A observes its contact held | Low: released or fault | | `DEADMAN_IN` | Harness-connected 5 V input | High when either parallel switch is held; ECU-side bias holds it low when both are released or the shared signal is open. |
| `DEADMAN_B_RELEASED` | Protected 5 V logic | High: deadman channel B does not observe its contact held | Low: contact held | | `DEADMAN_OK` | Conditioned 5 V logic | Active-high hardware observation of the single deadman input. It is not proof that a switch or harness fault is absent. |
| `DEADMAN_OK` | Protected 5 V logic | High: channels have the valid held-state relationship | Low: released or fault | | `DEADMAN_STATUS` | Protected 3.3 V MCU input | MCU observation of the same combined deadman state; high means asserted. |
| `MCU_RUN_PERMIT` | 3.3 V MCU logic | High: MCU permits engine operation | Low: no permission | | `MCU_RUN_PERMIT` | 3.3 V MCU logic | High permits engine operation; defaults low. |
| `ENGINE_PERMIT` | 5 V logic | High: both hardware and MCU permit operation | Low: no permission | | `ENGINE_PERMIT` | 5 V logic | High only when deadman and MCU permission are both asserted. |
| `MCU_INJECTOR_SIG` | 3.3 V MCU logic | High: requested injector on-time | Low: injector off | | `MCU_INJECTOR_SIG` | 3.3 V MCU logic | Requested injector on-time; defaults low. |
| `SAFE_INJECTOR_SIG` | 5 V logic | High: permitted injector command | Low: injector off | | `SAFE_INJECTOR_SIG` | 5 V logic | Permitted injector command; low means off. |
| `SAFE_IGNITION_INHIBIT` | 5 V logic | High: ignition output is inhibited | Low: ignition output is permitted | | `SAFE_IGNITION_INHIBIT` | 5 V logic | High inhibits ignition; low permits it. The driver must default to inhibited when permission logic is unpowered. |
| `DEADMAN_A_STATUS` | 3.3 V MCU input | High: channel A contact is observed held | Low: released or fault |
| `DEADMAN_B_STATUS` | 3.3 V MCU input | High: channel B contact is observed held | Low: released or fault |
Each deadman contact has its own harness signal, connector pin, connector-side ## Steering-wheel wiring and ECU input
protection, series/filter network, and default-low bias. The contacts may share
the protected 5 V source at the switch, but neither signal path may share a
pull-up, pull-down, connector pin, or post-contact conductor with the other.
Each contact closes to the protected 5 V source only while the driver holds the
switch. Thus an open signal path reads low; a short of only one signal path to
the source cannot create the valid two-channel state.
Channel A is conditioned non-inverting to create `DEADMAN_A_HELD`. Channel B The two switches share the protected 5 V source and the switched return signal.
is conditioned inverting to create `DEADMAN_B_RELEASED`. This complementary The parallel connection is made before the ECU: only one `DEADMAN_IN` signal
encoding makes the sole valid held state `A = high`, `B = low`. Both raw, conductor and one signal connector pin are required at the ECU, in addition to
conditioned contact observations also enter protected 3.3 V MCU inputs as the supply connection. No separate contact-status wires are provided.
`DEADMAN_A_STATUS` and `DEADMAN_B_STATUS`; these are diagnostic observations,
not the safety-critical shutoff path.
## Signal tree Use one dedicated connector-side protection, series/filter network, default-low
bias and non-inverting conditioning path. It produces the 5 V `DEADMAN_OK`
signal and a protected 3.3 V `DEADMAN_STATUS` observation for the MCU. Keep the
hardware gating independent of firmware; the MCU status input is observational.
Exact protection, filtering and connector assignments remain implementation
items. The generic digital-input module does not replace this dedicated path.
The permission gates operate from `+5V_MAIN` and accept 3.3 V MCU logic | Left switch held | Right switch held | Shared signal / `DEADMAN_OK` (healthy circuit) |
levels. Their outputs are 5 V logic levels. | --- | --- | --- |
| No | No | Low |
| Yes | No | High |
| No | Yes | High |
| Yes | Yes | High |
![Deadman inputs](../diagrams/deadman-inputs.svg) ## Hardware gating
![Deadman permit](../diagrams/deadman-permit.svg) The permission gates operate from `+5V_MAIN`, accept 3.3 V MCU logic levels,
and produce 5 V logic outputs.
![Deadman outputs](../diagrams/deadman-outputs.svg) ![Parallel switches and single deadman input](../diagrams/deadman-inputs.svg)
The logic equations are: ![Single-input engine permission](../diagrams/deadman-permit.svg)
![Permitted injector command and ignition inhibit](../diagrams/deadman-outputs.svg)
The healthy-switch relationship is a physical parallel connection at the
steering wheel, not an OR gate or two channels inside the ECU:
```text ```text
DEADMAN_OK = DEADMAN_A_HELD AND NOT(DEADMAN_B_RELEASED) DEADMAN_IN asserted = LEFT_SWITCH_HELD OR RIGHT_SWITCH_HELD
DEADMAN_OK = conditioned active-high DEADMAN_IN
ENGINE_PERMIT = DEADMAN_OK AND MCU_RUN_PERMIT ENGINE_PERMIT = DEADMAN_OK AND MCU_RUN_PERMIT
SAFE_INJECTOR_SIG = ENGINE_PERMIT AND MCU_INJECTOR_SIG SAFE_INJECTOR_SIG = ENGINE_PERMIT AND MCU_INJECTOR_SIG
SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT) SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT)
``` ```
`LEFT_SWITCH_HELD` and `RIGHT_SWITCH_HELD` above describe physical switch
states only; they are not separately available ECU signals.
## Output destinations ## Output destinations
| Logic output | Destination | Required behavior | | Logic output | Destination | Required behavior |
| --- | --- | --- | | --- | --- | --- |
| `ENGINE_PERMIT` | Hardware injection-command permission gate | Must prevent an injector command from reaching the injection output stage when low. | | `ENGINE_PERMIT` | Injection command gate and ignition-permission inverter | Low removes permission from both engine-output paths. |
| `SAFE_INJECTOR_SIG` | Dedicated injection output stage command input | The only injector on-command presented to the output stage. | | `SAFE_INJECTOR_SIG` | Injector driver command input | The only injector on-command presented to the output stage. |
| `SAFE_IGNITION_INHIBIT` | Dedicated ignition output stage inhibit/enable input | Must inhibit the ignition output stage when high and permit it only when low. | | `SAFE_IGNITION_INHIBIT` | Ignition driver inhibit input | High inhibits the ignition stage; low permits it. |
| `DEADMAN_A_STATUS`, `DEADMAN_B_STATUS` | STM32 digital inputs | Firmware observes both contacts, detects disagreement, clears schedules, and reports diagnostics. Neither input is the safety-critical shutoff path. | | `DEADMAN_STATUS` | One STM32 digital input | Firmware observes the combined deadman state and clears schedules when it deasserts. It cannot identify which switch is held. |
## Fail-safe behavior ## Release and fault behavior
- With the switch released, the valid relationship is - Releasing one switch while the other is held leaves permission asserted.
`DEADMAN_A_HELD = low` and `DEADMAN_B_RELEASED = high`; `DEADMAN_OK` is low. Releasing both switches deasserts `DEADMAN_OK` and removes `ENGINE_PERMIT`
- With the switch held, the only permissive relationship is through hardware, without waiting for firmware.
`DEADMAN_A_HELD = high` and `DEADMAN_B_RELEASED = low`; `DEADMAN_OK` is high. - An open shared signal conductor or loss of the switch supply deasserts the
- An open circuit, an open contact, or a short to the 5 V source on either one input through the ECU-side default-low bias. A shared signal short to ground
signal path produces a non-permissive relationship. A short to ground on a also deasserts it; the protected source must tolerate the assigned fault.
held path also removes permission. - An open individual switch branch disables that switch only. The other
- This architecture protects against one fault in one contact or signal path. parallel switch can still assert the shared signal.
It does not claim to detect a common-mode fault that energises both input - A stuck-closed switch, a bridged contact or the shared signal shorted to the
paths, or simultaneous faults in both contacts/paths. Harness routing and asserted 5 V source can hold `DEADMAN_OK` high after both switches are
connector assignment shall minimise such common-mode faults; any remaining released. This single-input arrangement cannot distinguish those faults
risk requires explicit system-level acceptance. from a legitimate held state. It provides no per-switch disagreement or
independent-channel fault detection.
- `MCU_RUN_PERMIT` and `MCU_INJECTOR_SIG` must default low during reset, - `MCU_RUN_PERMIT` and `MCU_INJECTOR_SIG` must default low during reset,
boot, brownout, or an unpowered MCU. External bias components shall provide boot, brownout or an unpowered MCU. External bias components establish these
these states during power sequencing. states through power sequencing. The MCU can withdraw permission even when
- If `ENGINE_PERMIT` becomes low during an injection command, the deadman signal is high.
`SAFE_INJECTOR_SIG` becomes low and removes the command from the injection - If `ENGINE_PERMIT` becomes low during injection, `SAFE_INJECTOR_SIG` becomes
output stage. low and removes the injector command.
- If `ENGINE_PERMIT` becomes low during an ignition dwell, - If `ENGINE_PERMIT` becomes low during ignition dwell,
`SAFE_IGNITION_INHIBIT` becomes high and commands the ignition output stage `SAFE_IGNITION_INHIBIT` becomes high and requests the ignition driver's
into its non-sparking shutdown behavior. documented non-sparking shutdown behavior.
- If the 5 V permission logic loses power, the injection command input must - If the 5 V permission logic loses power, the injector command must be biased
be externally biased low and the ignition output stage's inhibit input must low and the ignition driver must default to inhibited. Verify this behavior
default to its inhibited state. in the completed input, gate and driver implementation.
## Firmware responsibilities ## Firmware responsibilities
The hardware path is authoritative; firmware cannot override a released or Firmware samples the single `DEADMAN_STATUS` input, clears pending injection
faulted deadman switch. Firmware shall sample both `DEADMAN_A_STATUS` and and ignition schedules when it deasserts, and keeps `MCU_RUN_PERMIT` low except
`DEADMAN_B_STATUS`, clear pending injection and ignition schedules on a while engine operation is intentionally enabled. It has no individual switch
released state or disagreement, report any disagreement, and keep states to compare and must not claim to detect contact disagreement or a
`MCU_RUN_PERMIT` low except while engine operation is intentionally enabled. stuck-high shared signal from this observation alone.
A firmware test mode may assert `MCU_RUN_PERMIT`, but cannot override a low
hardware deadman input. Bench operation requires a deliberate external test
arrangement that asserts the single `DEADMAN_IN` signal.
+2 -2
View File
@@ -7,9 +7,9 @@ NeoECU V1. It accepts externally driven 5 V, 12 V, and protected
battery-domain signals, plus dry-contact and open-collector sources when the battery-domain signals, plus dry-contact and open-collector sources when the
appropriate ECU bias option is fitted. appropriate ECU bias option is fitted.
This is not the crank/cam trigger interface and is not either deadman This is not the crank/cam trigger interface and is not the dedicated deadman
engine-permit input. Those functions retain their dedicated conditioning and, engine-permit input. Those functions retain their dedicated conditioning and,
for the deadman, its independent two-channel hardware safety path defined in for the deadman, its single-input hardware permission path defined in
[DEAD_MAN.md](DEAD_MAN.md). [DEAD_MAN.md](DEAD_MAN.md).
V1 provisionally allocates six generic digital-input channels. The allocation, V1 provisionally allocates six generic digital-input channels. The allocation,
+1 -1
View File
@@ -43,7 +43,7 @@ temperature, and ignition noise.
SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT) SAFE_IGNITION_INHIBIT = NOT(ENGINE_PERMIT)
``` ```
When `ENGINE_PERMIT` is removed by the two-channel deadman interlock or the When `ENGINE_PERMIT` is removed by the single-input deadman interlock or the
MCU, `SAFE_IGNITION_INHIBIT` becomes high. If a dwell is active, this invokes MCU, `SAFE_IGNITION_INHIBIT` becomes high. If a dwell is active, this invokes
the VBG08H-E soft shutdown so coil current is removed without intentionally the VBG08H-E soft shutdown so coil current is removed without intentionally
generating a spark. The 1 kOhm resistors on `INP` and `EN` follow the generating a spark. The 1 kOhm resistors on `INP` and `EN` follow the
+2 -3
View File
@@ -29,7 +29,7 @@ low-impedance injector requires a different architecture.
## Command path ## Command path
`INPUT` is active high. It receives only the hardware-permitted injector `INPUT` is active high. It receives only the hardware-permitted injector
command defined by the two-channel deadman interlock. command defined by the single-input deadman interlock.
![Injector command](../diagrams/injector-command.svg) ![Injector command](../diagrams/injector-command.svg)
@@ -51,8 +51,7 @@ pin.
When `ENGINE_PERMIT` is removed, `SAFE_INJECTOR_SIG` goes low and turns the When `ENGINE_PERMIT` is removed, `SAFE_INJECTOR_SIG` goes low and turns the
injector output off. This is the hardware shutoff path; firmware also clears injector output off. This is the hardware shutoff path; firmware also clears
pending injection events when `DEADMAN_OK` becomes invalid or the two deadman pending injection events when the single `DEADMAN_STATUS` input deasserts.
status inputs disagree.
## Status diagnostic ## Status diagnostic
+5 -2
View File
@@ -66,8 +66,11 @@ Validate each circuit manifest with the installed topology validator:
- The Hall-input drawing separates sensor supply, sensor return and signal; - The Hall-input drawing separates sensor supply, sensor return and signal;
the original ASCII alignment could suggest an unintended join. The pull-up, the original ASCII alignment could suggest an unintended join. The pull-up,
divider and parallel filter follow the existing prose. divider and parallel filter follow the existing prose.
- The deadman equations are unchanged. Contact observations, permission gates - The steering-wheel deadman switches are wired in parallel and present one
and output gates occupy separate figures; shared net names connect them. shared `DEADMAN_IN` to the ECU. Either switch can assert permission. One
`DEADMAN_STATUS` input reports the combined state; the ECU has no per-switch
observations. The permission and output gates use the single `DEADMAN_OK`
signal. See the module document for release and stuck-high fault behavior.
- `VBG_LOCAL_KELVIN` labels the documented local ignition reference at the - `VBG_LOCAL_KELVIN` labels the documented local ignition reference at the
`IGN_PGND` joining point. `LOCAL_GND` in the sink-command figure denotes the `IGN_PGND` joining point. `LOCAL_GND` in the sink-command figure denotes the
TLE9104SH local ground reference. Neither denotes a new remote ground path. TLE9104SH local ground reference. Neither denotes a new remote ground path.
+93 -87
View File
@@ -658,11 +658,11 @@
] ]
}, },
"deadman-inputs": { "deadman-inputs": {
"title": "Deadman contacts and observations", "title": "Parallel switches \u00b7 one ECU deadman input",
"source": "IO_MODULES/DEAD_MAN.md: Logic domains", "source": "IO_MODULES/DEAD_MAN.md: Steering-wheel wiring and ECU input",
"nodes": { "nodes": {
"title": { "title": {
"label": "Deadman contacts and observations", "label": "Parallel switches \u00b7 one ECU deadman input",
"kind": "note", "kind": "note",
"bounds": [ "bounds": [
30, 30,
@@ -671,131 +671,137 @@
42 42
] ]
}, },
"As": { "supply": {
"label": "Protected 5 V\nIndependent NO contact A", "label": "Protected 5 V",
"kind": "power", "kind": "power",
"bounds": [ "bounds": [
30, 30,
100, 200,
260,
80
]
},
"Ap": {
"label": "Protected input A\nOwn filter + default-low bias",
"kind": "signal",
"bounds": [
370,
100,
290,
80
]
},
"Ah": {
"label": "DEADMAN_A_HELD\n5 V \u00b7 non-inverting",
"kind": "signal",
"bounds": [
750,
100,
260,
80
]
},
"Ad": {
"label": "DEADMAN_A_STATUS\n3.3 V \u00b7 held = high \u2192 MCU",
"kind": "device",
"bounds": [
370,
220, 220,
330,
75
]
},
"Bs": {
"label": "Protected 5 V\nIndependent NO contact B",
"kind": "power",
"bounds": [
30,
345,
260,
80 80
] ]
}, },
"Bp": { "left": {
"label": "Protected input B\nOwn filter + default-low bias", "label": "Left NO switch\nHeld = closed",
"kind": "signal",
"bounds": [
370,
345,
290,
80
]
},
"Bh": {
"label": "DEADMAN_B_RELEASED\n5 V \u00b7 inverting",
"kind": "signal",
"bounds": [
750,
345,
260,
80
]
},
"Bd": {
"label": "DEADMAN_B_STATUS\n3.3 V \u00b7 held = high \u2192 MCU",
"kind": "device", "kind": "device",
"bounds": [ "bounds": [
370, 340,
465, 90,
330, 230,
75 80
] ]
}, },
"note575": { "right": {
"label": "Separate harness paths. MCU status observations are diagnostic; the 5 V signals feed the permit gates.", "label": "Right NO switch\nHeld = closed",
"kind": "device",
"bounds": [
340,
300,
230,
80
]
},
"shared": {
"label": "DEADMAN_IN\nJoined at steering wheel",
"kind": "signal",
"bounds": [
740,
200,
270,
80
]
},
"note390": {
"label": "Switches are physically in parallel. Either held \u2192 asserted; both released \u2192 deasserted.",
"kind": "note", "kind": "note",
"bounds": [ "bounds": [
30, 30,
575, 390,
980, 980,
60 60
] ]
},
"input": {
"label": "DEADMAN_IN\nOne ECU signal pin",
"kind": "signal",
"bounds": [
30,
490,
240,
80
]
},
"conditioning": {
"label": "Protection + filter\nDefault-low bias",
"kind": "signal",
"bounds": [
340,
490,
270,
80
]
},
"ok": {
"label": "DEADMAN_OK\n5 V \u00b7 hardware gates",
"kind": "signal",
"bounds": [
740,
490,
270,
80
]
},
"status": {
"label": "DEADMAN_STATUS\n3.3 V \u2192 one MCU input",
"kind": "device",
"bounds": [
340,
630,
310,
80
]
} }
}, },
"connections": [ "connections": [
{ {
"from": "As", "from": "supply",
"to": "Ap", "to": "left",
"label": "", "label": "",
"kind": "signal" "kind": "signal"
}, },
{ {
"from": "Ap", "from": "supply",
"to": "Ah", "to": "right",
"label": "", "label": "",
"kind": "signal" "kind": "signal"
}, },
{ {
"from": "Ap", "from": "left",
"to": "Ad", "to": "shared",
"label": "", "label": "",
"kind": "signal" "kind": "signal"
}, },
{ {
"from": "Bs", "from": "right",
"to": "Bp", "to": "shared",
"label": "", "label": "",
"kind": "signal" "kind": "signal"
}, },
{ {
"from": "Bp", "from": "input",
"to": "Bh", "to": "conditioning",
"label": "", "label": "",
"kind": "signal" "kind": "signal"
}, },
{ {
"from": "Bp", "from": "conditioning",
"to": "Bd", "to": "ok",
"label": "",
"kind": "signal"
},
{
"from": "conditioning",
"to": "status",
"label": "", "label": "",
"kind": "signal" "kind": "signal"
} }
+17 -9
View File
@@ -99,15 +99,23 @@ f.note('Sensor output is the sensors signal pin. Both ADC channels use +3V3_A
chain('dac-output','Optional analogue-output provision','IO_ARCHITECTURE.md: Analogue-output provision',['MCU DAC','Rail-to-rail buffer','Protection /\nseries impedance','Connector'],'Provision only; final electrical range, load and protection remain to be defined.') chain('dac-output','Optional analogue-output provision','IO_ARCHITECTURE.md: Analogue-output provision',['MCU DAC','Rail-to-rail buffer','Protection /\nseries impedance','Connector'],'Provision only; final electrical range, load and protection remain to be defined.')
f=Figure('deadman-inputs','Deadman contacts and observations','IO_MODULES/DEAD_MAN.md: Logic domains',1040,650) f=Figure('deadman-inputs','Parallel switches · one ECU deadman input','IO_MODULES/DEAD_MAN.md: Steering-wheel wiring and ECU input',1040,750)
for i,c in enumerate('AB'): f.node('supply','Protected 5 V',30,200,220,80,'power')
y=100+i*245 f.node('left','Left NO switch\nHeld = closed',340,90,230,80,'device')
f.node(c+'s','Protected 5 V\nIndependent NO contact '+c,30,y,260,80,'power') f.node('right','Right NO switch\nHeld = closed',340,300,230,80,'device')
f.node(c+'p','Protected input '+c+'\nOwn filter + default-low bias',370,y,290,80,'signal') f.node('shared','DEADMAN_IN\nJoined at steering wheel',740,200,270,80,'signal')
f.node(c+'h','DEADMAN_A_HELD\n5 V · non-inverting' if c=='A' else 'DEADMAN_B_RELEASED\n5 V · inverting',750,y,260,80,'signal') f.edge('supply','left',points=[(290,240),(290,130)])
f.node(c+'d','DEADMAN_'+c+'_STATUS\n3.3 V · held = high → MCU',370,y+120,330,75,'device') f.edge('supply','right',points=[(290,240),(290,340)])
f.edge(c+'s',c+'p'); f.edge(c+'p',c+'h'); f.edge(c+'p',c+'d',exit=(.5,1),entry=(.5,0)) f.edge('left','shared',points=[(660,130),(660,240)])
f.note('Separate harness paths. MCU status observations are diagnostic; the 5 V signals feed the permit gates.',575);f.save() f.edge('right','shared',points=[(660,340),(660,240)])
f.note('Switches are physically in parallel. Either held → asserted; both released → deasserted.',390)
f.node('input','DEADMAN_IN\nOne ECU signal pin',30,490,240,80)
f.node('conditioning','Protection + filter\nDefault-low bias',340,490,270,80)
f.node('ok','DEADMAN_OK\n5 V · hardware gates',740,490,270,80)
f.node('status','DEADMAN_STATUS\n3.3 V → one MCU input',340,630,310,80,'device')
f.edge('input','conditioning');f.edge('conditioning','ok')
f.edge('conditioning','status',exit=(.5,1),entry=(.5,0))
f.save()
for name,title,part,pin,load,ground,source in [ for name,title,part,pin,load,ground,source in [
('ignition-power','Ignition power path','VBG08H-E','HVC','Coil primary','IGN_PGND','IGNITION'), ('ignition-power','Ignition power path','VBG08H-E','HVC','Coil primary','IGN_PGND','IGNITION'),
+4 -5
View File
@@ -160,11 +160,10 @@ def equation_gate(c,ref,xy,a,b,out,invert_b=False):
c.wire(start,(x-1.2,yy));c.wire((x-1.2,yy),(x-1.2,anchor.y));c.wire((x-1.2,anchor.y),anchor) c.wire(start,(x-1.2,yy));c.wire((x-1.2,yy),(x-1.2,anchor.y));c.wire((x-1.2,anchor.y),anchor)
c.wire(gate.out,(x+5,y));c.port(ref+'O',(x+5,y),out,loc='right') c.wire(gate.out,(x+5,y));c.port(ref+'O',(x+5,y),out,loc='right')
c=Circuit('deadman-permit','Hardware engine-permit equations','IO_MODULES/DEAD_MAN.md: Logic equations') c=Circuit('deadman-permit','Single-input hardware engine permission','IO_MODULES/DEAD_MAN.md: Hardware gating')
equation_gate(c,'VALID',(0,0),'DEADMAN_A_HELD','DEADMAN_B_RELEASED','DEADMAN_OK',True) equation_gate(c,'PERMIT',(0,0),'DEADMAN_OK','MCU_RUN_PERMIT','ENGINE_PERMIT')
equation_gate(c,'PERMIT',(0,-6),'DEADMAN_OK','MCU_RUN_PERMIT','ENGINE_PERMIT') c.label((0,3),'Single deadman input · hardware permission',size=18)
c.label((0,3),'Hardware permission · 5 V gate outputs',size=18) c.label((0,-3),'DEADMAN_OK: conditioned shared input. MCU_RUN_PERMIT: 3.3 V. Gate output: 5 V.',size=11);c.save()
c.label((0,-9),'Bubble inverts channel B. MCU_RUN_PERMIT is 3.3 V; gates must accept that input level.',size=11);c.save()
c=Circuit('deadman-outputs','Hardware permitted output commands','IO_MODULES/DEAD_MAN.md: Logic equations') c=Circuit('deadman-outputs','Hardware permitted output commands','IO_MODULES/DEAD_MAN.md: Logic equations')
equation_gate(c,'INJECT',(0,0),'ENGINE_PERMIT','MCU_INJECTOR_SIG','SAFE_INJECTOR_SIG') equation_gate(c,'INJECT',(0,0),'ENGINE_PERMIT','MCU_INJECTOR_SIG','SAFE_INJECTOR_SIG')
+61 -38
View File
@@ -1,58 +1,81 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<mxfile host="app.diagrams.net"> <mxfile host="app.diagrams.net">
<diagram name="Deadman contacts and observations" id="deadman-inputs"> <diagram name="Parallel switches · one ECU deadman input" id="deadman-inputs">
<mxGraphModel page="1" pageWidth="1040" pageHeight="650" grid="1" gridSize="10"> <mxGraphModel page="1" pageWidth="1040" pageHeight="750" grid="1" gridSize="10">
<root> <root>
<mxCell id="0" /> <mxCell id="0" />
<mxCell id="1" parent="0" /> <mxCell id="1" parent="0" />
<mxCell id="node_title" value="Deadman contacts and observations" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=26;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1"> <mxCell id="node_title" value="Parallel switches · one ECU deadman input" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=26;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxGeometry x="30" y="18" width="980" height="42" as="geometry" /> <mxGeometry x="30" y="18" width="980" height="42" as="geometry" />
</mxCell> </mxCell>
<mxCell id="node_As" value="Protected 5 V&#10;Independent NO contact A" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#fff1d6;spacing=10;" vertex="1" parent="1"> <mxCell id="node_supply" value="Protected 5 V" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#fff1d6;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="100" width="260" height="80" as="geometry" /> <mxGeometry x="30" y="200" width="220" height="80" as="geometry" />
</mxCell> </mxCell>
<mxCell id="node_Ap" value="Protected input A&#10;Own filter + default-low bias" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1"> <mxCell id="node_left" value="Left NO switch&#10;Held = closed" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="100" width="290" height="80" as="geometry" /> <mxGeometry x="340" y="90" width="230" height="80" as="geometry" />
</mxCell> </mxCell>
<mxCell id="node_Ah" value="DEADMAN_A_HELD&#10;5 V · non-inverting" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1"> <mxCell id="node_right" value="Right NO switch&#10;Held = closed" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="750" y="100" width="260" height="80" as="geometry" /> <mxGeometry x="340" y="300" width="230" height="80" as="geometry" />
</mxCell> </mxCell>
<mxCell id="node_Ad" value="DEADMAN_A_STATUS&#10;3.3 V · held = high → MCU" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1"> <mxCell id="node_shared" value="DEADMAN_IN&#10;Joined at steering wheel" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="220" width="330" height="75" as="geometry" /> <mxGeometry x="740" y="200" width="270" height="80" as="geometry" />
</mxCell> </mxCell>
<mxCell id="e0" source="node_As" target="node_Ap" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1"> <mxCell id="e0" source="node_supply" target="node_left" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="290" y="240" />
<mxPoint x="290" y="130" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e1" source="node_supply" target="node_right" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="290" y="240" />
<mxPoint x="290" y="340" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e2" source="node_left" target="node_shared" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="660" y="130" />
<mxPoint x="660" y="240" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="e3" source="node_right" target="node_shared" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="660" y="340" />
<mxPoint x="660" y="240" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="node_note390" value="Switches are physically in parallel. Either held → asserted; both released → deasserted." style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=16;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxGeometry x="30" y="390" width="980" height="60" as="geometry" />
</mxCell>
<mxCell id="node_input" value="DEADMAN_IN&#10;One ECU signal pin" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="490" width="240" height="80" as="geometry" />
</mxCell>
<mxCell id="node_conditioning" value="Protection + filter&#10;Default-low bias" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="340" y="490" width="270" height="80" as="geometry" />
</mxCell>
<mxCell id="node_ok" value="DEADMAN_OK&#10;5 V · hardware gates" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="740" y="490" width="270" height="80" as="geometry" />
</mxCell>
<mxCell id="node_status" value="DEADMAN_STATUS&#10;3.3 V → one MCU input" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="340" y="630" width="310" height="80" as="geometry" />
</mxCell>
<mxCell id="e4" source="node_input" target="node_conditioning" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" /> <mxGeometry relative="1" as="geometry" />
</mxCell> </mxCell>
<mxCell id="e1" source="node_Ap" target="node_Ah" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1"> <mxCell id="e5" source="node_conditioning" target="node_ok" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" /> <mxGeometry relative="1" as="geometry" />
</mxCell> </mxCell>
<mxCell id="e2" source="node_Ap" target="node_Ad" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1"> <mxCell id="e6" source="node_conditioning" target="node_status" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" /> <mxGeometry relative="1" as="geometry" />
</mxCell> </mxCell>
<mxCell id="node_Bs" value="Protected 5 V&#10;Independent NO contact B" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#fff1d6;spacing=10;" vertex="1" parent="1">
<mxGeometry x="30" y="345" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Bp" value="Protected input B&#10;Own filter + default-low bias" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="345" width="290" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Bh" value="DEADMAN_B_RELEASED&#10;5 V · inverting" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f0fc;spacing=10;" vertex="1" parent="1">
<mxGeometry x="750" y="345" width="260" height="80" as="geometry" />
</mxCell>
<mxCell id="node_Bd" value="DEADMAN_B_STATUS&#10;3.3 V · held = high → MCU" style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=18;fontColor=#172b40;strokeColor=#577086;fillColor=#e8f4ed;spacing=10;" vertex="1" parent="1">
<mxGeometry x="370" y="465" width="330" height="75" as="geometry" />
</mxCell>
<mxCell id="e3" source="node_Bs" target="node_Bp" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e4" source="node_Bp" target="node_Bh" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="e5" source="node_Bp" target="node_Bd" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=0;strokeWidth=2;strokeColor=#416680;fontSize=16;fontFamily=DejaVu Sans;labelBackgroundColor=#ffffff;endArrow=block;endFill=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="node_note575" value="Separate harness paths. MCU status observations are diagnostic; the 5 V signals feed the permit gates." style="rounded=1;html=0;fontFamily=DejaVu Sans;fontSize=16;fontColor=#172b40;strokeColor=#577086;fillColor=#ffffff;spacing=10;strokeColor=none;fillColor=none;align=left;" vertex="1" parent="1">
<mxGeometry x="30" y="575" width="980" height="60" as="geometry" />
</mxCell>
</root> </root>
</mxGraphModel> </mxGraphModel>
</diagram> </diagram>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 36 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

@@ -1,42 +1,8 @@
{ {
"title": "Hardware engine-permit equations", "title": "Single-input hardware engine permission",
"source": "IO_MODULES/DEAD_MAN.md: Logic equations", "source": "IO_MODULES/DEAD_MAN.md: Hardware gating",
"reference_scope": "documentation only", "reference_scope": "documentation only",
"components": [ "components": [
{
"ref": "VALID",
"kind": "and-with-inverted-B",
"pins": [
"A",
"B",
"Y"
],
"value": ""
},
{
"ref": "VALIDP0",
"kind": "port",
"pins": [
"P"
],
"value": "DEADMAN_A_HELD"
},
{
"ref": "VALIDP1",
"kind": "port",
"pins": [
"P"
],
"value": "DEADMAN_B_RELEASED"
},
{
"ref": "VALIDO",
"kind": "port",
"pins": [
"P"
],
"value": "DEADMAN_OK"
},
{ {
"ref": "PERMIT", "ref": "PERMIT",
"kind": "and", "kind": "and",
@@ -73,25 +39,9 @@
} }
], ],
"nets": [ "nets": [
{
"name": "DEADMAN_A_HELD",
"connections": [
"VALID.A",
"VALIDP0.P"
]
},
{
"name": "DEADMAN_B_RELEASED",
"connections": [
"VALID.B",
"VALIDP1.P"
]
},
{ {
"name": "DEADMAN_OK", "name": "DEADMAN_OK",
"connections": [ "connections": [
"VALID.Y",
"VALIDO.P",
"PERMIT.A", "PERMIT.A",
"PERMITP0.P" "PERMITP0.P"
] ]