Vonzack Posted March 28, 2014 Share Posted March 28, 2014 Hi, Inspired by other RMWeb members who have been using Arduino devices to control turntables and traversers, I have been doing some experiments to try and use one for Signal Control. I'm involved in the build of an 'N' Gauge exhibition layout and we want to have working 3 aspect signals, but to go along with this, we want to use various feathers and ground signals for realism when operating. It is also our intention that the signals would be automated, so we will have some form of computer control and signal logic based on route and block occupancy. The layout will have around 9 scenic modules when finished and the signals themselves are fairly spread out along them. So when we started looking at the costs to do this using 'off the shelf' DCC Accessory Decoders, things started to look quite costly. So, to the Arduino. There is allot of information on the web and on this forum about how to get an Arduino connected up to your DCC System and surprisingly for me, I found a simple enough circuit here - http://www.mynabay.com/arduino/14-arduino/dcc-monitor/16-arduino-dcc-monitor-2 to isolate the track voltage from the Arduino and get the DCC Packet info to it safely. Then using a slightly modified version of their 'sketch' I did some testing using the Serial Monitor and my Sprog as a Command Station. #include <DCC_Decoder.h> ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Defines and structures // #define kDCC_INTERRUPT 0 typedef struct { int address; // Address to respond to byte output; // State of output 1=on, 0=off int outputPin; // Arduino output pin to drive boolean isDigital; // true=digital, false=analog. If analog must also set analogValue field boolean isFlasher; // true=flash output, false=no time, no flash. byte analogValue; // Value to use with analog type. int durationMilli; // Milliseconds to leave output on for. 0 means don't auto off unsigned long onMilli; // Used internally for timing unsigned long offMilli; // } DCCAccessoryAddress; DCCAccessoryAddress gAddresses[8]; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Decoder Init // void ConfigureDecoder() { gAddresses[0].address = 3; gAddresses[0].output = 0; gAddresses[0].outputPin = 3; gAddresses[0].isDigital = true; gAddresses[0].isFlasher = false; gAddresses[0].analogValue = 0; gAddresses[0].durationMilli = 0; gAddresses[1].address = 4; gAddresses[1].output = 0; gAddresses[1].outputPin = 4; gAddresses[1].isDigital = true; gAddresses[1].isFlasher = false; gAddresses[1].analogValue = 0; gAddresses[1].durationMilli = 0; gAddresses[2].address = 5; gAddresses[2].output = 0; gAddresses[2].outputPin = 5; gAddresses[2].isDigital = true; gAddresses[2].isFlasher = false; gAddresses[2].analogValue = 0; gAddresses[2].durationMilli = 0; gAddresses[3].address = 6; gAddresses[3].output = 0; gAddresses[3].outputPin = 6; gAddresses[3].isDigital = true; gAddresses[3].isFlasher = false; gAddresses[3].analogValue = 0; gAddresses[3].durationMilli = 0; gAddresses[4].address = 7; gAddresses[4].output = 0; gAddresses[4].outputPin = 7; gAddresses[4].isDigital = true; gAddresses[4].isFlasher = false; gAddresses[4].analogValue = 0; gAddresses[4].durationMilli = 0; gAddresses[5].address = 8; gAddresses[5].output = 0; gAddresses[5].outputPin = 8; gAddresses[5].isDigital = true; gAddresses[5].isFlasher = false; gAddresses[5].analogValue = 0; gAddresses[5].durationMilli = 0; // Setup output pins for(int i=0; i<(int)(sizeof(gAddresses)/sizeof(gAddresses[0])); i++) { if( gAddresses[i].outputPin ) { pinMode( gAddresses[i].outputPin, OUTPUT ); } gAddresses[i].onMilli = 0; gAddresses[i].offMilli = 0; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Basic accessory packet handler // void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data) { // Convert NMRA packet address format to human address address -= 1; address *= 4; address += 1; address += (data & 0x06) >> 1; boolean enable = (data & 0x01) ? 1 : 0; for(int i=0; i<(int)(sizeof(gAddresses)/sizeof(gAddresses[0])); i++) { if( address == gAddresses[i].address ) { Serial.print("Basic addr: "); Serial.print(address,DEC); Serial.print(" activate: "); Serial.println(enable,DEC); if( enable ) { gAddresses[i].output = 1; gAddresses[i].onMilli = millis(); gAddresses[i].offMilli = 0; }else{ gAddresses[i].output = 0; gAddresses[i].onMilli = 0; gAddresses[i].offMilli = millis(); } } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Setup // void setup() { Serial.begin(9600); DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true); ConfigureDecoder(); DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT ); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Main loop // void loop() { static int addr = 0; //////////////////////////////////////////////////////////////// // Loop DCC library DCC.loop(); //////////////////////////////////////////////////////////////// // Bump to next address to test if( ++addr >= (int)(sizeof(gAddresses)/sizeof(gAddresses[0])) ) { addr = 0; } //////////////////////////////////////////////////////////////// // Turn off output? if( gAddresses[addr].offMilli && gAddresses[addr].offMilli<millis() ) { // Clear off time gAddresses[addr].offMilli = 0; // Disable output if( gAddresses[addr].isDigital ) { digitalWrite( gAddresses[addr].outputPin, LOW); }else{ analogWrite( gAddresses[addr].outputPin, 0); } // If still enabled and a flash type, set on time if( gAddresses[addr].output && gAddresses[addr].isFlasher) { gAddresses[addr].onMilli = millis() + gAddresses[addr].durationMilli; }else{ gAddresses[addr].output = 0; } return; } //////////////////////////////////////////////////////////////// // Turn on output? if( gAddresses[addr].onMilli && gAddresses[addr].onMilli<=millis() ) { // Clear off time gAddresses[addr].onMilli = 0; // Enable output if( gAddresses[addr].isDigital ) { digitalWrite( gAddresses[addr].outputPin, HIGH); }else{ analogWrite( gAddresses[addr].outputPin, gAddresses[addr].analogValue); } // If still enabled and a flash type, set off time if( gAddresses[addr].durationMilli ) { gAddresses[addr].offMilli = millis() + gAddresses[addr].durationMilli; } return; } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// After some tweaking of the wires on the breadboard, the Arduino sprang to life and started reacting to the accessory command being sent from the Sprog. Now it was time to put some LEDs and resistors (220 Ohm for the Arduinos 5v) onto the board and see what would happen. This is what I ended up with, seen here mocking up two 3 aspect signals displaying 'Proceed'. OK, so I had an Arduino Decoder with working LEDS now, but each aspect was being controlled independently and had a separate address. This didn't make for very realistic control from a throttle as the aspects would remain lit or the signal go out while the operator fumbled with the addresses. So what I needed was some control to send a burst of packets, to the signal to 'throw' or 'close' all of the aspect LEDs at a time. I decided on JMRI to do this, as it has an incredible level of support for signal logic, but it's a bit of a steep learning curve, so when I found these tutorials on YouTube it really helped. There should be 8 of them, but I could only find 1-7. Even so, Nigel and Kevin really deliver the info well and at a reasonable pace, thanks guys if you read this. So in a very short time, I'd defined my Signal Heads (in my case 3 Aspect), linked them to the Accessory addresses that the Arduino was reacting to and attached them to Signal Masts in JMRI meaning that I could then control them by setting the signals to 'Proceed', 'Caution' and 'Stop'. Here's a short video showing the signals being set to each in turn. For the layout, we'll be using Arduino Nanos, which if you shop around can be bought for around £5, add to that some vero board and components for the DCC Bus opto-isolator and it's possible to build a Accessory Decoder, able to operate as either 11 (digital only) or 17 (using the analogue output as digital) individual addresses for £7. Cheers, Mark. 1 Link to post Share on other sites More sharing options...
Nigelcliffe Posted March 28, 2014 Share Posted March 28, 2014 (edited) Mark, smart stuff. Sorry, video 8 never got done (my fault!). The tutorials are best followed from the JMRI website (under "clinics", link at bottom of home page) as that contains the sample files and some text to accompany the videos. One suggestion, you could investigate Aspect signalling instructions over DCC, rather than sending lots of Accessory thrown-closed instructions. With an Aspect packet, you send a message to the Accessory Address which includes which aspect (there can be at least 32 within a decoder) is to be displayed. You might need a few different aspects ( Red, Yellow, Green, Call-on (red plus call-on light), maybe some flashing versions), but I doubt UK signalling could use up 32 of them ! There are a couple of commercial signalling boards which use DCC Aspect Signalling, for UK modellers, the "Signalist" device from Paul Harman is perhaps the best known. The JMRI signalling capability has come on a lot since the tutorials were written, but the basics still hold. Kevin wrote a lot of the JMRI code. - Nigel Edited March 28, 2014 by Nigelcliffe Link to post Share on other sites More sharing options...
Vonzack Posted March 29, 2014 Author Share Posted March 29, 2014 Hi Nigel, Sending an Extended Accessory Packet would be of real benefit, as I'm not sure sending bursts of packets is always going to work for us. I can imagine a packet loss and a signal suddenly having two lit aspects or none at all, which wouldn't look good. I've found the NMRA specification for this, but it's going to take another couple of reads before it sinks in I'll have to check to see if the DCC_Decoder library I'm using for my Arduino sketch supports the Extended Accessory Packet as a first step. Then have a look at sending the packets from JMRI. The SIgnalist SC1 Manual has a paragraph covering the values it uses so this is something to go on. Cheers, Mark. Link to post Share on other sites More sharing options...
Vonzack Posted April 2, 2014 Author Share Posted April 2, 2014 Hi, I've been over the code for the DCC_Decoder library and it does support the Extended Accessory Packets. I believe I can also make use of this in the Arduino sketch easily enough. The problem now, is how to send one of these Extended Packets. As I'm using JMRI, can anybody suggest a way to do this. There isn't an awful lot of info about it. Ideally what I'd like to do is create a signal in JMRI, that has a single DCC Address and has a list of these extended values which given the signal type equate to the various display options and dark. Can anybody give me pointers on this? From 'Googling' for info, it also seems that apart from 0 being Dark, all other values for the Extended Packet are defined by the signal controller. So they can be pretty much anything. Cheers, Mark. Link to post Share on other sites More sharing options...
Nigelcliffe Posted April 2, 2014 Share Posted April 2, 2014 Most DCC systems will accept a passed through extended packets generated by JMRI (there's been a very recent conversation on the developer list about a possible issue around NCE, but someone is working on it). So for most systems, the issue is creating a signal within JMRI which uses the extended packet protocol. This is how I'd do it... Select the Signal Mast table, and "Add" a Signal Mast with the dialogue box. In the Add Signal Mast dialogue, give it a username, select signalling system (eg. BR 2003 for UK), mast type of choice, and the driver is "DCC Signal Mast Decoder". The "Add Signal Mast" dialogue extends, and you can enter the Accessory Address of the decoder, and the values which are sent for each aspect. Once you have a Signal Mast, this can be used on a Panel, and thus operated. You can optionally disable some aspects (eg. the flashing aspects might be inappropriate for your particular signal on a layout). With a few exceptions, its not possible to directly set an aspect from manufacturer's hardware DCC throttle handsets. Yes, the relationship between Aspect values set in JMRI and what happens in your decoder is totally in the hands of the decoder designer. So, if you want to have 6=red(danger) and 27=yellow(caution), and 25=green(proceed), that's your choice as accessory decoder designer. You might want a more sensible numbering scheme! Using a similar scheme to that Paul Harman uses in his Signalist decoders might be a good starting point, his UK scheme goes Red ( 0 ), Yellow ( 1 ), Green ( 2 ), Double Yellow ( 3 ), Flashing Red ( 4 ), Flashing Yellow ( 5 ), Flashing Green ( 6 ), Flashing Double Yellow ( 7 ) and Dark ( 8 ). I've had a Harman Signalist SC1 working with extended accessory packets generated through JMRI to both Sprog and Digitrax hardware; I've had several firmware versions from Paul Harman to aid in developing the JMRI decoder file for setting up the SC1's. I hope that helps. - Nigel Link to post Share on other sites More sharing options...
pewky Posted October 14, 2014 Share Posted October 14, 2014 Dear all, This is all very interesting and sounds good. I have been given a Romeo to control servos but without any knowledge of programming and working in DCC, I bought a ESU switch pilot for my servos and getting cobalts as well for points control. Those are easy to work with. However I still have this board doing nothing. I would like to use it as a DCC decoder for accessories mainly LED/lightings. I was reading through this thread and many other documents on the web and got very confused: how do you program your decoder (arduino)? Note that I have no intention to control my layout via a PC but via my DCC system(s). Link to post Share on other sites More sharing options...
RMweb Premium Steven B Posted October 14, 2014 RMweb Premium Share Posted October 14, 2014 The program in Mark's (Vonzack) original post does all the hard work for you. All you need is to save a copy of the code and "blow" it onto your Arduino. The Arduino software runs on your PC and talks to the microprocessor via a USB cable. Once programmed it can be disconnected and run as a standalone system. The clever bit is done by the DCC_decoder library which takes the raw DCC signal from the track feed and converts it into the individual messages. The code then looks at the addresses being controlled by the DCC system and decides what action it needs to take.. The address of each function is defined in the ConfigureDecoder function. The .Address= field links the DCC address to an individual pin (.OutputPin). In the example above changing accessory address 3 will change the output of pin 3 of the Arduino. Happy modelling. Steven B. Link to post Share on other sites More sharing options...
pewky Posted October 15, 2014 Share Posted October 15, 2014 Thank you Steven. It makes more sense now. Luc Link to post Share on other sites More sharing options...
ajaxjones Posted November 4, 2014 Share Posted November 4, 2014 I'm looking for an alternative to the 6n317 opto-isolator as RS are showing it as discontinued, any suggestions ? Link to post Share on other sites More sharing options...
RMweb Premium Steven B Posted November 4, 2014 RMweb Premium Share Posted November 4, 2014 Which RS part number are you looking at? A quick search on their website shows lots of 6N137's available; There are at least four which are through hole components: 625-7909 691-2325 699-8158 805-1267 Farnell have a similar number of parts. Also easily available from eBay. Happy modelling. Steven B. Link to post Share on other sites More sharing options...
Crosland Posted November 4, 2014 Share Posted November 4, 2014 I'm looking for an alternative to the 6n317 opto-isolator as RS are showing it as discontinued, any suggestion This came up on the MERG forum recently. The 6N137 is multi-source and is not obsolete. Farnell have plenty. It's only some particular Fairchild variants that are discontinued. Andrew Link to post Share on other sites More sharing options...
ajaxjones Posted November 5, 2014 Share Posted November 5, 2014 Ah, that makes sense Plus compounded with searching those sites on an iPad. All sorted on ebay as well now, thanks for the headsup Link to post Share on other sites More sharing options...
jbsorocaba Posted November 26, 2014 Share Posted November 26, 2014 Hi Mark Have you the schema of this hardware.. or Fritzing file..? JB Link to post Share on other sites More sharing options...
antogar Posted November 27, 2014 Share Posted November 27, 2014 Hi, I am trying CNX83 as alternative to 6N137. It has a transistor instead a cmos port, it works well putting a 10k resistance on the base to ground. ciao. 1 Link to post Share on other sites More sharing options...
joff Posted June 12, 2017 Share Posted June 12, 2017 I realise that this thread is a bit old, but I am desperately seeking a "how to" build cheaper DCC signal decoders. There is mention that future building would be by cheap arduinos, which can be programmed and driven by DCC using the Extended Accessory protocol and I was just wondering/hoping that someone had managed to finish the project and would be prepared to publish and "Idiot's Guide" into doing so. Trying to build four light heads with feathers means buying 1 Signalist per head, which becomes prohibitively expensive!! I have also found that there are differences across the board between the various decoder brands. For example, the LDT board cannot use Extended Accessory Protocol and so on! Help please. Joff Link to post Share on other sites More sharing options...
Suzie Posted June 12, 2017 Share Posted June 12, 2017 I realise that this thread is a bit old, but I am desperately seeking a "how to" build cheaper DCC signal decoders. There is mention that future building would be by cheap arduinos, which can be programmed and driven by DCC using the Extended Accessory protocol and I was just wondering/hoping that someone had managed to finish the project and would be prepared to publish and "Idiot's Guide" into doing so. Trying to build four light heads with feathers means buying 1 Signalist per head, which becomes prohibitively expensive!! I have also found that there are differences across the board between the various decoder brands. For example, the LDT board cannot use Extended Accessory Protocol and so on! Help please. Joff Hi Joff Take a look at the DIY Decoder website. The optional enhanced accessory firmware that is available to buy for the DIY accessory or function decoder is the same as is used in the Signalist products and that will allow you to use extended accessory packets for signals. Link to post Share on other sites More sharing options...
Railrodder Posted June 14, 2017 Share Posted June 14, 2017 Hi I use an Arduino emulating many nmra extended packet decoders controlling a string of ws2812 addressable leds. Each led is a searchlight signal that can display red green yellow blue lunar, flashing or solid. The physical signal construction is described here. http://nscaleaddiction.blogspot.ca/2012/01/cheap-simple-n-scale-signals-using.html. A single arduino, depending on memory can control up to the maximum 2047 signal heads. Steve G. Link to post Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now