Skip to main content

Ok follow along with me on this, as it is kinda confusing. 

I have the Lionel accessory "reading room".  It pretty much is an out house where when activated the door opens to see a guy on the hole reading a newspaper.  

I want to place it close to the track and as the train comes around it activates it and the door opens, as if the vibrations of the moving train opens the door.  

I do not want to activate it every time.  Maybe once every 20 passes of the train.  Is there any pre-made accessory that will do this?  Is there something that is easy to put together that will do this?

Thanks in advance.  

Original Post

Replies sorted oldest to newest

gunrunnerjohn posted:

I looked around and didn't see any "canned" solution to do the job.  I'd consider either an IR sensor or a short section of insulated track to do the triggering and one of the zillion eBay relay modules to perform the switching.  Any of the Arduino boards would do the job, it's a simple task.

John

Would you consider taking on the task?  put it together, program the Arduino, and sell it too me?

It depends on what you mean by "easy to put together." 

If the Arduino route is not in your comfort zone, are you able/willing to cobble together a circuit with a dozen or so components?  I'm imagining one of those eBay relay modules and/or a cycling timer module that turns ON 5% of the time.  For example, 1 second ON, 19 seconds OFF, 1 second ON, 19 seconds OFF, etc.  When the train initially hits the trigger point, a relay module looks at the cycling timer and if it is ON (1-in-20 chance) it lets the accessory activate for that pass of the train.  The other 95% of the time it ignores the trigger. 

Would need a DC supply to power the relay module(s)...but so would an Arduino.  I'm thinking less than $10 but would involve cobbling together some modules and a handful of components like capacitors, resistors, diodes...but NO writing software.

relay modules

Can you install an insulated-outer-rail section to serve as the trigger?  If not, there would be cost for an IR occupancy sensor or the like.

Attachments

Images (1)
  • relay modules
Last edited by stan2004
stan2004 posted:

It depends on what you mean by "easy to put together." 

 

Would need a DC supply to power the relay module(s)...but so would an Arduino.  I'm thinking less than $10 but would involve cobbling together some modules and a handful of components like capacitors, resistors, diodes...but NO writing software.

 

Can you install an insulated-outer-rail section to serve as the trigger?  If not, there would be cost for an IR occupancy sensor or the like.

Another no software option is a simple divide by N counter. This is just one of many types

Pete

Irrespective of how it's done, as is so often the case the what is the quagmire.

Do you really want 1 in 20 exactly like clockwork or do you want some randomness?  If you find 1 in 20 (or whatever) not to your liking, how do YOU change it?  For example, an Arduino could have provision to adjust the behavior...but you'd want to specify this up front.  A hardware-based approach might involve moving some wires around (if using a counter) or adjusting a trimmer control if using a timer.  Do you need an over-ride mode/switch to activate it every time or to manually activate it?  And so on.

As GRJ said, the best thing to use here is probably an Arduino or similar device.  The code is not very difficult, something like this:   (note that more than half of this "code" is comments describing how it works, the actual "program" that runs is only about the last 10 lines.)

int minimunLapsToTrigger = 10; // Set minimum number of laps before triggering.
int maximumLapsToTrigger = 25; // Set maximum number of laps before triggering.

int inputPin = 7; // Arduino pin connected to input circuit.
int outputPin = 8; // Arduino pin connected to output relay module.
int currentInputState = 0; // stores current state of input pin.
int lastInputState = 0; // stores last state of input pin.
int lapCounter = 0; // stores count of number of times train has passed.
int numberOfLapsBeforeTriggering = 0; // stores random number of laps before triggering.


void setup() {
// put your setup code here, to run once:
pinMode(inputPin, INPUT); // Set input pin as an input.
digitalWrite(inputPin, HIGH); // turn on internal pull-up resistor.
pinMode(outputPin, OUTPUT); // set output pin as an output
randomSeed(analogRead(A0)); // seed the random number generator with a floating value.


}

void loop() {
// put your main code here, to run repeatedly:
currentInputState = digitalRead(inputPin); // read input value into var.

// if train is there, and it was not on last loop:
if (currentInputState == 1 && currentInputState != lastInputState) {
lapCounter++; // increase lap counter by 1
}
lastInputState = currentInputState; // set last state to current one for next loop.

// if train is there and enough laps have passed:
if (lapCounter >= numberOfLapsBeforeTriggering && currentInputState == 1) {
digitalWrite(outputPin, LOW); // turn on relay, open outhouse door.
lapCounter = 0; // reset the lap counter.

// set a ner random number of laps for the next time.
numberOfLapsBeforeTriggering = random(minimunLapsToTrigger, maximumLapsToTrigger);
}
else { // if not enough laps:
digitalWrite(outputPin, HIGH); // turn relay off, outhouse door closed.
}
}

This code is untested, and needs a few tweaks in any case, like adding a de-bounce routine and such, but it shouldn't take much more than that.  A couple more lines could easily add options for a manual pushbutton trigger, or whatever other options you'd like.  I'd guess in a one off production all the parts to make a stand-alone, track powered, unit would cost less than $10 ordered from china, or $20 using US shipped parts.  I don't think the moderators here go much for folks peddling their services, but I'm sure you could find the email address in the profiles of folks that could throw such a thing together for a nominal fee.  

On the less computery end, you could use one of the timer relay modules in series with any other activator method, so that it would only allow the outhouse to be triggered every X number of minutes.  it's not as fancy, but it would get the job done.  

JGL

I like the JGL solution with the addition of a manual trigger input for a PB.  One of the dollar relay modules will do the switching, and you can use an insulated track signal trigger to do the inputs.  AAMOF, I'm currently finishing up building the first lot of these insulated rail signal drivers.   No debounce needed, that's all done for you with this insulated track module.

Attachments

Images (1)
  • mceclip0

So, I was sitting down with a glass of bourbon tonight and decided I may as well put this together instead of actually doing anything important.  

Added a couple features like a delay so that you can set the accessory to run for a minimum amount of time even if it is only triggered for a short time.  

This is all self contained, running off of track power, and seems to work pretty well.  The large blue LED represent power to the accessory.  The smaller led shows when the insulated rail is triggered.  The blue button represents a train on the insulated rail, and the green button is a manual override.  

JGL

Has the time required for activating the full sequence been brought up?

At the moment, mine is packed away, but I seem to recall the trigger requires a good holding of the circuit closure (it's a DC motor that I'm pretty sure slowly opens the door, pauses maybe for a moment and then closes it, and repeats if you keep the circuit closed).

I tried reviewing the manual on-line, but the only nugget I could glean from the manual is that the switch is shown as slide action for on/off rather than a "press to activate" type of scenario.  (It also refers to using AUX2 vs AUX1 if using TMCC, which matches this observation).

It would seem the length and speed of the train could affect operation, more so than say a classic Gateman that is an instantaneous motion driven by a solenoid that just remains activated until the circuit is again opened when the train leaves the area. 

I know nothing about Arduinos, so sorry if this is a trivial concern, but it seemed relevant to the operation I saw in JGL's video.

If it's OK for the door to partially open and stay that way (for a potentially long period if we are waiting for 20 train passes to activate again), or stop in whatever part of the cycle it's in when the train leaves, then everything will be fine.

-Dave

Dave45681 posted:

Has the time required for activating the full sequence been brought up?

At the moment, mine is packed away, but I seem to recall the trigger requires a good holding of the circuit closure (it's a DC motor that I'm pretty sure slowly opens the door, pauses maybe for a moment and then closes it, and repeats if you keep the circuit closed).

I tried reviewing the manual on-line, but the only nugget I could glean from the manual is that the switch is shown as slide action for on/off rather than a "press to activate" type of scenario.  (It also refers to using AUX2 vs AUX1 if using TMCC, which matches this observation).

It would seem the length and speed of the train could affect operation, more so than say a classic Gateman that is an instantaneous motion driven by a solenoid that just remains activated until the circuit is again opened when the train leaves the area. 

I know nothing about Arduinos, so sorry if this is a trivial concern, but it seemed relevant to the operation I saw in JGL's video.

If it's OK for the door to partially open and stay that way (for a potentially long period if we are waiting for 20 train passes to activate again), or stop in whatever part of the cycle it's in when the train leaves, then everything will be fine.

-Dave

The 'simple' fix here is that if the accessory always takes the same amount of time to complete one cycle, that can easily be added to the arduino's code.  You can say "when triggered turn on for however many seconds, then turn off.  Or you could say run until the train is past, then keep running until a full cycle is complete.  If the accessory does not run at a constant speed, it would get a little more complex to insure the door is closed except when triggered, but shouldn't be too hard to modify the accessory with some sort of sensor or microswitch to detect the position of the door.  

For the requests, I'll try to put together a proper schematic sometime later tonight or tomorrow morning, I'm traveling for work today and won't have any time till then.  This will likely sound like gibberish to some folks, but the electronics folks hopefully will follow along:  The basic set-up is fairly simple.  Connection from insulated-rail (blue button) goes through a diode and current limiting resistor(1.5k) then through the LED of an optocoupler.  track 'hot' connects to the other end of the optocoupler's led. Emitter of the opto to ground, collector goes to a digital input on the ProMini. A capacitor is then connected from the collector to Vcc to filter out the pulses caused by the 60Hz track cycle, providing a steady LOW signal to the digital input whenever a train is present.  I'm using the internal pull-up resistors on the ProMini, so that completed the RC circuit on the filter.  I arbitrarily chose 47uF for this cap, and it seems to work just fine.  I don't think precise timing is required here, so even if the thing stays 'active' for a couple hundred milliseconds after the train is gone shouldn't be a problem.  As it turns out it seems to respond pretty quick.  

On the code end, the random number is generated similarly to the code I posted above.  the total program is about 3 times as long now, but could probably be condensed by someone that actually knows what they are doing.  Anyway, the basic format is, a random number between X and Y is chosen.  I used between 15 and 25.  each time the input is triggered it adds 1 to a counter.  then when it reaches the random number the relay is turned on.  the program then waits for the input to turn off again (for the train to pass), then it sets the counter back to zero and chooses a new random number to start over with.  

Short answer, yes, it will be random even if you wait days between presses.  

JGL

For some reason every time you guys post something like this I end up getting the urge to and then placing a parts order. Someday, someone will post something that I already have ALL the parts for. Law of averages says it has to happen sooner or later? At least the electronic parts take up a LOT less room than the trains and they are a LOT less expensive too!! 

Anyway JGL, all kidding aside, I am interested in a schematic and the code as well. Looks like a neat and fun project.

EDIT:  Fixed an error with the original I posted.  

Ok, Put this together real quick tonight:  

random-trigger_schem2random-trigger_bb2

Note that button S1 and S2 are really only there for testing, either, or both could be removed with no effect on operation.  The LED and 220 Ohm resistor are also unneeded, but used to show when a train is detected.   I used a 470uF filter capacitor for the power supply, because I have a ton of them, and it does the job, but 1000-2200uf would probably be a better choice here.  Lastly, the LM7805 is running right on the edge of what is safe and reliable without a heat-sink when driving the circuit and energizing the coil on a relay module.  I would probably recommend using a small heat sink just to be safe.  

Without input from the OP about timing options, I'm not going to put any more into it for now, unless others are interested, but I'd probably use a 10 turn potentiometer and reprogram the unit to have that pot set how long the relay should stay turned on when the unit is triggered.  

All in all this does pretty much the same thing as GRJ's insulated rail module, with a programable timer added.  I bet one could use a much cheaper PIC or Atmel uProcessor, SMT parts, and build a similar board relatively inexpensively.  I may look into that.  At this point pre-made relay modules from china cost the same, or less, than the parts to mimic their functionality, so I don't see any point in adding the relay circuitry to this thing.  

Anyway, thats about all for now.  

JGL

Attachments

Images (2)
  • random-trigger_schem2
  • random-trigger_bb2
Last edited by JohnGaltLine

Nice John, the Arduino adding "smarts" is certainly a plus over the basic block sensing.  At some point in the future, I may add a PIC to a sensing module and have a smart one with delays and perhaps two relays to allow three-LED triggering.  Adding the ability to daisy-chain the detectors would be a neat feature as well.

For those wishing to duplicate this effort, can you post the code as well?

Last edited by gunrunnerjohn
gunrunnerjohn posted:

For those wishing to duplicate this effort, can you post the code as well?

Sure thing.  It's a bit of a mess, but it works, and I figure thats the important part.  

/* Random Lap Trigger
By: JGL JohnGaltLine@comcast.net
Open Source distribution. */
int minimunLapsToTrigger = 10; // Set minimum number of laps before triggering.
int maximumLapsToTrigger = 25; // Set maximum number of laps before triggering.
int maximumActivationTimer = 15; // max on-time hold timer(seconds)

int inputPin = 9; // Arduino pin connected to input circuit.
int outputPin = 10; // Arduino pin connected to output relay module.
int debouncedCurrentInputState = 1; // stores current state of input pin, debounced.
int lastInputState = 0; // stores last state of input pin.
int lapCounter = 0; // stores count of number of times train has passed.
int numberOfLapsBeforeTriggering = 0; // stores random number of laps before triggering.
int currentInputState = 1; // stores current state of input pin, actual.
int debounceTime = 20; // debounce time (ms.).
unsigned long currentTime = 0; //Var for clock.
unsigned long debounceClockOne; // var for main input debounce.
unsigned long debounceClockTwo; // var for manual overide input debounce.
int manualOverideInputPin = 12; // manual button input pin.
int debouncedManualButton = 1; // var for manual overide, debounced
int manualButtonInputState = 1; // var for manual overide, pin state.
int outputOn = 0; // var for output state, not timed.
unsigned long activationTimer = 500; // clock for minimum run time.
int OutputLastState = 0; // var stores state of output on last cycle.
int activationTimerPotInputPin = A2; // input pin for setting timer.
int activationTimerPotInput = 0; // var to store analog value from pot
int minimumActivationTime = 0; // Var to set minimum on time bottom limit for pot. (ms)

void setup() {
// put your setup code here, to run once:
pinMode(inputPin, INPUT); // Set input pin as an input.
digitalWrite(inputPin, HIGH); // turn on internal pull-up resistor.
pinMode(manualOverideInputPin, INPUT); // Set input pin as an input.
digitalWrite(manualOverideInputPin, HIGH); // turn on internal pull-up resistor.
pinMode(activationTimerPotInput, INPUT); // set pin as input.
pinMode(outputPin, OUTPUT); // set output pin as an output
pinMode(A0, INPUT);
randomSeed(analogRead(A0)); // seed the random number generator with a floating value.
digitalWrite(outputPin, HIGH); // make sure the relay is turned off when device starts.
Serial.begin(9600); // initialize the serial port for debugging
}

void loop() {
// put your main code here, to run repeatedly:
currentTime = millis(); // set the clock variable to the current time.
activationTimerPotInput = analogRead(activationTimerPotInputPin); // read in the delay falue fro the pot.
minimumActivationTime = map(activationTimerPotInput, 0, 1023 , 0, (maximumActivationTimer * 1000)); // remap pot value to min/max settings.

// debounce for main input
if (currentTime >= debounceClockOne + debounceTime) {
currentInputState = digitalRead(inputPin); // read input value into var.
debounceClockOne = currentTime; //reset debounce clock.
debouncedCurrentInputState = currentInputState; // set debounced value.
}

// debounce for manual overide input
if (currentTime >= debounceClockTwo + debounceTime) {
manualButtonInputState = digitalRead(manualOverideInputPin); // read input value into var.
debounceClockTwo = currentTime; //reset debounce clock.
debouncedManualButton = manualButtonInputState; // set debounced value.
}

// if train is there, and it was not on last loop:
if (debouncedCurrentInputState == 0 && debouncedCurrentInputState != lastInputState) {
lapCounter++; // increase lap counter by 1
}

lastInputState = debouncedCurrentInputState; // set last state to current one for next loop.

if (lapCounter >= numberOfLapsBeforeTriggering && debouncedCurrentInputState == 0) { // if train is there and enough laps have passed:
outputOn = 1; // set output on. (not timed)
}
else if (debouncedManualButton == 0) { // or if the manual button is pressed
outputOn = 1; // set output on. (not timed)
}
else { // if not enough laps:
outputOn = 0; // set output off. (not timed)
}
// when train is past after activating:
if (lapCounter >= numberOfLapsBeforeTriggering && debouncedCurrentInputState == 1) {
lapCounter = 0; // reset the lap counter.
// set a new random number of laps for the next time.
numberOfLapsBeforeTriggering = random(minimunLapsToTrigger, maximumLapsToTrigger);
}

// detect when first tirggered and start timer.
if (outputOn == 1 && OutputLastState != outputOn) {
activationTimer = currentTime; // start minimum on time timer.
}
OutputLastState = outputOn; //reset value for next cycle's check.
if (outputOn == 1) { // if output is supposed to be on...
digitalWrite(outputPin, LOW); // turn on output (relay on.)
}
else if (outputOn == 0 && currentTime >= activationTimer + minimumActivationTime){ // if output is supposed to be off, and minimum time has passed...
digitalWrite(outputPin, HIGH); // turn off output (relay off)
}
// serial print for debug.
Serial.print("Track state: ");
Serial.print(debouncedCurrentInputState); // print state of main input.
Serial.print(" Manual state: ");
Serial.print(debouncedManualButton); // print state of manual input button.
Serial.print(" Laps for trigger: ");
Serial.print(numberOfLapsBeforeTriggering); // print random number generated for laps between triggering.
Serial.print(" Lap Count: ");
Serial.print(lapCounter); // print total laps counted since last trigger.
Serial.print(" Min Time: ");
Serial.print(minimumActivationTime); // print current setting of minimum activation time.
Serial.println(" ");
} // end main loop.

 

I think that it would be fairly easy to modify for various functions, removing the random number for a standard timed output track sensor, for example.  Unfortunately feature creep makes things more complex.  it would be dead simple if I could count on folks to be willing to download the Arduino IDE, and plug each board in to change a couple variables at the top of the program,  but I don't see that as a marketable option, at least for most users of this forum.  Adding a set of dip switches to allow people to change the functions is another option, but that would add bulk and complexity to the think, and even then might be too confusing for some folks.  Before I think on it too much, I suppose it would be helpful to get a list of features that folks would like in a track sensor, then go from there to see what can be done easily, and what is best left undone.   As another thought, it might be that I could keep each individual sensor as simple as possible, then build a 'programer' module that is used to set up the sensor for the feature that is wanted.   Who knows at this point.  

JGL

Wow.  Okay I didn't think it would be this complicated.  I know this EE stuff is easy for you guys, but anything more then basic house wiring is over my head.  It has been about 10 years since I took a EE class in school.

So I will put out this offer.  If anyone is willing to take on this project I will be happy to pay for the parts and time.  Just send me an email with your offer at jdevleerjr at gmail.com

 

gunrunnerjohn posted:

I think I'd opt for a fixed set of functions and a jumper field to select.  If you just use a numeric decoding, a jumper field of 8 jumpers is good for 256 options.  A DIP switch is a possibility as well, they're fairly cheap.  I don't think having a computer in the mix works for a great many folks.

I think the jumpers or DIP switches is probably the best way to go, but it all really depends on what the desired feature set really is.  I fully agree that bringing a computer into the mix would turn off a lot of people.  I think the first thing to do before really deciding how to switch between options and adjust their settings would be to get a list together of the things people actually want.  I'm thinking maybe a new post is in order, and may start one up later.

Jdevleerjr posted:

Wow.  Okay I didn't think it would be this complicated.  I know this EE stuff is easy for you guys, but anything more then basic house wiring is over my head.  It has been about 10 years since I took a EE class in school.

So I will put out this offer.  If anyone is willing to take on this project I will be happy to pay for the parts and time.  Just send me an email with your offer at jdevleerjr at gmail.com

 

Decided to drop an email, since I think I've mostly got this together anyway.  For what it's worth, I know it's all Greek to folks that are not into electronics, but this one really is pretty simple.  Had a nice time the other night listening to the stereo, sipping my favorite bourbon, and putting together something that works.  All in all a good way to take a break form the other complex projects I've been working on.  

gunrunnerjohn posted:

I think John's just about completed it.   Given how cheap it is to fabricate a circuit board, I'd probably consider making a PCB for the rig, makes it a ton easier to build.

I'm not so sure that it's worth the trouble in this case.  At the moment it's a one-off, and half the connections are going off board.  For some universal timer/detector module it probably would be worth it, but at $1 per sq. inch for boards from OSH park (if you buy 100 sq. in.) it still doesn't make sense for me most of the time.  Especially for a one off of something like this, it would take much more time to design a PCB than the 5 minutes it would take to cobble it together on perf board.  For most one-off's the dollars and cents just don't add up, unless you need the space savings from using SMT parts neatly packed together.  As a side note, I'm working on getting my shops engraving machine set up for cutting copper clad board.  it's slow and not quite as nice looking as a proper PCB, but I have 10,000 sq.in. of copper clad sitting on a shelf I can use for small run boards when I get it going.  I'm also equipped for etching if needed, but it's really a PITA and I've never gotten the greatest results.  


One last thought for now:  GRJ I know you have some experience with this, and maybe you could give your thoughts.  With the circuit I proposed above, do you think there would be any problems with it interfering with the DCS signal?  I know you use a (22uH?) choke in many of your designs to prevent problems.  I just don't know enough about the problem or what specificity causes it as I am not a DCS user.  

JGL

Been doing PIC based stuff for years when one day a customer asked me to do an animation for him. It's a golfer who takes several practice swings on a green then proceeds to tap the ball into the hole. See it here. http://www.kramerproducts.com/

Guess what. I kept it simple (KISS principle) and didn't use a PIC or any electronics but just 2 microswitches.

 

 

Last edited by Gary E

Add Reply

Post
×
×
×
×
Link copied to your clipboard.
×
×