In deel vier van deze serie heb ik beschreven hoe een sein aan te sturen is vanuit de CS2 en Rocrail gebruikmakend van een Arduino. Ook een wissel is via een Arduino te bedienen. Er zijn verschillende mogelijkheden. Hieronder hoe ik e.e.a. heb gemaakt.
Op pin 2 van de Arduino komt het DCC signaal binnen via de eerder behandelde DCC naar Arduino omzetter.

Een elektrisch bediend wissel kan dan vervolgens via een MOSFET-module aangestuurd worden. Elke pin van een Arduino kan maar een beperkt aantal mA leveren. Om een wissel om te zetten is dat onvoldoende. Een MOSFET kan met die kleine hoeveelheid mA een veel grotere last schakelen.
Een handbediend wissel kan je, direct vanuit de Arduino, met een servo omzetten, zoals ook al hier beschreven. De elektronica is in dit geval dus minder ingewikkeld, maar je moet mechanisch nog het een en ander knutselen voordat een wissel om gaat.

Met behulp van onderstaande sketch van eerder genoemde Ruud Boer kan je 12 servo’s, en dus 12 wissels, omzetten. Zie ook hier zijn uitleg.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Arduino DCC Servo and Function Decoder
// Version: 1.4 - 2015-04-23
// Author: Ruud Boer
// This sketch turns an Arduino into a DCC decoder with max 12 servo motor outputs combined with function outputs.
// The DCC signal is optically separated and fed to pin 2 (=Interrupt 0). Schematics: www.mynabay.com
// Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code, which is used in this sketch.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: GOTO lines 23 and 44 to configure some data!
// IMPORTANT: To avoid servo movement and possible high current draw at startup:
// - First start the Arduino, the software now sets the servo angle values to 'offangle'.
// - After a few seconds, switch the servo power on ... they will possibly show just a minor jitter.
// - This only works if you set all servo's to offangle before shutdown!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <DCC_Decoder.h>
#include <Servo.h>
#define kDCC_INTERRUPT 0
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill in these 2 values ...
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const byte maxservos = 10; //The number of servos you have connected to this Arduino
const byte servotimer = 60; //Servo angle change timer. Lower value -> higher speed
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned long timetoupdatesetpoint = millis() + servotimer;
struct servoItem {
int address; // DCC address to respond to
byte output; // State of DCC accessory: 1=on, 0=off (ECoS: on=straight, off=turnout)
byte outputPin; // Arduino output pin for additional function (not where servo is attached to)
byte angle;
byte setpoint;
byte offangle;
byte onangle;
Servo servo;
};
servoItem servos[maxservos];
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill in the data for every function and servo.
// COPY - PASTE as many times as you have functions. The amount must be same as in line 22 above!
// A servo is coupled to an accessory[n]. It rotates based on accessory[n].output = 1 (CCW) or 0 (CW)
// If you have multiple servos you need to couple them to different accessories. However ...
// accessories may switch the same output pin (e.g. pin 13, which has the on board led attached)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void ConfigureFunctionsAndServos()
{
servos[0].address = 30; // DCC address for this accessory
servos[0].outputPin = 13; // Arduino pin number for additional function output (not where servo is attached to)
servos[0].servo.attach(3); //Arduino pin number where servo is connected to
servos[0].offangle = 68; //Angle for DCC=off. For ECoS turnout is DCC off, straight is DCC on.
servos[0].onangle = 126; //Angle for DCC=on. For ECoS turnout is DCC off, straight is DCC on.
servos[1].address = 31;
servos[1].outputPin = 13;
servos[1].servo.attach(4);
servos[1].offangle = 112;
servos[1].onangle = 62;
servos[2].address = 32;
servos[2].outputPin = 13;
servos[2].servo.attach(5);
servos[2].offangle = 128;
servos[2].onangle = 58;
servos[3].address = 33;
servos[3].outputPin = 13;
servos[3].servo.attach(6);
servos[3].offangle = 50;
servos[3].onangle = 128;
servos[4].address = 34;
servos[4].outputPin = 13;
servos[4].servo.attach(7);
servos[4].offangle = 60;
servos[4].onangle = 132;
servos[5].address = 35;
servos[5].outputPin = 13;
servos[5].servo.attach(8);
servos[5].offangle = 60;
servos[5].onangle = 116;
servos[6].address = 36;
servos[6].outputPin = 13;
servos[6].servo.attach(9);
servos[6].offangle = 46;
servos[6].onangle = 128;
servos[7].address = 37;
servos[7].outputPin = 13;
servos[7].servo.attach(10);
servos[7].offangle = 64;
servos[7].onangle = 124;
servos[8].address = 38;
servos[8].outputPin = 13;
servos[8].servo.attach(11);
servos[8].offangle = 50;
servos[8].onangle = 138;
servos[9].address = 39;
servos[9].outputPin = 13;
servos[9].servo.attach(12);
servos[9].offangle = 124;
servos[9].onangle = 64;
} // END ConfigureFunctionsAndServos()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DCC packet handler
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{
// Convert NMRA packet address format to human address
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;
boolean enable = (data & 0x01) ? 1 : 0;
for(int i=0; i<maxservos; i++)
{
if(address == servos[i].address)
{
if(enable) servos[i].output = 1;
else servos[i].output = 0;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup (run once)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
ConfigureFunctionsAndServos();
for(int i=0; i<maxservos; i++)
{
pinMode (servos[i].outputPin, OUTPUT );
digitalWrite (servos[i].outputPin, LOW);
servos[i].angle = servos[i].offangle; // Set start up angle to avoid movement at power on
}
DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );
pinMode(2,INPUT_PULLUP); //Interrupt 0 with internal pull up resistor (can get rid of external 10k)
pinMode(13,OUTPUT);
digitalWrite(13,LOW); //led off at startup
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main loop (run continuous)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop()
{
static int addr = 0;
DCC.loop(); // DCC library
if(++addr >= maxservos) addr = 0; // Next address to test
// Set servos output pin
if (servos[addr].output) digitalWrite(servos[addr].outputPin, HIGH);
else digitalWrite(servos[addr].outputPin, LOW);
// Every 'servotimer' ms, modify setpoints and move servos 1 step (if needed)
if (millis() > timetoupdatesetpoint)
{
timetoupdatesetpoint = millis() + servotimer;
for (int n=0; n<maxservos; n++)
{
if (servos[n].output) servos[n].setpoint=servos[n].onangle;
else servos[n].setpoint=servos[n].offangle;
if (servos[n].angle < servos[n].setpoint) servos[n].angle++;
if (servos[n].angle > servos[n].setpoint) servos[n].angle--;
servos[n].servo.write(servos[n].angle);
}
}
} //END MAIN LOOP
Per servo moet de volgende info opgegeven worden.
– address – het (NMRA) adres van het wissel,
– outputPin – wanneer er naast het wissel nog iets anders geschakeld moet worden,
– servo.attach() – op welke pin van de Arduino ie zit aangesloten,
– offangle – de hoek wanneer het wissel op afslaand staat,
– onangle – de hoek wanneer het wissel op rechtdoor staat.
Zie om die off- en onangle te bepalen deze video (en volgende) van Ruud Boer.
Het “signaal in” van de eerste servo (1e wissel) is aangesloten op de Arduino pin D3. Vervolgens moet in zowel CS2 en Rocrail e.e.a. ingesteld worden.
CS2
Ga naar “Layout” en dan naar “Configuratie”.

“Keyboard” en dan naar “Configuratie”.

Wat het verschil precies is? Geen idee. Met het knopje “Test” is te controleren of de servo omgaat.
Rocrail
Het wissel moet vervolgens ook in Rocrail ingevoerd worden. Of er een bepaalde volgorde aangehouden moet worden heb ik nog niet kunnen ontdekken.


Van belang is hier het adres: “Adres = 0, Poort = 30”. En het protocol: “NMRA-DCC”.
Vervolgens is de servo (wissel) vanuit zowel CS2 als ook vanuit Rocrail te bedienen.

