Skip to main content

Module traction

Module traction 

Source
Expand description

Traction Control protocol payloads (MTI 0x05EB command / 0x01E9 reply) and the Train Search protocol.

In OpenLCB every locomotive (or consist) is a train node. For DCC locos the train node is usually virtual and lives in the command station, which turns traction commands into DCC packets. A throttle drives a train by sending addressed Traction Control Command messages to it and reading Traction Control Reply messages back, as defined by the Traction Control Standard.

This module only encodes and decodes the payload bytes. Wrap them in Message::TractionCommand / Message::TractionReply and send them through a Node. The throttle guide walks through a whole session.

§A throttle session

  1. Find the train. Send Identify Producer for a search event built from the DCC address. The train node (allocated by the command station if needed) answers with Producer Identified for the same event; its source alias is the train.
  2. Assign controller. Send Command::AssignController with our Node ID. The train answers Reply::AssignController with result 0 if accepted. Only the assigned controller should send speed commands.
  3. Drive. Command::SetSpeed, Command::SetFunction, Command::EmergencyStop. Query state with Command::QuerySpeed / Command::QueryFunction.
  4. Stay alive. A train may send Reply::Heartbeat asking for any command within timeout_s seconds; answer with Command::Noop or the train will stop itself.
  5. Release with Command::ReleaseController.

§Controller handover

When a second throttle sends Assign Controller to a train that already has a controller, the train asks the current controller first. It sends the command Command::ControllerChangingNotify (20 04 flags NodeID, carrying the new controller’s Node ID) to the current controller, which answers with the reply Reply::ControllerChanged (20 04 result): result 0 accepts the handover, nonzero refuses it. So a throttle receives a Traction Control Command in this one case, even though it is not a train; Node delivers it instead of rejecting it. On accepting, the throttle should stop sending commands to that train and tell the user it lost control. The throttle guide shows the exchange.

§Command bytes

Byte 0Byte 1MeaningRest
0x00Set Speedhalf-float speed (2 bytes)
0x01Set Function24-bit address, 16-bit value
0x02Emergency Stop
0x10Query Speed
0x11Query Function24-bit address
0x200x01Assign Controllerflags, Node ID (6)
0x200x02Release Controllerflags, Node ID (6)
0x200x03Query Controller
0x200x04Controller Changing Notify (train → current controller)flags, new controller Node ID (6)
0x30Consist (listener) config
0x400x01Management: Reserve
0x400x02Management: Release
0x400x03Management: Noop / heartbeat

Replies reuse the same command bytes; see Reply. Constants are in cmd. Bit 7 of byte 0 (cmd::LISTENER_FLAG) marks a command forwarded to a consist member and is ignored by Command::decode.

use rolcb::traction::{Command, Reply, Speed};

// 1.0 m/s forward is half-float 0x3C00.
assert_eq!(Command::SetSpeed(Speed::from_mps(1.0, false)).encode(), [0x00, 0x3C, 0x00]);
// Same speed in reverse: the sign bit is set.
assert_eq!(Command::SetSpeed(Speed::from_mps(1.0, true)).encode(), [0x00, 0xBC, 0x00]);
// F3 on.
assert_eq!(Command::SetFunction { addr: 3, value: 1 }.encode(), [0x01, 0, 0, 3, 0, 1]);

assert_eq!(Reply::decode(&[0x40, 0x03, 10]), Reply::Heartbeat { timeout_s: 10 });

Modules§

cmd
Traction Control command and sub-command byte values.
search
Train Search protocol: find (or allocate) a train node by DCC address by emitting Identify Producer for a specially formed event ID. Matching train nodes answer with Producer Identified for the same event.

Structs§

Speed
A traction speed: IEEE half-float in scale m/s, sign bit = reverse.

Enums§

Command
A Traction Control Command (throttle → train).
Reply
A Traction Control Reply (train → throttle).

Functions§

function_value
Function number helpers: F0..F28 map directly to function addresses 0..28.