Introducing DCC++ ---a complete open-source DCC station and interface

Gregg Aug 25, 2015

  1. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    Hrm. Disappointing that I missed that. But I'm having the same problem with the SparkFun ArduMoto shield which does have the Direction/PWM interface, and on the correct pins, too. And I'm having the problem "talking" directly to the Arduino using the Serial Monitor, not using JMRI.

    I send <1> and I get <p1> back, and see the LEDs on the motor shield light up. I then send (for example) <R 8 0 82>, and I get <r 0|82|8 255> back.

    I think I know what might be wrong. I had it defaulting to hardware flow control, which worked OK on my Mac, but does not work on my dad's PC. If you can get into the preferences, click the "Additional Connection Settings" checkbox and change the flow control to "none". If you can't do it within the program, look in your JMRI folder, under the folder with the name of your profile, and open the ProfileConfig.xml file. A few lines down you'll see an XML tag with <name>FlowControl</name>. Change the corresponding value to <value>no flow control</value>. Save and restart JMRI. See if it works.

    Note that I haven't optimized the startup code, so it will spend a very long time with the opening splash screen before the main DecoderPro (or PanelPro) window pops up. That's on my bug list.
     
    Scott Eric Catalano likes this.
  2. esfeld

    esfeld TrainBoard Member

    442
    382
    17
    BINGO! Changed to no flow control in JMRI and I am operational. No problem interfacing with Digitrains, which is my walk around GUI of choice. Once again, thank you.
    Steve
     
    Scott Eric Catalano likes this.
  3. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    Good to hear it works! Please do test it out and report any bugs you find.
     
    Scott Eric Catalano likes this.
  4. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    Quick update... I switched over to the Main tracks, cleaned the wheels on my loco, and I can control the train via a JMRI throttle.

    Programming track is still not working, but I'm pretty sure I know why. The Ardumoto board does not have current feedback, so there is no way to read CVs with this board. I will have to upgrade my motor shield for that to work.
     
    Scott Eric Catalano likes this.
  5. RossNZ

    RossNZ TrainBoard Member

    12
    12
    5
    Hi everybody,
    An introduction from a lurker in the shadows. I had a "G" (45mm) lay out running in my back garden using DCC with LocoIO hardware and loconet for all signaling , detection and turnout control under RR & co software. All independent of the track. Locos where run using Aristocraft Revolution. Then we moved house.........
    Now while slowly doing the civil engineering required for a new railway I am creating additional hardware. Using Arduino pro minis I have signaling , turnout control, train detection all successfully bread boarded using RR & Co software and loconet. I will openly acknowledge all the work done by others on the open source software / Arduino sketches that are available. Up until this time I have had no need for DCC on the track for train control. Things have changed slightly with the purchase of two DCC enabled LGB Allegro railcar sets. Hence the need now to apply DCC to the track.

    Looking at this DCC++ project I am attracted by the cost:). I all ready have an Arduino Mega1280 and an Arduino motor shield is to arrive in my mail box in the next week or so.
    As for my coding abilities.... well I would say I can understand 75% of what I am reading.

    My intention is to get the DCC++ working on a piece of track and get a train to move.
    Then I will look at how it is possible to do what I would like to achieve.

    My end goal is to have the DCC++ get its DCC signal from the loconet to feed the track. I
    appreciate that in reality this is most likely more a booster type application than a master control situation but where it ends up is anybodies guess right now.
    In case anybody is curious, The only Digitrax hardware involved is one front panel UP5 to enable the Loconet to function. I use a RR-Cirkits locobuffer-Rs232 to connect the PC to loconet and all is well:).

    Ross
    New Zealand
     
    Scott Eric Catalano likes this.
  6. DJ79

    DJ79 TrainBoard Member

    36
    25
    14
    Hey, guys, great to see progress being made here. I've been busy with other stuff lately, but I've made some changes to the base station code to enable it to use shields with separate IN1, IN2 inputs instead of a single DIR input. Basically, instead of hardware output pin changes on compare B match which only works on some pins, and requires additional hardware (the Mega) to control more than a single pin, I'm turning this feature off, and using regular timer interrupts instead, controlling output pins through software. The added benefit is that no jumper wires are required, and it also works on the Uno. I was going to post the code, but just realized that changes were made in several files, not just in the main .ino file, so I'll need to clean up the code a little, and then I'll post it here.
     
    Scott Eric Catalano likes this.
  7. Gregg

    Gregg TrainBoard Member

    237
    311
    18
    That's a very interesting approach. I originally started down that path but was concerned about processing speed so I utilized the timer-match hardware control to the maximum extent possible. Do you find you drop any packets when sending serial commands, controlling turnouts, etc? Or is it still fast enough to keep the DCC signal intact?

    Also, I was going to implement register C for some of the timers to utilize dual pin outputs to control in1/in2 motor shields. Because these operate at the hardware level they two signals will flip on the same clock cycle. Do you find the software lag between the interrupt that flips the in1 pin and then the in2 pin is within tolerance of the DCC decoders (i.e. Doesn't cause a power drag)?
     
    Last edited: Nov 28, 2015
    Scott Eric Catalano likes this.
  8. w8one

    w8one TrainBoard Member

    89
    109
    5
    All that is needed to go from two input pins (in1) forward / (in2) reverse to one input (dir) is a npn transistor and some resistors like this image.

    not gate.gif

    Connect any Arduino i/o pin you are using AND in1 (forward) to A. Then Connect out(q) to in2 (reverse). R1 is a 1k resistor R2 is a 10k Resistor. Ground and +Vcc (+5v) FROM the Arduino.
    When the i/o pin is High in1 is High, When i/o is Low it turn on the transistor on and in2 will be High.
     
  9. DJ79

    DJ79 TrainBoard Member

    36
    25
    14
    The ISR takes about 15us on the average, and 22us in the worst case on the Uno at 16MHz, and I'm sure it could be further optimized. The ISR runs every 58us, so that leaves plenty of time for other functions. I haven't seen any issues running trains or stationary decoders, but I don't own an oscilloscope, so I can only theoretically claim that there are no dropped packets.

    As for the delay between changing output signals, my initial version was writing to the hardware port in a single instruction, so the changes were occurring simultaneously. Then I found in some motor driver datasheet (I forgot which one) that there should be a short delay (about 500ns or so) between the two input changes to avoid internal shorts caused by both sides of the H-bridge conducting at the same time during the transition, so I changed it to two separate writes. By the way, the inverter circuit introduces some propagation delay, but I'd think it's more on the order of 10-50ns. I haven't noticed any difference between the two versions, but I guess that I'd need some more sophisticated test equipment for that. I'll be posting the code shortly.
     
    Scott Eric Catalano likes this.
  10. DJ79

    DJ79 TrainBoard Member

    36
    25
    14
    Ok, I've attached the modified code. Note that the PacketRegister (fragment).cpp is only a fragment of the original file. I'm not sure if there were any changes in the new iterations, so I chose to show only the changes (additions): one line added to the RegisterList constructor, and one added member function: AdvanceFSM. Everything else is unchanged. PacketRegister.h shows added members to the RegisterList class (three added lines). The main .ino file is complete, but again, please check if it needs to be merged with new iterations, as I was working with the initial version. I hope this helps.
     

    Attached Files:

    Scott Eric Catalano likes this.
  11. NigelTwo

    NigelTwo New Member

    2
    1
    1
    [QUOTE="TwinDad,
    [/QUOTE]

    TwinDad,
    I wanted to followup on your proposals about sensor reporting. The existing BaseStation code reports as follows:
    <Q ID> for rising edge, and
    <q ID> for falling edge.
    It looks to be a minor change to make this operate as you proposed in your post of Nov 13,2015 i.e. <Q ID 1> and <Q ID 0>.

    I think there is more important addition to the BaseStation requirements that needs to be brought to Gregg's attention. This concerns synchronisation.
    Keeping the BaseStation and the external OSS e.g. JMRI, reliably synchronised requires two things. These are:
    1) the asynchronous updates provided by the <Q> messages, and
    2) a polling message that reports the status of all the sensors. Something like <Q> or <Q ?> maybe.
    This way the OSS and the BaseStation can startup fully synchronised.

    Being able to import sensor data into JMRI this way looks to be an exciting addition.
     
    Scott Eric Catalano likes this.
  12. Gregg

    Gregg TrainBoard Member

    237
    311
    18
    Done! See below.
     
  13. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    TwinDad,
    I wanted to followup on your proposals about sensor reporting. The existing BaseStation code reports as follows:
    <Q ID> for rising edge, and
    <q ID> for falling edge.
    It looks to be a minor change to make this operate as you proposed in your post of Nov 13,2015 i.e. <Q ID 1> and <Q ID 0>.
    [/QUOTE]

    The way Gregg has this (Q or q) is fine. The previous way just sent an ID number with no indication of active or inactive. My proposal was to fix that, but Gregg's change to Q/q also fixes it.

    A Query message would be helpful, but adding the Sensor states to the <s> reply (as the Register and Turnout states already are) would be enough for JMRI.
     
    Scott Eric Catalano likes this.
  14. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    See... what... below?
     
  15. Gregg

    Gregg TrainBoard Member

    237
    311
    18
    All,

    Just uploaded some big updates to the GitHub repository.

    First, per the recommendation above, I added a <Q> command that returns the status of all sensors in the form of a list of <Q ID> (if active) or <q ID> (if inactive) for each sensor ID. I haven't used the suggested format <Q ID 1> for active and <Q ID 0> for inactive to ensure backwards compatibility with the DCC++ Controller, but if this becomes a sticking issue I can see if we can add this as an alternative format.

    Second, I purchased a SEEED Studio Ethernet Shield from Radio Shack this weekend (it appears not all have gone out of business yet) and updated the BaseStation code so that users can select either the usual Serial connection, or an Ethernet connection. Works like a charm.

    Third, I updated the DCC++ Controller code so that user can select an Arduino Base Station using either a Serial Port OR the new Ethernet Connection. This is actually really neat. I ran two instances of the Controller from two different computers each accessing the same Arduino Base Station. Not only can they both control the Base Station, which would allow two users simultaneous control of a layout, but (and this is the really neat part), when you change the direction of a turnout via the Controller on one computer, it's updated on both! Same for the throttles --- increase the speed on one and you see it reflected on both. This is because the DCC++ Controller relies on throttle and turnout status messages returned from the Base Station, which keeps all connected controllers in sync. To use this new feature in the updated code, simply add a list of space-separated IP addresses to the DCCStatus.XML file in a tag called <serverList>. See the updated XML file within the DCC++ Controller GitHub repository for an example.

    Fourth, I updated the Base Station code to use Timer3 instead of Timer0 for the PROG Track signal when compiled for the Mega. This is because the output of the Timer0 signal we use on the Mega is Pin 4, and that interferes with the Ethernet Shield. On the other hand, the output of the Timer3 signal is on Pin 2. I could have created some logic so that the signal is only switched from Timer0 to Timer3 IF an Ethernet Shield is being used, but I figured it was easier to just always use Timer3 and Pin 2 instead of Pin 4. Of course my video on YouTube showing how to install a jumper wire from Pin 4 to Pin 13 is now out of date (oh well).

    Fifth, I added a Config.h file that includes all the user-definable Base Station parameters, and nothing else. This makes them much easier to find. Unfortunately there is one exception due to a "feature" of the Arduino IDE. Because different Ethernet Shield use different libraries, I wanted to make the Include File Name a defined parameter. However, this still needs to be hard-coded into the main DCC_Uno.ino file as well. It turns out that even if the main *.ino file does not use a given library, it cannot be invoked in any other *.cpp file unless the *.h file for that library is also included in the *.ino file. I guess this is how the Arduino IDE knows to include that library in the build.

    I also noted DJ79 implemented an alternate method to create the DCC Logic signals by having them change state using a software interrupt instead of through internal hardware. One of the benefits of this method is that it offers more choices for which pins you want to use for your output signals. I have not had a chance to review the code but should be able to do so next weekend, at which point I'll try to include it in the current build as an alternative means of producing DCC signals. The more flexibility the better --- and that's the whole point of open-source (note I'll retain the hardware-method as well, since on my own layout I have the Arduino performing a lot of other tasks, some of which require the use of other interrupts, and I want to minimize the chance that while in another interrupt routine, I may miss a call to the DCC signal generator).

    That's it for now!

    -Gregg
     
  16. Scott Eric Catalano

    Scott Eric Catalano TrainBoard Member

    205
    57
    6
    Hello Gregg,

    That is awesome....I can now add an ethernet shield and theoretically I should be able to control the base station via a wireless laptop or computer since the base station would be connected to an ethernet hub correct? Or even a wireless/bluetooth shield on the arduino stacked onto the motor shield? this even expands things to make hand held throttles as well. Thoughts comments?
     
  17. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    Basically, yes.

    I'm still working on adding a WiThrottle front-end to the Ethernet port... since Gregg got his running and "in" before me, I'll transition to using his Ethernet code and putting WiThrottle on top of it. Still busy working on the JMRI support for now. But once that is in place, you should be able to connect your smartphone directly to a DCC++ base station with an Ethernet or WiFi shield.

    Question: Gregg, does the Ethernet code send/receive EXACTLY the same byte strings as the Serial?
     
    Scott Eric Catalano likes this.
  18. esfeld

    esfeld TrainBoard Member

    442
    382
    17
    TD
    Off topic, but I know your active here .......
    Playing around with VSD ...... after assigning a VSD to a roster entry everything works .... I save to Roster and save all panels including VSD manager ... but upon restarting Panel Pro, I get a parse errror in VSDecoderpreferences.xml ......and VSD Manager says "no active decoders"..... Also, is there a way to start VSD with Panel Pro ... I see no option for VSD in Preferences .. Start Up or should the VSD just load with the Roster?
    To keep this thread on topic could you respond to: esfeld@cyberdude.com
    Thanks
    Steve
     
  19. TwinDad

    TwinDad TrainBoard Member

    1,844
    551
    34
    esfeld,

    Saw your message on NSN. I'll have to check on the answer, but I'm buried in a huge refactor of the DCC++ code just at the moment. Give me a day and I will get back to you. I will reply on NSN if the answer is clear, or email you if I have further questions.
     
  20. Gregg

    Gregg TrainBoard Member

    237
    311
    18
    I had wanted to use a wifi shield instead of an Ethernet shield but radio shack only had the Ethernet in stock. There may be an additional parameter required to use a wifi shield (the SSID of the network) and I will add that in once I get the shield.

    The Ethernet shield can be plugged into any router, wireless or otherwise. I happen to have mind plugged into a Sonos box which gives me wireless access.

    I should have noted that the BaseStation uses DHCP to set its own IP address. To determine which address it picked, open the serial monitor. Regardless of whether you compiled for serial or Ethernet connectivity, when the monitor is first opened the Base Station always prints a single status message to the serial port. This contains a <N> output that echoes back the COMM_TYPE setting followed by the actual IP address being used, or the word SERIAL. Once you know the IP address you can enter this into any controller program.

    As I write this I realize that it would be very easy to add a second configuration parameter that allows the user to preset a desired IP address instead of using DHCP. This would provide more certainty to which address would be used. I will add this in to an update next weekend.
     
    Scott Eric Catalano likes this.

Share This Page