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

fire place

Hi

As said new to this but did this code for a fire place.

the bases is Smoke and fan change intensity from time to time but lights/ fire keep flickering.

when switch1 on starts cycle when switch 1 off it stops

the intent being using red, Yellow and blue LED as flicker and a white as lighting room to go up and down.

with a ho scale or smaller smoke stack and a small Ex remote helicopter motor as fan to push smoke up and out of chimney to give a bit of oomph.

like to know your thoughts?

as before works in Virtonics Simulator

may need to be adjusted when built

 

/*
toms fire,fan,smoke.
 
 */
int switch1 = 2;
int led1 = 3;
int led2 = 4;
int led3 = 5;
int smokestack = 6;
int fan = 7;
int pin1 = 8;
int pin2 = 9;
int pin3 = 10;
int pin4 = 11;
int led4 = 12;
int delay1 =20;
int delay2 =15;
int repeat = 0;

// Variables will change:

int pin1State = 0;
int pin2State = 0;
int pin3State = 0;
int pin4State = 0;
int switch1State = 0;

// the setup routine runs once when you press reset:

void setup()  {

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(pin1, INPUT);
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);
  pinMode(pin4, INPUT);
  pinMode(smokestack, OUTPUT);
  pinMode(fan, OUTPUT);
  pinMode(switch1, INPUT);
 }

// the loop routine runs over and over again forever:

void loop(){
switch1State = digitalRead(switch1);
pin1State = digitalRead(pin1);
pin2State = digitalRead(pin2);
pin3State = digitalRead(pin3);
pin4State = digitalRead(pin4);
if (switch1State == HIGH){
digitalWrite (pin1, HIGH);
    }
if (pin1State == HIGH){
tomlights1();
    }
if (pin2State == HIGH){
smoke();
    }
if (pin3State == HIGH){
fan1();
    }
if (pin4State == HIGH){
lights2();
    }
if (switch1State == HIGH){
digitalWrite (pin1, HIGH);
    }
else {
        if (switch1State == LOW) {
        analogWrite(led3,  0);         
        analogWrite(led2,  0);  
        analogWrite(led1,  0);
          analogWrite(led4, 0); 
        analogWrite(smokestack,  0); 
        analogWrite(fan,  0);   
        digitalWrite(pin1, LOW);
        digitalWrite(pin2, LOW);
        digitalWrite(pin3, LOW);
        digitalWrite(pin4, LOW);
    }
  }
}
void smoke(){
for(int r=0; r<2; r++)
  {
    if(r<2)
    {
analogWrite(led4, 180); 
analogWrite(smokestack, 220);
analogWrite(fan, 180);
 analogWrite(led1, 80);   
delay(delay1);
   analogWrite(led2, 80); 
delay(delay2);
  analogWrite(led3, 80);
 delay(delay1);
  analogWrite(led3,  40); 
delay(delay2);
  analogWrite(led2,  220); 
delay(delay1);
  analogWrite(led1, 170);
delay(delay2);
  analogWrite(led2, 100); 
delay(delay1);
  analogWrite(led1, 200);
 delay(delay2);
  analogWrite(led3, 200); 
delay(delay1);
  analogWrite(led1, 120);
 delay(delay2);
  analogWrite(led2, 195);
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3, 150); 
delay(delay1);
  analogWrite(led1, 120); 
delay(delay2);
  analogWrite(led2, 120); 
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3,  200); 
delay(delay1);
  analogWrite(led1,  120);

digitalWrite(pin3, HIGH);
lights1();
    }
}
}
void fan1(){
for(int r=0; r<2; r++)
  {
    if(r<2)
    {
analogWrite(fan, 80);
analogWrite(smokestack, 180);
analogWrite(led4, 80); 
 analogWrite(led1, 80);   
delay(delay1);
   analogWrite(led2, 80); 
delay(delay2);
  analogWrite(led3, 80);
 delay(delay1);
  analogWrite(led3,  40); 
delay(delay2);
  analogWrite(led2,  220); 
delay(delay1);
  analogWrite(led1, 170);
delay(delay2);
  analogWrite(led2, 100); 
delay(delay1);
  analogWrite(led1, 200);
 delay(delay2);
  analogWrite(led3, 200); 
delay(delay1);
  analogWrite(led1, 120);
 delay(delay2);
  analogWrite(led2, 195);
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3, 150); 
delay(delay1);
  analogWrite(led1, 120); 
delay(delay2);
  analogWrite(led2, 120); 
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3,  200); 
delay(delay1);
  analogWrite(led1,  120);

digitalWrite(pin4, HIGH);
digitalWrite(pin1, LOW);
lights1();
    }
}
}
void lights2(){
  for(int r=0; r<2; r++)
  {
    if(r<2)
    {
analogWrite(fan, 20);
digitalWrite(pin1, HIGH);
digitalWrite(pin2, LOW);
digitalWrite(pin3, LOW);
digitalWrite(pin4, LOW);
    analogWrite(led1, 80);   
delay(delay1);
   analogWrite(led2, 80); 
delay(delay2);
  analogWrite(led3, 80);
delay(delay1);
  analogWrite(led3,  40); 
delay(delay2);
  analogWrite(led2,  220); 
delay(delay1);
  analogWrite(led1, 170);
delay(delay2);
  analogWrite(led2, 100); 
delay(delay1);
  analogWrite(led1, 200);
 delay(delay2);
  analogWrite(led3, 200); 
delay(delay1);
  analogWrite(led1, 120);
 delay(delay2);
  analogWrite(led2, 195);delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3, 150); 
delay(delay1);
  analogWrite(led1, 120); 
delay(delay2);
  analogWrite(led2, 120); 
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3,  200); 
delay(delay1);
  analogWrite(led1,  120);
        }  
    }
}

void tomlights1() {
  for(int r=0; r<1; r++)
  {
    if(r<1)
    {
analogWrite(smokestack, 180);
analogWrite(fan, 80);
digitalWrite(pin1, LOW);
digitalWrite(pin2, HIGH);
    analogWrite(led4, 100); 
   analogWrite(led1, 80);   
delay(delay1);
   analogWrite(led2, 80); 
delay(delay2);
  analogWrite(led3, 80);
 delay(delay1);
  analogWrite(led3,  40); 
delay(delay2);
  analogWrite(led2,  220); 
delay(delay1);
  analogWrite(led1, 170);
delay(delay2);
  analogWrite(led2, 100); 
delay(delay1);
  analogWrite(led1, 200);
 delay(delay2);
  analogWrite(led3, 200); 
delay(delay1);
  analogWrite(led1, 120);
 delay(delay2);
  analogWrite(led2, 195);
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3, 150); 
delay(delay1);
  analogWrite(led1, 120); 
delay(delay2);
  analogWrite(led2, 120); 
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3,  200); 
delay(delay1);
  analogWrite(led1,  120);
    }  
}
}
void lights1(){
  for(int r=0; r<2; r++)
  {
    if(r<2)
    {
analogWrite(led4, 50); 
    analogWrite(led1, 80);   
delay(delay1);
   analogWrite(led2, 80); 
delay(delay2);
  analogWrite(led3, 80);
delay(delay1);
  analogWrite(led3,  40); 
delay(delay2);
  analogWrite(led2,  220); 
delay(delay1);
  analogWrite(led1, 170);
delay(delay2);
  analogWrite(led2, 100); 
delay(delay1);
  analogWrite(led1, 200);
 delay(delay2);
  analogWrite(led3, 200); 
delay(delay1);
  analogWrite(led1, 120);
 delay(delay2);
  analogWrite(led2, 195);
  delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3, 150); 
delay(delay1);
  analogWrite(led1, 120); 
delay(delay2);
  analogWrite(led2, 120); 
delay(delay1);
  analogWrite(led1, 200); 
delay(delay2);
  analogWrite(led3,  200); 
delay(delay1);
  analogWrite(led1,  120);
        }  
    }
}

geoffb's picture

@Tom ttt Code Comments

Hi Tom,

First, what you are going to do completely workable. Comments follow for you to consider:

Lighting Sketch (first one)

Given the number of Digital pins you reference (50) the only Arduino I know that will support these is the larger Arduino Due. It is different in that it is a 3.3Volt device not 5 Volts, so you will have to adjust dropping resistors for LEDs accordingly. Given that you are controlling street lights, I would simply replicate your code for three - 17 output pin Arduino Pro Minis instead. The Pro Minis are 8-15 times cheaper depending on where you buy each.

Regardless there are two related points to be made. Not all Arduino pins are PWM outputs, which means that analogWrite statements will not work with all pins, and the compiler does not catch the error. On the Pro Minis only pins 3, 5, 6, 9, 10, or 11 are PWM pins. I suspect neither program will actually work, although they may well compile and load. You''ll have to look up the details of the Arduino Due to check its limitations.

Next, consider using the random( ) function to generate a number in a range:
e.g.    your_number = random ( 6, 20);
generates a pseudo random number in the range from 6 to 19 inclusive. Note well NOT to 20.
You can use this to get random time delays, on times, off times, etc. very effectively.

Here's an example of randomly lighting room lights that I use and demo a great deal:

//  This example assumes each pin is attached to negative side of an LED through a resistor
//  so setting the pin LOW will turn the LED on
#define numleds  16                                        //  number of LEDs this program will control
byte ledpins [ ] =  { 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 } ;    //  list  of all the LED pins
void setup( )  {      
    randomSeed ( analogRead ( 2 )  ) ;                 //  initialize the random number generator
    // initialize the digital pins as an outputs
    for ( int  i=0; i < numleds;  i++ )  {
    pinMode ( ledpins [ I ], OUTPUT)                
    digitalWrite ( ledpins [ i ] , HIGH)                 
   }                     
}
void loop ( )  {           
                           //  the following line picks a LED at random: ( ledpins [ random ( 0, numleds+1) ]
                           //  depending on what happens in lightsw ( ) it will return either a HIGH or LOW
             digitalWrite ( ledpins [ random ( 0, numleds+1 ) ], lightsw ( ) ) ;
             delay ( 900 ) ;    // wait 900 milliseconds-- 0.9 seconds                      
}
                           //  the following will return a LOW 60% of the time on average, randomly
                           //  remember that setting a pin low in our case turns the LED on!
boolean lightsw ( )  {
  if  ( random (0,100) > 40 ) return LOW ;
   else return HIGH ;
}

Perhaps these will give you some leads. Have fun!

Best Regards,

Geoff Bunza

 

geoffb's picture

Clarifying Decoder Comments

Hi to all,

There are quite a few modelers now building these little guys, and it's come to my attention (finally made it into my thick skull) that some explanation is warranted. To wit:

When you download the zip file here:   
http://home.comcast.net/~gbglacier/Articles/17-MULTIFunction-Decoder.zip

you will find 4 examples for the NmraDcc1 library Preconfigured for the following functions:
Decoder_10Serv_7LED_4FTN            10 Servos F0-F9      7 LEDs F10-F16
Decoder_13Serv_4LED_4FTN            13 Servos F0-F12    4 LEDs F13-F16
Decoder_15_Servos_1_LED_4FTN     15 Servos F0-F14    2 LEDs F15-F16
Decoder_17LED_1FTN                      17 LEDs On/Off Function ONLY

Please note that there are no configurations per pin in the last decoder. It merely mimiced the operation of the very first decoder I presented.

If you haven't read through the blog comments there is a new Decoder version that has 5 configurable functions per pin
here:   http://home.comcast.net/~gbglacier/Articles/Decoders_with_Fade.zip
Tha last one added is a LED turn on with a ramp up or fade on.

If you were one on the few people who downloaded a very early version of http://home.comcast.net/~gbglacier/Articles/17-MULTIFunction-Decoder.zip, you might get the error :  ‘CV_Decoder_Master_Reset’ was not declared in this scope.
Simply delete the old library, download the zip file and reinstall the NmraDcc1 library as one example had an error in it, which has already been fixed.

Have fun.
Best regards,
Geoff Bunza

 

10K or 1K

Geoff

Hi

Just checking use either 5 or 12 volt by placing  10K resistor on a an LED as on your list is a bit high as in the LED wont come on.

so im wondering did you mean a 1K / 1000ohm?

 

...

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!

I was having similar thoughts.  17 servos on one decoder is nice, but then you have 17 individual bus lines running out to each servo - that's a lot of unnecessary wire if the system can be done with a two wire or four wire [USB] bus.

If it comes down to $5 per servo device, that's still very affordable.

---------------------------------------------------------------------------------------------------------

Benny's Index or Somewhere Chasing Rabbits

geoffb's picture

Your LED " Mileage May Vary

 

Tom,

The LEDs I used were still bright with a 10K resistor! With less than .2ma -- not very typical. Many other LEDs will likely need a lower value resistor. For those you choose to use, try using the highest value resistor you can that still gives you a comfortably bright light.

Best Regards,

Geoff

 

 

pierre52's picture

A question for Geoff

Hi Geoff

As a complete newbie to the world of Arduino, would it be wise for me to buy one of these starter kits to gain some experience?

http://www.ebay.com/itm/UNO-R3-Starter-Kit-LCD1602-Servo-Motor-Breadboard-For-Arduino-Technical-Support-/351053947742?pt=LH_DefaultDomain_0&hash=item51bc72235e

Peter 

The Redwood Sub

Starter Sets

Peter,

As with most "beginner sets" the ebay set contains a lot of components which may or may not be useful tool for learning to use microcomputers, but I am more leery of the “support” or lack there of included in the set. The set includes paper Tutorials (more than 60 pages,PDF) where I would expect a CD or at least a link to web site with downloadable examples. Typing in code for examples can be a learning experience, but one typo can lead to hours of frustration. I usually recommend starting with just a basic Arduino board (eg. Uno), but (given the cost) the set does contain most of the components that could be used with the examples supplied with the Arduino IDE which would reduce the potential frustration of having to source the components yourself. Additional guidance and examples are available on the Arduino Learning pages, so a site is available from which you can download the software for the basic and additional examples. You can find more examples and code on sites like Adafruit which may utilize more of the components provide with the set.

Ken K

geoffb's picture

@Peter Comments about ramping up

Hi Peter,

First I want to make a distinction between "learning about the Arduino" and "learning to model" with the Arduino.

If you want to get up and running learning to model with the Arduino, I would recommend  looking at the ardunio,cc site at the "getting Started" section and the tutorials and this brief starting from scraatch tutorial: http://model-railroad-hobbyist.com/node/17244   and maybe first try the room lighting sketch (arduino uses call progreams sketches) and other example modeling sketches you can find in many places on the web ( google arduino model railroading) or in some of my blogs here: http://model-railroad-hobbyist.com/blog/geoff-bunza
Look at the examples, particularly ones you might use in your modeling and change some of the parameters in the code to get a feeling of what it's all about. Then, if you want more, take a look at the hundreds of tutorials on the web and get into it at your own pace. For modeling, you could wasily start with a Pro Mini and a USB download cable for less than $15-- so your risk is limited.

If you want to learn about the Arduino in a general sense, I would first ask if you had any electronics (hardware) or computer (software) background. If you have either, in any amount, use that as a starting point to understand what the arduino has to offer. There are literally hundreds of tutorials, books, and websites that you can access. The UNO R3 Starter Kit you cite is quite a collection of hardware, most of which you may never actually use.Ken has already made some good points, and I can't tell what the quality of the doc with the kit is, nor the availability of sketches for download, nor support availability. I think I would recommend you increment your way into this. There are lots of projects talked about in the forums at arduino.cc-- pick some to start.There are three highly respected web sorces for Arduino componennts of all sorts:    http://www.adafruit.com/ ,     https://www.sparkfun.com/ , and  http://www.pololu.com/
Both Adafruit and Sparfun have "Learning" sections with step by step guidance, and they can source all the materials for the exercises and larger projects listed, with additional videos, tutorials, online help, and online forums. Plus, virtually every arduino product they sell, you can download libraries that will work with their hardware-- sometimes saving a great deal of time and frustration. Agian these online resources are free, so you can increment your learning into whatever area you feel comfortable.

There is an interesting training guide that you can download on this page: http://www.instructables.com/id/Arduino-Expermentation-Kit-How-to-get-St... They have a similar, but smaller parts kit too, but download and look at the guide and see if that helps you start too.

There is another basic starting set of tutorials here: http://arduino-info.wikispaces.com/TUTORIALS
And a set of basic starting projects here:    http://www.richardvannoy.info/arduino.php

Generally I advocate you start reading before you buy. But if you're like me and want to dive in early, try some of the modeling projects or the basic projects to get you feet wet. And by all means ask questions-- there are many places to ask for help including here. Asking questions is a good way to learn.

Best Regards,
Geoff Bunza

 

Which Micro, Micro Board or Peripherals

The big exception I could conjure up would be when lots of electrical events need to be tightly synchronized ...

… that's a lot of unnecessary wire if the system can be done with a two wire ...

Expressly why I pointed to I/O chips capable of expanding and supporting additional outputs or inputs without overloading the microcomputer. Pick the appropriate microcomputer and peripherals that best fit the functional need. A 12 – 17 channel servo controller would be great for controlling the switches for a yard or a yard throat.

 I am designing a circuit to drive about ninety LEDs that rim a sign similar to a theater marque. The system has to be able to support about twenty lighting sequences. I could use a bunch of AVG micros, but with six to maybe twelve PWM outputs per chip, thats at least eight microcomputers (and a lot of wasted I/O pins). Although the software in each microcomputer would be essentially the same, it would still mean programming, debugging and supporting eight chips. Now using sixteen channel I2C bus chips or the twelve and twenty four channel SPI bus chips, the design will use fewer chips. Now I can implement a system with only five chips, and more importantly the software will reside in only one microcomputer. In fact it is entirely possible that I will be able to use a smaller Atmel chip like the eight or fourteen pin ATtiny85 device (small cousin of the micro used in the Arduino Pro Mini) for the controller.

As this sign will be on a portable layout, I will be using the Adafruit 24-Channel 12-bit PWM LED Driver - SPI Interface as PCBs will be more reliable than a wired breadboard and cheaper than a custom PCB. There are several additional advantages of this design including only one resistor is needed per chip to set the currents for all twenty four LEDs (four resistors instead of ~90 in series with each LED), the PCB will accommodate connectors which will reduce the the hookup and debugging hassles and Lady Ada of Adafruit has already developed an Arduino driver library for this board and chip.

On the other end of the design scale, I use the eight pin ATtiny85s for controlling servo and motor driven turnouts.

Ken K


>> Posts index


Journals/Blogs

Recent Blog posts: