C++ Objects for Layout Control, Part 1

The programming language supported by the Arduino IDE is C++, an object-oriented super-set of the C language (one of the fundamental languages of the computer programming world). This post is geared to newbies who have little or no previous experience with object-oriented programming. Experienced hands can skip past the basic explanations and see what I’m doing with it in a practical example.

Object-oriented programming (OOP) allows the programmer to conceptualize and write software in a way that is less like how the machine runs it (a list of instructions) and more like how humans think (objects, abstractions, relationships, etc.). Of course, you still have to write specific procedures, but they are placed in context within a software object. Don’t worry if this doesn’t make sense yet.

Without going into the more exotic aspects of OOP theory (we may get to some of those eventually, but not today), the point of OOP is to create the software equivalent of a “black box”—something that you can give data to and get a result from without knowing anything about how it works internally. This makes code highly reusable, the second major point of OOP.

OOP and the Arduino IDE

The Arduino IDE is a simplified environment within which to write C++ code. You cannot create and edit the formal file structures of C++ (.h header files and .cpp implementation files) within the IDE. However, within the IDE you can include C++ OOP code in your sketch with minimal formalities, so its a good place to get to know C++ objects. Those who write in C++ (whether professionally or as a dedicated amateur) can include their own work by installing it as a library the Arduino IDE can compile and include.

Given the context, from here on I’ll limit myself to how to do things in the Arduino IDE. To find out more about formal C++, here is one of many sites devoted to the subject: http://www.cplusplus.com/doc/tutorial/


Consider the things you are trying to control around the layout; would it be easier to manage turnouts, signals or animated/lit things as C++ objects? I think you’ll agree that it would. Lets explore an example.

A Basic Animated Object

My turntable bridge includes an operator’s hut containing a small stove with a fire for warmth.

If you Google Arduino fire simulations, you’ll find all kinds of algorithms and methods for simulating fire with LEDS and an Arduino. This fire is intended as a low, banked fire; the kind that has a variable glow and occasional sparks with no flame; probably coal is the fuel. So I’m keeping it simple: a single red LED on a PWM pin, its brightness rising and falling over time with random bright flashes. To do that, the code has to track the state of the led and whether brightness is rising or falling, periodically increment or decrement the brightness within a defined range, and randomly go high brightness for one cycle to represent a spark.

A First Class

The code that defines an object and its implementation is called a CLASS. Begin with the keyword class, give it a name and setup a pair of curly braces and a trailing semicolon to contain the definition:

class fire
{
};

In the Arduino IDE we can do this exactly the same way we create a TYPEDEF to define a data structure: put it in the head of your INO file (the sketch) before you use it and before the setup() function.

Now then, we need some content for this class: what data does a fire object need to do its job? It needs the know the pin it will use, the low and high values for brightness it will use, and the rate or frequency of updates. In order to run, it has to also keep track of its own state and when it was last updated.

class fire
{
  private:
   int ledPin;
   int high;  // value for maximum brightness
   int low;   // value for minimum brightness
   int rate;  // update frequency in milliseconds

   bool dirUp; // true if brightness is increasing
   int state;
   unsigned long lastUpdate;  // in milliseconds; can be a big number
  
};

That looks like a bunch of variable definitions, right? Exactly; just like local variables within a function. By convention we refer to these variables as the properties of the object. The private keyword that precedes the properties tells the compiler that these properties can only be accessed from within the object. While you can make properties public and thus directly accessible from outside the object, you should not do that without good cause because it could break the integrity of the “black box”. In general, the best practice is to create a public method to retrieve a private property from outside the object.

Methods

In order to do something useful a class has to have methods, the OOP term for class internal functions. Public methods are accessible from outside the object and constitute the interface you use to manipulate the object. Classes can also contain private methods, accessible only from within the objects. All objects require a special public method called the constructor which is called once when an object is instantiated—an instance is created in memory and initialized.

The Constructor

The constructor is a public method, with the same name as the class.

 public:
 
 fire(int pin, int zhigh, int zlow, int zrate){
   ledPin = pin;
   high = zhigh;
   low = zlow;
   rate = zrate;
 
   state = low;
   dirUp = true;
   lastUpdate = 0; 
   analogWrite(ledPin, state);
 }

The constructor takes 4 arguments. Upon entering the constructor, the first step is to transfer argument values to the object properties. Then the method sets the initial LED state to low brightness, sets the direction of brightness change to up (increasing brightness), initializes the lastUpdate property and turns the LED on at the desired PWM level.

The Update Method

In addition to the constructor, the fire object requires a public update method that is called regularly to allow the object to update itself and its LED.

void Update(unsigned long curMillis) {
   if(curMillis - lastUpdate >= rate){
     lastUpdate = curMillis;
     dirUp ? state++ : state--;
     if(random(80) == 1){ // do a spark at random intervals
       analogWrite(ledPin, 255);
     } else { // otherwise write the updated state to the LED
       analogWrite(ledPin, state);
     }
     if(state == high || state == low){ //if at end of range
       dirUp = !dirUp; // boolean logic flip
     }
   }
}

The update method takes a single argument, the current “time” (since the program started) in milliseconds. The intention here is that this method will get called more frequently than absolutely necessary, terminating immediately if it is not yet time to update. Note that here I need to use the random() function to trigger the spark, but up to this point I have not seeded the psuedo random number generator. In the final sketch, I include a call to randomSeed() in the constructor so that each instance will reseed the generator when it starts.

You might wonder why the update method doesn’t retrieve the time value on its own. Efficiency is important when running a stack of simultaneous animations, or your sketch will bog down and perform poorly. The best practice is to retrieve the time value at the beginning of your main loop() then pass that value to each animated object to allow it to determine what it should do at that time value. This also gives the function calling the update methods some flexibility in allocating time among competing priorities (for example, favoring a high priority object over a low priority one). If the update methods are efficient everything runs smoothly.

Putting it All Together

Now that we have defined a CLASS, lets create some objects and see how it works.

To try this out, create a simple double LED circuit with an UNO and a breadboard, like so — I put the resistors on the cathode side as a matter of habit because I’m using common anode wiring everywhere; put them on the anode side of the LEDs if you prefer:

A simple double LED circuit on PWM pins 5 & 6. The 220Ω resistors are on the ground side.

Why two LEDs? We are going to further enhance the class by generating random values for the initial state and direction of the fire object. That, plus instantiating each object with slightly different parameters, guarantees that each fire instance starts and progresses differently. Once started, each instance will do its own thing.

Here’s the sketch (download from the github site):

///////////////////////////////////////
// CLASS fire
// A demonstration C++ class 
// for simulating a fire with LEDS
//
// Author: Robin Simonds, theNscaler.com
// License: CC BY-SA 4.0
// https://creativecommons.org/licenses/by-sa/4.0/
///////////////////////////////////////

class fire {
 private:
   int ledPin;
   int high; // maximum brightness 
   int low; // minimum brightness 
   int rate; // update frequency in milliseconds 
   bool dirUp; // true if brightness is increasing 
   int state;
   unsigned long lastUpdate; // in milliseconds; can be a big number

public: 
 fire(int pin, int zhigh, int zlow, int zrate){
   ledPin = pin;
   high = zhigh;
   low = zlow;
   rate = zrate;

   lastUpdate = 0;
   // seed the psuedo random number generator by
   // reading an unconnected analog pin
   randomSeed(analogRead(0));
   // randomize the starting state of the object
   state = random(low + 1, high);
   dirUp = random(2) == 1;
   analogWrite(ledPin, state);
 }
 // call the Update method frequently to run the animation
 void Update(unsigned long curMillis) {
   if(curMillis - lastUpdate >= rate){
     lastUpdate = curMillis;
     dirUp ? state++ : state--;
     if(random(80) == 1){ // a possible spark
       analogWrite(ledPin, 255);
     } else {
       analogWrite(ledPin, state);
     }
     if(state == high || state == low){
       dirUp = !dirUp; // boolean logic flip
     }
   }
 } 
};

// create global instances of the fire class
fire demo_fire1 = fire(6, 80, 20, 30);
fire demo_fire2 = fire(5, 75, 15, 35);

void setup() {
 // no setup currently needed
}

void loop() {
 unsigned long current_millis = millis();
 
 demo_fire1.Update(current_millis);
 demo_fire2.Update(current_millis);
}

When you run it, it should look something like this:

Want to do a two or three LED fire algorithm (maybe red with amber/yellow for more of flame effect)? Its just a matter of additional properties and additional instructions in the Update method to implement the algorithm. Give it a try if you are so inclined. You’ll see first hand how OOP can make code more reuseable and easier to modify. For animation with Arduino, OOP provides just the right framework to create and manipulate multiple animated objects of all kinds.

In part 2 of this post, we’ll tackle a common and more complex layout object: turnouts.

L&NC Update; Running Lots of Turnouts

Its been a long stretch where there has been too much going on in real life and little time to write about model railroading. But I’ve been working away on the first module of the L&NC and have made lots of progress, so there’s plenty to write about.

This module has nine turnouts, presenting resource management problems that would arise in any substantial yard or staging facility. If you are familiar with the servo library then you know that you are limited to about 10 servos per microcontroller. With that many servos, your microcontroller will have few resources left to do anything else. This post will focus on a solution that problem, expanding the number of servos and other PWM devices a single microcontroller can manage.

Progress Tour

But first, a quick overview of progress to date.

Here’s the module in its current state:

Progress on the 1st Module as of June 2017. Fascia and dressing up of the edges will be the very last step; its pointless to do that while I’m disturbing things with new features and gear. Wires hanging out the pipe at the bottom of the photo are Anderson Powerpole connectors (track and master power) to the upper level.

As you can see I’ve done quite a bit of detailing. I realized early on that I need to complete all the basic scenicking and detailing of the module before moving on to the next. The big reason is having the module alone on a work table gives the best possible access, especially for electronic or animated items that require access to the underside. That’s not to say detailing will not continue after I move on to the next module, but it will mostly be passive rather than active elements.

By the way, if I were to build a room-sized layout, I’d use a modular (some call it “sectional” because you build it in sections) approach to construction even though the layout would not be portable. After laying mainline and other track spanning sections and cutting gaps between sections, I’d pull each section and do most of the remaining work in a work area under optimal conditions. When ready its just a matter of returning the section to its place in the layout and (literally) plugging it in.

Lets take a quick tour of some details so far.

Roundhouse / Turntable

If you’ve read the previous posts about the Roundhouse and the Turntable, you know these have been long term projects.

The turntable rotating beacon comes on whenever the turntable is in motion.

Then stove fire simulation inside the hut is visible through the door. It’s managed by a little PWM code that will the subject of an upcoming post.

The parking lot side of the Roundhouse has been enhanced with Rix power poles and some EZLINE power cables (which comes in two thicknesses and several colors. I use fine, and chose green–old copper–for its visibility). I fabricated a simple power connection and breaker box for the roundhouse out of a piece of styrene and a brass rod, and an EZLINE cable.

A Woodland Scenics light pole casts a pleasant white-yellow light over the parking lot in night mode. Figures, such as the worker (a Woodland Scenics prepainted figure) at the turntable end of the parking lot breath life into a scene.

Having gone to all the trouble to light the Roundhouse, I’ve started populating the space with some appropriate gear and figures.

A view of the lit Roundhouse interior.

Red Bluffs Yard

The Red Bluffs Yard area has its first structure — a fully lit Yard Office — plus a pickup truck with lighting passing by on the adjacent road.

The Red Bluffs Yard Office is fully lit for night operations. The Woodland Scenics light pole works just fine with my Duino Nodes controlled by an Arduino; treat it like any other 20 mA LED. The truck tailights in the background are from LEDS placed in the rear wheel wells, with the light allowed through tiny holes in the fenders.

Its amazing what a couple of SMD LED headlights can do for a really basic pot metal pickup truck kit from Micro Engineering.

The first of three planned scratch built Signal Bridges has been erected to control one of the approaches to the yard interchange.

And, finally, here is the underside, which is rapidly filling with gear supporting the layout above. This module, with its yard, multiple main tracks and turntable is one of the most electronically “dense” parts of the layout plan, to be exceeded only by the city scene planned for the upper level — that is going to be quite a project and I can hardly wait to finish the lower level and get started on the top!.

The underside of this module is rapidly filling with gear. Obviously overhead soldering is not an issue since I can put the module on its side. That said, I rely primarily on screw terminals and crimped fittings for connections.

PWM Drivers for Turnouts and Other Uses

Pulse Width Modulation (PWM) is used to output a timed pulse, where the output is on only part of the time. The width of the pulses — the percentage of time the pulse in the on state — is used to control external devices like servos or to vary the brightness of an LED.

Some, but not all, Arduino digital outputs are hardware PWM capable. Some of the PWM pins are SPI pins and the two serial pins, leaving only 5 or 6 PWM pins available for unrestricted use depending on the board model. If you want to make extensive use of PWM, that just won’t cut it.

PWM can also be synthesized with timed interrupts on any pin, which is how the servo library works and why it does not require you to attach to PWM pins. Unlike hardware PWM pins, PWM synthesized with interrupts represents a hidden load on your board that can affect the performance of your sketch.

External PWM Boards or “Drivers”

External PWM drivers allow  you to greatly expand the number of PWM devices a single Arduino can manage. PWM is used extensively in robotics, so PWM drivers are fairly ubiquitous and inexpensive. Aside from expanding the number of PWM devices you can control, PWM drivers allow you to off-load all of the PWM overhead and timing routines to the external device, freeing your Arduino for other tasks.

I decided to try Adafruit 16-Channel 12-bit PWM/Servo Driver for servo control and a couple of lighting applications on this module. Adafruit also sells a similar device in shield form.

Adafruit 16-Channel 12-bit PWM/Servo Driver, assembled with original terminal block (blue) that did not hold up to use. I eventually soldered leads to the underside of the board.

I chose the independent board rather than the shield because it has a number of advantages, not least of which it is chain-able with up to 61 additional boards, for a total 992 PWM outputs. A single chain of these can handle the servo needs of most club and museum sized layouts! A more modest layout could use these for both turnout servos and all lights and lighting effects, effectively centralizing and simplifying control of all connected devices. It uses the shared I2C interface for fast communication without using any regular pins on your Arduino. For more details, and a tutorial, see the Adafruit product page.

Assembling the board was straight forward, though there are a lot of pins to solder. The terminal block in the center provides independent power for the servo outputs (V+ center pin on outputs) per standard servo wiring; independent power is required by servos because of their substantial current draw. LED’s and other devices that draw their power from the PWM signal itself will not use the independent power.  Be warned: the terminal block Adafruit supplies is poor quality—substitute a better quality part or solder power leads directly to the board. The headers on the sides are for input and output, transferring both data and power to subsequent boards in a chain.

Adafruit 12 bit 16 Channel PWM Driver installed and connected to servos and lighting.

Connecting servos is just a matter of having a male->female servo extension the right size, or combining multiple extensions for longer runs. Any robotics supply store should have an assortment of extensions; as does Amazon. I have three different sizes to work with, which has worked well so far.

On the board positions 0 through 8 (1st 2 banks of four, plus the first pin of bank 3) are attached to the 9 turnout servos. Positions 9 and 10 are for headlights and taillights on the pickup truck. Using PWM I can have the headlights go between low beam and high beam, or have the taillights brighten as if the brakes have been applied. I have some thoughts about an animated animal crossing in front of the truck from time to time….

Using Adafruit’s PWM Driver Software

Adafruit’s software library for this device is available from their GitHub site. Using the software you create an object that you then use to control the board outputs:

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

Creating the Adafruit_PWMServoDriver object without arguments uses the base SPI address to access the board; any different address has to be specified as an argument (and the appropriate jumpers on the board have to be closed). With multiple boards, you create a pwm object for each board using its unique SPI address.

From there, the PWM pulse is set on any output by calling the setPWM() member function:

pwm.setPWM(pin, on, off);

where pin is the board output (a number between 0 and 15), on sets the point in the cycle when the signal goes from low to high (usually 0, the beginning of the cycle, but it can be another value) and 0ff is a number between 0  and 4095 setting the point in the cycle when the signal transitions from high to low.

With the Adafruit driver board you do not use degrees to set a servo’s position. Instead we use timing “tick” values that control the signal transitions from low to high and back. There are 4096 “ticks” (12 bits of resolution) during each cycle. That turns out to be a good thing. For servos, the correct off tick values (assuming the on tick is 0) range from about 150 (the minimum or 0 degree position) to 600 (maximum position, 180 degrees).

Directly setting the cycle through ticks at 12 bits of resolution confers highly granular control and extra smooth servo motion.  Using degrees for position, as the standard servo library does, results in jerkier motion since a degree represents a lower resolution–between 8 and 9 bits–than the 12 bit resolution of the Adafruit board. For LEDS and other lighting, you can vary brightness from off to full on in 4096 steps, allowing fine control of lighting effects.

If you ask me, the smooth motion you can achieve with this board makes its $14.95 price more than worthwhile.

The only difference in your code between working with the standard servo library and the Adafruit driver, is in the object and member function you use to cause the servo to move. Every other aspect of your code and logic should remain the same.

What’s Next?

More coding, and I promise I won’t make you wait long. In the next installment I’m going to introduce you to simplified Object Oriented Programming (OOP) in C++ with the Arduino IDE. I’ll demonstrate a different way to code that, I think, improves several aspects of working with multiple turnouts, and makes the intent and flow of your code easier to understand and maintain. We’ve done it procedurally; we are going to take what we’ve learned and create some OOP code to do the work using either the Adafruit driver or the standard servo driver (Hint: we’ll use a compiler directive to select which driver gets implemented, making the object itself agnostic on the issue and universally usable around the layout).

Until then, happy railroading!

Announcing theNscaler Github Repository

While I try to put complete, working sketches in my posts, there have been many instances where putting entire sketches in a post is impractical, so I frequently field requests for more complete code.  I also have noticed that, for whatever reason, some readers have difficulty copying code from the blog to their own work. So, I’ve opened a GitHub repository to make sharing code a little easier for everyone. Over time I’ll share out examples and useful library code.

The new repository can be found here: https://github.com/rpsimonds/thenscaler/

I’ll be using the “branch” feature to organize the repository.  I’ve seeded it with two branches: Current Sensing and Testloop.

Current Sensing — currently contains a single file with the current sensing functions originally developed for the ACS712.  I’ll be adding a comparable file for CT sensors shortly.

Testloop — contains the entire code set created for the test loop.  Note that this project contains multiple files that should all be copied into a single directory (named testloop to match the main file testloop.ino) in your Arduino documents. This code is provided for those who are ready to wade into deeper levels of complexity to multitask and get multiple threads working together. Some of the code — especially networking and the code for Duino Nodes is “library” reliable and part of my basic code set.  Other code was more experimental. Nothing here is the last word on anything, of course.  But it works and is worth studying on that ground alone.

I hope you find this useful.

Current Sensing and Occupancy Detection for DCC

I’ve had several projects going on more or less simultaneously over the last 6 weeks in connection with the build-out of the 1st module of the L&NC. One project has been to further refine block occupancy detection in DCC to achieve 1 mA detection sensitivity—the sensitivity needed to detect rolling stock equipped with a 10kΩ resistor wheel set. High sensitivity occupancy detection will be especially useful in the Red Bluffs yard part of the layout I’m working on right now

This part of the L&NC is a Yard/Staging facility with a roundhouse & turntable, so it has lots of blocks

Commercial block occupancy detection systems for DCC typically use current transformers to sense current draw from locomotives or resistor wheelsets. The sensors are usually attached to stand-alone logic boards that turn outputs on or off to signal occupancy detection. Typically, these outputs are used to directly power signals. The December 2016 issue of Model Railroader Magazine included an article (Build a signal system with Arduino micro-controllers) where the author connected the outputs of RRCir-Kits BOD boards to an Arduino Mega, and ran his signals from there.

I’ve been avoiding solutions like that because of the high cost and inflexibility of commercial detection systems. All I need is a way to sense very low current flow; the Arduino can do all the rest of the work.Thinking about the issue further, I wondered why not just use current transformers as sensors that can be directly read by an Arduino?

Finding Experimental Sensors

Current Transformer

The type of current transformer useful in model railroading are designed to allow you to wrap a wire (e.g. track feeders) around it through the central hole making the wire the “primary” coil of the transformer. The secondary coil produces an A/C current, that you can measure, proportional to the A/C current running through the primary wire.

I had seen little about using CT sensors with Arduino until I bumped into a seller on Amazon of boards with current transformers marketing them as Gikfun DIY 5A Range AC Current Transformer Module for Arduino. The assembled boards were about $7.50 each, a bit expensive, but then I found a 5 sensor unassembled kit from the same vendor for just under $9. Less than $2 per sensor is my price point for BOD sensors, so I bought the kit to see what i could do with it.

Gikfun Current Transformer Kit

The kit consisted five current transformers, five 82Ω resistors, connector pins and five 19mm x 19mm pc boards on a break-apart strip, drilled and traced for the parts. The resistor is placed across the transformer leads, placing a load (I’ve seen it referred to as a “burden”) on the transformer enabling current flow. No instructions on how to use the sensor were anywhere to be found.

So I went with the methods I already know work with ACS712 sensors. I set up some feeders from the DCC system to my cleaning track, wrapping one of the feeders around the CT coil three times. I hooked leads from the sensor board to pin 0 and ground of my Mayhhew Labs Extended ADC Shield, then threw together a test sketch with the current reading utilities I’d previously used (adapted for the shield).

A Simple CT Sensor Test Rig

I “let her rip” and watched the readings go by on the serial monitor.

Oh My! Putting a DCC equipped locomotive on the track and turning track power on, I was rewarded with a clear reading even though the decoder was idling and all lights were off.  Bring up the lights and the readings jumped up appropriately. Then, taking the loco off the track, I tried shorting the track with a 10kΩ resistor: an immediate and clear response in the readings told me this was going to work.

Test readings in single ended mode using a Mayhew Labs 14 bit ADC Shield. Everything from a 10k resistor shorting the track, to different stages of locomotive operation are clearly shown by the sensor outputs.

I tried it again, this time connecting the CT sensor to A0 and ground on my UNO, and got different but workable results. Amazing!

The readings through the UNO’s built-in ADC are similar, especially at the low end. But notice that the scaling, which is spot-on correct in the first example, fails at higher current levels here. Evidently, the greater bit depth of the Mayhew Labs Shield (14 bits) vs the built-in ADC’s (10 bits) makes a difference where absolute accuracy is concerned. Our purposes are much cruder — we just want to know when a minimum current (1 mA) is flowing. For that purpose direct-to-UNO works fine.

Testing current sensing with and InterMountain EMD F3A

Wait! This Shouldn’t Work!

You see, I was using the ADC in “single-ended”, “uni-polar” mode so that it would read a single input in the range of 0 to +5 volts; this is the same way Arduino analog inputs are read by the built-in ADC. However, the signal from the CT is an A/C signal that the ADC (in single-ended, uni-polar mode) will not be able to read during the negative voltage part of the cycle. Nevertheless, it works with both the built-in and the external ADC, even though it shouldn’t.

I was puzzling as to why, apparently, I was able to cheat when it occurred to me that the difference from ordinary applications was probably the frequency of the signal. Ordinary A/C is a 60 Hz cycle (60 cycles per second).  That is slow compared to the rate at which an Arduino ADC can sample, so a lot of samples would be at 0 during negative phase of the cycle. This would throw calculations off.

DCC is an 8kHz  (8000 cycles per second) cycle which is very fast. My Mayhew Labs ADC can sample at a maximum rate of 3kHz, which is somewhat faster than the Arduino built-in ADC but still slower than the DCC cycle. So even at the fastest rate every ADC read will span multiple DCC cycles, resulting in the ADC returning a positive reading every time.

Or something along those lines is going on.

Mayhew Labs Extended ADC Shield on an UNO, reading the test CT sensor in differential mode.

For hard core accuracy, a CT should be read in differential, bi-polar (+/- voltage) mode, requiring a 14 or 16 bit external ADC with that capability. In differential mode, each CT lead is attached to an ADC port, then the two ports are compared and their difference reported. This effectively captures the entire A/C cycle. Read in differential mode, CT sensors produce stable, high accuracy readings. During testing with my 14 bit ADC I was able to sense down to near 400µA in differential mode, the draw of a 20kΩ resistor at 11 volts. Now that is sensitive!

Same test sequence using the Mayhew ADC to read the sensor in differential mode. Notice the increased accuracy, stability and sensitivity.

Next Steps

The Gikfun 5 sensor kit is a viable sensor package where you will be watching no more than a few (up to the 6 or 8 analog ports on your Arduino or Mayhew Labs ADC shield) blocks. For small installations, buy these sensors and use the ADC in your favorite Arduino board to read them.

For larger installations, the external ADC shield is worth the cost because it is fast and more accurate.

But what if you are watching more blocks than you have analog ports for? That is a bit of a problem, especially if you don’t want to have to use a new microcontroller for every 8 blocks. The module I’m working with has this problem, because it is a yard zone (with turntable and roundhouse) with 24 blocks, and I want just one Arduino board to listen to them all and run signals for this part of the layout.

In the next post, I’ll go into a solution to the problem and install the system.


Code

My experiment was complicated by the fact that I was testing different ADC’s and different connection methods. Below is some basic code for testing a CT sensor such as the Gikfun units discussed above by directly attaching one lead to an Arduino analog port, and the other lead to ground. This is the simplest way to use CT sensors.

The code is built around current sensing techniques originally developed for ACS712 sensors. For more in-depth discussion of that development process, see these posts – 1 , 2, 3 and 4. ADC’s (analog-to-digital converters) read the voltage produced by a sensor which, in the case both current transformers and ACS712 sensors, is proportional to the current it is measuring.

The challenge with sensing alternating current comes from the fact that at any given moment when a sensor is read, the current could be anywhere in its cycle with a voltage somewhere between -Vmax and +Vmax (the nominal A/C voltage). Since we are sampling a bipolar wave form, it is necessary to take multiple samples spanning multiple cycles, then calculate the current from the samples using the Root Mean Square algorithm. This is the generally accepted method for determining A/C voltage and current from digital samples.

In addition to solving the basic problems of sampling an A/C signal, the RMS algorithm cuts through signal and sampling noise, a significant problem with ACS712 sensors when measuring low current. Since CT sensors are far less noisy, we can get accurate readings with fewer samples; but we still need the RMS method to calculate current flow.

To make the process I’ve described accurate across an array of sensors, I developed a calibration routine. All ADC’s will produce some minimal reading for a sensor even when the sensor is not producing a signal. This is a form of noise that has to be filtered out. Also, some sensors (such as the ACS712) produce a signal in the absence of any current to measure — this too is noise that has to be filtered.

Each ADC port / sensor combination will produce a unique amount of noise. The purpose of the calibration routine is to measure and record the noise level — I call it ADC Zero — for each port/sensor. This is recorded both as raw mV, and as a calculated current in mA. Later, the measured noise is subtracted from each raw reading (in mV) to determine what current (if any) has been detected. Then, when current is detected, I use a multiple of the ADC Zero calculated current to establish an occupancy threshold. This method allows me to overcome sensor differences and manage the sensor system in a uniform way.

// CT Sensor test
// Using UNO built-in ADC to read the sensor
//////////////////////////////////////////////////////////////////

#define VERSION "1.006"
#define SYS_ID "CT Sensor Test - Direct to UNO ADC"
const int adcpin = 0;

// Sampling Parameters
const unsigned long sampleTime = 2000UL; 
const unsigned long numSamples = 100UL; 
const unsigned long sampleInterval = sampleTime/numSamples; 

#define SENSITIVITY 5000
#define DETECTION_MULTIPLIER 1.3
#define CALIBRATION_READS 300

// variables to hold sensor quiescent readings
float aqv;  // Average Quiescent Voltage; e.g. ADC Zero
float aqc;  // Average Quiescent Current; 

void setup()
{
  Serial.begin(9600);
  Serial.println(String(F(SYS_ID)) + String(F(" - SW:")) + String(F(VERSION)));
  Serial.print("\nCalibrating the sensor at pin ");
  Serial.println(adcpin);
  aqv = determineVQ(adcpin); 
  Serial.print("AQV: ");
  Serial.print(aqv * 1000, 4);
  Serial.print(" mV\t");
  aqc = determineCQ(adcpin, aqv);
  Serial.print("AQC: ");
  Serial.print(aqc * 1000, 4);
  Serial.print(" mA\t");
  float sense = (aqc * DETECTION_MULTIPLIER) - aqc;
  Serial.print("Detection Sensitivity: ");
  Serial.print(sense * 1000, 3);
  Serial.println(" mA\n\n");
  delay(7500);
}

void loop(){
  float current = readCurrent(adcpin, aqv);
  float delta = abs(aqc - current);
  bool occupied = delta > ((aqc * DETECTION_MULTIPLIER) - aqc);
  
  Serial.print("Current Sensed: ");
  Serial.print(current * 1000,3);
  Serial.print(" mA\t");
  
  if(occupied){
    Serial.println("Occupied");
  } else {
    Serial.println("Not occupied");
  }
  delay(3000);
}

//////////////////////////////////////////
// Current Sensor Functions
//////////////////////////////////////////
float readCurrent(int pin, float adc_zero)
{
  float currentAcc = 0;
  unsigned int count = 0;
  unsigned long prevMicros = micros() - sampleInterval ;
  while (count < numSamples)
  {
    if (micros() - prevMicros >= sampleInterval)
    {
      float adc_raw = (float) analogRead(pin) - adc_zero; // sensor reading in volts
      adc_raw /= SENSITIVITY; // convert to amperes
      currentAcc += (adc_raw * adc_raw); // sum the squares
      count++;
      prevMicros += sampleInterval;
    }
  }
  //https://en.wikipedia.org/wiki/Root_mean_square
  float rms = sqrt((float)currentAcc / (float)numSamples);
  return rms;
}

//////////////////////////////////////////
// Calibration
// Track Power must be OFF during calibration
//////////////////////////////////////////

float determineVQ(int pin) {
  float VQ = 0;
  //read a large number of samples to stabilize value
  for (int i = 0; i < CALIBRATION_READS; i++) {
    VQ += analogRead(pin);
    delayMicroseconds(sampleInterval);
  }
  VQ /= CALIBRATION_READS;
  return VQ;
}

float determineCQ(int pin, float aqv) {
  float CQ = 0;
  // set reps so the total actual analog reads == CALIBRATION_READS
  int reps = (CALIBRATION_READS / numSamples);
  for (int i = 0; i < reps; i++) {
    CQ += readCurrent(pin, aqv);
  }
  CQ /= reps;
  return CQ;
}

Adjusting the Sketch

The SENSITIVITY and DETECTION_MULTIPLIER constants are the main values you can manipulate to adjust the sketch.  The SENSITIVITY constant defines the conversion from raw mV to sensed current in mA; raise that number to reduce the current reading and decrease dynamic range of the sensor readings (lower it to do the reverse).  The DETECTION_MULTIPLIER determines when a current reading is high enough to mean that a block is occupied. Try different values for these items and see what happens. The interaction between these two constants is the primary determinant of how the sketch performs.

If you have having stability trouble with your readings, try increasing the number of samples taken on each pass (numSamples) and/or changing the sampleTime variable that controls the interval between samples.

Bear in mind that for low current sensing, the 10-bit ADC in an UNO is just barely sensitive enough to work with a CT. For low current sensing you’ll need to adjust the variables to get a minimum of false readings.  The values given in the sketch above are what worked for me with the Gikfun CT coil and a particular UNO to achieve stable detection.  Expect different readings and different variable values for different brands of CT coils, and different Arduino boards. Working with large numbers of CT sensors, I can say that a given Arduino board and a given brand/model CT, using the same value for the load resistor, will generally produce the same readings.

 

Adding a Turntable to the L&NC, Part 2

The Roundhouse / Turntable complex at the Red Bluffs Yard is the focal point of the lower level of the L&NC and one of the more complex projects planned for the layout. In the first installment  (which is also step 4 of the build out of Module 1, lower level) I wrote about how I built the pit and bridge base, and showed the mechanism I developed for the turntable using Actobotics robotics gear.  In this installment, step 5 ( Links to step 1, steps 2 & 3) of this module build out, we’ll take a look at the buildup around the turntable, adding track and integrating it into the scene.  I’ll also talk about how I completed and wired the bridge. Along the way I took the time to install basic scenery elements while I have free access to this section of the layout.

Step 5

Finishing the Pit

The first task after installing and leveling the turntable pit was to create a rim and cover the rough opening for the  pit. After looking at a lot of pictures of prototype turntables I concluded that the rim needed to be around 4 or 5 scale feet wide. Rather than try to cut a circle out of styrene, or something like that, I elected to use a strip of cork roadbed. With the beveled edge against pit wall, and the square edge forming the outer edge of the rim, the look seemed about right.

The flexibility of n scale cork roadbed made it the perfect material for rimming the turntable pit.

The flexibility of n scale cork roadbed made it the perfect material for rimming the turntable pit.

One thing I found out in my research was that track rails are typically attached directly to the rim material (usually concrete) without ties. I decided not to model it that way because I just don’t want to get bogged down with gauging problems. So I elected to mount the ties to the rim so that they will keep the track in gauge.

Its not prototypical, but that’s OK with me because this is one of those places were functional reliability has to win out over prototypical niceties.  As you can see in the picture below, I weaved the ties of the adjoining tracks between each other to achieve the correct track placement along the rim where it meets the bridge. Preliminary testing established that I’m getting good alignment and smooth wheel transits across the gap.

Track from the Roundhouse meets the turntable.

Track from the Roundhouse meets the turntable. Ballasting is in progress so there are bits ballast everywhere at the moment!

I painted the rim concrete to match the rest of the pit.  The texture of the roadbed material is a little rougher than I anticipated. A second coat of paint smoothed it out more and left me with a surface that is a little worn from the effects of time and weather.  I’m pleased with the effect; a perfectly smooth surface just wouldn’t be right.

Finishing the Bridge

In addition to the powered track that also serves as a reversing section, the turntable bridge has an operators hut containing a warming stove with a red LED for creating a hot coals effect. The central arch–which prototypically was often a rotating connection point for the incoming power line to run the turntable–is outfitted with a simulated rotating beacon that will run whenever the turntable is in operation. Not even remotely prototypical, this little enhancement is just a way to animate and make the turntable even more interesting.  I did say at the outset of this project that I was going to throw in animations at every opportunity!

I started the deck by creating a base frame to fit over the bridge and hold a piece of flextrack (I’m doing this layout in Peco code 80 gear).

Bridge deck base frame.

Bridge deck base frame. The track has not been trimmed to its final length yet.

Starting with the base frame, I continued adding cross-members until there was one in each space between ties. Then I decked it with .030 x .080 styrene “planks” cut to various lengths from scale 8′ to scale 32′, creating a plausible planking effect..

The bridge deck before painting.

The bridge deck before painting.

The central arch is fabricated from .080 square tubing. I added etched brass X-bracing in a scale 18″ size so that it would resemble beams fabricated from plates and X-braces. I thought about trying to fabricate brace & plate beams, but felt it would be a little too difficult to pull off and make strong enough for practical use.

The rotating beacon at the top of the arch is fabricated from three red micro SMD LEDS arranged in a triangle. The magnet wires (1 common anode and 3 cathodes) are connected to an incredibly small rotating beacon simulator board that I purchased from Ngineering.com. The have a nice collection of simulator boards geared to model railroading, with everything sized for N scale (these boards will work in any scale, so don’t be deterred if you don’t do N).

The Ngineering rotating beacon simulator board with leads attached.

The Ngineering rotating beacon simulator board with leads attached.

Actually I bought 2 because I ended up screwing up one of the outputs on the first one. These boards are smaller than a dime and soldering wires to them is tricky. On my second attempt I soldered short 30 gauge solid wire leads to the board (easier than soldering magnet wire), then soldered the 40 gauge magnet wire to the leads.

To answer the obvious quesiton, I could very well have done the rotating beacon effect with an Arduino.  However, this little board is particularly good at that job, and I don’t have to use 3 PWM pins (plus the timing sensitive programming) to do the job.  I can run this effect from a single connection on a Duino Node, simply turning it on when the bridge moves and off when it stops at its intended destination.  This is good example of how one has to balance all the trade-offs when designing a system based on Arduino technology. Sometimes an external utility board gets you to the right place more efficiently than doing it from scatch.

Base and walls of the hut, and the stove.

Base and walls of the hut, and the stove.

The operator hut is made from a white metal “trackside shanty” kit by Stewart Products. I decided that the hut needed a little stove for heating, to go with the smoke jack provided by the kit. So I fabricated one from a piece of brass tubing and a styrene circle for a top. I cut an opening in the brass to serve as the front opening.  A red led mounted in the bottom of the tube (not shown) will be used to create a fire effect that you will just barely see through the open door of the hut. I’ll produce the effect with PWM on an Arduino board instead of a dedicated simulator. So the turntable bridge will have two different light animations.

With all the pieces assembled, the wiring in and everything painted, it was time to connect all the wires to the leads from the spinner and attach the deck assembly to the bridge base. If you look carefully you’ll see a black object to the right of the center — that is the beacon simulator in protective heat shrink tubing.

Attaching the deck assembly to the bridge base.

Attaching the deck assembly to the bridge base.

Are those fishing weights attached to the underside of the deck? You guessed it! The white metal hut is rather heavy (relative to the weight of the styrene); the weights are needed to balance the bridge. The white object between the girders on the left is a nylon screw with a rare earth magnet (Neodymium, available from K & J Magnetics) glued to its head, screwed into a nylon nut attached to the bridge. That is for the position sensor reed switches I’ve previously described.

The turntable fully assembled.

The turntable fully assembled.

Scenery

In addition to finishing the turntable I am doing as much scenicking as possible while I have this module on its own on a work table. As I am doing this I am reaping a bonus from my modular design: the ability to take a module and place it on a work table for 360 degree access at chair height.

I'm using CadRail's layers to record information. Here I've recorded feeder positions (in red) and turnout servo positioning data.

Module 1, Lower Level

 

Referring to the drawing of this part of the layout above, I decided to add a small mountain in the space between the yard at the top and the  two legs of the reversing loop at the bottom.  This creates a view block that isolates the yard into its own little world.

I also decided to create a couple of roads using Woodland Scenic’s Road System paving tape and Smooth-It pavement material. The system works pretty well. I do recommend viewing their video tutorials for instruction in using the system, which you will find on the product pages.

Creating an access road at the Red Bluffs Yard.

Creating an access road at the Red Bluffs Yard.

After removing the forming tape, you are left with this:

The road at Red Bluffs with forming tape removed.

The road at Red Bluffs with forming tape removed.

You’ll see that the road includes a driveway and parking lot at the top of the picture, and another driveway at the bottom that will lead to a gravel parking lot. These are provisions for future structures I have planned –a multi-unit rooming house for railroad workers at the top and a yard office at the bottom. I also created a road on the opposite side of the module, running between the legs of he reversing loop as an access road to the roundhouse / turntable complex.  I figure the employees need some way to get to and from work!

The mountain was made from several layers of foam insulation glued together then carved to a rough shape. I glued the foam shape to the layout, then covered the whole thing in plaster cloth. Then I selected some rock molds and cast a few rocks. After gluing the rocks to the mountain  (Attach rocks with wet plaster? Forgetaboutit! Liquid Nails for Projects makes attaching hydrocal rocks to another surface a snap, with its strong tack and immediate hold), I filled holes and blended the rocks into the terrain with Sculptamold. I painted everything except the rocks the medium tan I’m using as a base color, then painted the rocks themselves with a combination of iron oxide and earth tones. I glued down some earth blend and other ground foams — and, voilà, the red bluffs were born.

The Red Bluffs

The Red Bluffs

What’s Next?

More scenicking, of course.  But it is getting to be time to go underneath the module again and install more of the electronics, including controller hardware for the 9 turnout servos and the controller package for the turntable / roundhouse.

Until then, happy railroading!

Basic Signaling for a Small Layout

Continuing with the theme of controlling a small layout with an UNO, I thought I’d accept my own challenge from the last post and talk about how one might implement signals on a small layout as I did on the Test Loop.

Signals on the Test Loop

While I was actively testing block occupancy detection on the test loop, I set up three sets of signals as part of that effort. I wanted to both test some off-the-shelf signals from Tomar and take a crack at building my own searchlight signals using BLMA unlit signal heads. The former turned out to work well, but because they are wired for common anode, they sent me on a quest to tame common anode wiring. The latter also came out well, once I learned how to reliably solder magnet wire to SMD micro LEDS!

Block and Signal layout on the Test Loop

Block and Signal layout on the Test Loop

I did this primarily to see the block detection system working (block detection is also shown on on my programmable control panel, but that is another story) as a train moves around the track.  You can see it in action in this video—note that only the locomotive is detectable by the block occupancy detection system; the rolling stock is not set up for detection.

Since the test loop is just an oval with a single turnout and siding, the system is fairly simple.  As you watch the train go around the oval you will see signals change state as the train moves in and out of blocks, and as the turnout changes state.  The logic is imperfect in a few cases but good enough to show the various parts of the system working as a whole under the control of an UNO, which was the point of the exercise.

A Framework for ABS

Automatic Block Signalling (ABS) is straight forward and prototypical for late nineteenth / early twentieth century railroads. ABS signals are autonomous and react to block occupancy and turnout status; the red (next block obstructed), yellow (a subsequent block is obstructed) and green (no obstruction) indicators are near universal. Typical implementations handle blocks in groups of three or four, depending on how far ahead the system sensors extend.

Because each signal is an autonomous object that responds to specific environmental conditions, ABS lends itself well to a data-oriented approach. As with turnouts in the previous post, the best starting point is to devise a data structure that will encapsulate and represent everything that needs to be known about each signal in your system. Here is what I came up with for the test loop (see this post for an explanation of my Duino nodes, and this post for the addressing system in use).

typedef struct SIGNAL_DEF {
  byte type; // bit mask indicating available signal aspects
             // bit 1 = Red; bit 2 = Green; bit 3 = Yellow)
             // 1=R; 2=G; 3=RG; 4=Y; 5=RY; 6=GY; 7=RGY
             // 3 and 7 are the two types on the test loop
  nodeAddress addr; // base address of the Duino node for this signal
  byte R_ID; // pin/bit id for red indication
  byte G_ID; // pin/bit id for green indication
  byte Y_ID; // pin/bit id for yellow indication
  
  // data elements for running the signal
  byte state; // current signal state
  T_ALIGN *turnouts; // these turnouts must be aligned as defined to get SIGNAL_GREEN
  byte numTurnouts;
  byte *following; // additional blocks ahead (depends on direction signal faces)
  // watched for occupancy resulting in SIGNAL_YELLOW caution   
  byte numFollowing; 
};

By now you should recognize that this is my preferred approach to dealing with complex, interactive objects in the system.  As always, I define a compound data structure (the structure contains other structures as elements, in this case the T_ALIGN and NODEADDRESS types)  to collect all relevant data for each signal. Feel free to reinvent any of this — the point is to collect all necessary data in one place for each signal.

“T_ALIGN *turnouts”  is an example of pointer notation which allows for an array of zero (empty array) or more of the respective types; the “numTurnouts” element indicates how many items the T_ALIGN array contains. The “byte *following” and “numFollowing” do the same thing for a list of subsequent block IDs that are watched for occupancy.

Here is the declaration of a signals array from the Test Loop encapsulating all the signals in use, using the data types discussed. Notice how structures and arrays within the SIGNAL_DEF structure are defined inside their own curly braces:

// Signals definitions and data
SIGNAL_DEF signals[NUM_SIGNALS] = {
  {3, {3, 0}, 0, 1, -1, SIGNAL_OFF,{0, ALIGN_DIVERGENT}, 1,{2}, 1 },
  {3, {3, 0}, 2, 3, -1, SIGNAL_OFF,{0, ALIGN_MAIN}, 1, {2}, 1 },
  {7, {1, 0}, 0, 1,  2, SIGNAL_OFF,{}, 0, {0}, 1},
  {7, {0, 0}, 0, 1,  2, SIGNAL_OFF,{0, ALIGN_DIVERGENT}, 1, {}, 0 },
  {3, {0, 0}, 3, 4, -1, SIGNAL_OFF,{0, ALIGN_MAIN}, 1,{2}, 1}
};

Signal logic is handled by one function that gets called at the end of each loop cycle on the UNO, after block occupancy has been established.

void refreshSignals() {
  // First pass, set Stop (RED) state; default is GREEN
  // from block occupancy or turnout states
  for(int i = 0; i < NUM_SIGNALS; i++){ // for each signal
    // default state
    int state = SIGNAL_GREEN;
    SIGNAL_DEF sig = signals[i];
    for(int j = 0; j < max(sig.numTurnouts, sig.numBlocks); j++){ 
      if(j < sig.numTurnouts){
        // if the turnout is in motion OR 
        // if turnout alignment does not equal the required alignment
        if(turnout[sig.turnouts[j].id].is_moving || 
            turnout[sig.turnouts[j].id].alignment != sig.turnouts[j].align){
         state = SIGNAL_RED;
        } 
      }
      if(j < sig.numBlocks){ // for each linked block in the SIGNAL_DEF
        if(blocks[sig.blocks[j]].occ){ // if occupied
          state = SIGNAL_RED;
        }
      }
    }
    setSignalBits(i, state);
  }
  
  // Second pass to set caution states on
  // signals that support it and are currently set to GREEN
  
  for(int i = 0; i < NUM_SIGNALS; i++){ // for each signal
    SIGNAL_DEF sig = signals[i];
    if(bitRead(sig.type, 2)){ // if the signal supports the caution state
      if(sig.numFollowing > 0 && sig.state == SIGNAL_GREEN){
        // check occupancy of following block(s) if any
        for(int j = 0; j < sig.numFollowing; j++){
          if(blocks[sig.following[j]].occ){
            setSignalBits(i, SIGNAL_YELLOW);
          }
        }
      }
    }
  }
  // Refresh the nodes to show signals in their updated state
  nodeRefresh();
}

void setSignalBits(int signalID, byte signalState) {
  SIGNAL_DEF sig = signals[signalID];
  if (sig.state != signalState) {
    signals[signalID].state = signalState;
    byte nodeBits = nodeGet(sig.addr);
    switch (signalState) {
      case SIGNAL_OFF:
        if(bitRead(sig.type, 0)) bitWrite(nodeBits, sig.R_ID, LOW);
        if(bitRead(sig.type, 1)) bitWrite(nodeBits, sig.G_ID, LOW);
        if(bitRead(sig.type, 2)) bitWrite(nodeBits, sig.Y_ID, LOW);
        break;
      case SIGNAL_RED:
        if(bitRead(sig.type, 0)) bitWrite(nodeBits, sig.R_ID, HIGH);
        if(bitRead(sig.type, 1)) bitWrite(nodeBits, sig.G_ID, LOW);
        if(bitRead(sig.type, 2)) bitWrite(nodeBits, sig.Y_ID, LOW);
        break;
      case SIGNAL_GREEN:
        if(bitRead(sig.type, 0)) bitWrite(nodeBits, sig.R_ID, LOW);
        if(bitRead(sig.type, 1)) bitWrite(nodeBits, sig.G_ID, HIGH);
        if(bitRead(sig.type, 2)) bitWrite(nodeBits, sig.Y_ID, LOW);
        break;
      case SIGNAL_YELLOW:
        if(bitRead(sig.type, 0)) bitWrite(nodeBits, sig.R_ID, LOW);
        if(bitRead(sig.type, 1)) bitWrite(nodeBits, sig.G_ID, LOW);
        if(bitRead(sig.type, 2)) bitWrite(nodeBits, sig.Y_ID, HIGH);
        break;
    }
    nodeSet(sig.addr, nodeBits);
  }
  return;
}

void setSignal(int signalID, byte signalState) {
  setSignalBits(signalID, signalState);
  nodeRefresh();
}

For more in-depth discussion of my Duino Node devices, node functions and how they are used,  see Adding Signals to the Test Loop and Adding Signals to the Test Loop Part 2.

The idea here is that the logic of the signal system is executed in the refreshSignals() function. That function, in turn, calls setSignalBits() to interface with the hardware, using the hardware specific Duino Node functions to  drive the hardware.

How to Integrate Signals into Your Small Layout

Adding signals to your small layout consists of two basic steps: 1) setup your signal hardware so that it can be turned on and off in some way; either by direct connection to your UNO or using a shift register chain along similar lines to what I do with Duino Nodes. The choice of common anode vs. common cathode wiring is yours to make, but will depend on how your signal gear is wired. 2) Integrate signal handling in the sketch using turnout state and (if you have it) block occupancy data. Call your signal logic function at the end of each iteration of the main loop, and let that function interact with the signal hardware. Your signal logic should be in one place, and should be written as an “abstraction” that doesn’t know how to change signal display, but relies on other hardware specific functions to do that job.

Tomar Signals

Tomar N Scale Signals

I consider signals to be the most basic form of animation you can add to your layout to bring it to life. Its a little bit of trouble, but I hope you can see its really not hard.  The advantage of the Arduino approach over a hardware/hardwired approach (eg, connecting signals to the outputs of a stand alone block occupancy device) is the flexibility you gain in implementing signals while keeping wiring to an absolute minimum. Adding Absolute Permissive Block signalling is just as matter of additional logic to the sketch for the stretch of track you are trying to protect. Even full CTC functionality can be readily supported by responding to messages from a CTC control panel or system.

You’ll be amazed that how much work a single UNO can actually do for you.

Running a Small Layout with an Uno

Arduino Uno R3

Arduino Uno R3

A reader on another thread had questions about running multiple turnouts on a small layout with an Uno. Primarily he wants to control turnouts with a control panel and feedback indicators.  I thought that his needs are pretty typical for small layouts, and would be a good example for others planning and building on a similar scale.

So this post is bottom-up exercise in planning and implementing single UNO control on a small layout. I hope it will be helpful in planning and building your layout.

The Requirements

The layout has 5 turnouts that will be controlled with push buttons. Control is toggle-style: each button push causes the turnout to toggle between positions. Turnouts are run by micro servos. The control panel will have a layout map with turnout push buttons and LED position indicators.

First Decisions

The UNO is the first board many of us encounter and is certainly up to the task of managing 5 turnouts and a control panel, with capacity to spare. There are other Arduino boards suitable for model railroading use; but the UNO is cost-effective and easy to work with.

That said, the issue you have to contend with eventually is the number of connections required to support all the devices and LEDS that will be attached to the microcontroller.

Arduino boards provide three different types of connections/pins:

  • Digital: digital pins are basic on/off binary connections. In output mode they are either fully on (emitting 5 volts, with a max current of 40 mA) or off. In input mode they read the incoming current as either HIGH (on) or LOW (off). When used as inputs, digital pins may need pull-up or pull-down resistors so that they will function correctly.
  • Digital PWM: some, but not all, digital pins are also capable of PWM – pulse width modulation.  The output of a PWM pin, if not fully on or off, is a series of pulses that cause the output to to on a percentage of the time.  The pulses are used to control servos and other PWM devices. PWM with LEDS lets you vary their brightness between 0 and 100%, supporting a variety of interesting lighting effects.
  • Analog: Analog pins are primarily used to read sensors that produce a variable output. Pin inputs are fed to the on-board ADC (analog-to-digital converter) for conversion to a number between 0 and 1024. Current and temperature sensors are example of analog devices read through analog pins / ADC. What you may not know about analog pins is that they can also be used as basic digital pins.

It is essential in early planning to determine all the devices to be connected to the microcontroller and the type of connection each requires to determine what connection issues you will need to resolve. In some cases, going to the UNO’s bigger cousin, the MEGA, will solve connection limits.  But even the MEGA has limits. In some cases it makes sense to use pin-multiplying techniques using external chips to drive banks of LEDS, servos or other devices, even when you otherwise have enough pins.

A Connection Plan

The UNO has 14 digital connections, numbered 0 to 13, of which 6 (pins 3, 5, 6, 9, 10, and 11 ) are PWM. It also has 6 analog connections that can be used as digital connections with digitalRead() and digitalWrite() when referenced in the sketch as A0 through A5. That is a grand total of 20 digital pins, of which 6 are PWM.

Of those, two pins are generally off limits on an UNO: digital pins 0 and 1. They are Serial RX and TX respectively, and should be avoided for other uses on any UNO where you expect to use the USB interface — that would be most of the time. On boards without the built-in USB, pins 0 and 1 are fair game.

For five servos we need five digital pins. Even though PWM is used to control servos, the Arduino servo library creates the necessary pulses on any digital pin. However, using the library disables PWM functionality on pins 9 & 10, so some of the UNO’s native PWM capacity is sacrificed in any case.

For the five turnout control buttons we need five basic digital pins. For the control panel indicators, assuming one LED for each leg of each turnout, we need 10 basic digital pins.

That means we need 20 connections; but with pins 0 & 1 reserved for the USB interface, we’re short 2 connections. Many would want to use bi-color red/green LEDS so the state of each leg is continuously shown. That would require 10 additional basic digital connections.

Need Connections? No Problem!

That’s OK. Its exactly what I expected to happen when I started in on this exercise. Both inputs and outputs can be multiplied with external chips and boards; multiplying the basic digital outputs is far and away the easiest to implement, because the circuits are simple and the compiler includes native software support without add-on libraries.

I would use shift registers to control all the control panel indicators. That reduces the connection load on the UNO to just 3 connections for all LED indicators, no matter how many you end up with. With that, and the 10 pins needed to read the buttons and control the servos, the total digital pins requirement is 13. That leaves 5 available pins, one analog and up to three digital PWM, for other uses.

There is a great tutorial on controlling LEDs with shift registers, and chaining multiple registers together, on the Arduino website. That tutorial is mandatory if you are unfamiliar with shift registers; the circuit(s) shown are what you will be using for control panel LED indicators. The balance of this post assumes the basic knowledge contained in that tutorial.

Build A Control Board

Use a shift register chain to run your panel indicators. I use a TI 74HC595 chips that I buy from DigiKey. At less than $.50 each in lots of 10, they are a bargain. $5.00 worth of chips supports 80 outputs. Its the cheapest way I know of to extend the capabilities of an Arduino and run a lot of low current devices.

Decide how many shift registers you need — the 74HC595 has 8 outputs — and create a board based on the tutorial circuits to hold the chips and provide connection points for your LEDS. A single LED for each leg of each turnout (to show which leg is open to traffic) will need 10 connections—use two shift registers (use the two-chip circuit in the tutorial). Add a third chip (after the tutorial you will know how to do that) and your connection count rises to 24, enough to support red/green bi-color LEDS on each turnout leg on the panel. With 4 connections left, who knows what else you might light up?

Each push button will need a 10kΩ pull-down resistor connecting its pin to ground.  The purpose of the pull-down resistor is to drain stray current and keep the pin LOW unless the button is pushed and full current flow is applied.  See the diagram below. The resistor should be placed as close to the pin as possible.

Servo Control by Button

Basic Servo Control by Button

Power Issues

While you can run one or two servos off the power supplied by the UNO’s +5 volt pin, more servos than that would exceed the board’s power handling capabilities. Accordingly, you will need to supply power to the servos from a separate power source. VERY IMPORTANT: the ground for the servo power source must be tied to UNO ground or the servos will not work correctly.

One Sketch To Run it All

Alright. The control panel is built and wired; the servos are installed (see this post for my latest methods) and connected to power and the UNO. What you need now is a sketch to run the control panel and the servos.

Here is a demonstration sketch to get you started:

//////////////////////////////////////////
//
// Small Layout turnout control
// Demonstration Sketch
//
//////////////////////////////////////////

#include <Servo.h> // include the Servo library

////////////////////////////////////////
//
// Definitions
//
////////////////////////////////////////

////////////////////////////////////////
// Basic parameters; adjust for your actual setup
#define NUMBER_OF_TURNOUTS 5
#define NUMBER_OF_SHIFT_REGISTERS 3
#define STEP_DELAY 70  // servo movement step delay, in milliseconds
///////////////////////////////////////

///////////////////////////////////////
// Data Structures
///////////////////////////////////////

//////////////////////////////////////
// TURNOUT_DEF holds all configuration
// information about turnouts and panel LEDS
//////////////////////////////////////
typedef struct TURNOUT_DEF {
  uint8_t button_pin; // Digital or analog pin for the button associated with this turnout
  uint8_t servo_pin; // Digital pin for the servo associated with this turnout
  int pos_main; // servo position for the MAIN leg, in degrees
  int pos_div; // servo position for the DIVERGENT leg, in degrees
  int panel_LED_main_green; // The position(s)of panel LEDS in the shift register chain
  int panel_LED_main_red; // Example assumes a bi-color (red/green) LED for each turnout leg
  int panel_LED_div_green; // modify these elements to reflect the actual LEDS you are using
  int panel_LED_div_red;
};

/////////////////////////////////////
// TURNOUT_DATA is wrapper structure holding
// both configuration and runtime data for turnout operation
/////////////////////////////////////
typedef struct TURNOUT_DATA {
  TURNOUT_DEF data; // configuration
  bool is_moving;
  byte alignment;
  int pos_now;
  int target_pos;
  unsigned long last_move;
};

// Alignment state values
#define ALIGN_NONE 0
#define ALIGN_MAIN  1
#define ALIGN_DIVERGENT 2


// pin ids for shift register chain controlling panel LEDS
#define LATCH_PIN 7
#define CLOCK_PIN 8
#define DATA_PIN 9

//////////////////////////////////////////
//
// Global variables
//
//////////////////////////////////////////

//////////////////////////////////////////
// TURNOUT_DATA Array
// * A0, A1, etc refer to analog pins which are used for buttons in this example
// * Replace pos_main (93) and pos_div (117) with real values for each turnout
// * LEDS are identified by their output position in the shift register chain;
// the identifier is a number between 0 and (NUMBER_OF_SHIFT_REGISTERS * 8) - 1. 
// Example assumes LEDS are connected to shift register outputs sequentially 
// from the first output of first register. You can connect LEDS to any output in
// any order; just set the identifiers accordingly.
//
// Only the TURNOUT_DEF part of the TURNOUT_DATA structure has to be initialized here; 
// The remaining elements are managed internally and are initialized automatically
//////////////////////////////////////////

TURNOUT_DATA turnouts[NUMBER_OF_TURNOUTS] = {
  {{A0, 2, 93, 117, 0, 1, 2, 3}},
  {{A1, 3, 93, 117, 4, 5, 6, 7}},
  {{A2, 4, 93, 117, 8, 9, 10, 11}},
  {{A3, 5, 93, 117, 12, 13, 14, 15}},
  {{A4, 6, 93, 117, 16, 17, 18, 19}}
};

// servo objects
Servo servos[NUMBER_OF_TURNOUTS];

// array to hold shift register state bytes
byte panel_LEDS[NUMBER_OF_SHIFT_REGISTERS];

void setup() 
{
  // Setup pins for shift register chain
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
    
  // initialize each turnout 
  for(int i = 0; i < NUMBER_OF_TURNOUTS; i++){
    // attach the servo
    servos[i].attach(turnouts[i].data.servo_pin);
    // set the pin mode for the button pin
    pinMode(turnouts[i].data.button_pin, INPUT);
    // test and position the turnout by moving
    // to divergent then to main positions
    servos[i].write(turnouts[i].data.pos_div);
    turnouts[i].pos_now = turnouts[i].data.pos_div;
    setTurnout(i, ALIGN_MAIN);
    }
} // end of setup

void loop() 
{ 
  // get elapsed milliseconds at loop start
  unsigned long currentMillis = millis();

  // loop through the turnouts array
  for(int i = 0; i < NUMBER_OF_TURNOUTS; i++){
    if (turnouts[i].is_moving) {
      // if sufficient time has elapsed since the last move
      if ( (currentMillis - turnouts[i].last_move) >= STEP_DELAY ) {
        // move the turnout one degree
        turnouts[i].last_move = currentMillis;
        if (turnouts[i].pos_now < turnouts[i].target_pos) { // if the new angle is higher
          servos[i].write(++turnouts[i].pos_now);
        } else {  // otherwise the new angle is equal or lower
          if (turnouts[i].pos_now != turnouts[i].target_pos) { // not already at destination
            servos[i].write(--turnouts[i].pos_now);
          }
        }
      }
      // if target position reached, stop turnout motion
      if (turnouts[i].pos_now == turnouts[i].target_pos) {
        turnouts[i].is_moving = false;
        turnouts[i].last_move = 0;
        setIndicators(i);
      }
    } else {
      // if a turnout is NOT in motion, check to see if its button is pressed
      int button_state = digitalRead(turnouts[i].data.button_pin);
      if(button_state == HIGH){
        // toggle position
        if(turnouts[i].alignment == ALIGN_MAIN){
          setTurnout(i, ALIGN_DIVERGENT);
        } else {
          setTurnout(i, ALIGN_MAIN);
        }
      }
    }
  }
}// end of main loop

////////////////////////////////////////////////////////////////
// Supporting Functions
////////////////////////////////////////////////////////////////

void setTurnout(int id, int align){
    // Set indicators to show turnout in motion
    turnouts[id].alignment = ALIGN_NONE;
    setIndicators(id);
    // Set values to trigger motion on next loop iteration
    switch(align){
        case ALIGN_MAIN:
          turnouts[id].is_moving = true;
          turnouts[id].last_move = 0;
          turnouts[id].target_pos = turnouts[id].data.pos_main;
          turnouts[id].alignment = ALIGN_MAIN;
          break;
        case ALIGN_DIVERGENT:
          turnouts[id].is_moving = true;
          turnouts[id].last_move = 0;
          turnouts[id].target_pos = turnouts[id].data.pos_div;
          turnouts[id].alignment = ALIGN_DIVERGENT;
          break;
      }
}

void setIndicators(int id){
  switch(turnouts[id].alignment){
    case ALIGN_NONE: // means the turnout is in motion and not aligned
      panelWrite(turnouts[id].data.panel_LED_main_red, HIGH);
      panelWrite(turnouts[id].data.panel_LED_main_green, LOW);
      panelWrite(turnouts[id].data.panel_LED_div_red, HIGH);
      panelWrite(turnouts[id].data.panel_LED_div_green, LOW);
      break;
    case ALIGN_MAIN:
      panelWrite(turnouts[id].data.panel_LED_div_green, LOW);
      panelWrite(turnouts[id].data.panel_LED_div_red, HIGH);
      panelWrite(turnouts[id].data.panel_LED_main_green, HIGH);
      panelWrite(turnouts[id].data.panel_LED_main_red, LOW);
      break;
    case ALIGN_DIVERGENT:
      panelWrite(turnouts[id].data.panel_LED_div_green, HIGH);
      panelWrite(turnouts[id].data.panel_LED_div_red, LOW);
      panelWrite(turnouts[id].data.panel_LED_main_green, LOW);
      panelWrite(turnouts[id].data.panel_LED_main_red, HIGH);
      break;
  }
}
/////////////////////////////////////////////////
// Shift Register Functions
/////////////////////////////////////////////////
void panelWrite(int id, byte state) {
  int reg = floor(id / 8);
  int pos = id % 8;
  bitWrite(panel_LEDS[reg], pos, state);
  panelRefresh();
}

void panelRefresh(){
  // Prepare to shift by turning off the output
  digitalWrite(LATCH_PIN, LOW);
  // shift all bits out in MSB (most significant bit first) order
  for(int i = (NUMBER_OF_SHIFT_REGISTERS - 1); i>=0; i--) {
    // shift out the bits
    shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, panel_LEDS[i]);
  }
  // turn on the output to activate
  digitalWrite(LATCH_PIN, HIGH);
}

The sketch compiles into a compact package leaving plenty of memory and resources for additional functionality.

The main loop is built around a simple multitasking model, allowing you to control task timing and balance multiple competing tasks.  In this case, the main benefit of this methodology is control of the movement rate of turnout servos. On my test loop this methodology allows block occupancy detection to work in the background along with signal logic.

UP995 at Signal 34. Dual Searchlight Signals, Scratch Made with BLMA Signal Heads.

UP995 at Signals 3 & 4 on the Test Loop. Dual Searchlight Signals, Scratch Made with BLMA Signal Heads.

Troubleshooting

If you build the circuits accurately, everything should work out of the box (as it were). I am an obsessive tester — so I test things at critical stages as I build them.  Build and test your shift register circuits on a breadboard first, before soldering everything to a prototyping board.

To test the sketch I set up a simulation on a breadboard.

To test the sketch for this post I set up a 3 servo simulation on a breadboard.

Getting the connections to the UNO correct is key. If the LEDs don’t light at all, check all three connections, plus power connections; LEDS are polarized, so make sure the anodes are connected to incoming power and the cathodes to ground. Tracing power flow with a multi-tester should help you find problem areas quickly.

If your LEDs light but alternately flash odd/even, you probably reversed the LATCH_PIN and CLOCK_PIN connections.

For 3 or more servos, you must have an independent power supply to power them. BE SURE TO CONNECT GROUND FROM THE SERVO POWER SUPPLY TO ARDUINO GROUND.

Do Something with Unused Outputs

Old style hard wiring, without the help of a microcontroller, is a messy business at best, which tends to limit what you can do. DCC can help bridge the gap, but layout control is something of an afterthought for DCC (it was designed for locomotive control only) and is, frankly, awkward to use (my opinion; your mileage may vary).

To get the kind of functionality we have here without Arduinos — turnout control with a synchronous control panel — it would have to be hard wired. Or you could connect a full computer and run JMRI; that would require DCC (plus stationary decoders for the turnouts and a USB->DCC interface) to work . You would have to use stall-motor type turnout motors or add microcontrollers (Peco now sells a “smart” turnout system using servos and custom controllers) to interface with servo motors. So if you want to use servos instead of stall-motors, you can go Peco or do it the Arduino way from the start. As much as I appreciate Peco’s efforts here, the openness of the Arduino platform is a big part of what makes it useful and cost-effective.

Adding another function to a small layout — lets say a signal to protect a turnout — is a matter of connecting the signal leads to unused outlets and writing some code to run it.  If you’ve gotten this far, you’ll spend far more time thinking about exactly how the signal should run in conjunction with the turnout it is protecting, than you will connecting the device and adding code to the sketch.  Once you get into this way to doing things, I guarantee you’ll never look back.

So what will it be? Signals?  A fire simulation (using PWM and LEDS)? A lighted structure? Let your imagination run wild!


UPDATE

I starting working with shift registers a while back.  They are so effective my habit is to always use shift registers with LEDs, such as for signals, structure lighting and control panel applications.  The habit is so ingrained that I forget to mention the other important reason for using them: power management.

The power handling capability of an UNO is limited to 40 mA per pin and 400 mA for the entire board. LEDs typically draw between 20 and 30 mA.  So if you are directly powering 20 LEDs from an UNO, you are exceeding its power handling capacity and will burn out the board.

In the example given in the post, no more than half the LEDs well be lit at any one time so we are unlikely to exceed the 400 mA limit overall. A few more lit LEDS, though, would put it over the top.  Shift registers duck the problem altogether because each register is powered—and supplies power to connected devices—independently.  Other than the total load on your power supply, adding devices/lights to shift registers or even adding additional registers, puts no significant power load on the UNO.

Above I mentioned that an independent power supply is needed to run the servos.  From a “best practices” perspective, one should always power external devices with an independent power supply. Arduino’s current handling limits are tight; always using external power supplies avoids that problem.


UPDATE

Several readers asked if I have a fritzing image of the 3 servo demo.  I did not, but I put one together for those who might find this helpful.

3 Servo Demo

This circuit is intended to work with the above sketch, with the turnouts variable shortened to 3 elements instead of 5:

TURNOUT_DATA turnouts[NUMBER_OF_TURNOUTS] = {
  {{A0, 2, 93, 117, 0, 1, 2, 3}},
  {{A1, 3, 93, 117, 4, 5, 6, 7}},
  {{A2, 4, 93, 117, 8, 9, 10, 11}}
};

Always cross check all connections on a circuit like this against appropriate data sheets before powering it up for the first time! Be sure to connect the ground of your Arduino to the ground of your external power supply.

Adding a Turntable to the L&NC

This is the third installment in a series about the build out of Module 1, lower level of the L&NC. Step 1 was to install the basic wiring trunks and connection points, create track power distribution nodes then connect track feeders to the nodes. In Steps 2 & 3 I tested and corrected the track installation and installed servos at each of nine turnouts. Step 4 on this module is to install a turntable.

In this installment I will be introducing my fellow model railroaders to Actobotics system of robotic parts and supplies. If you are interested in creating kinetic components for your layout or diorama, you want to know about Actobotics.

Where are the Kits?

The plan for the L&NC has included a turntable since the earliest iterations. After all, what good is a roundhouse without a turntable to go with it? Way back when I bought the roundhouse (in the 90’s), Walthers also offered a 120′ turntable kit in the Cornerstone series. I had one at one time, but it did not survive multiple moves.

Roughed In Turntable

Roughed In Turntable

When I went looking for available kits and materials, the old Walthers kit was nowhere to be found and that there were few other choices in N scale. A new motorized turntable kit in N scale from Walters is due this fall.  It looks like a good kit—with an additional module it is USB controllable —but at $349 list price it is unaffordable for my project. In any case, it was not on my radar when I started thinking about turntables. The cheaper Kato, Bachmann and Atlas motorized kits are a little too toy-like for my tastes. As to unmotorized turntable kits, there are few choices in N and nothing in the 120′ class that I need to fit the roundhouse.

So I was going to have to do this from scratch. Exactly how that would be accomplished was a mystery.

The Pit

I always figured I could fabricate a bridge; but the pit looked like a problem only an injection molded plastic kit could solve.

But then it occurred to me that I could make a pit with a plywood base (same 1/4″ material as used to deck the layout frame) and styrene strip material to form the sides.

Building the Turntable Pit with Styrene Strips glued to a plywood base.

Building the Turntable Pit with Styrene Strips glued to a plywood base.

Using circle cutting and plunge routing attachments for my Dremel, I cut a 9″ plywood circle out of the base material I had on hand. I cut some .020″ styrene sheet into strips about 3/4″ wide.

I started by adhering a course of styrene around the edge of the plywood circle with medium viscosity gap-filling CA. After the first course was complete and the CA set, I laminated two additional courses of styrene to the first one to build up the thickness and rigidity of the pit wall.

The circle cutter left a tiny brad hole at the exact center of the circle, making it easy to cut a centered 1/2″ hole with a Forstner bit.  Why 1/2″? Because that is the outside diameter of a standard Actobotics bearing for 1/4″ OD tubing. A Forstner bit is precise enough that the hole will snugly hold an Actobotics bearing without glue or mechanical fasteners.

The Bridge

The basic bridge structure was an easy bash from two Micro Engineering 80′ Deck Girder bridge kits.

Two 80' bridge kits provided all the material needed for the basic bridge structure.

Two 80′ bridge kits provided all the material needed for the basic bridge structure.

One kit provided the center section of the bridge girders; the other provided material for four tapered end pieces required to complete the girders. Both kits contributed cross pieces. I found a set of pdf drawings of a 60′ turntable and used that as a guide to creating my bridge. After the basic bridge was assembled, I added a support plate with a 1/4″ hole to receive the top of the 1/4″ OD brass tube I’m using for the main drive shaft.

bridge-with-prototype-plans

The assembled bridge, including the shaft support plate in the center. The prototype plans are for a much smaller turntable, but were helpful nonetheless.

 

Checking the fit of the bridge in the pit.

Checking the fit of the bridge in the pit.

The Mechanism

My original concept for moving the bridge was to directly attach a small stepper motor to a shaft extending through the base from the bridge. A small 400 step (per 360 degree rotation) motor looked promising but there was no way to run wires up the shaft. Same problem with using a servo—most hobby servos are limited to 180 degrees of rotation because of position sensing; servos without stops and position sensing gear can rotate 360 degrees. But servos without position sensing are not useful where accuracy matters. For precision, a stepper motor is the way to go.

To  feed wires down a hollow shaft center for bridge track power and other purposes I have to offset the motor from the drive shaft. That necessitates a geared drive; but also creates the opportunity to to increase the positioning precision. So I started looking at off-the-shelf robotics gear.

I quickly homed in on Actobotics products available from ServoCity.com and Sparkfun.com. Its a very versatile line of structural and mechanical parts with standardized sizing and mounting patterns.

Great Stuff, but you’re on your own….

Unlike a lot of electronics gear for Arduino, Actobotics products do not come with tutorials. One useful exception is Sparkfun’s video on stepper motor mounts which helped sort that out.  Otherwise, its a struggle for a newbie to know what parts you need to get started, much less how they work best together. It doesn’t help that model railroading is not on their list of standard applications!

In the end I simply had to buy a bunch of plausible parts and try putting things together. A few orders later I figured out a mounting and gearing arrangement that works, and can be easily replicated by anyone who cares to try.

The Parts

  1. Actobotics Channel

    Actobotics Channel

    Channel.  The physical core of the Actobotics system are the channels and extrusions from which structures can be created. Aluminum channel comes in a range of lengths—from 1.5″ to 48″—pre-punched with holes that match the standard mounting patterns used in the system. I chose a 12″ channel to serve as the “spine” of the turntable structure to hold the pit, the mechanism and providing the means to mount the assembly to the layout.

  2. Stainless steel 'D' shaft.

    Stainless steel ‘D’ shaft.

    Shafts. Shaft sizing is tricky because it determines what parts can be attached to the shafts.  1/4″ OD turned out to be optimal for what I need.  For the hollow drive shaft connected to the bridge I’m using ordinary 1/4″ brass tube.  Actobotics products are precision milled; ordinary 1/4 brass tubing is not—it  tends to be slightly oversized. To size the drive shaft I chucked it into a drill and, while running the drill at a low speed, used 800 grit emery paper to slim it down to 1/4″ OD. In addition to the bridge drive shaft, I needed two solid 1/4″ D shafts to form a drive train transmitting motion from the stepper motor to the main drive shaft. Sizing was tricky; it took some trial and error to get the desired results.

  3. Bevel gears.

    Bevel gears.

    Gears. I settled on an 80 tooth hub gear for the drive shaft. It is driven by a much smaller 16 tooth pinion gear, providing a 5:1 gear reduction, implying a minimum positioning resolution with a 200 step/revolution stepper motor of .36 degrees. The pinion gear attaches to an idler shaft mounted parallel to the main drive shaft.  Since the stepper is mounted perpendicular to the main and idler shafts, I need a pair of bevel gears to interface the idler with the stepper output shaft, forming a complete drive train.

    Hub gears, with mounting hubs attached.

    Hub gears, with mounting hubs (left clamping, right set-screw) attached.

    Pinion gear attached to a 'D' shaft.

    Pinion gear attached to a ‘D’ shaft.

  4. Flanged bearings.

    Flanged bearings.

    Bearings, Hubs, Collars and Other Minutiae. You will need a bunch of bearings (mine are 1/2″ OD, 1/4″ ID), and some bearing to spacers to go with them. Flanged bearings are generally the most useful.  The main gear needs a mounting hub to connect it to the drive shaft, and that hub has to be the clamping type (set screw type will distort the brass tube). Collars are needed to stabilize both the idler and main drive shafts. Don’t forget screws and a ball-end hex key.

  5. Stepper motor.

    Stepper motor.

    The Stepper Motor and its Mount. Stepper motors are tricky to select because they are all over the map in terms of voltage, amperage, steps per revolution, size (form factor), etc. I chose a 200 step motor from Sparkfun that runs at 12 volts, but a relatively low amperage (.33A), and for which a mount is available. The motor’s shaft is 5mm, so a 5mm to 1/4″ shaft coupler is needed.  Additional parts needed to mount the motor included standoffs, a single channel flat bracket and a couple of attachment brackets. Finally, I needed a bearing block to support the shaft attached to the stepper output.

  6. A Slip Ring. The shaft on the top rotates.

    A Slip Ring. The shaft on the top rotates.

    The Slip Ring. When you look at the strategies in past decades for supplying power to a turntable bridge, you typically see some kind of wiper system for supplying power to moving feeders. Thankfully it is no longer necessary to build such contraptions; instead what you need is a slip ring.  Slip rings have incoming leads on the stationary side, and outgoing leads on a rotating shaft on the moving side. Internally they have a high durability wiper system for transferring power from the stationary to the moving sides. The only downside of the Sparkfun slip ring collection is that it is not configured for the Actobotics system; the mount for the stationary part does not match an Actobotics mounting pattern.  So, as you’ll see, I had to compromise a little to make it work. I bought the 6 wire/ 2 Amp version.

  7. Position Sensors. Stepper motors are very precise. Theoretically, once a stepper driven mechanism is set up and calibrated, positioning should be accurate indefinitely.  But the mechanism could get knocked out of alignment; and there should be some tools to aid calibration initially and to make sure the bridge is in its calibrated position at the start of a session. So I needed a position sensor of some sort. What I decided to do was place a pair of magnetic reed switches at a spot on the pit (behind the wall, out of sight).  One end of the bridge has a hidden magnet that will trip the switches. When the magnet is between and tripping both switches, the bridge will be in position 0, and all other positions can be calibrated from there. It should work …. but we will see.

Step 4: Assemble and install the turntable.

It took several months, and a lot of trial and error, to come up with a working turntable mechanism. So, getting back to the project in hand, it is time to assemble and install the turntable into the layout.

But first, a little detailing ….

The pit after some painting and detailing.

The pit after some painting and detailing.

It occurred to me that once installed the pit would be difficult to detail. So, having disassembled the mechanism to prepare it for installation, I painted the interior of the pit, detailing the circular support/drive rail with cinders and spreading a little earth blend ground foam on the pit floor.  After placing a few weeds, I declared it ready to install.

Underside of the pit, showing the sensors, stand-offs for attaching to the Actobotics system, and a solid shaft I used for alignment during assembly.

Underside of the pit, showing the magnetic reed sensors (bottom), stand-offs epoxy’d to the pit for attaching it to the Actobotics system, and a solid shaft I used for alignment during assembly.

Here is “the big picture” of how all the parts go together:

The completed turntable mechanism, with mounting blocks attached.

The completed turntable mechanism, with mounting blocks attached.

The mounting method may seem complex, but it is necessary to minimize the space occupied by the mechanism. My early attempts, which required putting the main gear beneath the channel, were too tall for the available space. Putting the gears between the pit and the channel turned out to be the most space efficient arrangement; the only one that allowed enough space for the spinner. With this assembly installed, there remains 1/2″ clearance between the spinner and the table top the layout is resting on. Excellent.

Turntable drive detail.

Turntable drive detail.

You’ll notice that the output side of the spinner is slightly off-center relative to the main drive shaft.  The output shaft of the spinner it too large to fit inside the brass tube, so it has to be mounted independently. As I mentioned above, the mounting holes on the spinner do not match the Actobotics mounting system. However, I found that I could anchor the spinner using two of the three mounting holes; the trade-off is that it is not perfectly centered.

Is this a problem? Probably not.  The turntable moves slowly, so the wires should not be unduly flexed by the off-center mount; the output side spins freely, so little stress will be exerted on the wires.  As always, of course, we will see under actual use conditions.

The turntable from below after installation.

The turntable from below after installation.

The installed turntable, ready for the next stage of build-up.

The installed turntable, ready for the next stage of build-up.

What’s Next?

Next step is to lay the remaining track for the roundhouse/turntable area, build up the rim of the pit, then build the deck and central arch of the bridge and finish bridge wiring. From there its on to the electronic controls and the initial calibration of the system. Along the way I’ll also be doing the basic scenicking (a little sculptamold, paint and ground foam) of this zone while I have easy access without taking the layout apart.

Until then, happy railroading!

 

 

 

Wiring the L&NC — Adding Servos

This it the second installment in a series (Part 1) about the build out of Module 1, lower level of the L&NC. This series covers all the basic steps I’m following to install all wiring, electronics and mechanical objects throughout the layout, so in subsequent phases of this project I can focus on the unique aspects of other modules. Step 1 was to install the basic wiring trunks and connection points, create track power distribution nodes then connect track feeders to the nodes.

Step 2

I tested the track with one of my most challenging locomotives—a Broadway Limited EMD E8A DCC with Sound. I say “challenging” because it has two 3-axle trucks, a long wheelbase and no big capacitors to buffer track power, making it susceptible to derailment or operational problems with faulty track.  If this loco can run a stretch of track problem-free, it’s good track!  Naturally I found and fixed a few (cough …. ) places where there were problems.

Correcting track problems for flawless running.

Correcting track problems for flawless running.

After tinkering with the problem zones, I realized that the “course of least resistance” was to rip out and re-lay a few short strips of track. The caulk adhesive track laying method makes this a piece of cake: after cutting the rails, run a long bladed knife under the track section you want to remove and its free in seconds. The ease of fixes really adds incentive to be fussy at this stage and get it right. I had everything in good order in a couple of hours including drying time for fresh caulk adhesive.

Step 3

The next step is to mount the servos running the 9 turnouts on this level. Installing them now is the best way to ensure they have the space they need for normal operation and maintenance.

test loop servo 1 in place

Servo mount on the Test Loop.

I’ve previously done a basic demo of the mounting method I used on the Test Loop. I chose that particular mounting method because it simplified the connection between the servo and the rod connected to the turnout; the rod fits easily but snugly through the hole in the horn. In this mounting method the base plate of the mount provides the fulcrum or pivot point for the rod.

Turnout operation on the Test Loop continues to be 100% reliable. The only issue with that mounting method is that noise is transmitted to the layout through the mount, so servo operation is noisier than it should be.

A New Low Noise, Low Profile Servo Mount

In addition to noise control, the equipment space beneath the layout level is about 1 3/4 deep, the width of a 1″ x 2″ frame member. For both protection and aesthetics, I need all equipment to fit inside that space. The old servo mounting method requires more space than that, and would stick out below the edge of the frame.

The solution is to mount the servo on its side, allowing the horn to rock a rod back and forth setting the turnout points. Several obvious ways to do that came to mind.  But I also wanted to make sure that alignment of the servo is easy and foolproof.

Layout Prep

I drilled holes for the turnout rods when I laid the track. To make installation and alignment of the servo easy, I  drilled the holes so that the rod would be in the 90 degree position (perpendicular to the plywood base) with the points aligned one direction or the other. I tried to keep the holes through the plywood small to serve as fulcrums  (mostly succeeded), then widened the holes in the foam and roadbed beneath the track so the rod can swing between the two positions of the points.

I inserted a 3″ rod cut from 1/16″ music wire (you need a hard wire cutter for this stuff) and made sure the positioning of the rod was correct. The advantage of the music wire is that it can flex without deforming, allowing you to apply pressure to the points.

Fulcrum pad for turnout 5

Fulcrum pad for turnout 5

That said, 1/16″ music wire I’m using is fairly stiff in the short lengths needed here. It is stiffer than the wire typically use with stall motor turnouts, stiff enough that it easily overcomes resistance from the built in springs in the Peco turnouts I’m using on this layout. Many people recommend removing the positioning springs in Peco and similar turnouts, since they can cause turnout movement to pause while overcoming resistance of the spring. Using 1/16″ music wire the servo is able to move a sprung turnout smoothly. I took a few springs out before I realized it was completely unnecessary.

 

At this point I made sure the rods could move the points properly.  In a few cases, the fulcrum hole was a little too large because of sloppy drilling; the easy solution is to fit a plywood plate with a fulcrum hole in the right diameter over the old one.

Servo Prep

Preparing the servo requires testing and setting it to the 90 degree position. Then with the case on its side, orient the output shaft to either the right or left (which ever you need for a given situation) and install a standard single arm horn pointing up, perpendicular to the case.

The offset shaft allows you to select the right orientation. In either case, 0 degrees is 1/4 turn to the right of center, 180 degrees is 1/4 turn left of center.

The offset shaft allows you to select the right orientation. In either case, 0 degrees is 1/4 turn to the right of center, 180 degrees is 1/4 turn left of center.

Here’s a sketch to test the servo by running it from 0 to 180 degrees (the travel of a typical micro servo), then to the required mid-point position:

#include <Servo.h> 
 
Servo myservo;  // global servo object
int midpoint = 90;  // in degrees
int pin = 6; // control pin

void setup() 
{ 
  int i;
  myservo.attach(pin);
  myservo.write(0);
  delay(1000);
  for(i = 1; i <= 180; i++){
    myservo.write(i);
    delay(50);
    }
  delay(1000);
  for(i = 180; i > midpoint; i--){
    myservo.write(i);
    delay(50);
    }
  delay(1000);
  myservo.write(midpoint);
} 
 
void loop() 
{ 
  
}

Mr. Hot Glue Strikes Again

If only micro servos came with side mounting tabs instead of just the ones on top. They do not. To do a side mount like I’m doing you need only fabricate two parts: 1) a strip of .080″ styrene, cut to about 2″ x .5″ and predrilled with holes at each end to accommodate mounting screws; and 2) a piece of 1/32″ brass wire with a loop (a little over 1/16″ inside diameter), a short straight section (about equal to the thickness of a servo horn) leading to a 90 degree bend and a longer straight section.

These two parts allow you to side mount a micro servo, and connect its horn to a rod.

These two parts allow you to side mount a micro servo, and connect its horn to a rod.

First I remove any labels on the side of the servo that attaches to the mount, then I put a dab of hot glue on the servo and press the styrene strip against it, centering and aligning the strip with the built in fins. Then I put a bead of hot glue down each side of the servo where it joins the mounting strip. Its probably overkill, but I want the servos mounted solidly and resistant to torsional stress.

Micro servo glued to a side mounting strip.

Micro servo glued to a side mounting strip.

The brass wire is threaded through the top hole of the horn, with the long leg aligned along the length of the back side of the horn and the loop parallel to the base. Apply dabs of hot glue to adhere the wire to the horn.

Here you can see how the brass wire is glued to the horn, and the turnout rod is threaded through the loop.

Here you can see how the brass wire is threaded through the top hole glued to the horn, and the turnout rod is threaded through the loop. Note the clearance between the rod and the horn.

Installation

Here a servo has been aligned to the motion of the rod, marked on the plywood.

Here a servo has been aligned to the motion of the rod, marked on the plywood.

First it is necessary to determine the plane along which each rod moves; that will depend on the angle of the turnout relative to the rest of the layout.

With the plane of motion marked and the rod set to its 90 degree position, I slip the rod through the loop glued to the horn and place the servo next to the rod, parallel to the plane of the rod. Placing just a little tension on the rod and maintaining even clearance between the horn and rod, I mark and drill mounting holes for the servo. Sometimes its easiest to do one mounting hole, attach the servo at that hole then—after adjusting positioning—drilling the second hole and completing the mount.

After a test fitting, I remove the servo and apply a strip of 3/4″ Rubber Splicing Electrical Tape (Scotch #2242) to the bottom of the mount to inhibit noise transmission. I remount the servo in its final position.

Servos 1, 2 and 9 mount in their final positions.

Servos 1, 2 and 9 in their final positions.

Problems at Turnout 4

The location for turnout 4's servo.

The location for turnout 4’s servo.

Turnout 4’s rod comes down at an awkward spot, close to a frame cross member, the edge of the layout, the main wiring bundle and three feeder sets. The feeders are the main problem; I should have located them further from the turnout. While moving the feeders is an option, I also realized that the fulcrum hole was too large so I was going to have to put in a new fulcrum plate anyway.

The solution I came up with was to fabricate a mounting plate from a couple of pieces of scrap plywood, that would provide a new fulcrum and cantilever over the feeders. Everything screws down so that it is removable and repairable.

Mounting solution for Turnout 4.

Mounting solution for Turnout 4.

 

Turnout 4 Servo Mounted. The horn swings UP in this photo, so the wire bundle below the servo does not interfere.

Turnout 4 Servo Mounted. The horn swings UP to change the position of the points (as oriented in this photo), so the wire bundle below the servo does not interfere. Its snug but effective.

Gathering Servo Positioning Data

At this point it makes sense to test each servo and determine the positions for each point setting.  Each servo installation is different so each one will have unique settings for turnout positions. The size or “looseness” of the fulcrum hole and the length of the rod are the main factors affect servo positioning

On this module and level it takes approximately 20 – 30 degrees movement of the servo to change the points. Once I determined that, it was easy to calculate initial positions that could then be fine tuned for individual installations.

I'm using CadRail's layers to record information. Here I've recorded feeder positions (in red) and turnout servo positioning data.

I’m using CadRail’s layers to record information. Here I’ve recorded feeder positions (in red; turntable area not yet built) and turnout servo positioning data (green). The two positions are “S”, straight or Mainline; and “D”, divergent.

The goal is to have the points firmly pressed against the rails at each end of their travel, without making the servo work so hard it gets noisy. A light hum while the servo is holding a position is OK; but it should not become a loud buzz and the servo should not feel “buzzy” to the touch. Try moving the turnout manually – you should get resistance to moving the points against the servo, but the flex of the music wire should still be evident. Tinker with this for a while and you’ll start to get a feel for it.

Next step is a big one: install the turntable mechanism, install the Roundhouse base, lay track, and so on. Until then, happy railroading!

 

 

 

Wiring Module 1 of L&NC

After a long pause, I’ve starting in on wiring the L&NC by doing the basic wiring on module 1, lower level (each module has two levels). Module one is the largest of the three modules at 54″ long, and is the intended entry point for all the incoming power and control connections. Everything I do here is intended to set the methods and practices for the remaining modules.

Applying Lessons from the Past

Test Loop wiring. Block sensors were added in Phase 2. Phase 3 signals and lighting in progress.

Test Loop wiring. Block sensors were added in Phase 2. Phase 3 signals and lighting in progress.

My early layouts were primitive from a wiring perspective (and other perspectives…. but lets not dwell on that ….). I never did get into the suitcase connector thing, but the old layouts were wired using a single bus pair connecting to feeders every few feet.  Not much to it, so there was not much to organize. Like many layouts, the wiring was somewhat exposed and disorganized underneath.

While I was experimenting on the Test Loop, the wiring was built up in layers without a master plan.  For example, the power distribution from a central barrier strip was fine at first, but later it became necessary to create secondary distribution points to support various power needs. I ended up with wiring  less than optimally organized. On the plus side, I found that small circuit boards with banks of screw terminals are an excellent way to distribute power to to individual feeders or devices.

The other major lesson from the test loop is that it is a pain in the rail to add a major electronic component after everything else has been wired up. Major components should be sited and accounted for before interconnecting anything.  Components that move—e.g., servos, turntable mechanisms or whatever—get priority to ensure they get the placement and space they need — everything else has to adapt to their needs. In this case I will be installing the servos and the turntable early … but I’m getting ahead of myself again.

Special Issues with the L&NC

The L&NC has to be wired with a different aesthetic given that it is intended to be dissembled, moved and reassembled reliably. I am using the Digitrax Empire Builder DCC system, along with my Arduino-based independent control system and a multi-voltage power system supporting the layout — with power provided by a converted computer power supply. Computer power supplies can furnish 300 or more watts of fully regulated power at 12, 5 and 3.3 volts, perfect for every need other than track power.

L&NC Lower Level, Version 2

L&NC Lower Level

The lower level of module 1 (left-most module in the drawing) is fairly complex to wire because it contains the Red Bluffs Yard and the Roundhouse/Turntable complex. Including the feeders needed for the Roundhouse/Turntable area, 24 track feeders with current sensors have to be managed.

Yikes! That’s a lot of feeders for a 54″ x 27″ layout section! Its because of the yard, Roundhouse and turntable. Each roundhouse bay, the turntable bridge and any adjacent track segments adjoining the turntable all need individual feeders; the turntable is a reversing segment. Then each leg of the yard needs feeders, plus the base feeder for the ladder, to support occupancy detection and reliable operation. The main track loops each have two feeders. It all adds up…

So there is a lot more wiring in the L&NC than might be considered normal, and it has to be secure and well organized.

Step 1

With most track laid (I’m deferring the Roundhouse area until the turntable is installed) and the locations of all feeders and turnouts established, the first step is to place the primary distribution nodes then route, terminate and secure the main power bundle, the track bus and the LOCONET bus.

Connection Panel

Connection Panel

At the far left end of the module I placed a connection panel fabricated from styrene. There are four connections:

 

  1. Main power (4 conductors: 12 volt, 5 volt & 3.3 volt, plus ground);
  2. track power connection (2 conductors: Track A & Track B);
  3. LOCONET RJ12 jack (6 conductors); and
  4. Ethernet RJ45 jack (8 conductors).

 

 

My primary color coding scheme:

  • Black = Ground
  • Yellow = 12 volts DC
  • Red = 5 volts DC
  • Blue = 3.3 volts DC
  • Green = Track A (right-hand rail)
  • Violet = Track B (left-hand rail)

For the two power connections, I’m using Anderson Powerpole 15 Amp connectors to create polarized, color coded connectors. 2 connector and 4 connector brackets secure the receiving connection to the panel. I really love these connectors because they are easy to assemble (provided you invest in the crimper), come in a wide variety of colors, allowing you to assemble plugs and matching receptacles that can only be connected together one way. I get my supplies from Powerwerx.com.

Connection Panel, Inside

Connection Panel, Inside

From the panel, the wires run a few inches to a barrier strip.  Here the power is split – one branch going off to feed other parts of this level, with another branch heading to the upper level.

To supply power to the upper level I installed a short piece of PVC pipe from underneath the module, running up next to the corner post, terminating above the bottom edge of the upper level (when installed) I ran wires from the barrier strip up through the pipe, leaving 8″ or so extra cable extending from the top of the pipe, terminated with Powerpole plugs coded for the two power bundles.

Center Barrier Strip

Center Barrier Strip

To get to other areas of the lower level I ran cables from the first barrier, along the edge of the frame, using screw-in eyelets every 6 – 8 inches to channel the cables.  I terminated the cable run at a strip near the middle of the module, then ran an addition  set of cables from the middle strip to the right hand edge of the module.  Leaving 8 inches of slack, I terminated the cables with Powerpole plugs to be connected to a panel on the adjoining module.

The RJ11 jack has leads that I soldered to a six wire cable, then run that cable along the front edge of the module, opposite the power cables, to the location of a Digitrax UP5 universal panel (attached to the frame pending the addition of fascia), terminating the cable with an RJ11 plug as required to attach to theUP5. I fabricated another cable to run from the UP5 to interconnect bundle at the right side of the module.

Track power distribution block with ACS712 current sensors.

Track power distribution block with ACS712 current sensors.

The Ethernet jack on the panel is one end of a prefabricated cable available from Adafruit Industries. The other end will connect to a small Ethernet switch which will install at a later date. From there I’ll  make custom Ethernet cables (my crimper does both 6 and 8 conductor connectors) to fit where needed. Ethernet wiring will be added after I know the location of the Arduinos it will be supporting. I have an 8 port unit ready for the task.

I set up two track power distribution areas with a current sensor for each block, one on each end of the module. At this point I’m keeping the center area clear pending installation of the turntable. A third distribution area will be setup in that area to service the Roundhouse, turntable, service  and approach tracks.

Wiring phase 1

The big picture: wiring step 1 done

Now that the basic wiring is in, its time — finally! — to test the track installation, and fix what ever problems I find before moving on to the next step.  Until then, happy railroading!

Correcting track problems for flawless running.

Correcting track problems for flawless running.