Appearance
Devices, addressing and discovery
Every box on the MUXEN bus answers to a number. Two boxes that answer to the same number is the single most common cause of "the tool cannot see my device", and it looks exactly like a dead bus. This chapter is about knowing what is on the bus and making sure each unit is distinguishable.
How a device is addressed
A device id is a 12-bit source address, 0x000–0xFFF, made of a 6-bit function code and a 6-bit instance:
deviceId = function * 64 + instance0x280 (640) is function 10, instance 0. The two halves mean different things:
- The function says what kind of device it is — battery monitor, power output board, tank sensor interface. It is a property of the product, not of the installation.
- The instance distinguishes several devices of the same kind on the same boat. It is a setting, stored in the device's
InstanceNumparameter, and it is what an installer assigns.
On the command line you give one or the other, never both:
sh
muxen-uds -d 0x280 … # by network address
muxen-uds -F 10 -I 0 … # by function and instanceMixing them is refused (can't use deviceId and both function/instance in the same time).
Instance 63 is the parking address. A device with no instance assigned answers there. It is also the address the tool itself uses when it addresses a unit by UID, which is why the parking address must be kept free for that to work.
Each device also carries a UID: 8 bytes, 16 hexadecimal digits, burned into the MCU. Unlike the device id, it is unique and cannot be changed. It is the identity to use when addressing is in doubt.
Passive scan — who is talking
sh
muxen-uds -i can0 scan --timeout 5 --max-device 128scan opens the CAN interface for reception only and records the source address of every broadcast frame it sees. It sends nothing.
| Option | Default | Meaning |
|---|---|---|
--timeout | 5 | seconds to listen |
--max-device | 128 | size of the result table |
Output, one line per distinct address, sorted by function then instance, then a count:
cmd: when=1753960000, deviceId=0x280 (640), instance=00, function=10 (…)
cmd: 1 devices detectedwhen is the UNIX timestamp of the first frame seen from that device.
What passive scan tells you is this device is alive and transmitting. What it cannot tell you is anything about a device that is quiet during the window — including a device that is perfectly healthy but only speaks when spoken to. Lengthen --timeout when in doubt; the whole window is always used.
Active scan — who is there
sh
muxen-uds -i can0 uid --scanuid --scan broadcasts a UID request frame, re-broadcasts it every second, and collects answers over a 4-second window (1 s and 2 s under --speedy). The repeat exists because a single lost request on a busy bus would otherwise drop a device from the inventory for the whole scan; duplicate answers are filtered.
cmd: scan done, found 3 devices
cmd: UID DeviceId Instance Function
cmd: 2000200007504255 640 0 … (10)
cmd: 49003A0003503159 64 X 0 … (01)
cmd: 4900190005504147 64 X 0 … (01)
cmd: 500019000A504147 703 63 (parking) … (10)Three things to read from that table:
Xmarks a collision. Two devices answered at the same address.(parking)marks instance 63 — a unit with no instance assigned. It answers the scan but will not serve UDS until it is activated.- The UID column is the stable identity. When a device id is contended, the UID is the only way to tell the two units apart.
Write the inventory to a file for tooling:
sh
muxen-uds -i can0 uid --scan-to-json inventory.jsonjson
{
"devices": [ { "deviceId": 640, "uid": "2000200007504255" } ],
"duplicate": false
}Address collisions
Two devices presenting the same function and instance answer at the same device id. While that lasts:
readconfigon that id returns nothing usable — both units answer the same ISO-TP exchange and the frames interleave.- Anything built on
readconfig(writeconfig,checkconfig,deploy) fails on that device. - The failure is indistinguishable from a device that is simply offline.
Detection is uid --scan: a contended address carries a trailing X, and the JSON output sets "duplicate": true.
Confirming it is easy if one of the two units can be unplugged: the scan then shows a single device at that id and readconfig starts answering. That is also how to work on one of a colliding pair without fixing the addressing first.
Fixing it means assigning a different instance to one of them, by UID:
sh
muxen-uds -i can0 uid --uid 0x49003A0003503159 --instance 2That sequence, in order:
- resets whatever currently sits at the parking address of that function (instance 63), so the parking address is free;
- broadcasts a UID-addressed enable UDS frame, which brings the target — and only the target — up at the parking address;
- writes
InstanceNumon it through a normalwriteconfig; - reboots the device, which comes back at its new address.
Two preconditions follow from step 1 and 2, and they are worth knowing before blaming the tool:
- The parking address must be free. If a device with an unassigned instance is sitting at instance 63 of that function, the write goes to the wrong unit or times out. Give unassigned units real instances one at a time.
- The target must be uniquely reachable by UID. This is what makes the operation work on a colliding pair: the UID is unique even when the device id is not.
The function used for the parking address is taken from the scan entry matching that UID; --preferred-function-code chooses which one when a UID answers on several.
Locating a device physically
sh
muxen-uds -i can0 -d 0x040 locate # by address
muxen-uds -i can0 uid --uid 0x49003A0003503159 --locate # by UIDBoth run the same device routine, which plays an LED animation. The UID form additionally enables UDS on the target first and then resets it with an 8-second delay, so the animation is visible before the unit restarts.
locate is the fastest way to answer "which box is device 64?" and costs nothing — no configuration is touched.
Enabling UDS on a parked unit
sh
muxen-uds -i can0 uid --uid 0x49003A0003503159 --uds--uds performs only the activation step: the target comes up at the parking address of its function and accepts UDS there. It is what --instance and --locate do internally, exposed on its own for the case where you want to run other commands against a parked unit.
Every UID-addressed operation requires --uid; without it the command prints its help and exits.
