Introducing A New DCC Accesory Decoder: The DCC-Serial Translator

drken Aug 25, 2018

  1. drken

    drken TrainBoard Member

    284
    59
    14
    Basically, this began as a project to control addressable LEDs via DCC. After many trials and consultations with others, I decided that Arduinos cannot read DCC and control addressable LEDs at the same time because both of them require too much precise timing. I therefore gave up trying to do that and came to the conclusion that this would require two Arduinos, one to read DCC packets and the other to control LEDs.

    After a bunch of trial and error, I can now announce Version 1.0 of the DCC Translator. The program itself is Geoff Bunza's 17 LED Accessory Decoder program, with everything not necessary removed and the line of programming that controlled the LEDs replaced with code that splits the 14 bit address into two, 8-bit bytes and flags the Most Significant Bit on the high byte with the on/off info. Each address then controls a different pattern on the other Arduino (or Teensy, or RasPi, or anything else that can read serial data). I also designed a circuit board for a Pro-Mini in EagleCAD that contains the "Dave Falkenberg" optoisolator circuit and a serial port "TO RX" output.

    Anyway, without further ado, here is the sketch for the translator, Dual_AccDec_Serial:

    #include <NmraDcc.h>
    byte AddrHB; // high byte for address
    byte AddrLB; // low byte for address

    #define This_Decoder_Address 40 //Starting address
    #define numAddrs 17 // number of sequential addresses for this decoder
    NmraDcc Dcc ;
    DCC_MSG Packet ;
    void setup(){
    Serial.begin(9600); // initialize serial communication
    // Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
    Dcc.pin(0, 2, 0);
    // Call the main DCC Init function to enable the DCC Receiver
    Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, 0 );
    }
    void loop(){
    // You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
    Dcc.process(); }
    extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
    uint8_t Bit_State = OutputAddr & 0x01;
    if ( Addr >= This_Decoder_Address && Addr < This_Decoder_Address+numAddrs) { //ignore any addresses outside specified range.

    // This replaces the digitalWrite(HIGH) function from Geoff's sketch with code to send the address and state via serial
    AddrHB = highByte(Addr); // split Addr into high and low 8 bit bytes, AddrHB and AddLB, respectively.
    AddrLB = lowByte(Addr);
    if (Bit_State == 1){ // if the decoder sends an on command
    AddrHB = AddrHB + 127;} // add 127 to high byte so MSB (Most Significant Bit) is 1, this will be subtracted out by receiver.
    Serial.write(AddrHB); // write the high bit (with MSB flag for Bit_State) to the serial port
    Serial.write(AddrLB); // write the low bit to the serial port
    }
    }
    End Code (If there's a post code function for this board, somebody let me know and I'll edit it in).

    The LED controllers are custom designed for each piece of scenery as each has its own lighting/mechanical needs, but they all should have this readDCC() function which produces an integer, Addr and a boolean, State.:

    void read_DCC() { // reads serial data from Dual_AccDec_Serial
    if (Serial.available() >= 2 ){ // check to see if both bytes are in buffer
    dataBytesH = Serial.read(); // read high byte
    dataBytesL = Serial.read(); // read low byte
    // *** Check State (on/off) ***
    if (dataBytesH >= 127){ // if State is == true, 127 was added to high byte at origin
    dataBytesH = dataBytesH - 127; // if it is, subtract out 127 to get original value
    State = true; // then set State to true (on)
    } // end check state loop
    else State = false; // otherwise, set State to false (off)
    Addr = (dataBytesH <<8|dataBytesL); // combine High and Low Bytes to get Address
    } // end if serial available loop
    } // end void read_DCC loop
    End Code

    There are then a bunch of if/then statements to run the function for each pattern (including off).

    Also, as if this post isn't long enough, here's a picture of the circuit board I designed for it. I'm not sure why it keeps posting upside down.
    Decoders.jpg
     
  2. crusader27529

    crusader27529 TrainBoard Member

    247
    166
    10
    I'm confused about what this device is and how you use it and control it.

    Since nobody else has commented, I'd guess that the confusion is not just for me.

    Can you be more specific in how this is used and how?
     
  3. drken

    drken TrainBoard Member

    284
    59
    14
    OK, they are for controlling things that cannot be controlled using Arduino based, DCC decoders. In my case, addressable RGB LEDs, such as these. Some of my buildings will be nightclubs, and I wanted to be able to choose the pattern of flashing colored lights inside them using JMRI. Unfortunately, Arduinos can read DCC packets and they can control addressable RGB LEDs, but they cannot do both at the same time. So, I resorted to a dual Arduino system where one Arduino reads DCC packets and the other controls the lights.

    If you're familiar with Geoff Bunza's 17 function accessory DCC decoder, it assigns a DCC address to each I/O pin of the Arduino and lets you turn each pin (and the LED attached to it) on and off by sending a closed or thrown command to that address. What this does is read the DCC packets as before, but instead of turning a pin on or off, it sends that information via the serial port (pin 0) to another Arduino.

    Once the second Arduino gets that information, it will run whatever subroutine is assigned to that address in response to a closed command or stop running it in response to a thrown command. In the case of the building I'm using as a test case, if a closed command is sent to address 40, 3 LEDs will rotate though the ROYGBIV spectrum in an alternating pattern (the first rotates from Red to Violet, the second from Violet to Red, etc). A closed command to address 41 will run a different pattern (all blue, for example). Also, while Geoff's decoder is limited to 17 addresses, this can control as many addresses as the Arduino has memory for. I'm not sure how many that is, but it's probably more than you'd ever need.

    That's pretty much it. Another advantage of this is that the second Arduino can theoretically be anything that can read serial data. For example, a Raspberry Pi can be programmed to run a drive in theater so that "Twister" plays on the screen when a closed command is sent to address 40 and "The Shining" plays when a closed command is sent to address 41. The only limit is your imagination and programming skill.
     
  4. mrtinvan

    mrtinvan TrainBoard Member

    34
    8
    6
    I'm hoping to design something similar that will take in DCC commands and play back MP3 files from a serial driven MP3 player, like a DFPlayer.
     
    Sumner likes this.
  5. RCMan

    RCMan TrainBoard Member

    255
    112
    9
    I know where he is going with this.
    Nice idea.

    Dennis
     
    drken likes this.
  6. Sumner

    Sumner TrainBoard Member

    926
    1,009
    20
    Last edited: Dec 9, 2019
  7. Jimbo20

    Jimbo20 TrainBoard Member

    274
    175
    9
    That's what I did on my small N-gauge layout; An Arduino Nano 'listens in' on the DCC++ commands and activates sound files on two DFPlayer modules to produce the sounds of a diesel railbus and a Class 08 via loudspeakers mounted under the layout.
     
  8. mrtinvan

    mrtinvan TrainBoard Member

    34
    8
    6
    I have programmed/built my own Arduino based crossing gate controller with sound. 4x IR detectors (2 on either side of the crossing) calculate train speed and adjust the timing of the crossing gates, which are lowered via Servo.

    I also want to use JMRI scheduler to trigger a building fire, and some other scenic things.
     
    drken likes this.
  9. drken

    drken TrainBoard Member

    284
    59
    14
    Wow. Thanks guys, I thought nobody was interested in the Translator, it's great that some people get it. Sometimes you need to control something that doesn't just turn on and off or move from one position to another (or in my case, something that is incompatible with the DCC library). Also, since it can control anything that can read serial data, or theoretically any communication protocol you know how to program into an Arduino, it opens up a world of possibilities.
     
  10. FlightRisk

    FlightRisk TrainBoard Member

    473
    166
    6
    Have you thought of using these?

    WiFi RGB LED Controller

    I have a few of these from China. I just linked to the walmart page for the picture. They are designed to control the addressable RGB strip lights that you cut down into segments as small as just 3 leds (but you can wire in any 5050). They can be controlled from IR signals or from the "Magic Home" phone app and Alexa. You could send whatever signals to that device to control the lights however you want from any microcontroller. Just another option that might be good for some applications.
     
  11. John W Zerbe

    John W Zerbe TrainBoard Member

    96
    59
    6
    I haven't yet built a dcc decoder. I am, however running dcc++ on a Mega and have digital outputs from it jumped as inputs to a second mega. The second mega sees the transitions and drives relays to drive atlas snap switches. So in jmri, I have the track switches defined as the output pins but, for example a transition from low to high causes the second mega to energize a relay for one direction of the snap switch for something like 100 milliseconds to trip it in that direction. When it sees the first mega's line drop back from high to low, it simply energizes a second relay to snap the track switch back. I've been considering making modifications to the dcc++ code to have the logic that sets pins high/low to instead send a serial pin based "command" to the next arduino or arduinos.
     
  12. Tom Hale

    Tom Hale TrainBoard Member

    14
    1
    2
    Can you give me a little (lot) more detail on this? I'm hoping to do something similar (although I only have an UNO right now but I'm not averse to upgrade).

    How many snap switches can you control?

    Circuit design?

    T.
     
  13. drken

    drken TrainBoard Member

    284
    59
    14
    It's not for snap switches, there are already plenty of Arduino based decoders that can do that. It's for controlling anything that otherwise couldn't be controlled via DCC/JMRI, but can read serial data. I came up with the idea because I wanted to control addressable RGB LEDs from Panel Pro, but the FastLED library is incompatible with the DCC library. So, I came up with this to act as a middle-man to read DCC signals and output serial data to another Arduino.

    However, now that I think of it, if you have addressable relays, you could control as many switches as addresses you could store on the Arduino. Of course, with the availability of high memory ARM and ESP based boards, that could be quite a lot.

    I have a circuit board that works using an external 5V power source at OSH Park here https://oshpark.com/shared_projects/scogyY5K
    I have another version that takes power from the DCC system itself, but I haven't worked out all the bugs yet. Technically, anything that contains the Dave Falkenberg circuit hooked up to an Arduino would work. Just hook up an output wire to the Tx pin (and a return ground) and you should be good to go.
     
  14. Tom Hale

    Tom Hale TrainBoard Member

    14
    1
    2
    My bad, I misunderstood.

    (I can take this to another post if prefered) Would you be willing to display out, soup to nuts, a solution for DCC controlling snap switches with an Arduino? For the uninitiated stupid noob? I've found several different options, but I can't seem to make any real sense of them (due to lack of DCC and Arduino knowledge) and none of them seem to be in the vein of "Get these parts, do this, and it'll work."

    If not, I'll keep digging and experimenting...

    T.
     
  15. vasilis

    vasilis TrainBoard Member

    109
    37
    7
    @drken, hi,
    So the problem is that there is a conflict between the two libraries(timer interrupt handling?). I'm saying this because my first impression was, that can't be done with one arduino, because it isn't fast and at the same time I see a low speed serial connection with additional communication handlers. Good job. It's easier from the conflict remove.
     
    drken likes this.
  16. drken

    drken TrainBoard Member

    284
    59
    14
    Thanks, I'm going with the assumption that it's some sort of conflict, rather than being just too slow. I tried to run addressable LEDs with a Teensy and couldn't get it to work either. Until somebody else gets it to work, it doesn't really matter.

    @Tom Hale
    I wouldn't begin to know how. Good luck with your search.
     
    vasilis likes this.
  17. John W Zerbe

    John W Zerbe TrainBoard Member

    96
    59
    6
    actually mine is for my snap switches. as of right now, I have two 8-relay boards which implies that I can only control 8 snap switches with them. one relay per direction per snap switch. I'm currently working on an urgent programming project for my day job, so it may be a few days until I can post another update here. This is what I based my second arduino/relay board design off of. I just modified the sketch in the second arduino to look for digital input transitions and drive the appropriate relay. I'm using a doorbell transformer as the power through the relays themselves and in the sketch, only activate the relay for something like 100ms to let the short jolt of 16v ac power through to the snap switch.
     
  18. John W Zerbe

    John W Zerbe TrainBoard Member

    96
    59
    6
    20200115_144845.jpg

    Tom, this is a picture of my current setup. The photo is sideways. Pi on bottom left running jmri. Pair of megas connected to pi via powered USB hub. Mega with the shield on top is dcc++ base station. Ribbon connection from dcc++ to second mega let's me map arduino pins to logical track switches in jmri. Much like drkin's design above the second mega could control anything. I'm just driving relays for snap switches and saving their state. I may, in the future, separate these via arduino dcc decoder but just wasn't ready to do that yet. Also, I actually have 3 power supplies in this thing. One 5vdc to power the usb hub which in turn powers the Pi, and both arduinos, one 15v dc for dcc++ track power, and an old 16v AC door bell transformer to power the snap switches. (was going to use the 15vdc for that but turns out that the solid state relays require AV voltage through them for them to work.)
     
    Last edited: Jan 15, 2020
    David Clemson likes this.

Share This Page