CAN Bus Input
Applies to: IOcan · Standalone controller. What this means
Overview
A CAN Bus Input decodes a single signal out of a raw incoming CAN frame, using a layout you enter by hand. Use it for a device that has no CAN preset and whose frame layout you know — from a DBC, a data sheet, or your own reverse engineering.
For a supported device, use a CAN Object Input instead and let the preset own the decoding.
⚠️ Firmware 2.1 changed what
Enable interpolationdoes, and it affects configurations you already have. Before 2.1 the raw → out scaling was applied whether the box was ticked or not. From 2.1 it is honoured, and a configuration where it was never ticked reports the raw frame value instead of your scaled one. What to do.
One field still does not behave the way its name suggests — see the one field that does not mean what it says.
If the device with no preset is your engine ECU, my ECU isn't listed walks the same job end to end — which signals you have to map, and how to find them in the stream.
Prerequisites
- A CAN bus defined on the channel the frame arrives on — see Working with the CAN bus.
- The frame's message ID and the signal's position, width, signedness and endianness.
Add it in the app
- Add a new input and choose CAN Bus Input as the type.
- Give it a clear name (e.g.
Engine RPM). - Enter the message ID and ID type.
- Enter the decoding type, length and offset that locate the signal in the frame.
- Tick Enable interpolation and set the raw → out scaling. From 2.1 the scaling is not applied unless you do.
- Set a timeout — the default if you leave it at zero is 500 ms, which is too slow for anything the transmission depends on.
Settings reference
| Setting | Meaning | Unit | Range / values | Notes |
|---|---|---|---|---|
| Message ID | Frame identifier to match | hex | fixed32 | The arbitration ID of the frame carrying the signal. |
| Message ID type | Identifier width | — | Extended (29-bit), Standard (11-bit) |
Must match how the sender addresses the frame. |
| Decoding type | How the bits are interpreted | — | UnsignedBigEndian, UnsignedLittleEndian, SignedBigEndian, SignedLittleEndian, BitField, BitFieldBigEndian, SignedBitField, SignedBitFieldBigEndian, FloatLittleEndian, FloatBigEndian |
All ten are implemented. |
| Length | Signal width | bytes / bits | uint32 | Bytes for the integer and float types, bits for the four bitfield types. |
| Offset | Where the signal starts in the frame | bytes / bits | uint32 | Same units as Length. |
| Enable interpolation | Applies the raw → out scaling | — | on / off | Off means no scaling at all — the input reports the decoded frame value. Changed in 2.1; see below. |
| Raw min / Raw max | Decoded range to scale from | raw | sint32 | The raw low and high points. Interpolation only. |
| Out min / Out max | Value range to scale to | your unit | sint32 | Both left at zero gives 0…1024, not 0…0. Interpolation only. |
| Saturate | Clamps the raw value into Raw min…Raw max | — | on / off | Off, a value past either end extrapolates beyond your Out range. Interpolation only. |
| Default value | Reported before the first frame arrives | raw | sint32 | Also the substitute in UseDefault. In raw units — see below. |
| Fault value | The substitute in UseFault |
raw | sint32 | In raw units — see below. |
| Timeout | Longest acceptable gap between frames | ms | uint32 | Zero means 500 ms, not "no timeout". |
| Timeout mode | What to report after a timeout | — | UsePrevious, UseDefault, UseFault |
All three implemented from 2.1. |
| Fault min / Fault max | Out-of-range window on the decoded value | — | sint32 | Labelled Allowed Range Min / Max in the configuration app and Fault Min / Max Value in the transmission-configuration editor. Both zero disables the check. Reversed values are swapped automatically. |
Enable interpolation, and the 2.1 migration
Before firmware 2.1 the two-point scaling was applied unconditionally — the setting was read into an empty branch and had no effect. From 2.1 it does what it says: with it off, the input reports the decoded frame value and Raw min/max, Out min/max and Saturate are unused.
That is the behaviour you want when a Map Input is going to do the scaling, or when the frame already carries the value in the units you work in.
⚠️ Existing configurations need attention. The setting defaults to off and the transmission-configuration editor never wrote it, so a CAN input made before 2.1 is scaling today and will report the raw frame value once the device is flashed with 2.1. Tick Enable interpolation on every CAN bus input that has a raw → out scaling, and re-save the configuration.
The symptom if you miss one is a channel reading in raw frame units — often a large number where you expected a small one, occasionally the reverse. It does not fault. Check every CAN input in the datalogger after the update.
Timeouts
A frame that stops arriving does not raise anything on its own. What the input reports afterwards is decided entirely by the timeout mode:
| Mode | After the timeout elapses |
|---|---|
UsePrevious |
Holds the last received value, indefinitely |
UseDefault |
Substitutes Default value |
UseFault |
Substitutes Fault value |
All three are implemented from firmware 2.1; before that UseFault had no case
in the firmware and left the mode undefined.
Three details that matter in practice:
UseFaultdoes not raise a fault. The name is misleading: it substitutes a second, separate value and nothing else happens. Its usefulness is that you can distinguish "this signal dropped out" from "this signal is at its default" — give Default and Fault different values and the datalogger tells you which happened.- Default value and Fault value are in raw units, not your scaled ones.
They are substituted on the decoded side, before the raw → out scaling, so
they go through it exactly like a received frame value. With Raw 0…65535
mapped to Out 0…8191, a Fault value of
0reports as0, but a Fault value of65535reports as8191. - The substitution happens once, when the timeout elapses, and the value returns to the frame contents on the first frame after the dropout. From 2.1 the datalogger shows the substituted value too — before that the log kept showing the last received value while the control path used the substitute, so the two disagreed exactly when you needed them to agree.
On anything the transmission depends on, use UseDefault or UseFault.
UsePrevious holds a stale value forever and nothing indicates it is stale —
see If an input drops out.
The one field that does not mean what it says
Timeout of zero means 500 ms, not "no timeout". There is no way to
disable the timeout — only to make it long. Set it deliberately on anything the
transmission depends on.
The fault window
Fault min and Fault max are checked against the decoded value and raise the
same watchdog faults as an analog input — 0x0101 below the minimum, 0x0102
above the maximum. The same inhibit applies: the check does not run until
ignition is on and the battery is above about 8 V, so it is invisible on a
USB-only bench. See the fault window.
Identifying which CAN input raised one takes more work than for an analog input. These faults carry an input identifier that the configuration does not set for a CAN input, so it does not point back at the channel the way it does elsewhere. Narrow it down from the fault window you configured and the value the datalogger was showing when it tripped.
Common settings
CAN Bus Input uses the shared Name setting, and the Pin field selects which CAN channel to listen on rather than a physical pin. A correct frame definition pointed at the wrong channel reads nothing, and looks exactly like a wrong message ID. See Common IO settings.
Example — engine speed from a J1939-style frame
- Type CAN Bus Input, name
Engine RPM. - Message ID
0x0CF00400, ID typeExtended (29-bit). - Decoding type
UnsignedLittleEndian, Length2bytes, Offset3bytes. - Enable interpolation on, Raw min/max
0/65535→ Out min/max0/8191, Saturate on. - Timeout
100ms, Timeout modeUseFault, Default value0, Fault value0.
Both substitutes are raw, and raw 0 scales to 0 rpm. A lost ECU now reports
zero rather than holding the last live value — which is detectable, where a
frozen reading is not.
To tell a dropout apart from a genuine zero, give Fault value a raw value
that cannot occur — 65535 here, which scales to 8191 rpm — and watch for that
number in the log. Do this only where a wildly wrong value is safe; on a
torque-critical signal it is not, and 0 is the right answer.
Troubleshooting
- Value is garbage: check the decoding type first — signedness and endianness. Then check that Length and Offset are in the right units: bytes for the integer and float types, bits for the bitfield types.
- Reads zero and never updates: wrong message ID or ID type, or a bitrate mismatch on the bus. CAN bus diagnostics.
- A channel that used to be scaled now reads in raw frame units: the 2.1 change to Enable interpolation. Tick it and re-save — see above.
- Reads 0–1024 instead of your range: Out min and Out max were both left at zero, so Out max defaulted to 1024.
- Value holds after the sender drops off: the timeout mode is
UsePrevious. UseUseDefaultorUseFault. - The substituted value is not what you entered: Default and Fault values are in raw units and go through the raw → out scaling. Work backwards from the value you want to see.
- Timeout seems far too slow: the timeout was left at zero, which means 500 ms.
Related
- CAN Object Input — let a preset own the decoding
- CAN Bus Output — the outbound equivalent
- Working with the CAN bus
- Signal requirements — what happens when a signal stops