Purple hat is a hardware platform by Hans Tanner used to automate speed profiling for Digital Command Control (DCC) equipped model railroad locomotives. Both the hardware design and provided software are open source and can by found on the internet of toy trains (IOTT) stick git hub repository:
https://github.com/tanner87661/IoTTStick
In addition many excellent support videos can be found on the IOTT you tube channel:
https://www.youtube.com/c/IoTTCloud
Here are just a few that highlight the development of the purple hat, but check out the channel for these and many more concerning all apsects of using new technology with the model railroading hobby.
This github repository comprises a derivative work from Hans Tanner's Purple hat IOTT stick SW. The derivative software supports over the air (OTA) firmware (FW) download and OTA logging. Adding the ability to download FW over the air wirelessely allows the M5 stick to be updated in place on the layout without a COM port connection. This is a nice feature since the battery I use to run the M5 stick does not allow for COM port access. With OTA FW dowload I can also update the M5 FW without having to remove the M5 from the battery.
Note
This is Purple hat only other hats have been removed and only a subset of the features are supported. This was to make flash memory space available for the the over the air FW download and over the air debug logging.
The purple hat module code has been converted to a platform.io project hosted by microsoft visual studio code. Both the IDE and platformIO are free to use. The main motivation for this change was to support incremental builds which lead to build / compile times on average of less than 40 seconds. The repo has the required launch file in the .vscode folder in the src tree.
The required platformio.ini file setup to build for the M5-stick is also provided in the main src folder. This links to all of the external libraries as well as specifies the spiffs settings for the memory layout. The min-spiffs.csv is also provided in the main src folder.
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env]
lib_deps = https://github.com/m5stack/M5Unified.git
https://github.com/me-no-dev/AsyncTCP.git
https://github.com/alanswx/ESPAsyncWiFiManager.git
https://github.com/me-no-dev/ESPAsyncWebServer.git
https://github.com/ayushsharma82/AsyncElegantOTA.git
https://github.com/bblanchon/ArduinoJson.git
https://github.com/adafruit/Adafruit_Sensor.git
https://github.com/adafruit/Adafruit_BNO055.git
https://github.com/taranais/NTPClient.git
extra_scripts = pre:buildscript_versioning.py
[env:m5stick-c]
platform = espressif32
framework = arduino
board = m5stick-c
board_build.partitions = custom_spiffs.csv
monitor_speed = 115200
upload_speed = 115200
build_type = debug
monitor_filters = esp32_exception_decoder
Important
Even though the documentation reports that a custom partitions file can be in the main project folder I have found that with some versions of platform io it may be required to copy the file to the platform io partitions folder.
C:\Users\xxxx.platformio\packages\[email protected]\tools\partitions
i.e. manually copy custom_spiffs.csv to the above folder
The purple hat module SW introduces several additional features not present in the original purple hat IOTT version. These features are designed with G-scale modellers in mind, and help to ease the process of the speed magic test. While tailored for G-scale, the new features may also prove valuable for enthusiasts in other scales. If there is interest in these features, let me know and perhaps I can ask Hans Tanner about including one or more of them into the main IOTT repository.
The first feature is not scale-specific but rather pertains to the setup used to run purple hat and the IOTT stick. I obvserved that, when aligning the engine to the test starting position from the reverse direction, the engine would move backward instead of forward for the first leg of the speed magic test. This occasionally led to a direction mismatch, requiring a reboot of the IOTT stick.
To address this issue, a simple workaround is to stop the test, align the engine from the forward direction or manually set forward direction from the throttle. Many times I forgot to set forward direction and the test wound up with the direction mismatch. As a solution, I introdcued a -1 state to the PurpleHatModule state machine for the speed magic test. This new state automatically sets the direction of the engine to forward, effectively resolving the problem. This adjustment not only saves time but also eliminates one more thing to remember during testing.
case -1: // force to forward direction in case direction is reversed after test stop.
{
Log::println("Start test set forward.", LogLevel::INFO);
forwardDirCommand();
upDirIndex = speedSample.adminData.upDir ? 1 : 0;
forwardDir = ((*focusSlot)[3] & 0x20) == 0x20;
speedSample.adminData.testState[0].startSpeedStep = 0;
speedSample.adminData.testState[1].startSpeedStep = 0;
// Set these for testing to start at a different step.
speedSample.adminData.testState[0].lastSpeedStep = 0;
speedSample.adminData.testState[1].lastSpeedStep = 0;
speedSample.adminData.testRemainingDistanceStartingLinIntegrator = 0;
speedSample.adminData.masterPhase = 0;
speedSample.adminData.result = 0;
}
break;
One of the more difficult settings to tune to the correct value was the track length for the test. Through this process I discovered that the speed magic test perfoms best with G scale with long distances. Currently the shortest distance I use is 13500 mm. Ocassionally, I found with distances that were too short that the test was not able to measure a single speed step and it could get into an infinite loop since the step counter was not effectively incrementing. To fix this a feauture was added to the test where it now requires a minumum of at least two speed steps to be completed in a single speed magic pass. If the minimum two speed steps are not completed in a given test test cycle, the stops width a warning that the track length may be too short.
The purple hat sensor, as provided from IOTT, requires setting the acceleration and decleration CVs for the decoder to a value of 0. Unfortuately, many G-scale locomotives can suffer from cracked drive gears if drive forces exceed certain levels. At higher speeds, I felt uneasy with the engines being directly driven to high speeds and stopped very quickly during the speed magic test.
As a consequence, in the purple hat module version of the test, support was added to wait for the engine to come up to speed before the testing resumes for the next test sequence or pass. This feature allows non-zero accelertion / deceleration values to be used during the test. A downside to this approach is that the speed magic test will require a longer track length in order to complete successfully. See the previous feature regarding the warning added to support a track length that is too short. This can help "dial in" the correct track length for the speed magic test.
As with the force forward direction feature described above, an additional state was added to the state machine to achieve this new function. (The new step is step 4 and the original IOTT step four is now step 5 in the state machine.) As can be seen with this new step in the state machine the speed magic test waits for either the speed to be 80% of the speed from where the test left off or 35% of the tracklength distance used for the test (whichever comes first). In this way acceleration and deceleration values can be used to reduce stress on engine drive components.
case 4:
if(speedSample.adminData.testState[upDirIndex].lastSpeedStep > 1)
{
float_t dataEntry = forwardDir ? speedSample.fw[speedSample.adminData.testState[upDirIndex].lastSpeedStep] : speedSample.bw[speedSample.adminData.testState[upDirIndex].lastSpeedStep];
float_t distanceSoFarDirection = cpyData.relIntegrator - speedSample.adminData.testRemainingDistanceStartingLinIntegrator;
if(abs(cpyData.currSpeedTech) < (0.80 * dataEntry) &&
(abs(distanceSoFarDirection) < (0.35 * speedSample.adminData.testTrackLen)))
{
Log::print("Wait for speed: [mm/s] ", LogLevel::INFO);
Log::print(cpyData.currSpeedTech, LogLevel::INFO);
Log::print("accel: [km/h s]", LogLevel::INFO);
Log::println(cpyData.currScaleAccelTech, LogLevel::INFO);
Log::print("distance so far: ", LogLevel::INFO);
Log::println(distanceSoFarDirection , LogLevel::INFO);
return true;
}
}
speedSample.adminData.masterPhase++;
break;
It is still possible in G-scale to find engines whose decoders do not support the 28-step speed table of the NMRA DCC standard. However it may still be desirable to run a second engine in a consist with the engine that does not support programming custom speed tables. One option could be to replace the decoder in the engine that does not support speed matching with one that does. But the original decoder may have other desirable features such as custom sounds or smoke generator settings that may not be available on the replacement decoder and/or very difficult to reproduce on the reaplcement decoder.
Purple Hat Module adds a feature where a measured locomotive speed profile can be converted to a throttle profile. The new throttle profile can be used with IOTT pruple hat's speed table recalculation feature to generate a new custom speed table for the other engine in the consist. Obivously any engine in the consist must be capable of having its speed table programmed. Now both engines can be consisted together becuase the second engine has been speed matched to the first engine that did not support 28-step speed tables.
Measured Speed Profile: Reference Engine | Throttle Profile: Reference Engine |
---|---|
Measured Speed Profile: Engine To Match | Matched Speed Table: Engine To Match |
---|---|
As can be seen from above after using the generated throttle profile from the reference engine the new calculated speed table for the engine to match when applied now allows the speed to very closely match the speed of the reference engine allowing them to be run in a consist together. Here it is on the layout:
Consist with Reference Engine and Engine to match |
---|
This folder contains various measurements I've made for the G-scale engines in the fleet. The roster folder contains an excel template that documents the various steps for the profiling. i.e. Set high, mid, low speed control, CV29 bit 4, wheel diameter etc. It also shows an overview of the pre-calibrated, speed table and post calibrated data. An example for the RhB 616 Kohle is below: