MERG CBUS/VLCB hardware support

Moin Tom,

I’ve made some adjustments to the node parameter reading, now it sends them one by one. Implemented in the CBUS/VLCB simulator based on your screenshot :slight_smile:

Hope this works in the real world too :slight_smile:

Greetings,
Reinder

p.s. Added another #include <format>, so you might need to patch that.

Moin Reinder,

I work this evening only on the documentation branch. I changed the build.py to use language parameters to create the index (sidebar) of the manual. And I translated some more text. No pull request, but I pushed it to my fork.

I will test the new cbus branch tommorrow, ops, later :wink: Time to go to bed.

Greetings, Tom

Moin Reinder,

the problem with the non-existent `<format>` under Debian 12 is annoying. Now I have to modify another file :wink: I’ve now made these changes. You don’t want that in the code, but couldn’t we just implement it in the CBUS branch?

CMakeLists.txt:

# Debian 12 has no <format> so switch to fmt
+   include(CheckCXXSourceCompiles)
+   check_cxx_source_compiles("
+     #include <format>
+     int main() { auto s = std::format(\"{}\", 1); }
+     " HAS_STD_FORMAT)
+ 
+   if(NOT HAS_STD_FORMAT)
+     set(USE_FMT ON)
+   endif()
+ 
+   if(USE_FMT)
+     find_package(fmt REQUIRED)
+     target_link_libraries(traintastic-server PRIVATE fmt::fmt)
+     target_compile_definitions(traintastic-server PRIVATE USE_FMT)
+     target_link_libraries(traintastic-server-test PRIVATE fmt::fmt)
+     target_compile_definitions(traintastic-server-test PRIVATE USE_FMT)
+   endif()
+   # Debian 12 end

cbusnodelisttablemodel.cpp:

/* Debian 12 has no <format> */
#ifdef USE_FMT
  #include <fmt/core.h>
  namespace std {
    using fmt::format;
  }
#else
  #include <format>
#endif

cbustostring.cpp

/* Debian 12 has no <format> */
#ifdef USE_FMT
  #include <fmt/core.h>
  namespace std {
    using fmt::format;
  }
#else
  #include <format>
#endif

So cmake uses always fmt if format is not present. However, everyone using Debian 12 or a distro like MX Linux based on Debian 12 must have this problem.

I enabled the CANCMDB to send every 5s the track current.

The current mulitplier is 50.

With JMRI it looks like that:

JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 0 50  Long Event On Ex2 
JMRI  < <  CBUS |  DFUN Session: 1 Range: 1 Fn 18 Set Engine Functions 
JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 0 50  Long Event On Ex2 

The message from CANCMDB is a ACON2 with 2 bytes. So I think, the current is 50 x 50 = 250mA. This test I have done with a Roco BR93, ESU LokSound 5. I think the power consumption should be about right. I think the power consumption should be about right; but to really know, I would need to take a resistor and check the current with a multimeter.

With Traintastic (shorten):

2026-03-25 23:33:16.323752 cbus_1 D2002: RX: DSPD session=1 speed=127 direction=fwd [47 01 FF]
2026-03-25 23:33:16.506005 cbus_1 D2002: RX: DSPD session=1 speed=127 direction=fwd [47 01 FF]
2026-03-25 23:33:16.972127 cbus_1 D2002: RX:  [D0 FF FE 00 01 02 26]
2026-03-25 23:33:17.780142 cbus_1 D2002: RX: DSPD session=1 speed=79 direction=fwd [47 01 CF]
2026-03-25 23:33:17.837398 cbus_1 D2002: RX: DSPD session=1 speed=75 direction=fwd [47 01 CB]
2026-03-25 23:33:18.139440 cbus_1 D2002: RX: DKEEP session=1 [23 01]
2026-03-25 23:33:18.977122 cbus_1 D2002: RX: DSPD session=1 speed=21 direction=fwd [47 01 95]
2026-03-25 23:33:19.454272 cbus_1 D2002: RX: DSPD session=1 speed=20 direction=fwd [47 01 94]
2026-03-25 23:33:19.466817 cbus_1 D2002: RX:  [D0 FF FE 00 01 00 C8]
2026-03-25 23:33:19.618797 cbus_1 D2002: RX: DSPD session=1 speed=8 direction=fwd [47 01 88]
2026-03-25 23:33:19.683686 cbus_1 D2002: RX: DSPD session=1 speed=4 direction=fwd [47 01 84]
2026-03-25 23:33:19.764674 cbus_1 D2002: RX: DSPD session=1 speed=0 direction=fwd [47 01 80]
2026-03-25 23:33:19.878802 cbus_1 D2002: RX: DSPD session=1 speed=0 direction=fwd [47 01 80]
2026-03-25 23:33:21.961649 cbus_1 D2002: RX:  [D0 FF FE 00 01 00 00]
2026-03-25 23:33:22.333192 cbus_1 D2002: RX: DKEEP session=1 [23 01]
2026-03-25 23:33:24.456458 cbus_1 D2002: RX:  [D0 FF FE 00 01 00 00]

The last two bytes are the current. I’m not sure how to convert that. Since I only have estimated values ​​for the loco, I’ll probably have to measure it properly with some power resistory, I should have enough here .

Greetings, Tom

Hi Reinder,

also test this now, but at first:

After every new build I have to set the checkmark “Online” again:

Otherwise the server says “bad address” if it tries to open the port.

But this looks very nice! :slight_smile:

Tomorrow I should get the parts, so I can build next weekend a CANUSB and CANMIO for you. I flash the controller with the Universal-Software for the CANMIO, because this version has much events and node variables to configure with MMC, fine for testing.

But as we already have discussed, not all of this will be needed in Traintastic, but there are much possibilities for testing. I want to do a test with two CANUSB devices, one for Traintastic and one for MMC - to use both at the same time.

Greetings, Tom

Moin Tom,

I’ve added fmt::fmt fallback, added a compat folder with a stdformat.hpp header, that can be used anywhere so the rest of the codebase isn’t polluted :slight_smile:

The message from CANCMDB is a ACON2 with 2 bytes. So I think, the current is 50 x 50 = 250mA.

50x50=2500, that is a bit high…maybe the second by is a fraction. I think we need to dive into the CANCMD source (or ask at the MERG forum) how to read it. Would be nice to show the track current :slight_smile:

Otherwise the server says “bad address” if it tries to open the port.

Is the “bad address” message in the Traintastic log? If so what is the exact log line?

But this looks very nice! :slight_smile:

Thanks, any other columns that are useful to add? SLiM/FLiM? CBUS/VLCB node?

The module configuration is very extensive, that is really cool.

Other nice option to test is JMRI and Traintastic both connected, then one can switch a turnout, and the other should detect that as well.

Greetings,
Reinder

Moin/goeie,

@reinder @DL7BJ i might be able to help testing a bit if you want/need
( my coding abilities don’t want to subject you to :grinning_face::grimacing:)
I currently have a test board up with

Dcc-ex via Ethernet

Canusb with 2 canservo / canmio

Will soon build canether and rfid concentrator

If it helps I have:

1 3way switch, 1 regular

6 dtc ( power detection ) blocks

5 irda end of track devices

And events for switch movements ( thrown/mid/closed )

Happy to share the config dump ( jmri export )

Above all on cbus though

Ps love the progress you have made within a short amount of time

@MZwa welcome to the forum! Thanks for reaching out!

Additional testing is very welcome!

Currently I don’t have any hardware, I just implemented it based on the specs and @DL7BJ does the testing, it works quire well :slight_smile:

CANEther is implemented but not yet tested, so that would be very helpfull. Do you know the default port number where Traintastic should connect to?

Long/short events with no additional data are supported currently, so if you can give that a test drive that would be nice. As you may have read above Traintastic can also list all discovered nodes. It had some timing issues on the first try, it now works at @DL7BJ can you give it a try too?

RFID concentrator is not you supported, but I’m willing to add that as well, do you use it for locomotive/wagon identification?

The IRDA devices, do the send ON/OFF events or events with additional data?

You can find the Traintastic development builds with CBUS/VLCB support at: traintastic.org/download/develop/cbus

Greetings,
Reinder

p.s. DCC-EX via network is also supported by Traintastic :slight_smile:

@reinder
Will try and have a look tomorrow / later this weekend

Ps one future request perhaps for the Zagreb release? Mqtt support would be nice
Esp since that might be a very universal entry utilizing / enabling many micro controllers / home brew things

I have been working on a home brew Esp32 Mqtt to rfid gateway merg style as well as a pca9685 ledlight / signal controller via Mqtt
[ and failing :rofl: ], but that is probably more my (in)ability

I’m fairly sure canether port is 5550
Which afaik is the same default port jmri sets for its cbus gateway

And if you are willing to spend £

https://www.rmeuk.com/buycbuskits.html

Is offering a bunch of kits to the general public

Intention is indeed to stick a tag under locos and rolling stock. Jmri and friends are able to track once detected and registered tags and follow once seen and assigned

( one uid of a tag is linked to a loco or piece of rolling stock )

Tbh rfid is for me a nice to have and not a show stopper

I’m more excited to see an open source software jump up and grow up quick

Hi All,

I’ve added two mode columns to the node list:

  • Mode: FLiM or SLiM
  • Type: CBUS or VLCB

@DL7BJ the MMC node list also has Status, do you now how that is requested?


Ps one future request perhaps for the Zagreb release? Mqtt support would be nice
Esp since that might be a very universal entry utilizing / enabling many micro controllers / home brew things

MQTT would be nice indeed, we’ll see if it is Zagreb or another city :slight_smile:

Intention is indeed to stick a tag under locos and rolling stock. Jmri and friends are able to track once detected and registered tags and follow once seen and assigned

( one uid of a tag is linked to a loco or piece of rolling stock )

Tbh rfid is for me a nice to have and not a show stopper

If it works some communication logs would be interesting :slight_smile:

I’m more excited to see an open source software jump up and grow up quick

Traintastic is slowly gaining some traction, interaction on the forum is also growing slowly. But that is fine for now, there are still some important basics todo, the big one is routes/automatic driving which is planned for the “Edinburgh” release.

Greetings,
Reinder

A post was split to a new topic: First impressions testing Traintastic 0.4

CBUS notes:

  1. The construct node/address feels a bit … weird?
    probably node and event would be a little clearer description?
    i will hook up my jmri instance later and check in FLiM to check
    their nomenclature. Potentially swap node and event [ address today ]
    I use Flim [ windows configuration tool ] to configure CBUS nodes.
    However: until now i used JMRI’s CBUS Hub function to expose that to my
    internal network. Until i get to build my canether.
    or to be honest my current can-ether pcb+ components is damaged → need to order and build a new one :sob:

  2. Exiting without a clear save button feels strange.
    If you had to back out a change because you made an error?
    that is particularly a risk if you have an extensive event list.
    Ask me how i know…
    Hint:
    3 switches
    6 blocks sensors
    5 end of track sensors
    3 switches x 3 events [ trown / mid / closed ]
    and you are already looking at 40+ events over 3 or so boards..
    I am probably being a bit playful but i have seen large Cbus installs
    where these numbers would be on the low side …

  3. I am wondering: you have reed sensor and occupancy detector
    Maybe section and spot detector is covering more?
    section detection for a longer section; Spot for a single short spot

    ( i use mergs’s dtc2 power measurement based for blocks/sections and a bunch of
    InfraRed sensors for spot detection; ie end of track.
    i might change them out for Time of flight or ToTI [ laser based ]
    but that is still spot detection anyway as far as i am concerned )

Lets also celebrate the good stuff:
Sofar both my end of track as well as block detectors [ dtc ] work.
My GUI runs from windows, the backend runs sofar faultless from a separate computer. As far as i am concerned: this is a step forward from previous experiences… Thanks @reinder [ and others ] for making it happen!

@reinder Happy to share the current track and/or the export for my cbus env

Hi,

  1. The construct node/address feels a bit … weird?
    probably node and event would be a little clearer description?

It should look like this, I’ve changed that some time ago:

I wonder why you don’t see it. :thinking:

  1. Exiting without a clear save button feels strange.
    If you had to back out a change because you made an error?

Both systems the classic ok/apply/cancel and modern direct method have their pros/cons. For Traintastic I choose to use the modern direct method, as it eliminates conflict resolving if two users alter the same object at the same time, that is now handled smoothly. Dependencies between settings are also much easier to handle. It has also some cons…

I usually save the world before making such changes, it is not ideal, but it works :slight_smile:

  1. I am wondering: you have reed sensor and occupancy detector
    Maybe section and spot detector is covering more?
    section detection for a longer section; Spot for a single short spot

I like the term, it is more generic :slight_smile: Thx!

Can you share a screenshot of the CBUS node list, and the log messages regarding node discovery (QNN/PNN)? For that you need to enable Log all communication:

The server log then will display something like this:

How did you configure the three-way turnout?

Many thanks for testing and providing feedback!

Greetings,
Reinder

1 Like

Moin Reinder,

I can’ find a state in the specs of CBUS/VLCB. I have seen only to states “OK” and “OFFLINE”. I think, it’s an MMC internal, if a node answers at startup.

Greetings, Tom

@DL7BJ In case you need it:
JMRI has a CBUS concentrator exposing it via network
There is also a NodeJS merg Cbus server to expose a single canUSB as a network device.

( if you are brave enough to run the nodejs supply chain gauntlet… )

@reinder

I configured the 3way layout as 2 nested "normal" turnouts.
This due to old habits where support for a 3way driven by servos is not obvious. 
Also [ technically ] i would have to stack 2 commands if i go to 1 of the extremes 
Otherwise the frogs will be pushed out of position ever so slightly. 
Since lazy me did not implement electro-frogs on that tester board... 

i have configured the 3 way switch and your config is FANTASTIC, allowing to set and unset what is required!
( → to prevent frogs being slightly pushed out of line )

Please mind i only run servo’s so i do not have Tortoises/Seep/Electro magnetics

I have also captured the following from JMRI:
A find all nodes run:
sync-all_nodes.txt (989 Bytes)

and a JMRI initiated backup of my existing nodes:
sync-canmio-svo_node256.txt (64.6 KB)
sync-canmio-node257.txt (10.7 KB)
sync-canmio-node259.txt (10.7 KB)

And a complete dump of the merg config from jmri in more readable form:
This is a dump from before i started mucking around with things. Should still be mostly intact.
cbus-events.csv (6.2 KB)

Unfortunately i have lost the world i built yesterday → restart.
Which led to the discovery that Traintastic does not want to talk to JMRI/CBUS hub; Flim is working fine via that path tho…

If there is anything i can do to help debug here, please let me know.

After connecting i see only 1 node appear:

That remains even after adding events from other boards.

CBUS is not happy if you go offline for unrelated interface modifications
… required futzing with CBUS → offline → online

Oh the QNN/PNN details:

That’s exactly why it works like that. Good to hear it does its job well :slight_smile:

Unfortunately i have lost the world i built yesterday → restart.

Didn’t you save it? (Traintastic doesn’t ask…that could be an improvement)

Which led to the discovery that Traintastic does not want to talk to JMRI/CBUS hub.

Based on the JMRI CBUS Hub Control page it should be the same protocol as CANEther, maybe there is a bug in my implementation, the CANEther implementation isn’t tested yet. Just had another look at the implementation, there was a write flaw that could be the issue, I’ve just committed it, can you try again with build #1942?

Can you do the node discovery again?, I need to see the full message timestamps, include the microseconds.

Traintastic CBUS initialization / node discovery work like this:

  • Interface state = Initializing
  • Send QNN
  • Wait for PNN, 200ms timeout
  • If a PNN received, reset set the timeout and wait for another 200ms.
  • If no PNN is received within these 200ms it will continue with reading the node parameters using RQNPN.
  • Wait for max. 50ms for the node’s response, then continue with the next RQNPN until all are sent.
  • Send a RSTAT to query command station status.
  • Wait until STAT, 200ms timeout
  • Interface state = Online

As I can’t see the timestamp it seems the modules response to slow, therefor they are not listed.

Greeetings,
Reinder

Hi,

Development update:

  • For CBUS/VLCB short/long event input, address is now labeled event.
  • When CBUS/VLCB goes online it now requests the state of all used events.

Available for testing in Build #1943

Greetings,
Reinder

Moin Reinder,

I completely missed this post, sorry!

It’s nice with the compat folder, so I don’t need to change the files after every fetch.

I want to test the JMRI MERG Hub, as suggested by John or Jane Doe :wink: @MZwa Just kidding, do you have a first name? I am Tom and DL7BJ is my Amateur Radio Callsign.

Reinder, I can’t compile the cbus branch at the moment, much errors which all have to do with SocketCAN. I am not sure, if this is the main error:

/home/tom/projects/linux/traintastic/server/src/hardware/protocol/can/iohandler/socketcaniohandler.hpp:41:145: error: ‘std::span’ has not been declared
   41 |   SocketCANIOHandler(boost::asio::io_context& ioContext, const std::string& interface, std::string logId, OnReceive onReceive, OnError onError, std::span<Filter> filter = {});

I attach the build log.

build.txt (67.2 KB)

Before I try to build this version I test another thing, the current meter of JMRI.

MRI  < <  CBUS |  DSPD Session: 1 Geschw 116 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 120 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 124 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DKEEP Session: 1 Keep Alive 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 2 88  Long Event On Ex2 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  DSPD Session: 1 Geschw 126 Forward  Speed/Dir 
JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 1 244  Long Event On Ex2 
JMRI  < <  CBUS |  DKEEP Session: 1 Keep Alive 
JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 0 200  Long Event On Ex2 
JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 0 100  Long Event On Ex2 
JMRI  < <  CBUS |  DKEEP Session: 1 Keep Alive 
JMRI  < <  CBUS |  ACON2 NN:65534 EN:1  Data: 1 244  Long Event On Ex2 

The data 1 244 are the average of the voltage read by A/D conversion of the controller multiplied by 50 as 16 Bit value, found it in the CANCMDB code. For the main track it use a 0.1R current sense resistor at Sense A (pin 1) of the L298N; I never used this driver and read just the datasheet. The max current for a half L298 is 2A. So the max voltage for A/D conversion can be 200mV. The two bytes are 1 x 256 + 244 = 500 → 500 / 50 = 10. The converted A/D value must be ~10 for 550mA. The A/D converter is a 10Bit, the reference voltage 5V → 10 / 1023 * 5 = 49mV. I = U/R → 49mV/0.1R = 0.49A

For other shunt values the multiplier can be used to adjust the result. I think with all measurement and converting errors, this it is. I hope I haven’t miscalculated again! :wink: :wine_glass:

Greetings, Tom

Moin Tom,

Did a quick commit, I’d hope that fixes the build issue. Looking into the current meter stuff tomorrow (Tuesday), time to sleep…

Greetings,
Reinder