Arduino - Points/turnout/accessory Control V2

4,378

5

28

Introduction: Arduino - Points/turnout/accessory Control V2

Updated 19 Oct 2021: new PCB v3 (Jan 2021) available with added memory push button to set the first turnout address.

PCB v3 version Jan 2021 also has a push button to store the accessory address. To use this on the finished assembly, hold this button while you select the required address from your DCC controller.


Updated 20 Jan 2021: On v2 version of the PCB (Oct 2019) Arduino Nano pin A6 may not work as designed (analog pin used to switch 5v)

I now provide the PCB for this project with a modification to make pin A5 feed the LED and to switch 5v to the h-bridge ICs.

[If you already have a V2 version (Oct 2019), please Modify the PCB as above]


Updated 13 Nov 2019: Added a new sketch to control 8 servos, 6 LED's and 2 flashing LED's

Updated 30 Oct 2019: I have added a new step for a servo points controller.


I now have a new PCB designed for this application - available from eBay from 19 Sep 2019.

PCB is identified as 'DCC turnouts / points Oct 2019' on the top surface of the PCB.

An Arduino Nano module provides 8 turnouts each configurable for momentary surface (or under base) mount or tortoise slow motion motor types, or for on/off switches (signals, station lighting, sounds etc)

Step 1: Arduino Sketches:

NB: In the Arduino Nano sketch, the NmraDCC library files must be version NmraDcc-1.2.1.zip - later versions will not work. Download here nmrdcc

Attached sketches for:

T1-T6 twin coil turnouts plus T7 T8 as switches
T1 - T8 twin coil turnouts
T9 - T16 twin coil turnouts


From an excellent tutorial by Geoff Bunza in the Model Railroad Hobbyist Magazine forum. It described how an Arduino Pro Mini (a low cost Arduino board) could be wired and programmed to respond to function keys on a DCC controller. This opens up a wide world of control options for animations, sound and other options on a DCC equipped model railroad.

I have made use of this circuit to capture DCC packets from my Arduino based Command Station (see DCC Command Station). The Command station may control up to 16 turnouts.

Basic Accessory decoder packet is : 0 10AAAAAA 0 1AAACDDD 0 EEEEEEEE 1

From analysing the packet used by Lenz (Compact / Atlas) for points control, I have used the following binary packet format for bytes 1 and 2 :
tunAddr = 1 //Accessory decoder address
Turnout 1a : 1000 0001 1111 1000
Turnout 1b : 1000 0001 1111 1001
Turnout 2a : 1000 0001 1111 1010
Turnout 2b : 1000 0001 1111 1011
Turnout 3a : 1000 0001 1111 1100
Turnout 3b : 1000 0001 1111 1101
Turnout 4a : 1000 0001 1111 1110
Turnout 4b : 1000 0001 1111 1111

tunAddr = 2
Turnout 5a : 1000 0010 1111 1000
Turnout 5b : 1000 0010 1111 1001
Turnout 6a : 1000 0010 1111 1010
Turnout 6b : 1000 0010 1111 1011
Turnout 7a : 1000 0010 1111 1100
Turnout 7b : 1000 0010 1111 1101
Turnout 8a : 1000 0010 1111 1110
Turnout 8b : 1000 0010 1111 1111

tunAddr = 3
Turnout 9a : 1000 0011 1111 1000
Turnout 9b : 1000 0011 1111 1001

etc

By manipulation of the binary packet, we can extract the turnouts required and send a pulse (t_on) of variable duration.

if (tunAddr == 1){
if ((((Msg->Data[1]) - 0xf8>>1) + 1) == 1 && (Msg->Data[1] & 0x01) == 1){ // f1a on
// pin 3
digitalWrite(FunctionPin1a, 1);
pulse = true;
t_on = 50; }

if ((((Msg->Data[1]) - 0xf8>>1) + 1) == 1 && (Msg->Data[1] & 0x01) == 0){ // f1b on
// pin 4
digitalWrite(FunctionPin1b, 1);
pulse = true;
t_on = 50; }

Step 2: Turnout Control - PCB and Components

Bill of Materials:

All components including PCB are available from eBay.

NB: Please use a on/off switch to supply power to the board. Plug in power supply first before switching on. This helps to protect sensitive points/turnouts e.g. side mounting with coils that are prone to burn out if an applied current is extended beyond normal pulse times.

1 off v2 PCB (no longer available on eBay)

Or, 1 off v3 PCB eBay item number 234244550455 (with memory function)

6 off Ceramic Capacitor; capacitance 100 nF; package 200 mil

1 off Capacitor Polarized variant pth1; package cpol-radial-100uf-25v

2 off Screw terminal - 2 pins pins 2; hole size 1.0mm,0.508mm; pin spacing 0.197in (5.0mm);

1 off 1kΩ Resistor bands 5; tolerance ±5%; pin spacing 400 mil;

1 off 1.5kΩ Resistor bands 5; tolerance ±5%; pin spacing 400 mil;

1 off 10kΩ Resistor bands 5; tolerance ±5%; pin spacing 400 mil;

2 off 4.7kΩ Resistor bands 5; tolerance ±5%; pin spacing 400 mil;

1 off Diode variant 1n4148;

8 off Screw terminal - 3 pins pins 3; hole size 1.0mm,0.508mm; pin spacing 0.137in (3.5mm);

1 off 5v reg Voltage Switching Regulator RECOM 5v 500mA;

1 off 0.1Ω 2W Metal Film Resistor; tolerance ±5%; pin spacing 11.5 mm;

1 off 6N137 IC chip label IC; pins 8; hole size 1.0mm,0.508mm; true; pin spacing 300mil; package DIP

2 off Generic female header - 15 pins; hole size 1.0mm,0.508mm; pin spacing 0.1in (2.54mm);; row single

17 off Diode variant pth; package diode-1n4001

4 off H-Bridge SN754410

1 off 3mm LED (any colour)

1 off Arduino Nano module (5v)

On v3 version of PCB Jan 2021, there is are 2 additional components:

1 off momentary TACT PCB Mount Switch Push Button 6x6x5mm

1 off 4.7kΩ Resistor

NB: For the memory function on this version V3 of the PCB (Jan 2021) , use Arduino sketch 'DCC_turnout_control_v2_t1_t8_momentary_jan_2021_memory.ino'

Step 3: Current Limit Control

Current sense circuit detects >2 amps. This triggers all outputs to off state and disables the sketch.
The LED will switch off.
You must clear the fault and reset the Arduino Nano before resuming points operations.

void current()
delay(2);
amp = 10.8 * analogRead(currentSense);
if (amp > 150){
Serial.print("current (mA) = ");
Serial.println(amp); //milli amps }

if (amp > 2000){ // approx 2 amps
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 1.1V) = 1.08mv per division
// 0.1 ohm resistor on current sense gives 200mv at 2 Amps or, 100mv per Amp
// 1.08 mv per div for Internal Ref of 1.1v : 100/1.08 = 92.6 divisions per 1000mA or 1 div = 10.8mA
// current = 10.8 * currentSense ; // mA

digitalWrite(enable, LOW); // disable the h-bridge IC's
digitalWrite(led, LOW); // turn LED off
Serial.println("Over current - Power off");
Serial.println(amp); //Amps
shut_down(); } //close all outputs
}

Step 4: Accessory Control

The Arduino sketch may be modified to include on/off switching or timed switching for control of lights, signals, etc. The SN544110 h-bridge can supply at least 250mA per output.
For configuration of on/off switches, remove the pulse logic and t_on :

if ((((Msg->Data[1]) - 0xf8>>1) + 1) == 4 && (Msg->Data[1] & 0x01) == 1){
// f8a on ; f8b off
// pin A3
digitalWrite(FunctionPin8a, 1);
digitalWrite(FunctionPin8b, 0); }
if ((((Msg->Data[1]) - 0xf8>>1) + 1) == 4 && (Msg->Data[1] & 0x01) == 0){
// f8b on ; f8a off
// pin A4
digitalWrite(FunctionPin8b, 1);
digitalWrite(FunctionPin8a, 0); }


The signal common wire is connected to the middle pin of connector f8a / f8b.
Remember, turnout / point motors are designed to activate on momentary applied voltage for around 25 milli-seconds.
Always be careful NOT to connect a turnout / point motor to this on / off pin as it will over heat and probably burn out.

Step 5: Tortoise Points/turnouts

The Arduino sketch may be modified to operate Tortoise slow motion motorised points.

The DC power connections are made to f1a and f1b (or any other output required)
The common middle pin connection is not required.
Alter the code for the output pin required to be on or off, for example for f1a (pin3) and f1b (pin 4):

if ((((Msg->Data[1]) - 0xf8>>1) + 1) == 1 && (Msg->Data[1] & 0x01) == 1){
digitalWrite(FunctionPin1a, 1); // motor on
digitalWrite(FunctionPin1b, 0); }

if ((((Msg->Data[1]) - 0xf8>>1) + 1) == 1 && (Msg->Data[1] & 0x01) == 0){
digitalWrite(FunctionPin1a, 0);
digitalWrite(FunctionPin1b, 1); // motor on (reversed)
}

If the stall current is <100 mA, there is no need to switch the motor off.

Step 6: Servo Points

I have attached a sketch for 8 servo points control, 6 LED's and 2 flashing LED's.
You will need to edit the variables etc to suit your application - e.g. angle of rotation and speed of operation

In the setup void of the sketch:

min_pos[3] = 35; max_pos[3] = 82; //D3 servo 1
min_pos[4] = 56; max_pos[4] = 90; // D4 servo 2
min_pos[5] = 35; max_pos[5] = 82; // D5 servo 3
min_pos[6] = 36; max_pos[6] = 100; // D6 servo 4
min_pos[7] = 55; max_pos[7] = 135; // D7 servo 5
min_pos[8] = 40; max_pos[8] = 110; // D8 servo 6
min_pos[9] = 55; max_pos[9] = 88; // D9 servo 7
min_pos[10] = 30; max_pos[10] = 84; // D10 servo 8

This sketch requires a simpler circuit with no need for h-bridge IC's - see diagram above.

The 5 volt regulator may need to be upgraded to a 1 amp version to handle the total servo current.

Be the First to Share

    Recommendations

    • Jewelry Challenge

      Jewelry Challenge
    • One Board Contest

      One Board Contest
    • Photography Challenge

      Photography Challenge

    28 Comments

    0
    alberth1
    alberth1

    5 weeks ago

    I cannot open the downloaded file of this instructable - It says the file is corrupted.
    Both adobe reader and sumatra do this.

    0
    BillC35
    BillC35

    Reply 5 weeks ago

    Hi, sorry to hear you are having difficulty in downloading files.
    Which file is corrupted ?
    I have checked using my laptop and find all files download fine.
    I can offer to send the files directly by email if you wish.
    My contact is : billc@john-lewis.com

    Best regards
    Bill

    0
    alberth1
    alberth1

    Reply 5 weeks ago

    The firmware files are fine but the download of the whole thing is where the problem is. It says it is zero bytes.

    0
    BillC35
    BillC35

    Reply 5 weeks ago

    I have refreshed the Instructable entry and I can now download the project.
    Please try again.
    Bill

    0
    alberth1
    alberth1

    Reply 5 weeks ago

    I still get the same:

    0
    alberth1
    alberth1

    Reply 5 weeks ago

    Thank you very much - that worked.
    I have ordered the PCB and while typing this the board has arrived.

    0
    monteirosanges
    monteirosanges

    Question 2 months ago on Step 6

    Boa Tarde. Onde obtenho VarSpeedServo.h ?
    Desde já, obrigado pela resposta.

    0
    rafael.barriel
    rafael.barriel

    Question 1 year ago on Introduction

    DCC_turnout_control_8servo6led2flash_nov_2019
    Good Morning:
    first of all congratulate him for the excellent work done.
    My question is: How can I connect a second arduino with address 17?
    I understand that you are using the first 16 addresses, but I need to connect a second arduino to control another 10 more turnouts and I don't know how to do it.
    I would appreciate a little help.
    Thanks a lot.

    0
    rafael.barriel
    rafael.barriel

    Answer 1 year ago

    Buenos días Bill:
    Con la última modificación todo está funcionando bien.
    Es el decodificador mas rápido que he encontrado en Internet y he probado unos pocos.
    Muchas gracias por su atención y su tiempo.
    Muy feliz año nuevo
    Rafael.

    0
    BillC35
    BillC35

    Answer 1 year ago

    Thanks for your interest in my project.
    To control address 17 onwards change lines in the code:
    From:
    addr1 = 1; // gives decoder address of 1 to 4
    addr2 = 2; // gives decoder address of 5 to 8
    addr3 = 3; // gives decoder address of 9 to 12
    addr4 = 4; // gives decoder address of 13 to 16
    To:
    addr5 = 1; // gives decoder address of 17 to 20
    addr6 = 2; // gives decoder address of 21 to 24
    addr7 = 3; // gives decoder address of 25 to 28
    addr8 = 4; // gives decoder address of 29 to 32


    From:
    if( (Msg->Data[0] == 0x81) || (Msg->Data[0] == 0x82) || (Msg->Data[0] == 0x83) ||(Msg->Data[0] == 0x84)){ //for Addr1 = 1, Addr2 = 2, Addr3 = 3, Addr4 = 4
    To:
    if( (Msg->Data[0] == 0x85) || (Msg->Data[0] == 0x86) || (Msg->Data[0] == 0x87) ||(Msg->Data[0] == 0x88)){ //for Addr5 = 5, Addr6 = 6, Addr7 = 7, Addr8 = 8

    Then amend each segment of code :
    From:
    if (MainAddr == addr1){ // T1 to T4
    To:
    if (MainAddr == addr5){ // T17 to T20
    ............
    From:
    if (MainAddr == addr2){ // T5 to T8
    To:
    if (MainAddr == addr6){ // T21 to T24
    .............
    etc
    if (MainAddr == addr7){ // T25 to T28
    if (MainAddr == addr8){ // T29 to T32


    Otherwise, the rest of the code remains the same.

    Bill

    0
    BillC35
    BillC35

    Reply 1 year ago

    Hi Rafael,

    Sorry I also had a senior moment in giving you the wrong instructions !
    Please change this part of the code:

    From:
    addr5 = 1; // gives decoder address of 17 to 20
    addr6 = 2; // gives decoder address of 21 to 24
    addr7 = 3; // gives decoder address of 25 to 28
    addr8 = 4; // gives decoder address of 29 to 32
    To:
    addr5 = 5; // gives decoder address of 17 to 20
    addr6 = 6; // gives decoder address of 21 to 24
    addr7 = 7; // gives decoder address of 25 to 28
    addr8 = 8; // gives decoder address of 29 to 32

    Bill

    0
    rafael.barriel
    rafael.barriel

    Answer 1 year ago

    Good night Bill:
    Thank you very much for your quick response, but unfortunately my servos are not working.
    apart from changing the lines of code that you told me, I have taken the liberty of also changing the following line to
    int addr5; int addr6; int addr7; int addr8; because there were errors when compiling, (addr5 not declared in this scope) etc.
    With the serial monitor, when giving a status change order to servo 17, I can see the following:
    Main Addr = 5
    DccMsg 3 133 249 124
    10000101
    11111001
    0
    1
    17
    turnout = 17
    tun = 1 (this value changes to 0 when I press again)
    Sorry to bother you, but at my age (68 years old), I've been a bit late to this technology and I hope I don't make it too difficult for you.
    Many thanks.
    Rafael.

    0
    kiwi64ajs
    kiwi64ajs

    1 year ago

    Bi Bill,
    I see you've used part of my NmraDcc library (I'm the original author) in your project, but you seem to have reinvented much of the wheel in decoding the DCC packets yourself, rather than letting the library do it for you.
    I'd be interested in adding an example DCC Accessory Decoder sketch that supports your hardware, however the schematic you've posted is _very_ blurry and difficult to read, making software development rather difficult.
    Can you post a clearer version please?
    Perhaps print it to PDF of something that is scaleable as opposed to the screen shot or image dump that you appear to have done?
    Regards
    Alex Shepherd

    0
    BillC35
    BillC35

    Reply 1 year ago

    Hi Alex, yes I did start with your great idea on this, thanks for all your efforts.
    I decided to keep options open to users to allow for variations in use of the circuit. For example in my own loft railway, I use 6 turnouts using solenoids plus 2 on/off switches for lights and station announcement (switches on an Arduino based sound circuit).
    I did not want to turn the circuit into a decoder and preferred to keep options within the Arduino code.

    As you know, other users require different pulse widths, use of tortoise and servos, etc. The servo example by passes the h-bridge IC's.

    Please find attached circuit diagram - hopefully fully readable and printable.
    Thanks for your interest and if you want a PCB let me know - I have only 1 left.
    I plan to get more manufactured later this month.

    Take care and stay safe.

    Bill

    DCC_turnout_control_SN754410_oct_2019_schem.png
    0
    kiwi64ajs
    kiwi64ajs

    Reply 1 year ago

    Hi Bill,
    This image isn't much better than the original. I expect the Instructables platform is resizing it, so perhaps can you email the original to me on: kiwi64ajs@gmail.com please.

    0
    ed.terry.simon
    ed.terry.simon

    Question 1 year ago on Step 2

    Thanks for all your information, Bill, but I checked on ebay and found no results for 233264617488 or 233461778549. Do you have a new item number to search? Thanks for all your efforts... very much appreciated. Ed in Ohio

    0
    BillC35
    BillC35

    Answer 1 year ago

    Hi Ed in Ohio
    I have run out of PCB's for the moment (been popular) and should have 10 more to sell on eBay within a few days. I will let you know when they are available.
    Bill from Falkland in Scotland.