{"id":942,"date":"2016-10-29T14:52:20","date_gmt":"2016-10-29T21:52:20","guid":{"rendered":"http:\/\/thenscaler.com\/?p=942"},"modified":"2021-02-08T10:01:54","modified_gmt":"2021-02-08T18:01:54","slug":"running-a-small-layout-with-an-uno","status":"publish","type":"post","link":"https:\/\/thenscaler.com\/?p=942","title":{"rendered":"Running a Small Layout with an Uno"},"content":{"rendered":"<div id=\"attachment_181\" style=\"width: 310px\" class=\"wp-caption alignright\"><a href=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/11\/Uno.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-181\" class=\"wp-image-181 size-medium\" src=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/11\/Uno-300x199.jpg\" alt=\"Arduino Uno R3\" width=\"300\" height=\"199\" srcset=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/11\/Uno-300x199.jpg 300w, https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/11\/Uno.jpg 600w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-181\" class=\"wp-caption-text\">Arduino Uno R3<\/p><\/div>\n<p>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.\u00a0 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.<\/p>\n<p>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.<\/p>\n<h4>The Requirements<\/h4>\n<p>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.<\/p>\n<h4>First Decisions<\/h4>\n<p>The <a href=\"https:\/\/www.arduino.cc\/en\/Main\/ArduinoBoardUno\" target=\"_blank\" rel=\"noopener\">UNO<\/a> 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 <a href=\"https:\/\/www.arduino.cc\/en\/Main\/Products\" target=\"_blank\" rel=\"noopener\">other Arduino boards<\/a> suitable for model railroading use; but the UNO is cost-effective and easy to work with.<\/p>\n<p>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.<\/p>\n<p>Arduino boards provide three different types of connections\/pins:<\/p>\n<ul>\n<li><strong>Digital<\/strong>: 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.<\/li>\n<li><strong>Digital PWM<\/strong>: some, but not all, digital pins are also capable of <a href=\"https:\/\/www.arduino.cc\/en\/Tutorial\/PWM\" target=\"_blank\" rel=\"noopener\">PWM &#8211; pulse width modulation<\/a>.\u00a0 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.\u00a0 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.<\/li>\n<li><strong>Analog<\/strong>: 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.<\/li>\n<\/ul>\n<p>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&#8217;s bigger cousin, the <a href=\"https:\/\/www.arduino.cc\/en\/Main\/ArduinoBoardMega2560\" target=\"_blank\" rel=\"noopener\">MEGA<\/a>, will solve connection limits.\u00a0 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.<\/p>\n<h4>A Connection Plan<\/h4>\n<p>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.<\/p>\n<p>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 &#8212; that would be most of the time. On boards without the built-in USB, pins 0 and 1 are fair game.<\/p>\n<p>For five servos we need five digital pins. Even though PWM is used to control servos, the <a href=\"https:\/\/www.arduino.cc\/en\/Reference\/Servo\" target=\"_blank\" rel=\"noopener\">Arduino servo library<\/a> creates the necessary pulses on any digital pin. However, using the library disables PWM functionality on pins 9 &amp; 10, so some of the UNO&#8217;s native PWM capacity is sacrificed in any case.<\/p>\n<p>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.<\/p>\n<p>That means we need 20 connections; but with pins 0 &amp; 1 reserved for the USB interface, we&#8217;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.<\/p>\n<h4>Need Connections? No Problem!<\/h4>\n<p>That&#8217;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.<\/p>\n<p>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.<\/p>\n<p>There is a <a href=\"https:\/\/www.arduino.cc\/en\/Tutorial\/ShiftOut\" target=\"_blank\" rel=\"noopener\">great tutorial on controlling LEDs with shift registers, and chaining multiple registers together<\/a>, 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.<\/p>\n<h4>Build A Control Board<\/h4>\n<p>Use a shift register chain to run your panel indicators. I use a <a href=\"https:\/\/www.digikey.com\/product-detail\/en\/texas-instruments\/SN74HC595N\/296-1600-5-ND\/277246\" target=\"_blank\" rel=\"noopener\">TI 74HC595 chips that I buy from DigiKey<\/a>. 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.<\/p>\n<p>Decide how many shift registers you need &#8212; the 74HC595 has 8 outputs &#8212; 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\u2014use 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?<\/p>\n<p>Each push button will need a <a href=\"https:\/\/www.arduino.cc\/en\/Tutorial\/DigitalPins\" target=\"_blank\" rel=\"noopener\">10k\u03a9 pull-down resistor<\/a> connecting its pin to ground.\u00a0 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.\u00a0 See the diagram below. The resistor should be placed as close to the pin as possible.<\/p>\n<div id=\"attachment_235\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/12\/Servo-Control-by-Button.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-235\" class=\"wp-image-235 size-full\" src=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/12\/Servo-Control-by-Button.jpg\" alt=\"Servo Control by Button\" width=\"625\" height=\"638\" srcset=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/12\/Servo-Control-by-Button.jpg 625w, https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/12\/Servo-Control-by-Button-293x300.jpg 293w, https:\/\/thenscaler.com\/wp-content\/uploads\/2014\/12\/Servo-Control-by-Button-50x50.jpg 50w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><p id=\"caption-attachment-235\" class=\"wp-caption-text\">Basic Servo Control by Button<\/p><\/div>\n<h4>Power Issues<\/h4>\n<p>While you can run one or two servos off the power supplied by the UNO&#8217;s +5 volt pin, more servos than that would exceed the board&#8217;s power handling capabilities. Accordingly, you will need to supply power to the servos from a separate power source. <strong>VERY IMPORTANT<\/strong>: <em>the ground for the servo power source must be tied to UNO ground or the servos will not work correctly<\/em>.<\/p>\n<h4>One Sketch To Run it All<\/h4>\n<p>Alright. The control panel is built and wired; the servos are installed (see <a href=\"https:\/\/thenscaler.com\/?p=848\">this post for my latest methods<\/a>) and connected to power and the UNO. What you need now is a sketch to run the control panel and the servos.<\/p>\n<p>Here is a demonstration sketch to get you started:<\/p>\n<pre>\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/\n\/\/ Small Layout turnout control\n\/\/ Demonstration Sketch\n\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n#include &lt;Servo.h&gt; \/\/ include the Servo library\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/\n\/\/ Definitions\n\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Basic parameters; adjust for your actual setup\n#define NUMBER_OF_TURNOUTS 5\n#define NUMBER_OF_SHIFT_REGISTERS 3\n#define STEP_DELAY 70\u00a0 \/\/ servo movement step delay, in milliseconds\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Data Structures\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ TURNOUT_DEF holds all configuration\n\/\/ information about turnouts and panel LEDS\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ntypedef struct TURNOUT_DEF {\n\u00a0 uint8_t button_pin; \/\/ Digital or analog pin for the button associated with this turnout\n\u00a0 uint8_t servo_pin; \/\/ Digital pin for the servo associated with this turnout\n\u00a0 int pos_main; \/\/ servo position for the MAIN leg, in degrees\n\u00a0 int pos_div; \/\/ servo position for the DIVERGENT leg, in degrees\n\u00a0 int panel_LED_main_green; \/\/ The position(s)of panel LEDS in the shift register chain\n\u00a0 int panel_LED_main_red; \/\/ Example assumes a bi-color (red\/green) LED for each turnout leg\n\u00a0 int panel_LED_div_green; \/\/ modify these elements to reflect the actual LEDS you are using\n\u00a0 int panel_LED_div_red;\n};\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ TURNOUT_DATA is wrapper structure holding\n\/\/ both configuration and runtime data for turnout operation\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ntypedef struct TURNOUT_DATA {\n\u00a0 TURNOUT_DEF data; \/\/ configuration\n\u00a0 bool is_moving;\n\u00a0 byte alignment;\n\u00a0 int pos_now;\n\u00a0 int target_pos;\n\u00a0 unsigned long last_move;\n};\n\n\/\/ Alignment state values\n#define ALIGN_NONE 0\n#define ALIGN_MAIN\u00a0 1\n#define ALIGN_DIVERGENT 2\n\n\n\/\/ pin ids for shift register chain controlling panel LEDS\n#define LATCH_PIN 7\n#define CLOCK_PIN 8\n#define DATA_PIN 9\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/\n\/\/ Global variables\n\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ TURNOUT_DATA Array\n\/\/ * A0, A1, etc refer to analog pins which are used for buttons in this example\n\/\/ * Replace pos_main (93) and pos_div (117) with real values for each turnout\n\/\/ * LEDS are identified by their output position in the shift register chain;\n\/\/ the identifier is a number between 0 and (NUMBER_OF_SHIFT_REGISTERS * 8) - 1. \n\/\/ Example assumes LEDS are connected to shift register outputs sequentially \n\/\/ from the first output of first register. You can connect LEDS to any output in\n\/\/ any order; just set the identifiers accordingly.\n\/\/\n\/\/ Only the TURNOUT_DEF part of the TURNOUT_DATA structure has to be initialized here; \n\/\/ The remaining elements are managed internally and are initialized automatically\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nTURNOUT_DATA turnouts[NUMBER_OF_TURNOUTS] = {\n\u00a0 {{A0, 2, 93, 117, 0, 1, 2, 3}},\n\u00a0 {{A1, 3, 93, 117, 4, 5, 6, 7}},\n\u00a0 {{A2, 4, 93, 117, 8, 9, 10, 11}},\n\u00a0 {{A3, 5, 93, 117, 12, 13, 14, 15}},\n\u00a0 {{A4, 6, 93, 117, 16, 17, 18, 19}}\n};\n\n\/\/ servo objects\nServo servos[NUMBER_OF_TURNOUTS];\n\n\/\/ array to hold shift register state bytes\nbyte panel_LEDS[NUMBER_OF_SHIFT_REGISTERS];\n\nvoid setup() \n{\n\u00a0 \/\/ Setup pins for shift register chain\n\u00a0 pinMode(LATCH_PIN, OUTPUT);\n\u00a0 pinMode(CLOCK_PIN, OUTPUT);\n\u00a0 pinMode(DATA_PIN, OUTPUT);\n\u00a0\u00a0 \u00a0\n\u00a0 \/\/ initialize each turnout \n\u00a0 for(int i = 0; i &lt; NUMBER_OF_TURNOUTS; i++){\n\u00a0\u00a0\u00a0 \/\/ attach the servo\n\u00a0\u00a0\u00a0 servos[i].attach(turnouts[i].data.servo_pin);\n\u00a0\u00a0\u00a0 \/\/ set the pin mode for the button pin\n\u00a0\u00a0\u00a0 pinMode(turnouts[i].data.button_pin, INPUT);\n\u00a0\u00a0\u00a0 \/\/ test and position the turnout by moving\n\u00a0\u00a0\u00a0 \/\/ to divergent then to main positions\n\u00a0\u00a0\u00a0 servos[i].write(turnouts[i].data.pos_div);\n\u00a0\u00a0\u00a0 turnouts[i].pos_now = turnouts[i].data.pos_div;\n\u00a0\u00a0\u00a0 setTurnout(i, ALIGN_MAIN);\n\u00a0\u00a0\u00a0 }\n} \/\/ end of setup\n\nvoid loop() \n{ \n\u00a0 \/\/ get elapsed milliseconds at loop start\n\u00a0 unsigned long currentMillis = millis();\n\n\u00a0 \/\/ loop through the turnouts array\n\u00a0 for(int i = 0; i &lt; NUMBER_OF_TURNOUTS; i++){\n\u00a0\u00a0\u00a0 if (turnouts[i].is_moving) {\n      \/\/ if sufficient time has elapsed since the last move\n\u00a0\u00a0\u00a0\u00a0\u00a0 if ( (currentMillis - turnouts[i].last_move) &gt;= STEP_DELAY ) {\n        \/\/ move the turnout one degree\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[i].last_move = currentMillis;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (turnouts[i].pos_now &lt; turnouts[i].target_pos) { \/\/ if the new angle is higher\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 servos[i].write(++turnouts[i].pos_now);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\u00a0 \/\/ otherwise the new angle is equal or lower\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (turnouts[i].pos_now != turnouts[i].target_pos) { \/\/ not already at destination\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 servos[i].write(--turnouts[i].pos_now);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0 }\n      \/\/ if target position reached, stop turnout motion\n\u00a0\u00a0\u00a0\u00a0\u00a0 if (turnouts[i].pos_now == turnouts[i].target_pos) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[i].is_moving = false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[i].last_move = 0;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 setIndicators(i);\n\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0 } else {\n\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ if a turnout is NOT in motion, check to see if its button is pressed\n\u00a0\u00a0\u00a0\u00a0\u00a0 int button_state = digitalRead(turnouts[i].data.button_pin);\n\u00a0\u00a0\u00a0\u00a0\u00a0 if(button_state == HIGH){\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ toggle position\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(turnouts[i].alignment == ALIGN_MAIN){\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 setTurnout(i, ALIGN_DIVERGENT);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 } else {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 setTurnout(i, ALIGN_MAIN);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0 }\n\u00a0 }\n}\/\/ end of main loop\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Supporting Functions\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nvoid setTurnout(int id, int align){\n\u00a0\u00a0\u00a0 \/\/ Set indicators to show turnout in motion\n\u00a0\u00a0\u00a0 turnouts[id].alignment = ALIGN_NONE;\n\u00a0\u00a0\u00a0 setIndicators(id);\n\u00a0\u00a0\u00a0 \/\/ Set values to trigger motion on next loop iteration\n\u00a0\u00a0\u00a0 switch(align){\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 case ALIGN_MAIN:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].is_moving = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].last_move = 0;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].target_pos = turnouts[id].data.pos_main;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].alignment = ALIGN_MAIN;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 case ALIGN_DIVERGENT:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].is_moving = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].last_move = 0;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].target_pos = turnouts[id].data.pos_div;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 turnouts[id].alignment = ALIGN_DIVERGENT;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break;\n\u00a0\u00a0\u00a0\u00a0\u00a0 }\n}\n\nvoid setIndicators(int id){\n\u00a0 switch(turnouts[id].alignment){\n\u00a0\u00a0\u00a0 case ALIGN_NONE: \/\/ means the turnout is in motion and not aligned\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_main_red, HIGH);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_main_green, LOW);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_div_red, HIGH);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_div_green, LOW);\n\u00a0\u00a0\u00a0\u00a0\u00a0 break;\n\u00a0\u00a0\u00a0 case ALIGN_MAIN:\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_div_green, LOW);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_div_red, HIGH);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_main_green, HIGH);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_main_red, LOW);\n\u00a0\u00a0\u00a0\u00a0\u00a0 break;\n\u00a0\u00a0\u00a0 case ALIGN_DIVERGENT:\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_div_green, HIGH);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_div_red, LOW);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_main_green, LOW);\n\u00a0\u00a0\u00a0\u00a0\u00a0 panelWrite(turnouts[id].data.panel_LED_main_red, HIGH);\n\u00a0\u00a0\u00a0\u00a0\u00a0 break;\n\u00a0 }\n}\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Shift Register Functions\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid panelWrite(int id, byte state) {\n\u00a0 int reg = floor(id \/ 8);\n\u00a0 int pos = id % 8;\n\u00a0 bitWrite(panel_LEDS[reg], pos, state);\n\u00a0 panelRefresh();\n}\n\nvoid panelRefresh(){\n\u00a0 \/\/ Prepare to shift by turning off the output\n\u00a0 digitalWrite(LATCH_PIN, LOW);\n\u00a0 \/\/ shift all bits out in MSB (most significant bit first) order\n\u00a0 for(int i = (NUMBER_OF_SHIFT_REGISTERS - 1); i&gt;=0; i--) {\n\u00a0\u00a0\u00a0 \/\/ shift out the bits\n\u00a0\u00a0\u00a0 shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, panel_LEDS[i]);\n\u00a0 }\n\u00a0 \/\/ turn on the output to activate\n\u00a0 digitalWrite(LATCH_PIN, HIGH);\n}<\/pre>\n<p>The sketch compiles into a compact package leaving plenty of memory and resources for additional functionality.<\/p>\n<p>The main loop is built around a <a href=\"https:\/\/thenscaler.com\/?page_id=661\">simple multitasking model<\/a>, allowing you to control task timing and balance multiple competing tasks.\u00a0 In this case, the main benefit of this methodology is control of the movement rate of turnout servos. <a href=\"https:\/\/thenscaler.com\/?p=684\">On my test loop this methodology allows block occupancy detection to work in the background along with signal logic<\/a>.<\/p>\n<div id=\"attachment_658\" style=\"width: 233px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/01\/UP995-at-Signal-34.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-658\" class=\"size-medium wp-image-658\" src=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/01\/UP995-at-Signal-34-223x300.jpg\" alt=\"UP995 at Signal 34. Dual Searchlight Signals, Scratch Made with BLMA Signal Heads.\" width=\"223\" height=\"300\" srcset=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/01\/UP995-at-Signal-34-223x300.jpg 223w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/01\/UP995-at-Signal-34-768x1033.jpg 768w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/01\/UP995-at-Signal-34-762x1024.jpg 762w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/01\/UP995-at-Signal-34.jpg 946w\" sizes=\"auto, (max-width: 223px) 100vw, 223px\" \/><\/a><p id=\"caption-attachment-658\" class=\"wp-caption-text\">UP995 at <a href=\"https:\/\/thenscaler.com\/?p=684\" target=\"_blank\" rel=\"noopener\">Signals 3 &amp; 4 on the Test Loop<\/a>. Dual Searchlight Signals, Scratch Made with BLMA Signal Heads.<\/p><\/div>\n<h4>Troubleshooting<\/h4>\n<p>If you build the circuits accurately, everything should work out of the box (as it were). I am an obsessive tester &#8212; so I test things at critical stages as I build them.\u00a0 Build and test your shift register circuits on a breadboard first, before soldering everything to <a href=\"http:\/\/amzn.to\/2dVyYF9\" target=\"_blank\" rel=\"noopener\">a prototyping board<\/a>.<\/p>\n<div id=\"attachment_960\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/Breadboarding-a-small-layout-control-system.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-960\" class=\"size-medium wp-image-960\" src=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/Breadboarding-a-small-layout-control-system-300x212.jpg\" alt=\"To test the sketch I set up a simulation on a breadboard.\" width=\"300\" height=\"212\" srcset=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/Breadboarding-a-small-layout-control-system-300x212.jpg 300w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/Breadboarding-a-small-layout-control-system-768x543.jpg 768w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/Breadboarding-a-small-layout-control-system.jpg 900w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-960\" class=\"wp-caption-text\">To test the sketch for this post I set up a 3 servo simulation on a breadboard.<\/p><\/div>\n<p>Getting the connections to the UNO correct is key. If the LEDs don&#8217;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.<\/p>\n<p>If your LEDs light but alternately flash odd\/even, you probably reversed the LATCH_PIN and CLOCK_PIN connections.<\/p>\n<p>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.<\/p>\n<h4>Do Something with Unused Outputs<\/h4>\n<p>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).<\/p>\n<p>To get the kind of functionality we have here without Arduinos &#8212; turnout control with a synchronous control panel &#8212; it would have to be hard wired. Or you could connect a full computer and run <a href=\"http:\/\/jmri.sourceforge.net\/\" target=\"_blank\" rel=\"noopener\">JMRI<\/a>; that would require DCC (plus stationary decoders for the turnouts and a USB-&gt;DCC interface) to work . You would have to use stall-motor type turnout motors or add microcontrollers (Peco now sells a<a href=\"http:\/\/www.peco-uk.com\/prodtype.asp?strParents=3309,3337&amp;CAT_ID=3363&amp;numRecordPosition=1\" target=\"_blank\" rel=\"noopener\"> &#8220;smart&#8221; turnout system using servos and custom controllers<\/a>) 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&#8217;s efforts here, the openness of the Arduino platform is a big part of what makes it useful and cost-effective.<\/p>\n<p>Adding another function to a small layout &#8212; lets say a signal to protect a turnout &#8212; is a matter of connecting the signal leads to unused outlets and writing some code to run it.\u00a0 If you&#8217;ve gotten this far, you&#8217;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.\u00a0 Once you get into this way to doing things, I guarantee you&#8217;ll never look back.<\/p>\n<p>So what will it be? Signals?\u00a0 A fire simulation (using PWM and LEDS)? A lighted structure? Let your imagination run wild!<\/p>\n<hr \/>\n<p>UPDATE<\/p>\n<p>I starting working with shift registers a while back.\u00a0 They are so effective my habit is to always use shift registers with LEDs, such as for signals, structure lighting and control panel applications.\u00a0 The habit is so ingrained that I forget to mention the other important reason for using them: power management.<\/p>\n<p>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.\u00a0 So if you are directly powering 20 LEDs from an UNO, you are exceeding its power handling capacity and will burn out the board.<\/p>\n<p>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.\u00a0 Shift registers duck the problem altogether because each register is powered\u2014and supplies power to connected devices\u2014independently.\u00a0 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.<\/p>\n<p>Above I mentioned that an independent power supply is needed to run the servos.\u00a0 From a &#8220;best practices&#8221; perspective, one should always power external devices with an independent power supply. Arduino&#8217;s current handling limits are tight; always using external power supplies avoids that problem.<\/p>\n<hr \/>\n<p><strong>As of 2021<\/strong>, a commercial port multiplier\/power management board is available for digital outputs! These boards, called <a href=\"http:\/\/beaglebay.com\/duinogear\/ldg-duinonodes\/\" target=\"_blank\" rel=\"noopener\">duinoNodes<\/a>, combine shift registers and power management components, providing the high current (up to 1\/2 amp on a single port) digital outputs a model railroader needs. To find out more, go to <a href=\"http:\/\/beaglebay.com\/duinogear\/ldg-duinonodes\/\" target=\"_blank\" rel=\"noopener\">Lew&#8217;s Duino Gear<\/a>.<\/p>\n<hr \/>\n<p>UPDATE<\/p>\n<p>Several readers asked if I have a fritzing image of the 3 servo demo.\u00a0 I did not, but I put one together for those who might find this helpful.<\/p>\n<div id=\"attachment_1114\" style=\"width: 620px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/3-servo-demo_bb.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-1114\" class=\"size-large wp-image-1114\" src=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/3-servo-demo_bb-1024x896.jpg\" alt=\"\" width=\"610\" height=\"534\" srcset=\"https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/3-servo-demo_bb-1024x896.jpg 1024w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/3-servo-demo_bb-300x263.jpg 300w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/3-servo-demo_bb-768x672.jpg 768w, https:\/\/thenscaler.com\/wp-content\/uploads\/2016\/10\/3-servo-demo_bb.jpg 1168w\" sizes=\"auto, (max-width: 610px) 100vw, 610px\" \/><\/a><p id=\"caption-attachment-1114\" class=\"wp-caption-text\">3 Servo Demo<\/p><\/div>\n<p>This circuit is intended to work with the above sketch, with the turnouts variable shortened to 3 elements instead of 5:<\/p>\n<pre>TURNOUT_DATA turnouts[NUMBER_OF_TURNOUTS] = {\n\u00a0 {{A0, 2, 93, 117, 0, 1, 2, 3}},\n\u00a0 {{A1, 3, 93, 117, 4, 5, 6, 7}},\n\u00a0 {{A2, 4, 93, 117, 8, 9, 10, 11}}\n};\n<\/pre>\n<p>Always cross check all connections on a circuit like this against <a href=\"http:\/\/www.ti.com\/lit\/ds\/symlink\/sn74hc595.pdf\" target=\"_blank\" rel=\"noopener\">appropriate data sheets <\/a>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.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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.\u00a0 I thought that his needs are pretty typical for small layouts, and would be a good example for others planning and building on a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":602,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[35,21,34,15],"tags":[22,44,52,31,39,37],"class_list":["post-942","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-electronics","category-layout-control","category-lighting-and-animation","category-planning","tag-arduino","tag-circuit-design","tag-layout-wiring","tag-micro-servo","tag-programming","tag-shift-register"],"_links":{"self":[{"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/posts\/942","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/thenscaler.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=942"}],"version-history":[{"count":26,"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/posts\/942\/revisions"}],"predecessor-version":[{"id":1961,"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/posts\/942\/revisions\/1961"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/thenscaler.com\/index.php?rest_route=\/wp\/v2\/media\/602"}],"wp:attachment":[{"href":"https:\/\/thenscaler.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=942"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thenscaler.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=942"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thenscaler.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=942"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}