Ever since work started on this layout, it became evident that stopping trains in front of signals in a realistic manner is a must. In the early days an oval track loop was used with detectors mounted at various points to perform some measurements. I would say copious amounts of time have been spent over this operation during the years, with scores of written pages.
The first thing was getting a consistent terminology. It was during my discussions with Lenz in the beginning of 2010 - when I couldn't figure out how the decoder in the their BR66 was working - when this was established. The value displayed on the DCC handheld controller is the external speed step. As a side node, I've never had a need to switch to anything else than the default 28-step mode. Internally, the DCC decoders use the internal speed step, which translated into the voltage applied to the motor. Separating between the 2 allows creation of custom speed curves, allowing for example accelerating in small increments at lower speeds. The decoders themselves can use 2 modes of operations: 1. CV2, CV5 and CV6 are used to specify relative values for the start, max and medium speed respectively. 2 a user defined speed table is programmed in a specific set of CVs (for ESU LokSound v3.5, this is the range CV67-96).
However trains also have acceleration and deceleration, which DCC models by using correspondent registers for each: CV3 and CV4. The NMRA standard makes things very simple, by saying that the time taken to cycle between 2 subsequent external speed steps is equal to CV3 * 0.869 / . Unfortunately in practice things aren't that simple. Lenz uses a different formula, based on internal speed steps, and ESU doesn't seem to implement it also.
In august last year I spent almost one day in getting measurements for the Brawa V100, equipped with an ESU LokSound v3.5. To be more exact, the goal was to answer the question "what is the formula for the time taken to bring the locomotive to a stop ?". A section on the layout itself was used for measuring, with several lines of C# code written to send instructions to the Lenz LZV100 via the Lenz LI-USB-Ethernet interface. However since I had no way at the time to detect when a locomotive came to a stop, I had to sit next to the track and press a key when the locomotive would stop - *every* time. There wasn't enough data to see a pattern, so solving this problem was postponed.
Original sheet containing measurements results for the Brawa V100 tests done in August 2015 |
The issue to be solved was detecting when the locomotive was actually stopped. With this out of the way, measuring tests could be fully automated. Since there are already quite a few Phidgets boards I've bought during the time, a current sensor sensitive enough would do. From past observations I figured their most sensitive one would do the job, so I went ahead and purchased 2 of them (an additional one for 1. backup in case the first one fails and 2. error reduction in measurements by averaging, would this were to become an issue). Hooking one of them to the old Phidgets 1018 board that was no longer used revealed it did the job, the only glitch being measuring rapidly dropping currents (eg suddenly breaking the circuit) wouldn't result in a 0 value being read out, however for locomotive under normal deceleration rates this was no issue.
The Hardware setup |
Completing the hardware setup involved getting the right number of coils around the current detector. Being an AC current detector, only one of the wires needs to be inserted through its area. Its possible to reinsert the same wire multiple times through this area, thus resulting in increased sensitivity (albeit increasing error). 2 passings of the wire proved low enough to provide enough sensitivity for when the locomotive becomes stopped versus moving with the minimum possible speed step.
Speed measurement for CV2/5/6 set. Note that the top 2 straight lines are actually artifacts due to automatic connection of points in the series |
First thing to check was that real speed versus internal speed was linear for the ESU v3.5, or in other words measure the real speed (cm/s) for each external speed step. The default decoder user speed curve - which is linear - was activated using bit 4 in CV29. The code for speed profiling was actually implementing a state machine, along the following path: locomotive gets configured with CV3=1 and CV4=3, in order to allow quick acceleration but a slower stop; it gets sent on its way using the maximum external speed step; when hitting the 1st detector the time is marked; when hitting the 2nd one the speed can be computed, given each distance between the detectors is known in each direction (this IS important, since the distance between detectors can differ depending on the way and based on the detector orientation) - also a stop command is sent; once the idle current level is detected, the external speed step is decreased by 1 and the locomotive sent the other way and the process continues. The data was automatically saved in a .csv for post-analysis. 160 runs were captured. The first thing to notice was that indeed the real speed is indeed linear with the internal speed step, so no surprise here (the correlation coefficient was averaged to 0.26 (real speed / internal speed step). Secondly, when switching to the CV2/5/6 mode for the speed curve, the profile was indeed verified to be as in the ESU v3.5 LokSound manual (pg 19, an online copy here) - namely the speed curve didn't end up as an exponential function (hint: Lenz does this), but as 2 simple lines "broken" at the middle point. Thirdly, if the CV6 value (mid) is greater than CV5, then the detector will simply consider a straight line for the speed curve, based on CV2 and CV5 only.
Brawa V100 after the runs were done |
Next, deceleration was considered. The state machine was slightly altered, to consider 4 detectors and operated as follows: CV3 is always set to 1, while CV4 is chosen each time; locomotive gets send with the maximum speed; once the first detector gets triggered, a stop command is sent; once the threshold value for current is hit (signalling the locomotive just stopped), the time it took to stop is marked. Then, depending if the detector behind the 2nd one on the direction of the run (called the fallback detector) is triggered, the locomotive is moved safely until this fallback one is hit. Then the locomotive is again issued a stop command, the idle current value is waited for, after which the speed gets decreased by one and the locomotive sent the other way. This slightly complicated way was chosen in order to leverage a flat section of track between the 2 "principal" detectors, however at this point I think it was just overkill. 252 runs were done. Running in both the user defined speed curve, as well as the CV2/5/6 one, confirmed that the ESU LokSound v3.5 doesn't take into account the internal speed steps, but only the external ones (Lenz does the opposite).
Time to stop versus external speed step, for 4 different CV4 values, given CV2=3,CV5=35, CV6=13. Note the linear aspect, suggesting dependency on external speed step only |
The graphs indicated that a linear function could be used to generalize for any CV4 value, provided the reference of this one was slightly moved "up" - to give a few more details, on the graph to the right, the place where all the lines meet is at 1.13 on the vertical axis; the fraction of the differences between the time value for 2 curves corresponding to the same external speed step minus the "base" point (1.13) will roughly be the same and equal to the fraction of CV4s involved (eg time value for external step 20 on the top line, corresponding to CV4=20, minus 1.13, all divided by the time value for external speed step 20 on the 2nd line from the bottom, corresponding to CV4=10, minus 1.13, will equal approximately 2, the same ratio of 20:10).
A final formula based on the linear functions for 2 sets of results belonging to CV4=5 and CV4=10 was deducted:
t(E, CV4) = (a*E + b - B) * CV4 / 10 + B
where a=0,337; b=0,479; B=1,13.
The difference between the real measured value and the one computed based on the formula usually stays inside 0.2 seconds, but there are exceptions.