Introduction: Arduino - Points/turnout/accessory Control V2
Updated 19 Oct 2021: new PCB v3 (Jun 2021) available with added memory push button to set the first turnout address.
PCB v3 version Jun 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.
28 Comments
1 year ago
I cannot open the downloaded file of this instructable - It says the file is corrupted.
Both adobe reader and sumatra do this.
Reply 1 year 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
Reply 1 year ago
The firmware files are fine but the download of the whole thing is where the problem is. It says it is zero bytes.
Reply 1 year ago
I have refreshed the Instructable entry and I can now download the project.
Please try again.
Bill
Reply 1 year ago
I still get the same:
Reply 1 year ago
Please try this attached pdf file I managed to download this morning.
Reply 1 year ago
Thank you very much - that worked.
I have ordered the PCB and while typing this the board has arrived.
Question 1 year ago on Step 6
Boa Tarde. Onde obtenho VarSpeedServo.h ?
Desde já, obrigado pela resposta.
Answer 1 year ago
The link to library files is here:
https://github.com/netlabtoolkit/VarSpeedServo
Bill
Question 2 years 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.
Answer 2 years 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.
Answer 2 years 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
Reply 2 years 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
Answer 2 years 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.
2 years 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
Reply 2 years 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
Reply 2 years 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.
Question 3 years 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
Answer 3 years ago
Hi Ed
I now have the PCB for turnout control available on eBay:
https://www.ebay.co.uk/itm/DCC-Digital-Model-rail-...
The DCC system is also available on eBay:
https://www.ebay.co.uk/itm/DCC-Controller-for-mode...
Bill
Answer 3 years 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.