Model Train-related Notes Blog -- these are personal notes and musings on the subject of model train control, automation, electronics, or whatever I find interesting. I also have more posts in a blog dedicated to the maintenance of the Randall Museum Model Railroad.
2021-04-24 - DCC++ EX support in Android Cab Engineer appCategory Jmri
Today on the bench, we have two things going on:
On the left side, we have a “Wifi Kit 32” ESP32 running a fork of the latest DCC++ EX firmware.
On the right side, we have my Cab Engineer DCC Throttle app for Android communicating with the DC++ EX command station.
A few clarifications and explanations are needed here.
First, I’ll be very clear: the DCC++ EX firmware does not support any ESP32, and my fork is mostly non-functional. That project supports a few Arduino variations with corresponding motor shields used to generate the DCC track power. The firmware also supports very specific wifi or ethernet shields for the remote app communication.
I do have a few supported Arduino UNO or Nano, yet I did not have the adequate motor / wifi / ethernet shields to run the whole thing as-is.
Since I want this to adapt my app to work with the device, the wifi or ethernet shield is the mandatory part and that’s precisely what I did not have around. I do have a Digistump DigiX (mega with wifi clone) for my old layout using my Translate control software; I don’t want to rip that off though. I could order some Arduino wifi shields but right now shipping from low cost providers overseas is taking about forever.
On the other hand, I have a handful of ESP32 around. All of them have wifi, which is exactly what I need. How hard would it be to run the DCC++ EX firmware on them?
The DCC++ EX firmware is not designed to build on ESP32, and without corresponding motor shields it’s rather moot to control any DCC. Yet for my Android app communication needs, that’s fine. So I did just that:
- https://github.com/ralfoide/CommandStation-EX is my fork of the DCC++ EX firmware to build on ESP32.
- It uses the same PlatformIO configuration file with a new “esp32” target.
- I don’t have a suitable motor shield driver so I added a new “no-op motor driver” that does exactly nothing.
- My fork further disables DCC waveform generation ISR since I have no need for it.
- I was agreeably surprised to see the firmware had support for an I2C LCD (got one here), or even an OLED exactly like the one included on the “Wifi Kit 32” board. However the default implementation is Arduino-pin centric so I added a new implementation to support the OLED screen via the U8G2 library.
- The default firmware supports either the AT-based wifi (ironically implemented using an ESP8266) or an ethernet shield. Neither of these are suitable as-is on the ESP32. I added a new “Wifi ESP32” implementation by forking their ethernet shield support and adapting it to support the late-init style of the wifi.
- The was some low-level code that I simply disabled with the appropriate “#if !defined(ESP32)” which was performing I don’t know what DCC-related duty.
The result of that fork is available here on Github at https://github.com/ralfoide/CommandStation-EX after I cleaned it a bit. The “no-op motor driver” is IMHO something the DCC++ EX project should have upfront, to make it trivial to debug the firmware without affecting any real DCC accessories or to make it easier to port their firmware to new architectures. The OLED U8G2 and the Wifi ESP32 support are fairly obvious. For that latter, I used the WiFiServer / WiFiClient Arduino-based classes; they integrate very well with the ESP32 and basically mirror the “Ethernet Interface” that was implemented in the DCC++ EX code.
I obviously did not spend any effort trying to support the feature set of the ESP32 nor its FreeRTOS foundation. For example the DCC++ EX firmware is very careful to only perform a small incremental unit of work in its main loop, updating only part of the OLED display, or processing only part of the DCC cab wifi chatter. All these would be better architectured as individual FreeRTOS tasks communicating between each other with the appropriate FreeRTOS semaphores, queues, or message buffer synchronization APIs. That would allow using the two CPU cores more efficiently when available.
In the end, that did serve me well to debug the app behavior though, which was the whole point.
The Cab Engineer DCC Throttle app for Android is available on the Google Play store and the latest “beta” v0.1.5 version is available by joining the “beta channel”. It features:
- New: Connect to DCC++ EX command stations.
- There is no auto-discovery yet. I will likely add that later; apparently this is done by scanning for a wifi access point with a name of “dccex-<mac address>” and I could change my ESP32 port to perform that too.
- New: Support for Track Power control in the JMRI / WiThrottle protocol.
- This is supported by the DCC++ EX command stations.
- For JMRI using an NCE command station, the track power is shown as “Unknown”. I’ve added an app setting to hide the track power control card in that case, so if you want that card yet don’t see it, enable it in the app settings.
- New: Connection status card (useful with flaky wifi).
- Connection status used to be a small line updating at the bottom of the screen. Although I do like that a lot, I do realize it can be quite subtle for many users. The new card makes the connection status more obvious. More importantly it clearly indicates if the connection is being lost and a reconnection attempt is happening. The card can be disabled in the settings, in which case the old one-line status is shown.
- New: Edit/delete server entries.
- Sort of the kind of obvious functionality that is coming slowly… That’s still version 0.1.x after all.
- Updated JMRI heart beat handling & reconnection.
- That’s an area where I had partial support so I finally completed it. I believe I’m following the WiThrottle heartbeat protocol properly (as much as I can tell from the lacking documentation).
- I also added my own check on that. If the app can’t talk to the JMRI server, it automatically disconnects and reconnects. I found that useful on flaky wifi networks. I prefer the app to tell me it fails to connect to the server than let me hanging and believe my commands may be received some day later.
The step in the app is translating as well as focusing on implementing DCC Fn support, with both profiles and customization. The current UI in the app is limited to F0..F8 and fixed quick functions, which is not even enough for my own needs.