The other night I stumbled across the LCC spec, maybe I'm late to the party but I'm seeing more and more devices coming out that support it. For those who haven't yet, TL;DR it stands for Layout Command Control and it specifies a new protocol specifically for accessories to talk to each other - think throttles, switches, lights, anything that isn't on the track itself basically. For the most part, they do bidirectional communication through a standard CAN bus at 125kbps.
It's specifically not designed to replace DCC, which carries both power and data through the rails. DCC is one-directional for the most part (controller to decoder). Various open and proprietary solutions have come and gone over the years to try and bolt on that missing second direction, so trains could communicate and build more advanced occupancy systems etc. But they're mostly limited by the very design of DCC, which only really allows one side to talk.
LCC has none of those restrictions; it's designed to be fully bidirectional. If it could be applied to a locomotive's decoder, it could allow a number of cool features:
- Full block and occupancy control, knowing exactly which locos/cars etc are in any given block
- Reporting from the train, knowing the actual speed, if it's stalled, any issues etc
- Much more advanced programming, the decoder can talk back and tell you what it is and what it does
- Full, safe firmware upgrade support over the rails. The concept of a programming track goes away completely
- The much higher bandwidth (compared to DCC) could enable more advanced things like sending sounds on demand. Maybe a low res camera if you push it?
LCC specifically avoids being a replacement to DCC, but that got me thinking: why not? LCC already has the full concept of train control, but it's intended for DCC boosters and other things to represent the trains to other LCC devices, as a bridge.
There's probably some motivations for this separation outside of the purely technical reasons (standards adoption is one) but I'm a techy guy, so I just want to focus purely on the technical aspect. The question I asked myself: is it possible?
So naturally I spent almost 2 days feverishly researching, and I'll share just the basics. Plenty more to figure out, this is all theoretical.
Problem 1: Can CAN work over power?
There's various devices on the market that are able to inject a data signal into a standard power outlet at much higher data rates than LCC, so it must be possible. The idea is to apply 15V DC to the rails, and then essentially overlay the CAN bus signal on it. With the right circuitry on each end, an injector and a decoder could separate the high frequency CAN signal from the DC power, and then use standard CAN transceivers to communicate.
On the electrical side, we basically use inductors and capacitors to form a high and low pass filter to both combine and separate the two from each other. These components are not small. Based on the components I specced, it's taller than most decoder specs allow, and I think it'll only fit in HO scale and above. This is the advantage DCC has - it only requires a few diodes, and these can be tiny.
Problem 2: How do we keep the trains running?
The injector would need to be smart. While we could just straight up inject the CAN bus into the rails, dirty tracks and small disconnects will cause a lot of errors on the bus. CAN handles this through retransmission and retries, but it will pollute the network a lot. This is solved through a simple forwarder, that is responsible for taking messages in from the backbone, and creating its own bus for the track. Additionally, because we have bidirectional communication, an injector will always know exactly which trains are on its section, so it only has to forward messages for that section.
This in theory could lead to a MUCH higher volume of trains that could be handled on one bus. 1) because LCC only transmits train control messages when something has changed while DCC sends them over and over, and 2) because each block only has to send messages for the train within it. And 3) much higher bandwidth, of course.
Problem 3: What happens when a train crosses from one block to another?
As they're both running the same DC power, from the power side, nothing! This is already a nice advantage over DCC, where the boosters need to be kept in sync to prevent shorts. On the data side, what happens is that the two CAN buses are temporarily joined together, and both injectors see the train at the same time. This will lead to duplicate messages being forwarded. The decoder can handle duplicate messages, it just drops one. But message collisions could happen. Each injector needs to add a tiny random delay to their forwarding, which should prevent this. They also need to not forward messages that have already been forwarded to prevent loops.
You'd need an injector for every block, which might get expensive. It's all using "off-the-shelf" components though, nothing fancy. Depends how prototypical you want to get, and therefore how big your blocks are.
Plus, reversing loops become super simple. Reverse the polarity, and the data reverses with it. Which brings me to...
Problem 4: What happens when I put a train on the track the other way around?
CAN buses expect a certain polarity to the signal. If you turn the train around and have it see the rails the other way around, then communication doesn't work.
This one's fairly simple, just needs a few components. We handle power the same way as AC power with a bridge rectifier. For the filtered CAN bus, the MCU can detect the track polarity, and flip the signal if needed. It needs a few components on the board for this which I won't get into.
Problem 5: What happens if a train loses power very briefly on the track?
The LCC standard is very explicit that when a node starts up, it should reinitialize and go through the whole song and dance of announcing itself to the network. It's fairly common for a loco to encounter some dirty track, temporarily lose power and have its own momentum carry it through.
In this process, the microcontroller loses power and forgets what it's doing. DCC handles this by just sending the same commands over and over, so it can just be read and get going. LCC only sends messages when something changes.
So we need to bend/extend the spec slightly here. We add a new signal sent out by the decoder every 200ms that acts as a transponder. The injector can use this to understand what is occupying its block (full occupancy capabilities, yay!) and also that same transponder signal contains all the information about what the decoder is doing right now. It stores its own alias address and controller ID in flash as these change rarely.
The injector stores this information. If the decoder loses power, on startup, it asks the injector "Hey! What was I doing again?" and the injector responds, but only if it saw the decoder within the last second or so. If the decoder gets its state back, it doesn't go through the initialization song and dance, and as far as the rest of the network cares, it never went away.
Conclusion
Thanks for reading my essay. I'm hoping for people to poke holes in my idea, because I'm sure that this was thought about and discussed a lot when the LCC spec was being made. Do you think it's technically viable, and if it existed, would you buy it?