{"id":3754,"date":"2024-12-28T18:33:57","date_gmt":"2024-12-28T17:33:57","guid":{"rendered":"https:\/\/www.rommelkist.nl\/elec\/?p=3754"},"modified":"2024-12-31T00:19:24","modified_gmt":"2024-12-30T23:19:24","slug":"modelbaan-deel-10-proefbaantje-uitgebouwd","status":"publish","type":"post","link":"https:\/\/www.rommelkist.nl\/elec\/arduino\/modelbaan-deel-10-proefbaantje-uitgebouwd\/","title":{"rendered":"Modelbaan &#8211; deel 10 &#8211; Proefbaantje uitgebouwd"},"content":{"rendered":"\n<p>Het proefbaantje uit <a href=\"https:\/\/www.rommelkist.nl\/elec\/3d-printen\/modelbaan-deel-6-proefbaantje\/\" data-type=\"post\" data-id=\"3585\">deel 6<\/a> is weer verder uitgebouwd. Naast de S88 onderdelen (2x Arduino Nano &amp; 1x OKKIE8) heeft de &#8220;DCC-naar-Arduino omzetter&#8221; een plaatsje gekregen en is vervolgens aangesloten op twee Arduino Nano&#8217;s om accessoires aan te sturen: \u00e9\u00e9n voor het aansturen van specifiek servo&#8217;s, de andere voor het aansturen van algemene accessoires (zoals een sein, een wissel, een ontkoppelrail). <br>Ook is er een voeding bijgekomen voor 15V en voor 5V. Middels verdeelstrips zijn deze twee voltages op meerder plaatsen beschikbaar.<br>De Automatische Knipper Installatie AKI (uit <a href=\"https:\/\/www.rommelkist.nl\/elec\/elektronica\/n-spoor-deel-24-aki-met-geluid\/\" data-type=\"post\" data-id=\"2517\">deel 24 van de vorige serie<\/a>) heeft een plekje gekregen en er is een breadboard geplaatst voor de nodige testjes.<\/p>\n\n\n\n<p>Alle eerdere testjes komen hier samen. De in eerdere delen opgenomen sketches zullen verwijderd worden. Vanaf nu zullen alleen sketches gelist worden die daadwerkelijk ingezet zijn\/worden in de proefbaan. Dit om verwarring (vooral voor mijzelf \ud83d\ude42 ) te voorkomen.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.rommelkist.nl\/elec\/wp-content\/uploads\/2024\/12\/image-40.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"794\" src=\"https:\/\/www.rommelkist.nl\/elec\/wp-content\/uploads\/2024\/12\/image-40-1024x794.png\" alt=\"\" class=\"wp-image-3771\" srcset=\"https:\/\/www.rommelkist.nl\/wp-content\/uploads\/2024\/12\/image-40-1024x794.png 1024w, https:\/\/www.rommelkist.nl\/wp-content\/uploads\/2024\/12\/image-40-300x233.png 300w, https:\/\/www.rommelkist.nl\/wp-content\/uploads\/2024\/12\/image-40-768x595.png 768w, https:\/\/www.rommelkist.nl\/wp-content\/uploads\/2024\/12\/image-40-425x329.png 425w, https:\/\/www.rommelkist.nl\/wp-content\/uploads\/2024\/12\/image-40.png 1201w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Onderzijde proefbaantje.<\/figcaption><\/figure>\n\n\n\n<p>Hieronder worden de diverse onderdelen behandeld.<\/p>\n\n\n\n<p class=\"has-large-font-size\">Sketches<\/p>\n\n\n\n<pre class=\"wp-block-syntaxhighlighter-code\">\/*\nS88 occupancy sensor interface to Command Station (in my case an ESU ECoS2)\n\nSoftware by Ruud Boer, November 2014.\nFreely distributable for private, non commercial, use.\n\nConnections for S88 bus:\ns88 pin 1 Data - Arduino pin 13 = Data_Out to Oommand Station, or to the previous Arduino in the chain\ns88 pin 2 GND  - Arduino GND\ns88 pin 3 Clock - Arduino pin 2, interrupt 0\ns88 pin 4 PS - Arduino pin 3, interrupt 1\nS66 pin 5 Reset (not used here) - Arduino pin 12, used as DATA IN from previous Arduino DATA OUT\ns88 pin 6 V+ - Arduino 5V\n\nIMPORTANT: To avoid S88 signals to jitter, it is best to put DATA_in pin 12 to GND on the last Arduino in the chain.\n\nConnections for sensors: see table in void Setup() at line 35.\nREMARK1: Inputs have the internal pullup resistor active, the sensors must pull the input to GND.\nREMARK2: How short a pulse is allowed from the sensors before it is not seen?\nA test showed that the main loop where all sensors are read runs once every 76 microseconds.\nIf a train runs over the reed switch with a speed of 1m\/s, which is over 300 km\/hr, that translates to 1 mm\/ms.\nSo even if the reed switch would be on only for a 1 mm travel distance, then still the Arduino\nwill read that info more than 10 times!\n\n*\/\n\nint clockCounter=0;\nlong loopCounter=0; \/\/used in lines 55 and 88, see there for explanation\nunsigned int sensors=0;\nunsigned int data=0xffff;\nconst byte dataIn=12;  \/\/data input from next Arduino in S88 chain\nconst byte dataOut=13; \/\/data output pin=13\nboolean loadSensors=false; \/\/flag that says to load sensor bits into dataOut bits\n\nvoid setup() {\n  pinMode(2, INPUT_PULLUP);\n  attachInterrupt(0,clock,RISING); \/\/pin 2 = clock interrupt\n  pinMode(3, INPUT_PULLUP);\n  attachInterrupt(1,PS,RISING);    \/\/pin 3 = PS interrupt\n  pinMode(dataIn,INPUT_PULLUP); \/\/pin 12 = data in from next Arduino S88 in chain\n  pinMode(dataOut, OUTPUT); \/\/pin 13 = data out to ECoS or to previous Arduino in S88 chain\n  digitalWrite(dataOut, LOW);   \/\/LED off\n  pinMode(A0, INPUT_PULLUP); \/\/sensor 01\n  pinMode(A1, INPUT_PULLUP); \/\/sensor 02\n  pinMode(A2, INPUT_PULLUP); \/\/sensor 03\n  pinMode(A3, INPUT_PULLUP); \/\/sensor 04\n  pinMode(A4, INPUT_PULLUP); \/\/sensor 05\n  pinMode(A5, INPUT_PULLUP); \/\/sensor 06\n  pinMode(0, INPUT_PULLUP);  \/\/sensor 07\n  pinMode(1, INPUT_PULLUP);  \/\/sensor 08\n  pinMode(4, INPUT_PULLUP);  \/\/sensor 09\n  pinMode(5, INPUT_PULLUP);  \/\/sensor 10\n  pinMode(6, INPUT_PULLUP);  \/\/sensor 11\n  pinMode(7, INPUT_PULLUP);  \/\/sensor 12\n  pinMode(8, INPUT_PULLUP);  \/\/sensor 13\n  pinMode(9, INPUT_PULLUP);  \/\/sensor 14\n  pinMode(10, INPUT_PULLUP); \/\/sensor 15\n  pinMode(11, INPUT_PULLUP); \/\/sensor 16\n}\n\nvoid loop() {\n  if (loopCounter==600){bitSet(sensors,0);}\n  \/*\n  For an unknown reason the ECoS sets the first 8 bits to 1 after startup \/ reset of the S88 Arduino's.\n  When one of the sensor inputs is changed, from there on everything goes well.\n  Therefore, over here we give sensor bit 0 an automatic change after 30 seconds, when the ECoS is fully started.\n  The 1 second is created via 'loopCounter', which increments in the PS interrupt (line 88).\n  There are appr0ximately 20 PS pulses per second, therefore we use 20x30=600 in the if statement.\n  *\/\n  if (!digitalRead(A0)) {bitSet(sensors,0);}\n  if (!digitalRead(A1)) {bitSet(sensors,1);}\n  if (!digitalRead(A2)) {bitSet(sensors,2);}\n  if (!digitalRead(A3)) {bitSet(sensors,3);}\n  if (!digitalRead(A4)) {bitSet(sensors,4);}\n  if (!digitalRead(A5)) {bitSet(sensors,5);}\n  if (!digitalRead(0)) {bitSet(sensors,6);}\n  if (!digitalRead(1)) {bitSet(sensors,7);}\n  if (!digitalRead(4)) {bitSet(sensors,8);}\n  if (!digitalRead(5)) {bitSet(sensors,9);}\n  if (!digitalRead(6)) {bitSet(sensors,10);}\n  if (!digitalRead(7)) {bitSet(sensors,11);}\n  if (!digitalRead(8)) {bitSet(sensors,12);}\n  if (!digitalRead(9)) {bitSet(sensors,13);}\n  if (!digitalRead(10)) {bitSet(sensors,14);}\n  if (!digitalRead(11)) {bitSet(sensors,15);}\n}\n\nvoid PS() {\n  clockCounter=0;\n  data=sensors;\n  sensors=0;\n  loopCounter++; \/\/Increment loopCounter to cretae a timer. See line 55 for explanation.\n}\n\nvoid clock() {\n  digitalWrite(dataOut,bitRead(data,clockCounter));\n  delayMicroseconds(16); \/\/Delay makes reading output signal from next Arduino in chain more reliable.\n  bitWrite(data,clockCounter,digitalRead(dataIn));\n  clockCounter =(clockCounter +1) % 16;\n}<\/pre>\n\n\n\n<pre class=\"wp-block-syntaxhighlighter-code\">\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ DCC Accessory \/ Function Decoder\n\/\/ Author: Ruud Boer - September 2015\n\/\/ This sketch turns an Arduino into a DCC decoder with max 17 function outputs.\n\/\/ Output pins used: 3-19 (14-19 = A0-A5). Pin becomes LOW when accessory is switched ON\n\/\/ Modes: 1-continuous, 2=oneshot, 3=flasher with 2 alternatin outputs, 4=signal with 2 inverted outputs\n\/\/ The DCC signal is fed to pin 2 (=Interrupt 0).\n\/\/ Optocoupler schematics for DCC to 5V conversion: www.rudysmodelrailway.wordpress.com\/software\n\/\/ Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code.\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ IMPORTANT: GOTO lines 22 and 43 to configure some data!\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n#include &lt;DCC_Decoder.h>\n#define kDCC_INTERRUPT 0\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Fill in the number of accessories \/ functions you want to control\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nconst byte maxaccessories = 4;\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\ntypedef struct {\n  int               address;          \/\/ User Configurable. DCC address to respond to\n  byte              mode;             \/\/ User Configurable. Mode: 1=Continuous, 2=Oneshot, 3=Flasher\n  byte              outputPin;        \/\/ User Configurable. Arduino pin where accessory is connected to\n  byte              outputPin2;       \/\/ User Configurable. 2nd pin for AlternatingFlasher (e.g. railway crossing)\n  int               ontime;           \/\/ User Configurable. Oneshot or Flasher on time in ms\n  int               offtime;          \/\/ User Configurable. Flasher off time in ms\n  byte              onoff;            \/\/ User Configurable. Initial state of accessory output: 1=on, 0=off (ON = pin LOW)\n  byte              onoff2;           \/\/ User Configurable. Initial  state of 2nd output: 1=on, 0=off\n  byte              dccstate;         \/\/ Internal use. DCC state of accessory: 1=on, 0=off\n  byte              finished;         \/\/ Internal use. Memory that says the Oneshot is finished\n  unsigned long     onMilli;          \/\/ Internal use.\n  unsigned long     offMilli;         \/\/ Internal use.\n} \nDCCAccessoryAddress;\nDCCAccessoryAddress accessory[maxaccessories];\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Fill in the attributes for every accessory \/ function\n\/\/ COPY - PASTE as many times as you have functions. The amount must be same as in line 22 above!\n\/\/\n\/\/\n\/\/\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid ConfigureDecoderFunctions() \/\/ The amount of accessories must be same as in line 22 above!\n{\n  \/*\n  accessory[0].address = 50; \/\/ DCC address\n  accessory[0].mode = 1; \/\/ Continuous: HIGH until DCC switches the address off again\n  accessory[0].outputPin = 3; \/\/ Arduino pin to which this accessory is connected\n\n  accessory[1].address = 51;\n  accessory[1].mode = 2; \/\/ Oneshot: HIGH for ontime ms, then LOW and stays LOW.\n  accessory[1].outputPin = 4;\n  accessory[1].ontime = 1000;\n \n  accessory[2].address = 52;\n  accessory[2].mode = 3; \/\/ Flasher: HIGH for ontime ms, LOW for offtime ms, repeats till DCC off\n  accessory[2].outputPin = 5;\n  accessory[2].outputPin2 = 6; \/\/ Flasher can use 2 outputs, they will flash  on\/off alternatively\n  accessory[2].ontime = 500;\n  accessory[2].offtime = 500;\n  \n  accessory[3].address = 53; \/\/ DCC address\n  accessory[3].mode = 4; \/\/ Continuous: HIGH until DCC switches the address off again\n  accessory[3].outputPin = 7; \/\/ Green signal\n  accessory[3].outputPin2 = 8; \/\/ Red Signal\n  accessory[3].onoff2 = 1; \/\/ Initially set Red signal to ON\n  *\/\n\n  accessory[0].address = 50; \/\/ DCC address\n  accessory[0].mode = 2; \/\/ Oneshot: HIGH for ontime ms, then LOW and stays LOW.\n  accessory[0].outputPin = 3;\n  accessory[0].ontime = 1000;\n\n  accessory[1].address = 51;\n  accessory[1].mode = 2; \/\/ Oneshot: HIGH for ontime ms, then LOW and stays LOW.\n  accessory[1].outputPin = 4;\n  accessory[1].ontime = 1000;\n \n  accessory[2].address = 52;\n  accessory[2].mode = 2; \/\/ Oneshot: HIGH for ontime ms, then LOW and stays LOW.\n  accessory[2].outputPin = 5;\n  accessory[2].ontime = 1000;\n  \n  accessory[3].address = 53; \/\/ DCC address\n  accessory[3].mode = 2; \/\/ Oneshot: HIGH for ontime ms, then LOW and stays LOW.\n  accessory[3].outputPin = 6;\n  accessory[3].ontime = 1000;\n  \n}  \/\/ END ConfigureDecoderFunctions\n\n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n  \/\/ DCC accessory packet handler \n  \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n  void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)\n  {\n    \/\/ Convert NMRA packet address format to human address\n    address -= 1;\n    address *= 4;\n    address += 1;\n    address += (data &amp; 0x06) >> 1;\n\n    boolean enable = (data &amp; 0x01) ? 1 : 0;\n\n    for (int i=0; i&lt;maxaccessories; i++)\n    {\n      if (address == accessory[i].address)\n      {\n        if (enable) accessory[i].dccstate = 1;\n        else accessory[i].dccstate = 0;\n      }\n    }\n  } \/\/END BasicAccDecoderPacket_Handler\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Setup (run once)\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid setup() \n{ \n  ConfigureDecoderFunctions();\n  DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);\n  DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );\n  pinMode(2,INPUT_PULLUP); \/\/ Interrupt 0 with internal pull up resistor (can get rid of external 10k)\n\n  for(int i=3; i&lt;20; i++)\n  {\n    pinMode(i, OUTPUT);\n    digitalWrite(i, LOW); \/\/all function outputs are set to 0 at startup - SV: LOW ipv HIGH\n  }\n} \/\/ END setup\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Main loop (run continuous)\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid loop()\n{\n  static int addr = 0;\n\n  DCC.loop(); \/\/ Loop DCC library\n    \n  if( ++addr >= maxaccessories ) addr = 0; \/\/ Next address to test\n\n  if (accessory[addr].dccstate)\n  {\n    switch (accessory[addr].mode)\n    {\n    case 1: \/\/ Continuous\n      accessory[addr].onoff = 1;\n      break;\n    case 2: \/\/ Oneshot\n      if (!accessory[addr].onoff &amp;&amp; !accessory[addr].finished)\n      {\n        accessory[addr].onoff = 1;\n        accessory[addr].offMilli = millis() + accessory[addr].ontime;\n      }\n      if (accessory[addr].onoff &amp;&amp; millis() > accessory[addr].offMilli)\n      {\n        accessory[addr].onoff = 0;\n        accessory[addr].finished = true; \/\/this is reset to flase below in the 'else' statement\n      }\n      break;\n    case 3: \/\/ Flasher, is always an 'alternating' flasher together with .outputPin2\n      if (!accessory[addr].onoff &amp;&amp; millis() > accessory[addr].onMilli)\n      {\n        accessory[addr].onoff = 1;\n        accessory[addr].onoff2 = 0;\n        accessory[addr].offMilli = millis() + accessory[addr].ontime;\n      }\n      if (accessory[addr].onoff &amp;&amp; millis() > accessory[addr].offMilli)\n      {\n        accessory[addr].onoff = 0;\n        accessory[addr].onoff2 = 1;\n        accessory[addr].onMilli = millis() + accessory[addr].offtime;\n      }\n      break;\n    case 4: \/\/ Signal\n      accessory[addr].onoff = 1;\n      accessory[addr].onoff2 = 0;\n      break;\n    }\n  }\n  else \/\/accessory[addr].dccstate == 0\n  {\n    accessory[addr].onoff = 0;\n    if (accessory[addr].mode == 4) accessory[addr].onoff2 = 1; else accessory[addr].onoff2 = 0;\n    if (accessory[addr].mode == 2) accessory[addr].finished = false; \/\/ Oneshot finished by DCCstate, not by ontime\n  }\n\n  \/\/ activate outputpin, based on value of onoff\n  if (accessory[addr].onoff) digitalWrite(accessory[addr].outputPin, LOW);\n  else digitalWrite(accessory[addr].outputPin, HIGH);\n  if (accessory[addr].onoff2) digitalWrite(accessory[addr].outputPin2, LOW);\n  else digitalWrite(accessory[addr].outputPin2, HIGH);\n  \n} \/\/END loop<\/pre>\n\n\n\n<pre class=\"wp-block-syntaxhighlighter-code\">\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Arduino DCC Servo and Function Decoder\n\/\/ Version: 1.4 - 2015-04-23\n\/\/ Author: Ruud Boer\n\/\/ This sketch turns an Arduino into a DCC decoder with max 12 servo motor outputs combined with function outputs.\n\/\/ The DCC signal is optically separated and fed to pin 2 (=Interrupt 0). Schematics: www.mynabay.com\n\/\/ Many thanks to www.mynabay.com for publishing their DCC monitor and -decoder code, which is used in this sketch.\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ IMPORTANT: GOTO lines 25 and 44 to configure some data!\n\/\/ IMPORTANT: To avoid servo movement and possible high current draw at startup:\n\/\/ - First start the Arduino, the software now sets the servo angle values to 'offangle'.\n\/\/ - After a few seconds, switch the servo power on ... they will possibly show just a minor jitter.\n\/\/ - This only works if you set all servo's to offangle before shutdown!\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\n#include &lt;DCC_Decoder.h>\n#include &lt;Servo.h> \n#define kDCC_INTERRUPT 0\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Fill in these 2 values ...\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nconst byte maxservos = 10; \/\/The number of servos you have connected to this Arduino\nconst byte servotimer = 60; \/\/Servo angle change timer. Lower value -> higher speed\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\nunsigned long timetoupdatesetpoint = millis() + servotimer;\n\nstruct servoItem {\n  int address; \/\/ DCC address to respond to\n  byte output; \/\/ State of DCC accessory: 1=on, 0=off (ECoS: on=straight, off=turnout)\n  byte outputPin; \/\/ Arduino output pin for additional function (not where servo is attached to)\n  byte angle;\n  byte setpoint;\n  byte offangle;\n  byte onangle;\n  Servo servo;\n};\nservoItem servos[maxservos];\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Fill in the data for every function and servo.\n\/\/ COPY - PASTE as many times as you have functions. The amount must be same as in line 22 above!\n\/\/ A servo is coupled to an accessory[n]. It rotates based on accessory[n].output = 1 (CCW) or 0 (CW)\n\/\/ If you have multiple servos you need to couple them to different accessories. However ...\n\/\/ accessories may switch the same output pin (e.g. pin 13, which has the on board led attached)\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid ConfigureFunctionsAndServos()\n{\n  servos[0].address = 30; \/\/ DCC address for this accessory\n  servos[0].outputPin = 13; \/\/ Arduino pin number for additional function output (not where servo is attached to)\n  servos[0].servo.attach(3); \/\/Arduino pin number where servo is connected to\n  servos[0].offangle = 68; \/\/Angle for DCC=off. For ECoS turnout is DCC off, straight is DCC on.\n  servos[0].onangle = 126; \/\/Angle for DCC=on. For ECoS turnout is DCC off, straight is DCC on.\n \n  servos[1].address = 31;\n  servos[1].outputPin = 13;\n  servos[1].servo.attach(4);\n  servos[1].offangle = 112;\n  servos[1].onangle = 62;\n\n  servos[2].address = 32;\n  servos[2].outputPin = 13;\n  servos[2].servo.attach(5);\n  servos[2].offangle = 128;\n  servos[2].onangle = 58;\n\n  servos[3].address = 33;\n  servos[3].outputPin = 13;\n  servos[3].servo.attach(6);\n  servos[3].offangle = 50;\n  servos[3].onangle = 128;\n\n  servos[4].address = 34;\n  servos[4].outputPin = 13;\n  servos[4].servo.attach(7);\n  servos[4].offangle = 60;\n  servos[4].onangle = 132;\n\n  servos[5].address = 35;\n  servos[5].outputPin = 13;\n  servos[5].servo.attach(8);\n  servos[5].offangle = 60;\n  servos[5].onangle = 116;\n\n  servos[6].address = 36;\n  servos[6].outputPin = 13;\n  servos[6].servo.attach(9);\n  servos[6].offangle = 46;\n  servos[6].onangle = 128;\n\n  servos[7].address = 37;\n  servos[7].outputPin = 13;\n  servos[7].servo.attach(10);\n  servos[7].offangle = 64;\n  servos[7].onangle = 124;\n\n  servos[8].address = 38;\n  servos[8].outputPin = 13;\n  servos[8].servo.attach(11);\n  servos[8].offangle = 50;\n  servos[8].onangle = 138;\n\n  servos[9].address = 39;\n  servos[9].outputPin = 13;\n  servos[9].servo.attach(12);\n  servos[9].offangle = 124;\n  servos[9].onangle = 64;\n\n} \/\/ END ConfigureFunctionsAndServos()\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ DCC packet handler \n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)\n{\n  \/\/ Convert NMRA packet address format to human address\n  address -= 1;\n  address *= 4;\n  address += 1;\n  address += (data &amp; 0x06) >> 1;\n\n  boolean enable = (data &amp; 0x01) ? 1 : 0;\n\n  for(int i=0; i&lt;maxservos; i++)\n\t{\n    if(address == servos[i].address)\n\t\t{\n      if(enable) servos[i].output = 1;\n      else servos[i].output = 0;\n    }\n  }\n}\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Setup (run once)\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid setup() \n{ \n  DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);\n  \n  ConfigureFunctionsAndServos();\n  for(int i=0; i&lt;maxservos; i++)\n  {\n    pinMode (servos[i].outputPin, OUTPUT );\n    digitalWrite (servos[i].outputPin, LOW);\n    servos[i].angle = servos[i].offangle; \/\/ Set start up angle to avoid movement at power on\n  }\n\n  DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );\n  pinMode(2,INPUT_PULLUP); \/\/Interrupt 0 with internal pull up resistor (can get rid of external 10k)\n  \n  pinMode(13,OUTPUT);\n  digitalWrite(13,LOW); \/\/led off at startup\n  \n}\n\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\n\/\/ Main loop (run continuous)\n\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\nvoid loop()\n{\n  static int addr = 0;\n\n  DCC.loop(); \/\/ DCC library\n\n  if(++addr >= maxservos) addr = 0; \/\/ Next address to test\n\n  \/\/ Set servos output pin\n  if (servos[addr].output) digitalWrite(servos[addr].outputPin, HIGH);\n  else digitalWrite(servos[addr].outputPin, LOW);\n  \n  \/\/ Every 'servotimer' ms, modify setpoints and move servos 1 step (if needed)\n  if (millis() > timetoupdatesetpoint)\n\t{\n    timetoupdatesetpoint = millis() + servotimer;\n    for (int n=0; n&lt;maxservos; n++)\n\t\t{\n      if (servos[n].output) servos[n].setpoint=servos[n].onangle;\n      else servos[n].setpoint=servos[n].offangle;\n\n      if (servos[n].angle &lt; servos[n].setpoint) servos[n].angle++;\n      if (servos[n].angle > servos[n].setpoint) servos[n].angle--;\n      servos[n].servo.write(servos[n].angle);\n    }\n  }\n\n} \/\/END MAIN LOOP<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Het proefbaantje uit deel 6 is weer verder uitgebouwd. Naast de S88 onderdelen (2x Arduino Nano &amp; 1x OKKIE8) heeft de &#8220;DCC-naar-Arduino omzetter&#8221; een plaatsje gekregen en is vervolgens aangesloten op twee Arduino Nano&#8217;s om accessoires aan te sturen: \u00e9\u00e9n voor het aansturen van specifiek servo&#8217;s, de andere voor het aansturen van algemene accessoires (zoals een sein, een wissel, een ontkoppelrail). Ook is er een voeding bijgekomen voor 15V en voor 5V. Middels verdeelstrips zijn deze twee voltages op meerder plaatsen beschikbaar.De Automatische Knipper Installatie AKI (uit deel 24 van de vorige serie) heeft een plekje gekregen en er is een breadboard geplaatst voor de<span class=\"more-link\"><a href=\"https:\/\/www.rommelkist.nl\/elec\/arduino\/modelbaan-deel-10-proefbaantje-uitgebouwd\/\">Read More &rarr;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,104],"tags":[],"class_list":["entry","author-admin","post-3754","post","type-post","status-publish","format-standard","category-arduino","category-modeltreinbaan"],"_links":{"self":[{"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/posts\/3754","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/comments?post=3754"}],"version-history":[{"count":0,"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/posts\/3754\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/media?parent=3754"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/categories?post=3754"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rommelkist.nl\/elec\/wp-json\/wp\/v2\/tags?post=3754"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}