SMA12 - 17 Channel Configurable Multifunction $5 DCC Decoder For Servos

geoffb's picture

One of my earlier entries:  SMA10 – Build a 17-Function DCC Decoder for about $5 ( http://model-railroad-hobbyist.com/node/19070 ) generated a considerable amount of interest regarding the possible enhancement for controlling Servomotors (Servos). This is my next version of a 17 Channel Multifunction DCC Decoder based on a low cost $2.56 Arduino Pro Mini. This version supports configuring each of the 17 function pins for On/Off (LED/TTL) Control, or Configurable Blinking Control, or Configurable Servo Control, or Configurable Pairs Blinking Control. Yes, that does mean it can support 17 servos, each with rate, start point, and end point setting via DCC CV’s, per pin, as well as new LED configurable functions. Read On. Additional doc found here: http://model-railroad-hobbyist.com/node/19775 There is another decoder version added herein. Look for "New Decoder Version to Control Lighting Groups" in Page 12 of the Comments: http://model-railroad-hobbyist.com/node/19446?page=11   The most recent Update can be found here: SMA20 New Low Cost 17 Channel DCC Decoders with PC Boards & Dual Motor, LED, & Servo Control    http://model-railroad-hobbyist.com/node/24316

Comments

Michael T.'s picture

Loconet and JMRI

So if I'm understanding correctly Dave, your circuit makes Geoff's decoder Loconet and JMRI compatible? If so, that sounds like the road I want to travel down.   Right now, I manually throw my turnouts  but since I have a dedicated notebook PC right by my Digitrax Zephyr, I have been intrigued by throwing turnouts and setting routes via JMRI but I just have not had the budget to invest in commercial hardware to do so.  This is looking like something I can afford to do though and since  I have the know how with electronic components  I'm getting excited about the prospects.

Michael

Michael

Original member of the "Gang of Six"

R.I.P. Verne Niner. The time I got to know you was way too short my friend.

"We all model the prototype, to suggest otherwise is ridiculous"

My Pike, https://mrhmag.com/blog/MichaelT

 

John C H's picture

10 servos on 2 channels

Geoff

Here is a link for setting an Arduino to control many servos with few channels, which leaves lots of room to do other things at the same time on the Arduino. 

http://diydrones.com/profiles/blogs/drive-10-servos-using-only-2

 

John Houghton

Collingwood, Ontario

 

 Canada 

HVT Dave's picture

@ Michael - LocoNet and JMRI

Michael,

Yes, the circuit shown on my earlier post will connect to LocoNet and hence can be controlled by JMRI.  Using LocoNet should allow you to utilize the input capability of the Arduino to give feedback for such things as occupancy and turnout state.  Open source JMRI is a good fit to open source Arduino.

Geoff's decoder circuit does have the advantage that it will work with any DCC system, albeit sans feedback.

Regards,

Dave

Dave

Geoff very nice piece of

Geoff

very nice piece of work.

only new back in the game and love seeing thinking out side the box.

question

after in the loop part of sketch after

  if (FuncNum==1) {  //Function Group 1 F0 F4 F3 F2 F1
      digitalWrite( FunctionPin0, (FuncState&0x10)>>4 );

And Im assuming that when you hit F1 that it write to functionPin 0,

can you put in a fade up command like

if (switch1State == 1) {
for(int fadeValue1 = 20 ; fadeValue1 <= 60; fadeValue1 +=50)
    // sets the value (range from 0 to 60):
    analogWrite(led1, fadeValue1); 
for(int FadeVaule = 60);

 

so if I hit F1 or any other how do i write it to do something other than on, off.

not quite sure where/ how to put it.

if you can give an example of code use just F1 turn a led on with fade.

from the the and with the other sketches i work it out.

Many Thanks

Tom

 

fading an led

// analogWrite(pwmPin, brightness)   // needs to a pwm pin, brightness ranges from 0 to 255

 

//so use something like the following for fading an led off

if(switch1State == 1)

{

for(int brigtness = 255; brightness > -1; analogWrite(pwmPin,brightness--) )

  delay(1);   //gives .255 of a second until led off 

}

//for fading up

if(switch1State == 1)

{

for(int brightness = 0; brightness <256 ; analogWrite(pwmPin,brightness++) )

  delay(1);   //gives .255 of a second until led on at full

}

 

So who wants to discuss firebox flicker, Mars light, rotary beacons, FREDs and the like.

fading an led

my previous post is actually a bad idea, in that it forces the arduino to wait .25 of a second for the next dcc packet.

 

A better idea would be, fad up  (already in loop from arduino sketch)

if(switch1State == 1)

{

analogWrite(pwmPin,?brightness<255:++brightness,255);

  delay(1);   //gives .255 of a second until led on at full, waits 1/1000 of sec for next dcc packet

}

 

Fading an led

Sorry if this is a bit off topic, but why does the 2nd example code NOT result in the dcc packet delay but the first code does? 

Thanks, I'm really enjoying this thread and all of the great ideas.

Neil

geoffb's picture

@Tom Fading On a LED

Hi Tom,

The code you were looking for is:

extern void notifyDccFunc( uint16_t Addr, uint8_t FuncNum, uint8_t FuncState)  {
#define fadedelay 15
  if (FuncNum==1) {  //Function Group 1 F0 F4 F3 F2 F1
      digitalWrite( FunctionPin0, (FuncState&0x10)>>4 );
      {
            if (FuncState&0x01==1 && (!digitalRead(FunctionPin1))) {
                for (int i=0; i<100; i++) {
                  digitalWrite( FunctionPin1, 1);
                  delay(fadedelay*(i/100.));
                  digitalWrite( FunctionPin1, 0);
                  delay(fadedelay-(fadedelay*(i/100.)));
                }
            }
            digitalWrite( FunctionPin1,  FuncState&0x01 );
          }
          
      digitalWrite( FunctionPin2, (FuncState&0x02)>>1 );
      digitalWrite( FunctionPin3, (FuncState&0x04)>>2 );
      digitalWrite( FunctionPin4, (FuncState&0x08)>>3 );

I've provided two more decoder files here:

http://home.comcast.net/~gbglacier/Articles/Decoders_with_Fade.zip

One modifies the 17 LED decoder with the code above just for F1 as requested.

The second file:  Decoder_17LED_5FTN_Fade

adds a 5th function to the general decoder set to fade on any LED. See the F1 settings-- it is already set up.

Both Neil and Getsmart (Sorry-- I still don't know your name) point out timing issues. Timing is an issue and a big pain. The decoder DCC queue, and if using Servos, the servo update queue, as well as the timing for slowing the servos, and servicing the blink rate ALL interact to varying extents. Also, I have no interest in combining everything into one timing queue and re-writing libraries. That would actually be the elegant solution. Again, my primary interest is in modeling, not cutting code. When trying to service everything, especially 17 functions that can be configured, you can easily configure your way into dropping DCC message packets. I originally wanted one of the function options to be a Pulse Width Modulation (PWM) function to control LED dimming and simple motor control. I may still get to it sometime, but it will be a timing issue worse than the blinking or fade startup. In effect another timing queue would have to be set up, and I'm not yet convinced that DCC and servo timing could be well served simultaneously. BUT, I haven't thought much about it yet. It's another "nice to have" on the list, and could be much more easily done as a separate PWM decoder. Maybe one of you will try it and share it with the rest of us?

Well there's some more for you all to have fun with!

Best regards,

Geoff Bunza

 

 

 

geoffb's picture

@John Re: Many Pinouts

Hi John,

Thanks for your leads. Even though I maxed out the pins on my Pro Mini examples, I am not looking for more pin expansion techniques, simply because the low cost (last 2.25) of the Pro Mini has changed my thinking about placement and construction for my modeling. I think they are far easier to use with fewer connections than more. The big exception I could conjure up would be when lots of electrical events need to be tightly synchronized (say for a complex animation), In my modeling I haven't come across such circumstances... yet!

But I do think it's great to know how others have treated the pin expansion problem. There are a number of good SPI I/O chips out now. I seem to recall MicroChip having produced some good ones too.

Thanks again.

Best Regards,

Geoff Bunza

 

Geoff Thank you for that

Geoff

Thank you for that code

wil have to wait until i build it to test it as i don't think it will work in a simulator.

also just want to share and get your thoughts on this code i put together to turn on 50 street lights in a random way with random fade on.

again it works in the Virtronics simulator.....

//Street lighting slow on quick off
//for toms model train setup HO scale using mega Arduino 48 pins to lights
//2 switch set up one for on one for off must be momentary can use double pole double throw

 
int ledPins[] = {4,4,8,9,12,14,18,19,25,17,26,42,51,49,47,46,45,37,29,13,11,24,41,43,
44,36,48,27,5,32,7,6,33,40,3,22,10,15,39,34,16,20,38,28,21,23,31,35,50,30,};       // an array of pin numbers to which LEDs are attached
int pinCount = 54;
int fade2 = -85;  //fade valule to off
int fade1a = 7;//fade vaule to fully on
int switch1 = 01; // switch for on
int switch2 = 02;// switch for off

// Variables will change:
int switch1State = 0;
int switch2State = 0;
      

void setup() {
                                                                                     
  for (int thisPin = 1; thisPin < pinCount; thisPin++) {                    // use a for loop to initialize each pin as an output:
   pinMode(ledPins[thisPin], OUTPUT);
}
    pinMode(switch1, INPUT);
    pinMode(switch2, INPUT);    
 
}

void loop() {
switch1State = digitalRead(switch1);                                            // reads if switch is in on position
switch2State = digitalRead(switch2);                                           // reads if switch in in on position
if (switch1State == HIGH)                                                   // if switch HIGH
for(int fadeValue1 = 0 ; fadeValue1 <= 255; fadeValue1 +=fade1a )  {       // starts fade loop starting at 0 until 255 is reached
  for (int thisPin = 1; thisPin < pinCount; thisPin++)                     // loop from the lowest pin to the highest
 analogWrite(ledPins[thisPin], fadeValue1);                             // writes to pin  amount of fade increment
delay(300); 

digitalWrite(switch1, LOW);                                                                                     
}

if (switch2State == HIGH)                                                        // if switch HIGH

 // loop from the lowest pin to the highest:
for(int fadeValue2 = 255 ; fadeValue2 >= 0; fadeValue2 +=fade2 ) {        // starts fade loop starting at 255 until 0 is reached
  for (int thisPin = 1; thisPin < pinCount; thisPin++)                     // loop from the lowest pin to the highest
    analogWrite(ledPins[thisPin], fadeValue2);                             // writes to pin  amount of fade increment
}

digitalWrite(switch2, LOW);                                              

}


>> Posts index


Journals/Blogs

Recent Blog posts: