Cheap and universal Automatic Bidirectional Reversing Loop controller

Erik84750 May 7, 2017

  1. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Hi,

    after reading hundreds of webpages and fora on the quest for a autoreversal controller I found there is an enormous load of talk but often either confusing, conflicting, contradicting, or marketing substance on this subject. So I decided to try and fabricate something using both my C++ programmer knowledge and my electronics knowhow.

    In my quest for the holy grail of reversal control I did discover that the most crucial part in any kind of model railroad automation is the detection part: what detector to use for what purpose?

    Any kind of detector has its pros and cons, its cost, its reliability, its electrical characteristics, etc.. What I absolutely wanted to avoid is "Short-Circuit Based Detection": that is similar to fighting fore with fire, and for an electrical engineer like me the idea of short-circuit based detection is the same as cursing in the church. To my complete surprise I did find most fo the commercial units based on this principle, and as well most of fora discussions assuming this would be the only saviour for those wanting reliable autoreversal control.

    As far as detection is concerned, some systems not using short-circuit detection would require sensors that do sense a train over it but sometimes do not work properly when gaps between the wagons are present. Other non-short-circuit detection AR units would depend on just one type of sensor, or worse: on a sensor sold by the manufacturer as the only saving grace but sold at a prohibitive cost.

    So I decided one of the design constraint of my fabrication should be the possibility to use any kind of capactive, inductive, optical or other sensor that senses a loco or a full train above or underneath or alongside it without being fooled by the gaps between wagons in the train, nor by spurious false detction spikes or pulses.

    Last week I posted a first attempt on this forum in a thread that was started several years ago. Since my post there I optimised my code and improved the related drawing.

    After a few days of testing I want to present to you my new version v2 of a full automatic bi-directional auto-reverser. The drawing (part of which is credited to Dutch_Master). The new software version includes "debouncing": spurious detections, false contacts, train wagon gaps, etc.. are excluded in the detection software routines. The debouncing time is currently set at 1000 milliseconds ("unsigned debounceDelay = 1000;") but that value can be freely adjusted.

    I decided not to include frog powering because that is part of the switch command hardware.

    Design constraints:

    1. create a full automatic autoreversing controller
    2. for bi-directional use
    3. with no stopping of the loco/train
    4. without use of short-circuit detection (IMO this is a rather crude way of automating a project).
    5. with the use of any type of sensor (optical, inductive, capacitive, reed-relay, current sensing, .. just anything that reliably detects a loco above, alongside or underneath it), with preferably (but not necessarily: I just need to change the code a bit) a LOW signal when nothing is detected and a HIGH signal when detection occurs
    6. cheap (I used for testing a ATtiny85 (1.5EUR), and 3 LDR's (1EUR for 20) and a 1EUR DPDT relay (4-pole must be used if the optional tracks are cut): total cost less then 5EUR in hardware.
    7. reliable: it all depends on the sensors used; the software is foolproof and thoroughly tested.
    8. any type of Atmega controller can be used: Arduino, Pro-Mini, ATtinyxx, etc..
    9. 5V power supply for relay, sensors, controller
    10. Must be able to be used for any kind of reversing loop (see attached drawing)

    If needed I can program the controller for you, just send me 2 units: one for return programmed and one to cover postage; just pm me.

    The ATtiny I used has following connections (see also the code):

    PB0 = LDR1 (the one inside the loop)
    PB1 = LDRa
    PB2 = LDRb
    PB3 = Relay output (EDIT: beware: a controller supplies a max of about 10 to 20mA safely per output: use a high impedance relay https://www.aliexpre...d-58936f8fd807 which in turn drives the power relay).

    Make sure you cut the trace to the LED connected to PB1 or the voltage divider used for the LDR will not work properly. But best of all is to use an LDR driving a comparator, no need for calibration.

    This is the controller I use: https://www.aliexpre...d3-7dd445f0e91d

    Sensors of any shape, type, price can be found on that site. So far I have ordered 450+ items from them and just a few never arrived for which I got my money back.

    Thanks for your attention, comments are greatly appreciated,

    Erik

    My code:
    Code:
    const byte Relay = 3;
    const byte LDRa = 1;
    const byte LDRb = 2;
    const byte LDR1 = 0;
    boolean A = LOW;
    int stateLDRa;
    int lastStateLDRa = LOW;
    int stateLDRb;
    int lastStateLDRb = LOW;
    int stateLDR1;
    int lastStateLDR1 = LOW;
    unsigned long lastDebounceTimeLDRa = 0;
    unsigned long lastDebounceTimeLDRb = 0;
    unsigned long lastDebounceTimeLDR1 = 0;
    unsigned debounceDelay = 1000;
    
    void setup() {
      pinMode(Relay, OUTPUT); //setting the pin mode to Output
      digitalWrite(Relay, LOW);
    }
    
    void loop() {
      // read LDRa and debounce
      int readingLDRa = digitalRead(LDRa);
      //digitalWrite(ledPin, readingLDRa);
      if (readingLDRa != lastStateLDRa) {
        lastDebounceTimeLDRa = millis();
      }
      if ((millis() - lastDebounceTimeLDRa) > debounceDelay) {
        if (readingLDRa != stateLDRa) {
          stateLDRa = readingLDRa;
        }
      }
    lastStateLDRa = readingLDRa;
      // read LDRb and debounce
      int readingLDRb = digitalRead(LDRb);
      if (readingLDRb != lastStateLDRb) {
        lastDebounceTimeLDRb = millis();
      }
      if ((millis() - lastDebounceTimeLDRb) > debounceDelay) {
        if (readingLDRb != stateLDRb) {
          stateLDRb = readingLDRb;
        }
      }
    lastStateLDRb = readingLDRb;
      // read LDR1 and debounce
      int readingLDR1 = digitalRead(LDR1);
      if (readingLDR1 != lastStateLDR1) {
        lastDebounceTimeLDR1 = millis();
      }
      if ((millis() - lastDebounceTimeLDR1) > debounceDelay) {
        if (readingLDR1 != stateLDR1) {
          stateLDR1 = readingLDR1;
        }
      }
    lastStateLDR1 = readingLDR1;
       if (stateLDRa == HIGH && stateLDR1 == LOW && stateLDRb == LOW)  //condition 1; clockwise
      { digitalWrite(Relay, HIGH);
        A = HIGH;
      }
      if (stateLDRa == LOW && stateLDR1 == HIGH && stateLDRb == LOW && A == HIGH) //condition 2; clockwise
      { digitalWrite(Relay, LOW);
      }
      if (stateLDRa == LOW && stateLDR1 == LOW && stateLDRb == HIGH) //condition 3; clockwise and counterclockwise: set relay low
      { digitalWrite(Relay, LOW);
        A = LOW;
      }
      if (stateLDRa == LOW && stateLDR1 == HIGH && stateLDRb == LOW && A == LOW)  //condition 4; counterclockwise: set relay high
      { digitalWrite(Relay, HIGH);
      }
    }
    
     

    Attached Files:

  2. kmcsjr

    kmcsjr TrainBoard Member

    1,700
    53
    27
    Erik
    That looks really neat. Have you considered liking at DCC++ and seeing if this could be somehow incorporated? That would be really cool.


    Sent from my iPhone using Tapatalk
     
  3. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Hi Marty,

    thank you for your reply. What do you mean by "linking to DCC++"? Please explain because I think my proposal could indeed be of use to many of us, and I would like to continue to support any request for help.
    Also, I am currently testing a number of detector ideas that should be able to be used with this autoreversal unit; in time I will duly report on my progress on this issue.
    Rgds,
    Erik
     
  4. Greg Elmassian

    Greg Elmassian TrainBoard Member

    312
    47
    11
    he said "liking" not "linking", and I believe he meant "looking"....
     
  5. kmcsjr

    kmcsjr TrainBoard Member

    1,700
    53
    27
    I meant linking, as in incorporating it into the DCC++ software. That said. I'm clueless, on how his works. I just know, that my daughter is taking an uno, motor shield a Rpi, a double loop, a double crossover, and a few locos, to her internship, this summer. She's a computer engineering major, and will help me get this going. I am PARTICULARLY interested in this, not only for reverse loops, but to throw a turnout, or a ladder, if a loco approaches from a point! I'm very excited.


    Sent from my iPhone using Tapatalk
     
  6. Grey One

    Grey One TrainBoard Supporter

    7,822
    24
    90
    Very interesting. I don't understand much of it but I'll follow this anyway.
     
  7. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    The wiring in drawing 1 is pretty self-explanatory in that it shows each wire and each contact. However, this is shown for a 4-pole relay.
    If you want to keep it simple use a 2-pole relay and delete lower two poles in the drawing, delete the orange and brown wires, and delete the optional cuts (pink rectangles).

    If you want to use this autoreverser for circuit such as drawings 2 to 4: just use a 2-pole relay and connect the DET-a, DET-b and DET-1 sensors to the following controller inputs (italics copied from my initial post, but now with the correct detector designations in bold red so that it corresponds with the drawing 1):

    The ATtiny I used has following connections (see also the code):

    PB0 = LDR1 (the one inside the loop)
    PB0 to DET-1 (always use this one INSIDE the loop)
    PB1 = LDRa PB1 to DET-a
    PB2 = LDRb PB2 to DET-b
    PB3 = Relay output (EDIT: beware: a controller supplies a max of about 10 to 20mA safely per output: use a high impedance relay https://www.aliexpre...d-58936f8fd807 which in turn drives the power relay).

    Little remark: in my program I designate DET-1 to variable LDR1, DET-a to variable LDRa; and DET-b to variable LDRb; in my next revision of the program I will change the variable names to those used in the drawings.

    If you want to control switch points too then you can use the relay contact; this is however a latching contact so it will burn switch contacts that just want a pulse. If it is desired I can add an extra output in the program (for example to PB4) to give a pulse of any length to it as soon as the RELAY output is activated.
     
    Last edited: May 9, 2017
  8. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Hi, thank you for your "compliments" (I don't know if this is the correct english word). Please do not hesitate to tell me what it is that you would like to be clarified in my post. My goal is that this should be understood by anyone who knows how to connect wires to a DPDT switch or to a relay.
     
  9. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    [QUOTE="kmcsjr, post: 1014758, member: 10057"... I just know, that my daughter is taking an uno, motor shield a Rpi, a double loop, a double crossover, and a few locos, to her internship, this summer. She's a computer engineering major, and will help me get this going. I am PARTICULARLY interested in this, not only for reverse loops, but to throw a turnout, or a ladder, if a loco approaches from a point! I'm very excited..
    Sent from my iPhone using Tapatalk[/QUOTE]

    I will work out and post a solution for a double crossover that is linked to a loop.
     
  10. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Double crossover: that is a special one because it contains two reversing loops in one when seen by the program.

    This can be solved by using 2 detectors called DET-a and 2 detectors called DET-b. Both pairs of detectors have to be connected to their respective controller inputs: both DET-a to PB1 and both DET-b to PB2.
    Since the controller inputs are high impedance these inputs don't care from which detector the HIGH or LOW signals come. However, to avoid conflicts between the detector pair outputs (since they are wired to the same input), it may be advisable to add a forward diode to each detector output before connecting them to their controller inputs.
     

    Attached Files:

  11. chi.sp

    chi.sp New Member

    7
    12
    3
    Hi Erik,

    Thank you for sharing this project!

    I think I've got the concept but my electronic skills are still of someone who are playing with Arduino not too long ago and not so familiar with all type of modules, relay models, etc...so could you help me with the relay part?

    I'm not sure how to connect cables into relay module you suggested in the Aliexpress link. Using your Illustrator draw as reference, do we need two modules, one having Green cable into COM input, Black into NC, Red into NO and another module with Blue cable into COM input, Red into NC and Black into NO input? Sorry for the rookie question.

    Alternatively, may I use a DPDT Relay Module Polarity Reversal such as this one?
    http://www.ebay.com/itm/DR21A01-DC-...065783?hash=item1eb4118477:g:BmIAAOSwhOVXfgKv

    Regards
    Chi
     
  12. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Hi chi.sp,
    thanks for your kind post; to me it is a pleasure to return my knowledge to a board that already gave me so much information.

    The relay I refer to in my post has the following conections on the input side:
    Vcc: to be connected to the controller +5V
    GND: to be connected to the controller GND
    IN: to be connected to the controller PB3 pin (designated as output in the program)

    Then this relay also has a GND, NO and NC output contacts: use GND and NO to drive the 2-pole double throw relay that I refer to in my drawing (and that is used to switch around the DCC poles). Connect the relay power supply to either the GND or the NO connection, then you connect the other output (either GND or NO, whichever you did not use) to one of the relay coil contacts, the other coil contact needs to go to the GND of the relay power supply.
    My relay can drive anything up to 240Vac, so for that matter you could even drive contactors with my relay!

    I think the relay board you refer to in your post will be applicable: connect as above, Vcc to +5V, GND to controller GND and the IN or INPUT or whatever the contact that is used to switch the relay is named. I fact I think it is even better than my proposal because it looks to me you can drive the relay straight from an Arduino output pin and switch quite large amperage loads.
     
    Last edited: May 9, 2017
    chi.sp likes this.
  13. RT_Coker

    RT_Coker TrainBoard Supporter

    517
    31
    13
    Nice work!

    Using only one detector in the center of the reverse-loop requires the loop to be twice as long as the length of the “powered” part of the trains that can cross the rail-cuts. It should be possible to use 2 detectors in the reverse-loop (with the added code) to allow for ~2 times the “powered” train length.

    Bob
     
  14. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Not right: the software takes care of this; the "powered" part between the cuts only needs to be as long as your longest train. Not twice as long.
     
  15. RT_Coker

    RT_Coker TrainBoard Supporter

    517
    31
    13
    An example of what I am saying is a train that is more than half the length of the reverse-loop and with multi-wheel-power-pickup-locos at both ends will cause a track-cut to be shorted. But I will not argue with the point further. I will just suggest than you give it a test.

    Bob
     
  16. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Bob, when a train passes over DET-a then the tracks in the DET-1 section will be made electrically in line with the tracks on DET-a. This will remain so as long as DET-a is covered plus the debounce time. Regardless of where the train is in the DET-1 section.
    Only when DET-a is cleared will the relay be activated.
    So, the track between the cuts will have to be only as long as your longest train, regardless of the amount of electrically connected wheels, regardless whether you have loco's front and end.
     
    Last edited: May 9, 2017
  17. RT_Coker

    RT_Coker TrainBoard Supporter

    517
    31
    13
    Have you tied stopping a train in the loop “Only when DET-a is cleared will the relay be activated” and then reversing the trains direction out of the loop?

    Bob
     
  18. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Once the train enters the loop over DET-a and is inside the loop with DET-a cleared there is no way you can back out again over DET-a without an additional sensor inside the isolated track and before DET-a.
    In this routine it is provided that the trains run out the way they run in.

    If you need this additional feature then this can be done by adding 2 additional sensors inside the loop at the entrance and exit; the routine can easily be programmed for that feature.
     
  19. RT_Coker

    RT_Coker TrainBoard Supporter

    517
    31
    13
    Just trying to help. Most of us in the hobby (in USA) need to try and make things as accident proof as possible, including me. I think it has something to do with our advanced age.

    Bob
     
  20. Erik84750

    Erik84750 TrainBoard Member

    92
    49
    4
    Sure, it is appreciated.

    Concerning your previous question: is it something considered "nice to have", or rather a nice necessity? That will help me in prioritising the swiftness of me tackling this issue (y)
     

Share This Page