OpenLCB Note: Locomotive Control

Locomotive control is traditionally the domain of DCC in the NMRA. OpenLCB will likely need to eventually take part, and this note is a place to put some of the discussion now taking place.

Environment of Proposal


Not just DCC, but also other existing and future systems.

Provide large address space for locating locomotives.

Simple “big knob” throttles through full-capability iPhones.

A throttle attached to any segment should be able to control a train anywhere.


Efficient on CAN.

Must be able to query throttle capabilities, e.g. ability to display information.

Must work well with multiple forms of wireless.

Nodes may have little compute power; simple nodes must be able to use pre-formatted messages for most things.

Cleanly handle the need for multiple command stations.

It should be possible to hand a running train off from one throttle to another.

A throttle node can control more than one locomotive at a time via some form of “sub-throttle”, e.g. “right knob” and “left knob”. Might be physical, might be just virtual e.g. switch back and forth via button.

Throttles need to be able to retrieve roster information (name, perhaps description and picture?) in addition to talking to control system. Might not come from the same place!

Design Points

Use events for global communication, but mostly exchange point-to-point datagrams. A large series of unique node IDs has been reserved for each control system for this purpose.

Use “throttle” and “command station” metaphors, at least for start.

Throttles could be either a physical handheld or computer program.

The separate display protocol can be used to drive displays on the throttle once it's identified.

A node may have multiple “throttles” in it, e.g. two in a hand-held. Need to be able to specify which when talking to and from the throttle, e.g. need to have a way to identify a specific “throttle” in the node with a specific display.

Proposed Protocol

Throttles locate the command station (controllers) currently servicing a locomotive (or other addressable unit) by emitting an event in the OpenLCB-reserved space. Four bytes are reserved to identify which one, which could be e.g. two bytes of system prefix and two bytes of DCC address, or something else; see below. All command stations (controllers) receive this, as it's a true global message. The node making the request is identified by the source of the message. (Note that the throttle within the node is not, and there will have to be enough information in replies to match up returning information with the request) The one(s) controlling the locomotive reply to the throttle via datagram with identification and status information. Nodes with roster information also proffer information via datagram. The point-to-point connection has then been made.

Datagrams flow between the throttle node and CS node to control the train. Because both throttles and CSs can control multiple trains, the datagrams contain a “session ID” that was negotiated at the start. This doesn't have to have any meaning, though of course the two ends can use it for their own internal purposes.


Simple Acquisition

Node T wishes to open throttle connection, sends event message with (OpenLCB Prefix – 3 bytes)(Locate Controller – 1 byte)(Locomotive ID – 4 bytes)

Command station C sends datagram to Throttle T with (throttle command – 1 byte)(Locomotive ID – 4 bytes)(Op: Located – 1 byte) (Status, nominally two bytes)

Note T sends reservation request to C, which prevents deadlock and allocation holes by using test-and-set operations; results in a two-byte ID assigned to this communication by CS; could be slot number or anything else, throttle&CS just use for rendezvous during interchange.

Throttle T sends single-frame datagrams with speed, functions as needed; 5 byte payload in 1st frame if Type, ID present, allowing a command byte and speed, with some functions. Might still want to separate speed and function.

Command station C returns status datagrams as needed

Transfer command station

A train is being controlled by Throttle T with command station C1. The train is about to leave C1's control. Assume that C1 is aware of this, and knows that C2 will be able to control it. (Does T need to send speed commands to both C1 and C2 for a while? e.g. do they really know where the edge is?)

C1 sends a “transfer” datagram to T informing T of this, which carries C2's address.

Alternately, C1 sends a “please reacquire” datagram to T, telling T that control is about to be lost. T goes through the simple acquisition operation, this time getting communications from C2.

Datagram Format

Basic format is datagram-ID-byte, one byte session ID, then a command byte for throttle-CS communication, then arguments. Five bytes of arguments fit in the first CAN frame.

CS to

to CS




Have Information


(and also Assign?)



Get roster information


Set speed


Set function



Get speed and function information
(and reply)


Get throttle properties



Release (End)

Throttle to Command Station


Set speed – what's the appropriate range? 0-255 probably not enough steps for the long run. Fit a couple more bits in? 16 bits too large? 15, using one for sign?

Set functions/outputs – There are multiple function spaces available, e.g. DCC NMRA now has three overlapping function address spaces, perhaps more if you count consisting. Bit mask is convenient for some things, but most option operations are just one change. Include a duration code for precise timing? Then sequences for sounds? Then what? If use bit mask, how many? 0-28 fits in four bytes, which is available. Any systems have more than that? Is CAN fast enough that two consecutive commands to change two things at the same time doesn't introduce too much skew?

Allocation commands – release, allow dual use, etc.

Get status: Read back everything the command station knows.

Get info: For e.g. roster information. Might have to go to some other node than CS, e.g. a separate computer.

Need protocol for handing off to next command station, which can be initiated either by new CS or old one. Is that a CS-CS communication, with the throttle being told at the end, or does the throttle initiate it when told “I can't control this any more, find somebody who can”?

Command Station to Throttle


Must transfer to another; Transfer to CS node N

Get throttle properties: enquire about display, etc.

Remaining Points

What is the unit of addressability? A “locomotive”, a “decoder”, a “consist” or what? Does that vary per system?

Alex, via email: Although explicitly excluded from our initial work I think we should have some place holders for this at a high level. Needs to include: - DCC - DC - Multi-Block DC (MERG SuperBloc, QuadThrottleUnit etc) - Wireless direct to Locos - Other?

DPH: Yes, I started to list possibilities, but they seem endless: (1) One block/one CS/ one booster: DC, DCC, PWM DC (2) Multi- block/CS/booster (3) direct RF control Perhaps our model should look like Throttle <---> Loco. Whether that is really: (a) Throttle-RF <--> RF-receiver <--> CS-service <--> aBooster ---> Track --> Loco-decoder <---> BOD <---> Throttle or just: (b) Throttle-RF <--> Loco-RF-decoder ; GPS<-->Throttle All the in-between bits are hidden from the user - but not unfortunately, from us.

Should users have to know what they're addressing in detail, e.g. “Locomotive 12345 on the TCS system”? Or just “Locomotive 12345” and have system locate? (Note number of digits; four is not enough!)

How can a command station attach a specific locomotive to a throttle? To a control point within a throttle (“left knob”)? Very useful in some applications to be able to do that centrally.

To what extent does consisting need to be explicitly handled?

Control Systems:

A list, to try to remember the options, in no particular order:

Items from DPH email May 24, 2010:

1. Messages are between a throttle and a train. In the future messages will likely be send directly from throttle to train, via RF. It is the job of today's CS, perhaps with the help of a helper-node, to model a train as a fully functioning pseudo-node. Messaging will use directed messages, or Datagrams, but, could use bidirectional streams. This interchange is really between the throttle and the CS, but conceptually and in appearance to the user, it should appear to be between the throttle and the train.

2. In large layouts with more than one command station (CS), each CS will have a defined territory and associated DCC stream. When a train crosses two territories, there must be automatic hand-off of the train from one CS to the next. An block-occupation event will announce a train 'crossing the frontier'. The receiving CS will negotiate with the first for the train's NID, direction, speed, acceleration, functional state, etc.

3. Two CSs cannot drive the same block, nor two adjacent blocks with an engine bridging them, with their differing DCC streams. This requires a special intervening block between the two CSs' territories, which is switched between the two DCC streams. To prevent more than one train entering the shared block, signaling and speed control is used. This may fail with the simultaneous arrival of two trains, and two additional short, protective, blocks may be necessary to this. These can use 'Bit-switch'-like techniques to halt oncoming trains. This has been done by the Freemo group in Europe, see:

4. Despite the train's movement, its NID is fixed, just like any node. Each engine can be assigned a unique 48-bit NID by its manufacturer, a user, or perhaps constructed from a RFID tag number. Using the user's space would allow the lower 16-bits to equal the engine's road number, which would simplify display without translation tables.

5. Each train also has a NID. This can be assigned from the lead engines NID, but it would be nice if the bottom digits represented the train number as some of these have historical significance. Therefore, the NID prefix could be derived from the layout ID, the meet's range, or a fixed number denoting 'Train'. Train NIDs would then have the form TRAIN.x, where x is 0-65k, and TRAIN is a fixed 48-bit number.

Controlling turnouts from a throttle

E.g. LocoNet throttles let you send a message “change turnout 23” to the DCC system. How to do that in OpenLCB?

First, people don't want to enter the actual address of a turnout on a their throttle; they want to enter some useful number. LocoNet has an entire mechanism in place to do that, but it's such a pain to set up that almost nobody uses it (Bushby bit). Right way to do it is to teach the throttle a set of useful names for the things it wants to address, e.g. by downloading a list of names that can be scrolled through. WiThrottle does this by downloading the JMRI user names into the iPhone/Android for selection by the user. Need a protocol for that.

For a really simple throttle, e.g. PIC-based, the best approach might be to do this in some central node that supports the IT (idiot throttle) and does any needed translation.

Site hosted by

This is SVN $Revision: 761 $