Google+
Doel:€250.00
Donaties:€29.30

Per saldo:€-220.70

Steun ons nu!

Laatst bijgewerkt
op 17-06-2018
Algemeen

De stichting

Recente berichten

Update: baan in de tropen door Hans Grasmaijer
Vandaag om 14:57:18
n baan ardennen 2.90-1.22 mtr. mobile station 66955 DCC door C_cornelis_S
Vandaag om 14:55:20
Raadplaatje door Klaas Zondervan
Vandaag om 14:47:14
Diorama in Wijnkist door wouter-
Vandaag om 14:17:21
Mijn eerste H0 modeltreinbaan in aanbouw door Wim Vink
Vandaag om 14:16:51
Arduino Mega 2560, voor spoorwegoverweg met fotocellendetectie door gvandersel
Vandaag om 13:54:21
LSModels 2018 door Peter Crossrail
Vandaag om 13:22:40
Modelspoorfabrikanten en hun "fantasiemodellen" door Sobat Kras
Vandaag om 13:01:38
Hof Tramrails, met welke lijm zit spoorstaaf vast aan bedding? door MMTB
Vandaag om 12:50:20
BNLS-module: "Groeten uit Jottum" door Pauldg
Vandaag om 12:19:35
NL Baan in Canada door 72sonett
Vandaag om 12:07:36
BNLS Baanbreker - Project 083 tot 338 door 44
Vandaag om 12:05:01
De bouw van Schellenbach door Rondje_HO
Vandaag om 12:03:25
25 jaar geleden door Willem1951
Vandaag om 11:24:59
"Litter Bin" voor Brits spoor en Britse modelspoorprojecten door jakeman
Vandaag om 11:18:34
Ermehuizen anno 1974 door Jeroen Water
Vandaag om 10:18:52
Oersik in schaal 1 door 1795
Vandaag om 10:18:27
DE 64/6500 verbouwde varianten in model door Peter Crossrail
Vandaag om 09:15:03
Saint Tourbière, een Franse enkelsporige lijn door de Ardeche door tothebeach
Vandaag om 09:14:45
Piko Railjet, ingebouwde decoder wordt te warm? door Frederikus
Vandaag om 08:59:10
BNLS-Module: "Rvbr-Btk, Ringvaartbrug Haarlemmermeer nabij Buitenkaag" NS H0 door tothebeach
Vandaag om 08:23:32
Boom valt voor stoomtrein bij de South Devon Railway door GD
Vandaag om 06:24:48
Westlandbaan door knutselaar
Vandaag om 06:18:50
Mallnitzer Tauernbahnstrecke ÖBB N Spoor door Schachbrett
19 juni 2018, 22:48:50
  

Auteur Topic: Ali-lichtsluisjes en overwegaansturing met arduino  (gelezen 2021 keer)

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3031
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #30 Gepost op: 22 mei 2018, 11:54:37 »
Oke,

Alles even samenvatten:

Eisen/Wensen:

Aansturing van een AKI door een trein. Aan de trein mogen geen aanpassingen gedaan worden. De AKI is dubbelsporig en moet van beide zijde op hetzelfde spoor aangestuurd worden. Gekozen is voor aansturing via "lichtsluizen" en een Arduino.
Eventuele knippenringen door de lichtsluizen worden door een schuine opstelling verminderd, geheel voorkomen kan niet. Dit wordt niet door extra hardware opgelost.

Opstelling:


Even in "Grasland" gekeken voor de juiste opstelling. De overweg bevind zich links op de module. Dus er is een ongelijke tijd voor het aanrijden van de AKI. Is in dit geval niet storend, daar de korte aanrijtijd door de BBL (blackbox links) gecamoufleerd wordt. De rode lijnen zijn de 4 sensoren voor de AKI aansturing.


Schema:


Voeden uit de Arduino. De sensoren zullen ieder zo'n 30mA trekken, dus dat moet kunnen. Voeden uit de USB poort van de PC is dan niet meer mogelijk. De voeding van de Arduino gebruiken. Waar de 4 sensoren aangesloten worden is niet van belang, zolang pen 0 (RX), 1 (TX) en 13 (LED) maar niet gebruikt worden. Probeer zoveel mogelijk de pennen 2 (INT0) en 3 (INT1) te vermijden. In dit geval is dat niet nodig, daar we deze functionaliteit toch niet nodig hebben.

Software:

// Definitie van de 4 ingangen voor de sensoren
#define SBBLSP1    3   // BlackBox Links, Spoor 1
#define SBBLSP2    4   // BlackBox Links, Spoor 2
#define SBBRSP1    5   // BlackBox Rechts, Spoor 1
#define SBBRSP2    6   // BlackBox REchts, Spoor 2

#define DELAY    500   // Vertraging in milli seconde

// Laatste stand van de melder
bool MBBLSP1;
bool MBBLSP2;
bool MBBRSP1;
bool MBBRSP2;

// Timers om het vrijgeven te vertragen
unsigned long TSBBLSP1;
unsigned long TSBBLSP2;
unsigned long TSBBRSP1;
unsigned long TSBBRSP2;

// Variabelen die richting in de sporen bij houden
// < 0: trein rijdt van rechts naar links
// 0: geen trein
// > 0: trein rijdt van links naar rechts
byte DIRSP1;
byte DIRSP2;


// Functies om de melders te lezen (true = bezet)
bool readBBLSP1() {
  // if (digitalRead(SBBLSP1) > 0) {
  if (digitalRead(SBBLSP1) == 0) {
    TSBBLSP1 = millis() + DELAY;
  }
  return (TSBBLSP1 > millis());
}

bool readBBLSP2() {
  // if (digitalRead(SBBLSP2) > 0) {
  if (digitalRead(SBBLSP2) == 0) {
    TSBBLSP2 = millis() + DELAY;
  }
  return (TSBBLSP2 > millis());
}

bool readBBRSP1() {
  // if (digitalRead(SBBRSP1) > 0) {
  if (digitalRead(SBBRSP1) == 0) {
    TSBBRSP1 = millis() + DELAY;
  }
  return (TSBBRSP1 > millis());
}

bool readBBRSP2() {
  // if (digitalRead(SBBRSP2) > 0) {
  if (digitalRead(SBBRSP2) == 0) {
    TSBBRSP2 = millis() + DELAY;
  }
  return (TSBBRSP2 > millis());
}

// Initialialatie van de Arduino
void setup() {
  // put your setup code here, to run once:
  // Maak de inputs met extra pullups
  pinMode(SBBLSP1, INPUT_PULLUP);
  pinMode(SBBLSP2, INPUT_PULLUP);
  pinMode(SBBRSP1, INPUT_PULLUP);
  pinMode(SBBRSP2, INPUT_PULLUP);
  // Zet de interne LED output
  pinMode(LED_BUILTIN, OUTPUT);
  // Initialiseer de laatste waarde
  MBBLSP1 = readBBLSP1();
  MBBLSP2 = readBBLSP2();
  MBBRSP1 = readBBRSP1();
  MBBRSP2 = readBBRSP2();
  // Initialiseer de timers
  TSBBLSP1 = millis();
  TSBBLSP2 = millis();
  TSBBRSP1 = millis();
  TSBBRSP2 = millis();
  // Meld geen trein (waarde 0)
  DIRSP1 = 0;
  DIRSP2 = 0;
  // LED uit
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

  // fase: toestand nu en de vorige keer van de melder
  // volgorde:
  //  0: geen trein
  //  1: trein komt binnen
  //  2: trein verlaat
  //  3: trein aanwezig
  byte fase;

  // Spoor 1 (links)
  fase = (MBBLSP1 ? 2 : 0);
  MBBLSP1 = readBBLSP1();
  fase += (MBBLSP1 ? 1 : 0);
  if (fase == 1) {
    // Trein komt binnen
    if (DIRSP1 == 0) {      // Bij het bereiken van de andere kant alleen reageren op het verlaten
      DIRSP1++;       
    }
  }
  if (fase == 2) {
    // Trein verlaat
    if (DIRSP1 < 0) {       // Bij het verlaten van de binnen melder niet een extra puls geven.
      DIRSP1++;
    }
  }
  // Spoor 1 (rechts)
  fase = (MBBRSP1 ? 2 : 0);
  MBBRSP1 = readBBRSP1();
  fase += (MBBRSP1 ? 1 : 0);
  if (fase == 1) {
    // Trein komt binnen
    if (DIRSP1 == 0) {      // Bij het bereiken van de andere kant alleen reageren op het verlaten
      DIRSP1--;       
    }
  }
  if (fase == 2) {
    // Trein verlaat
    if (DIRSP1 > 0) {       // Bij het verlaten van de binnen melder niet een extra puls geven.
      DIRSP1--;
    }
  }
 
  // Spoor 2 (links)
  fase = (MBBLSP2 ? 2 : 0);
  MBBLSP2 = readBBLSP2();
  fase += (MBBLSP2 ? 1 : 0);
  if (fase == 1) {
    // Trein komt binnen
    if (DIRSP2 == 0) {      // Bij het bereiken van de andere kant alleen reageren op het verlaten
      DIRSP2++;       
    }
  }
  if (fase == 2) {
    // Trein verlaat
    if (DIRSP2 < 0) {       // Bij het verlaten van de binnen melder niet een extra puls geven.
      DIRSP2++;
    }
  }
  // Spoor 2 (rechts)
  fase = (MBBRSP2 ? 2 : 0);
  MBBRSP2 = readBBRSP2();
  fase += (MBBRSP2 ? 1 : 0);
  if (fase == 1) {
    // Trein komt binnen
    if (DIRSP2 == 0) {      // Bij het bereiken van de andere kant alleen reageren op het verlaten
      DIRSP2--;       
    }
  }
  if (fase == 2) {
    // Trein verlaat
    if (DIRSP2 > 0) {       // Bij het verlaten van de binnen melder niet een extra puls geven.
      DIRSP2--;
    }
  }
 
  // Aansturen van de AKI / AHOB (overweg)
  if ((DIRSP1 == 0) && (DIRSP2 == 0)) {
    // Overweg geopend
    digitalWrite(LED_BUILTIN, LOW);
  } else {
    // Overweg gesloten
    digitalWrite(LED_BUILTIN, HIGH);
  }
}
Uitleg bij de code:
In de eerste regels zijn de ingangen gedefinieerd. Gebruik gewoon de nummers die op het Arduino bordje staan. Doordat de ingangen nu een naam hebben gekregen zijn ze gemakkelijk te gebruiken in de code.
Hierna is de vertraging gedefinieerd, die bij het wegvallen van de detektie opgeteld wordt om in de software korte onderbrekingen op te vangen.

Dan volgen de variabelen zoals die gebruikt worden in het programma. Als eerste 4 booleans om de stand van de melder te onthouden. Daarna 4 timers om bij te houden wanneer voor het laatst een sensor is gezien.
Tenslotte een tweetal variabelen om de toestand van de sporen vast te leggen. Dit is een zogenaamde state variabele (zie uitleg Meino).

Nu volgens de functies waaruit het programma is opgebouwd, naast de verplichte functies setup() en loop().
Dit zijn 4 functies die ieder een sensor behandelen.
De werking van de functie is als volgt:
Eerst wordt het niveau van de ingang vastgesteld. Meld deze dat er een trein aanwezig is, dan wordt de timer van deze ingnag geladen met de huidige stand van de millis teller (interne teller van de Arduino) plus de vertraging.
Tenslotte wordt er boolean gemaakt die aangeeft of de huidge stand van de millis teller kleiner is dan de timer value.
Dit is om te zorgen dat het resultaat van deze functies niet gestoord wordt door verstoringen, doordat de uitgang van de sensor even van stand veranderd.
Dan volgen de verplichte functies setup() en loop(). Setup zal alle in- en uitgangen goed zetten en de variabelen van hun begin waarde voorzien.
Loop() is het uiteindelijke programma. Ook hier wordt weer een finite state pattern gebruikt (het is tenslotte mijn favoriete pattern en ben de "Gang of four" dankbaar voor het definiëren.) Het gaat in dit geval om de variabele fase. Deze kent de waardes 0 t/m 3 en ontstaat uit de waarde van de sensor van de vorige loop() doorloop en de huidige. De waarde van fase doorloopt de 4 waardes op de volgende manier:
De waarde van de melder uit de vorige loop zal de waarde van fase vullen met 0 (geen trein) of 2 (trein). Hierna wordt naar aanleiding van de huidige weaarde er 0 (geen trein) of 1 (trein) bij opgeteld. Als een trein door de sensor (lichtsluis) rijdt, ontstaat nu het volgende patroon:
.......000013333........333320000........
De waardes 0 en 3 komen vaak voor en vertellen dat de situatie constant is gebleven. Echter 1 (voorkant van de trein) en 2 (achterkant van de trein) komen per passage maar een keer voor. Nu moet alleen nog uitgezocht worden hoe de toestand waarin het spoor rond de AKI zich bevind is. Hiervoor zal de volgende finite state variabele gebruikt worden. Dit is dirSPx. Deze variabele kent de waardes 0 (geen trein), 1 (trein rijdt van links naar rechts) en -1 (trein rijdt van rechts naar links). De variabele idrSPx mag alleen onder bepaalde voorwaarde verhoogd / verlaagd worden.
Uiteindelijk zal dirSPx altijd terug komen op 0. Als alle dirSPx variabelen 0 zijn, mag de AKI geopend worden. Indien een disSPx niet 0 is moet de AKI gesloten worden. In dit geval zal bij gesloten AKI de LED op de Arduino oplichten en pen 13 5V voeren, ten teken dat de AKI dicht moet.
(Verderop gaan we de code uitbreiden met het aansturen van de LEDs van de AKI.)

Huiswerk:  ;D
@Edsko (en wie nog meer wil):
Schakeling bouwen en testen. We zijn hier nieuwsgierig naar het resultaat. Gezien het weer verwachten we dat je een poosje bezig zult ziijn.

@Allen:
Mochten er vragen opmerkingen of andere dingen zijn, post ze gerust.

@C goeroes:
Het programma roept om optimalisatie. Ik weet dat dit mogelijk is, maar moet te veel research op het internet doen om het in C voor elkaar te krijgen.
Help mij en Edsko door met voorbeelden te komen hoe stukken code geoptimaliseerd kunnen worden. Zie het als een een simpele wedstrijd zoals Meino aangaf.

Zo ik ga met vakantie en zal alleen via mijn mobiel meelezen en reageren. Dus verwacht de komende dagen geen lappen tekst meer.

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

meino

  • Offline Offline
  • Berichten: 167
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #31 Gepost op: 22 mei 2018, 12:28:19 »
Oke,

Alles even samenvatten:

Eisen/Wensen:

Aansturing van een AKI door een trein. Aan de trein mogen geen aanpassingen gedaan worden. De AKI is dubbelsporig en moet van beide zijde op hetzelfde spoor aangestuurd worden. Gekozen is voor aansturing via "lichtsluizen" en een Arduino.
Eventuele knippenringen door de lichtsluizen worden door een schuine opstelling verminderd, geheel voorkomen kan niet. Dit wordt niet door extra hardware opgelost.

Je bent snel. Ik vind het ook een mooie uitdaging/puzzle, dus ben ik ook maar aan een stukje code begonnen, alleen mijn code is totaal anders (Object oriented met classes), wel gebruik ik de zelfde toestanden als jij. Als ik klaar ben zal ik mijn versie ook wel even publiceren.

Citaat
@C goeroes:
Het programma roept om optimalisatie. Ik weet dat dit mogelijk is, maar moet te veel research op het internet doen om het in C voor elkaar te krijgen.
Help mij en Edsko door met voorbeelden te komen hoe stukken code geoptimaliseerd kunnen worden. Zie het als een een simpele wedstrijd zoals Meino aangaf.
Ik ben lang geleden gestopt om de code zelf te optimaliseren, mijn ervaring is dat de GNU compilers dermate goed zijn in het optimaliseren, dat eigen pogingen vaak averechts werken of hooguit geen invloed hebben. Ik vind het veel belangrijker dat de code goed leesbaar is.

Citaat
Zo ik ga met vakantie en zal alleen via mijn mobiel meelezen en reageren. Dus verwacht de komende dagen geen lappen tekst meer.
Prettige vakantie, ook ik vertrek van de week. Heb wel de laptop bij me, dus zolang er wifi is kan ik kontact houden.

Groet Meino
« Laatst bewerkt op: 22 mei 2018, 12:31:03 door meino »
A clean desk is a sign of an empty mind

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3031
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #32 Gepost op: 22 mei 2018, 13:47:34 »
<off topic>

Kom er al 11 jaar. In geen velden of "asfaltwegen" wifi te vinden. De telefoon gaat terug naar 3G. Internet is er traaaaaaaaag (dankzij de EU is er tenminste internet voor buitenlanders). Gaan twee keer per dag koffie drinken om "up to date" te blijven. Verder genieten van het groeien van de rijst in de rijstvelden (ja, ik ben in Europa). Maar eerst vrijdag en zaterdag 1700 km rijden met dit:

<on topic>

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

NS264

  • Team forummoderators
  • Offline Offline
  • Berichten: 4701
  • Koen Frijlink
    • Midland
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #33 Gepost op: 22 mei 2018, 13:56:47 »
Met interesse kijk ik mee:

Ik heb een leuke voor jullie.

Zelfde situatie, alleen driesporig.

- knipperleds(oranje)
- stepper controller voor 2 servos voor slaghekwerk.
- fotocellen als lichtsluis.

Verder breadboard en verzameling weerstanden en toebehoren aan draad tot beschikking om te experimenteren.

Ben nu alleen ook niet thuis, maar wel van plan dit te gebruiken met een Arduino Mega 2560.

Zonodig in eigen draadje want het is niet met Ali-lichtsluisjes.

Heb een leuk tutorial (klik) gezien van een Duitser die ook nastuiterende slagboom geprogrammeerd heeft.
Erg interessant, moet ik ff opzoeken
Sketch staat er ook bij.

Start bij terugkomst uit het verre Lettele ::) wel een topic in deze hoek van het forum.

Gr Koen.
« Laatst bewerkt op: 22 mei 2018, 14:14:17 door NS264 »
Kijk eens op Midland Industriebaan, IV
MultiMuis en Arduino Techniek. HO
NewMancavemusic

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3031
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #34 Gepost op: 22 mei 2018, 14:25:00 »
Hm een forum moderator. Nu even voorzichtig zijn, want voor het weet mag je niet meer op de site.

De code is "per spoor" geschreven. Als je de namen volgt dan zie je dat er SP1 en SP2 gebruikt wordt. Copieer iedere SP2 en maak daar SP3 van dan ben je al halverwege (SBBLSP3, SBBRSP3, MBBLSP3, MBBRSP3, TSBBLSP3, TSBBRSP3 en DIRSP3 ). Van de read functies de laatste twee copieren en de 2 vervangen door een 3 en tenslotte in setup() de nieuwe variabelen toevoegen en initialiseren.
In loop() het stuk gemarkeerd met spoor 2 (links) en spoor 2 (rechts) copieren (eronder). De 2-en vervangen door 3-en. en tenslotte de regel
if ((DIRSP1 == 0) && (DIRSP2 == 0)) {
vervangen door:
if ((DIRSP1 == 0) && (DIRSP2 == 0) && (DIRSP3 == 0)) {

Je hebt de code nu voor 3 sporen.
Het knipperen komt als Edsko er aan toe is, want ook zijn AKI gaat knipperen.

Groet,

Gerard van der Sel.

Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

meino

  • Offline Offline
  • Berichten: 167
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #35 Gepost op: 22 mei 2018, 14:44:49 »
Met interesse kijk ik mee:

Ik heb een leuke voor jullie.

Zelfde situatie, alleen driesporig.

- knipperleds(oranje)
- stepper controller voor 2 servos voor slaghekwerk.
- fotocellen als lichtsluis.

Ik weet nog niet hoe het met Gerards code zit (dat nog niet goed bestudeerd), maar mijn code heeft daar geen probleem mee. Ik hanteer voor ieder spoor een aparte state machine. De stand voor de AKI wordt bepaald door een AND conditie over de staat van alle sporen. Dus het is simpel te imlementeren door de de AND conditie met extra sporen uit te breiden.
Het aansturen van steppers in plaats van leds is een wijziging in de techniek. en niet zo moeilijk.

Groet Meino
A clean desk is a sign of an empty mind

NS264

  • Team forummoderators
  • Offline Offline
  • Berichten: 4701
  • Koen Frijlink
    • Midland
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #36 Gepost op: 22 mei 2018, 15:13:24 »
@Gerard,

Ik maak gewoon dankbaar gebruik van alle technische kennis die er is hier.
Mijn kennis is 0.
Maar het lijkt me niet het allermoeilijkste om dit voorelkaar te krijgen.
Achter de forum schermen al een beetje opweg geholpen door Meino.
Loop wel iets vooruit op mijn eigen planning want ik wou eerst een enkele servo en een enkele led laten werken voor oefening, maar dat geloof ik naar aanleiding van de vele filmpjes op YouTube eerlijk gezegd wel en maakt het interessant voor mij om gelijk maar een stap verder te gaan.

Zoals ik al zei ben ik ook nu niet thuis, maar ik heb al een testplankje klaar liggen met stukje spoor om van start te gaan.

Zal het as weekend starten ;D
Kijk eens op Midland Industriebaan, IV
MultiMuis en Arduino Techniek. HO
NewMancavemusic

meino

  • Offline Offline
  • Berichten: 167
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #37 Gepost op: 22 mei 2018, 19:03:56 »
Gerard was sneller met zijn code. maar ik was ook al begonnen omdat ik ook op Kranenberg wel een werkende AKI wil hebben.

Dit is mijn stukje code. Let wel het is nog niet getest. Voor test doeleinden kun je de define DEBUG op 1 zetten dan genereert de code log output op de seriele monitor van de Arduino IDE.

#define DEBUG 0

enum SpoorState {leeg,
                 sensor1komend,
                 sensor2komend,
                 sensor1gaand,
                 sensor2gaand
                };
//
//  Class for a single (white) led which flickers 50 times per
//  minute when on
//             
class SingleLed
{
  private:
    int ledPin;
    bool ledOn = true;
    int interval = 600;      // *** 50 keer per minuut
    bool lightOn = false;
    unsigned long lastTime;

  public:
    //
    //  Create a new instance of a (white) led, connect it to the specified
    //  digital pin and put it in the specified state (true = on, false = off)
    //
    SingleLed(int aPin, bool state)
    {
      ledPin = aPin;
      ledOn = state;
      lightOn = false;
      pinMode(ledPin, OUTPUT);

      lastTime = millis();
    }

    //
    //  Set the state of the led (true = on, false = off)
    //
    void setOn(bool state)
    {
      ledOn = state;
    }

    //
    //  If the state is on, put power on the pin of the led, using timers
    //  to make the flicker work.
    //  If the led is off, remove the power from the pin of the led.
    //
    void heartBeat()
    {
      if (ledOn)                               // Do we need to light the led?
      {
        unsigned long currTime = millis();
        if ((currTime - lastTime) >= interval) // Has the interval time passed?
        {
          lastTime = currTime;                 // Start new interval
          if (!lightOn)                        // Was the led lighted?
          {
            digitalWrite(ledPin, HIGH);        // No, so switch it on
            lightOn = true;
          }
          else
          {
            digitalWrite(ledPin, LOW);         // Yes, so switch it off
            lightOn = false;
          }
        }
      }
      else if (lightOn)                        // No light, but is the led still on?
      {
        digitalWrite(ledPin, LOW);             // Switch ir off
        lightOn = false;
      }
    }
};

//
//  Class for a set of two (red) leds which alternate(flicker) 50 times per
//  minute when on
//
class DuoLed
{
  private:
    int led1Pin;
    int led2Pin;
    bool ledOn = true;
    int interval = 600;      // *** 50 keer per minuut
    bool lightOn = false;
    unsigned long lastTime;

  public:
    //
    //  Create a new instance, connect it to the specified
    //  digital pins and put it in the specified state (true = on, false = off)
    //
    DuoLed(int aPin1, int aPin2, bool state)
    {
      led1Pin = aPin1;
      led2Pin = aPin2;
      ledOn = state;
      lightOn = false;
      pinMode(led1Pin, OUTPUT);
      pinMode(led2Pin, OUTPUT);

      lastTime = millis();
    }

    //
    //  Set the state of the leds (true = on, false = off)
    //
    void setOn(bool state)
    {
      ledOn = state;
    }

    //
    //  If the state is on, put power on the pins of the leds, using timers
    //  to make the alternating flicker work.
    //  If the led is off, remove the power from the pins of the leds.
    //
    void heartBeat()
    {
      if (ledOn)                                  // Are the leds activated
      {
        unsigned long currTime = millis();
        if ((currTime - lastTime) >= interval)    // Has the interval passed?
        {
          lastTime = currTime;                    // Yes, start new interval
          if (!lightOn)                           // The leds alternate, are we in phase1 (led1 on, led2 off)
          {
            digitalWrite(led1Pin, HIGH);          // Yes, led1 on
            digitalWrite(led2Pin, LOW);           // led2 off
            lightOn = true;                       // When the interval expires, switch the leds
          }
          else                                    // We are in phase2 (led1 off, led2 on)
          {
            digitalWrite(led1Pin, LOW);           // Led1 off
            digitalWrite(led2Pin, HIGH);          // Led2 on
            lightOn = false;                      // When the interval expires, switc the leds
          }
        }
      }
      else                                        // The leds are not active, switch of both leds
      {
        digitalWrite(led1Pin, LOW);
        digitalWrite(led2Pin, LOW);
        lightOn = false;
      }
    }
};

enum AkiStaat {aan, uit};

//
//  A simple class that represents a complet AKI with all its leds
//
//  TBD, the sound of the bells
//
class AKI
{
  private:
    SingleLed *whiteLight;
    DuoLed    *redLights;
    AkiStaat state = uit;
   
  public:
    //
    //  Create an instance of the AKI, using the specified Led objects
    //
    AKI(SingleLed *aWhiteLed, DuoLed *aRedLed)
    {
      whiteLight = aWhiteLed;
      redLights = aRedLed;
      state = uit;
    }

    //
    //  Activate the connected leds. TBD: the sound
    //
    void heartBeat()
    {
      redLights->heartBeat();
      whiteLight->heartBeat();
    }

    void set(AkiStaat aState)
    {
      state = aState;
     
      if (state == uit)
      {
#if (DEBUG)
          Serial.println("[AKI::set] AKI uit");
#endif
        redLights->setOn(false);
        whiteLight->setOn(true);
      }
      else
      {
#if (DEBUG)
          Serial.println("[AKI::set] AKI aan");
#endif
        redLights->setOn(true);
        whiteLight->setOn(false);
      }
    }
};

//
//  Some sensors use a digital signal and keep it high when not active and drop the signal
//  when the sensor trips, use in that case the laag setting. Others use a digital signal
//  and are low when not active and make the signal high when the sensor trips, use in that case
//  the hoog setting.
//  if the sensor doesn't generate a digital signal, you have to use a pullup resistor (or INPUT_PULLUP)
//  and in that case specify hoog.
//
enum SensorTrigger {laag, hoog};

//
//  A simple class which represents the state of a single sensor
//
class Sensor
{
  private:
    int sensorPin;
    SensorTrigger type = hoog;
    bool state = false;           // true = on, false = off 

    unsigned long lastTime = 0;   // Timer to ignore short interrupts
    #define JITTER_TIME   1000    // wait a second before the sensor goes off

  public:
    //
    //  Create a new instance
    //
    Sensor(int aPin)
    {
      sensorPin = aPin;
      pinMode(sensorPin, INPUT);
    }

    //
    //  Create a new instance
    //
    Sensor(int aPin, SensorTrigger aType)
    {
      sensorPin = aPin;
      type = aType;
      pinMode(sensorPin, INPUT);
    }

    //
    //  Return the current logical state of the sensor
    //
    bool getState()
    {
      return state;
    }

    //
    //  Monitor the physical sensor and update the state accordingly
    //
    void heartBeat()
    {
      if (digitalRead(sensorPin) == HIGH)
      {
        if (type == laag)       // For sensors type laag an high signal means they are in the off state     
        {
          if (state != false)   // Process this signal only when the current state is ON
          {
            if (lastTime == 0)
            {
              lastTime = millis();  // start Interval
            }
            else
            {
              unsigned long currTime = millis();
              if ((currTime-lastTime) >= JITTER_TIME)
              {
#if (DEBUG)
                Serial.println("[Sensor::heartBeat] sensor goes off");
#endif
                state = false;       // sensor goes OFF
                lastTime = 0;        // Reset interval timer
              }
            }
          }
        }
        else
        {
#if (DEBUG)
          Serial.println("[Sensor::heartBeat] sensor goes on");
#endif
          state = true;        // Sensor goes ON
          lastTime = 0;        // Reset interval timer
        }
      }
      else          // sensorPin  = LOW
      {
        if (type == laag)
        {
#if (DEBUG)
          Serial.println("[Sensor::heartBeat] sensor goes on");
#endif
          state == true;       // Sensor goes ON
          lastTime = 0;        // Reset interval timer;
        }
        else
        {
          if (state != false)   // Process this signal only when the current state is ON
          {
            if (lastTime == 0)
            {
              lastTime = millis();  // start Interval
            }
            else
            {
              unsigned long currTime = millis();
              if ((currTime-lastTime) >= JITTER_TIME)
              {
#if (DEBUG)
                Serial.println("[Sensor::heartBeat] sensor goes off");
#endif
                state = false;       // sensor goes OFF
                lastTime = 0;        // Reset interval timer
              }
            }
          }
        }
      }     
    }   
};

//
//  A finite state machine that guards a occupance of a single track
//
class SpoorControl
{
  private:
    Sensor *sensor1;
    Sensor *sensor2;
   
    SpoorState  state = leeg;

    //
    //  Based on the state of sensor 1 and the current state of the FSM, a new state
    //  is calculated.
    //
    void handleSensor1(bool trigger)
    {
      if (trigger)                      // Sensor 1 is ON
      {
        if (state == leeg)              // If the state is "leeg" it means that a train enters the section
        {
#if (DEBUG)
          Serial.println("[SpoorControl::handleSensor1] state is sensor1komend");
#endif
          state = sensor1komend;        // so set it to state komend
        }
        else if (state == sensor2komend) // if the other sensor tripped first
        {
#if (DEBUG)
          Serial.println("[SpoorControl::handleSensor1] state is sensor1gaand");
#endif
          state = sensor1gaand;          // The train is starting to leave the section
        }
      }
      else
      {                                  // Sensor went OFF
        if (state == sensor1gaand)       // If the train started to leave via sensor 1
        {
#if (DEBUG)
          Serial.println("[SpoorControl::handleSensor1] state is leeg");
#endif
          state = leeg;                  // the section is "leeg"
        }
      }
    }

    //
    //  Based on the state of sensor 2 and the current state of the FSM, a new state
    //  is calculated.
    //
    void handleSensor2(bool trigger)
    {
      if (trigger)                          // Sensor 2 is ON
      {
        if (state == leeg)                  // Is the section "leeg"?
        {
#if (DEBUG)
          Serial.println("[SpoorControl::handleSensor2] state is sensor2komend");
#endif
          state = sensor2komend;            // A Train entered the section via sensor 2
        }
        else if (state == sensor1komend)    // No a train entered the section via the other sensor
        {
#if (DEBUG)
          Serial.println("[SpoorControl::handleSensor2] state is sensor2gaand");
#endif
          state = sensor2gaand;             // Start the leaving process
        }
      }
      else
      {
        if (state == sensor2gaand)          // A train is in the process of leaving
        {
#if (DEBUG)
          Serial.println("[SpoorControl::handleSensor2] state is leeg");
#endif
          state = leeg;                     // Section is empty again
        }
      }
    }

  public:
    //
    // Create an instance with two sensors
    //
    SpoorControl(Sensor *aSensor1, Sensor *aSensor2)
    {
      sensor1 = aSensor1;
      sensor2 = aSensor2;
    }

    //
    //  Get give the sensors a kick and check their state so we can update our own
    //  state.
    //
    void heartBeat()
    {
      sensor1->heartBeat();
      sensor2->heartBeat();

      handleSensor1(sensor1->getState());
      handleSensor2(sensor2->getState());
    }

    //
    // Return the current state of the section
    //
    SpoorState getState()
    {
      return state;
    }
};

//
//  Create 2 FSM controling two track sections
//
SpoorControl spoor1(new Sensor(A0, hoog), new Sensor(A1, hoog));
SpoorControl spoor2(new Sensor(A2, hoog), new Sensor(A3, hoog));

//
// Create an instance of the AKI
//
AKI aki(new SingleLed(A4, true), new DuoLed(A5, A6, false));

void setup()
{
#if (DEBUG)
  //Serial.begin(9600);
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Starting");
  Serial.flush();
#endif //DEBUG
 

}

void loop()
{
  spoor1.heartBeat();     // These object must monitor their sensors
  spoor2.heartBeat();     // so they can update their states

  if ((spoor1.getState() == leeg) && (spoor2.getState() == leeg))
  {
    aki.set(uit);         // Stop sound and flashing red lights
  }
  else
  {
    aki.set(aan);         // Start flashing red lights and sound
  }

  aki.heartBeat();        // Let the AKI update it's connected bells and leds
}

Zoals jullie kunnen zien kom ik uit een andere IT wereld dan Gerard, dus ik probeer altijd zoveel mogelijk de functionaliteit in aparte classes (objecten) te stoppen.

Groet Meino
A clean desk is a sign of an empty mind

meino

  • Offline Offline
  • Berichten: 167
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #38 Gepost op: 23 mei 2018, 00:09:56 »
Ik heb een kleine opmerking over de code van Gerard. Ik zie dat hij de sensor pins initialiseer met INPUT_PULLUP, ik denk dat dat niet goed gaat werken, omdat deze bordjes zelf een goede 5v of een goede gnd maken. Ik initialiseer de pinnen dus met INPUT. Verder als de IR receiver geen IR ziet, dan zet hij het signaal hoog (5v), op het moment dat hij IR ziet, gaat het signaal naar low (0v). Dat betekend dat als de detector gemodificeerd wordt om als lichtsluis te werken, een HIGH signaal betekend dat de IR is onderbroken en een LOW signaal betekend dat IR niet onderbroken is.
Tenminste dat is de situatie met de benadering detectors die ik heb van het merk "Flying fish", die het zelfde zijn als die Edsko heeft aangeschaft.

@Gerard
Leuk stekje waar je naar toe gaat.

Groet Meino
« Laatst bewerkt op: 23 mei 2018, 00:15:15 door meino »
A clean desk is a sign of an empty mind

Hennik

  • Offline Offline
  • Berichten: 7
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #39 Gepost op: 23 mei 2018, 00:55:31 »
Geïnspireerd door de vele berichten op dit forum wat je allemaal met Arduino kan, heb ik me er de laatste weken flink in verdiept en mee geëxperimenteerd. Geweldig hoeveel kennis hier gedeeld wordt!

Ik ben zelf meer een lezer dan een reageerder (sorry), maar wellicht kan ik hier toch even wat zinvols toevoegen als het gaat om stuiterende slagbomen.

Volgende link kwam ik namelijk tijdens mijn zoektochten op internet tegen. Het toont weliswaar een sketch voor locloodsdeuren, het principe van de versnelling en vertraging bij openen, en ook de terugvering, kan met kleine wijzigingen het gedrag van de eerder genoemde Duitse tutorial leuk benaderen.
Zie: http://www.locoduino.org/spip.php?article159

Te 2/2

  • Offline Offline
  • Berichten: 524
  • Metrop-Märklin
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #40 Gepost op: 23 mei 2018, 09:46:03 »
Jaren geprogrammeerd in zowel de Gerard als de Meino stijl, in alles waarmee te  programmeren viel, maar toch allermeest als glu'er (5 regeltjes code schrijven om 2 programma's die niet voor elkaar gemaakt zijn, te laten samensmelten alsof ze een geheel zijn). Beide codes laten zich lezen als een speer.  Mooie codes ook.

Maar ik voel me 't meest aangetrokken door Meino's aanpak vanwege het bereikte abstractieniveau:
//class SpoorControl
//
//  Create 2 FSM controling two track sections
//
SpoorControl spoor1(new Sensor(A0, hoog), new Sensor(A1, hoog));
SpoorControl spoor2(new Sensor(A2, hoog), new Sensor(A3, hoog));

Ik ben alweer jaren geleden gestopt met dat werk als "mastergluer" (=lijmen-jan)  ;D
Maar ik nam de code even door, en toen kwam het allemaal weer boven.

Ik zie nu in waarom Gerard en Meino van 4 sluisjes uit gaan op 4 aparte pinnen en niet van 4, 2 aan 2 aangesloten, sluisjes (wat weliswaar 2 arduino pinnen scheelt, maar ook aanzienlijk minder flexibel is).

Toch vraag ik me af of je met twee sluizen over 2 of meer sporen, niet beter af bent dan met 2 sluizen per spoor.
Jan Willem

analoog hybride DC baan (2-rail+3-rail),
CH, peco, piko, roco, k-rail

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3031
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #41 Gepost op: 23 mei 2018, 09:50:17 »
Aangespoord door de opmerking van NS264 toch maar de code herzien naar objecten. Ik werk graag met de classes in aparte files dus in mijn geval spat de sketch uiteen in drie files, de sketch en 2 ander files voor een class.
In tegen stelling tot wat Meino in zijn code alvast heeft gedaan, heb ik nog niet de AKI knipper-lichten van aansturing voorzien. Dit komt wel als dit door Edsko wat duidelijker gedefinieerd is.

Hieronder de nieuwe sketch:
// Definitie van de 4 ingangen voor de sensoren (2 per spoor)
#define SBBLSP1    2   // BlackBox Links, Spoor 1
#define SBBRSP1    3   // BlackBox Rechts, Spoor 1
#define SBBLSP2    4   // BlackBox Links, Spoor 2
#define SBBRSP2    5   // BlackBox Rechts, Spoor 2

#define DELAY    500   // Vertraging in milli seconde

#define NUMSPOREN  2   // Aantal sporen

#include "Spoor.h"

Spoor sporen[NUMSPOREN];

// Initialialatie van de Arduino
void setup() {
  // put your setup code here, to run once:

  // Define sporen
  sporen[0] = Spoor(SBBLSP1, SBBRSP1, DELAY);     // Spoor 1
  sporen[1] = Spoor(SBBLSP2, SBBRSP2, DELAY);     // Spoor 2
 
  // LED uit
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

  bool bezet = false;
  for(int i = 0; i < NUMSPOREN; i++)
  {
     bezet |= sporen[i].calcBezet();
  }
 
  // Aansturen van de AKI / AHOB (overweg)
  if (bezet) {
    // Overweg gesloten
    digitalWrite(LED_BUILTIN, HIGH);
  } else {
    // Overweg geopend
    digitalWrite(LED_BUILTIN, LOW);
  }
}

En in dezelfde directory als de sketch komen de twee volgende bestanden:
Filenaam Spoor.h (definitie van de class):
#ifndef Spoor_h
#define Spoor_h

#include "Arduino.h"

class Spoor {
public:
  Spoor();      // for array
  Spoor(byte sensorLinks, byte sensorRechts, int sensorDelay);
  bool calcBezet();

private:
  bool readLinks();
  bool readRechts();

  byte _sensorLinks;
  byte _sensorRechts;
  bool _memLinks;
  bool _memRechts;
  unsigned long _timerLinks;
  unsigned long _timerRechts;
// < 0: trein rijdt van rechts naar links
// 0: geen trein
// > 0: trein rijdt van links naar rechts
  byte _dir;
  int _sensorDelay;
};

#endif

Filenaam Spoor.cpp (functionaliteit van de class):
#include "Spoor.h"

Spoor::Spoor() {
  // Empty constructor, don't use (for array)
}

Spoor::Spoor(byte sensorLinks, byte sensorRechts, int sensorDelay) {
  // Variabelen met externe waardes
  _sensorLinks = sensorLinks;
  _sensorRechts = sensorRechts;
  _sensorDelay = sensorDelay;
    // Maak de inputs met extra pullups
  pinMode(_sensorLinks, INPUT_PULLUP);
  pinMode(_sensorRechts, INPUT_PULLUP);
  // Voorzie overige variabelen van een default value
  _timerLinks = millis();
  _timerRechts = millis();
  _memLinks = readLinks();
  _memRechts = readRechts();
  _dir = 0;
}

bool Spoor::readLinks() {
  // if (digitalRead(_sensorLinks) > 0) {
  if (digitalRead(_sensorLinks) == 0) {
    _timerLinks = millis() + _sensorDelay;
  }
  return (_timerLinks > millis());
}

bool Spoor::readRechts() {
  // if (digitalRead(_sensorRechts) > 0) {
  if (digitalRead(_sensorRechts) == 0) {
    _timerRechts = millis() + _sensorDelay;
  }
  return (_timerRechts > millis());
}

// return true als bezet
bool Spoor::calcBezet() {
  // fase: toestand nu en de vorige keer van de melder
  // volgorde:
  //  0: geen trein
  //  1: voorkant trein
  //  2: achterkant trein
  //  3: trein aanwezig
  byte fase;

  // Links
  fase = (_memLinks ? 2 : 0);
  _memLinks = readLinks();
  fase += (_memLinks ? 1 : 0);
  if (fase == 1) {
    // Trein komt binnen
    if (_dir == 0) {      // Bij het bereiken van de andere kant alleen reageren op het verlaten
      _dir++;       
    }
  }
  if (fase == 2) {
    // Trein verlaat
    if (_dir < 0) {       // Bij het verlaten van de binnen melder niet een extra puls geven.
      _dir++;
    }
  }
  // Rechts
  fase = (_memRechts ? 2 : 0);
  _memRechts = readRechts();
  fase += (_memRechts ? 1 : 0);
  if (fase == 1) {
    // Trein komt binnen
    if (_dir == 0) {      // Bij het bereiken van de andere kant alleen reageren op het verlaten
      _dir--;       
    }
  }
  if (fase == 2) {
    // Trein verlaat
    if (_dir > 0) {       // Bij het verlaten van de binnen melder niet een extra puls geven.
      _dir--;
    }
  }
  return (_dir != 0);
}

Bij het openen van de sketch zal de Arduino IDE automatisch de beide class files mede openen in extra tabs.

PS. Mocht iemand Hilversum in de jaren 80 na willen bouwen, dan kan nu eenvoudig het aantal sporen uitgebreid worden.

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3031
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #42 Gepost op: 23 mei 2018, 09:57:45 »
Ik heb een kleine opmerking over de code van Gerard. Ik zie dat hij de sensor pins initialiseer met INPUT_PULLUP, ik denk dat dat niet goed gaat werken, omdat deze bordjes zelf een goede 5v of een goede gnd maken. Ik initialiseer de pinnen dus met INPUT. Verder als de IR receiver geen IR ziet, dan zet hij het signaal hoog (5v), op het moment dat hij IR ziet, gaat het signaal naar low (0v). Dat betekend dat als de detector gemodificeerd wordt om als lichtsluis te werken, een HIGH signaal betekend dat de IR is onderbroken en een LOW signaal betekend dat IR niet onderbroken is.
Tenminste dat is de situatie met de benadering detectors die ik heb van het merk "Flying fish", die het zelfde zijn als die Edsko heeft aangeschaft.
Waarom INPUT_PULLUP in plaats van INPUT. Edsko gaat werken met straal breking. Dit betekend dat de pen van de uitgang altijd laag is, tenzij er een trein de straal onderbreekt. Als extra beveiliging gebruik ik de INPUT_PULLUP, zodat bij draadbreuk tussen sensor en Arduino de Ardiono een bezette sensor ziet. Dit heeft bij reflectie geen zin en kan zelfs tot misvattingen leiden.

@Meino: Er is nog een verschil. Ik heb 30 jaar bij de NS (waaronder Movares) gewerkt. Je krijgt dan tussen je oren gestampt dat een fout in de software mensenlevens kan kosten. Dus veel code en hardware ontwerpen hebben dit nog steeds als achtergrond. Ik ben onbewust altijd opzoek naar passieve beveiligingen.

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3031
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #43 Gepost op: 23 mei 2018, 12:02:59 »
Jan Willem,

Toch vraag ik me af of je met twee sluizen over 2 of meer sporen, niet beter af bent dan met 2 sluizen per spoor.

Ik zal het proberen te verklaren. Stel je voor twee parallelle sporen met hierover zoals jij aangeeft een sluis op basis van straal onderbreking.
Op beide sporen rijdt een trein, en ze rijden naar elkaar toe (moet kunnen toch  ;D).
Een van beide treinen komt aan bij de sluis en doorbreekt de straal. De trein wordt gemeld. Terwijl deze trein door de sluis rijdt komt de andere trein ook bij de sluis. Deze kan zich niet melden, want de eerste trein heeft de straal al onderbroken. Als de eerste trein geheel weg is en de tweede trein bevindt zich nog in de sluis zal deze het onderbreken van de straal voor zijn rekening nemen. Als tenslotte de sluis weer vrij is, zal de sluis een trein gemeld hebben, terwijl er toch twee door gegaan zijn.

Ik hoop dat het voorbeeld helpt om het beveiligen te begrijpen. Je kan met een sluis over meerdere sporen werken, als je zeker weet dat er maar een trein tegelijk door de sluis gaat. Een voorbeeld hiervan is in een schaduw station. Je kunt met een straal de einden van alle sporen bewaken, als je maar zorgt dat de trein die het laatst de straal heeft doorbroken een stukje terug rijdt. Dit kan je bij Koploper zien in een schaduwstation.

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

nighttrain1

  • Powered bij Oltronix;2x300VA & plaatser moeilijkste raadplaat 2013
  • Offline Offline
  • Berichten: 3358
  • Ook deze tijd zal ooit die goeie ouwe tijd worden!
Re: Ali-lichtsluisjes en overwegaansturing met arduino
« Reactie #44 Gepost op: 23 mei 2018, 13:01:35 »
Even in "Grasland" gekeken voor de juiste opstelling. De overweg bevind zich links op de module. Dus er is een ongelijke tijd voor het aanrijden van de AKI. Is in dit geval niet storend, daar de korte aanrijtijd door de BBL (blackbox links) gecamoufleerd wordt. De rode lijnen zijn de 4 sensoren voor de AKI aansturing.

Tenzij je in de rechter BB van je linker buurman/vouw een uitschuifbare set lichtsensoren monteert zodat de in/uitrij tijd iets verlengt kan worden...
Groeten Richard, nighttrain

DCC,NS,H0,Tijdperk 3B t/m 5 + vleugje nu,Koploper,Intellibox
VAM- E'tjes- & Beneluxtreinen

2011-2018 ***** + 22x X
X=extra plaat geplaatst

Bouw:Zwederbaan & Ringvaartspoorbrug nabij Buitenkaag, deelnemer BNLS modulebaan