Pages: 1 [2]   Go Down
Author Topic: Model Railway Level Crossing  (Read 1788 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3969
Where is your SSCCE?!?!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looking through the latest iteration of your program I see it is still full of delay() calls.  You will never be able to do two things at once (like change lights, and move a boom) with those there.  Every single change of state that should happen after a period of time (such as a light going on, or an alarm sounding, etc) should be keyed to the millis() function, and not paused with delay().
Logged

Why not visit my eBay shop? http://stores.ebay.co.uk/Majenko-Technologies
Replacement for the Arduino IDE: UECIDE - Proper serial terminal, graphing facilities, plugins, overhauled internals.
Java isn't bad in itself, but it has enabled morons to write programs.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Am I at least on the right track? I'm still trying to understand how all the different functions work. Is it possible to do the different stages as case functions?
Logged

UK
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3969
Where is your SSCCE?!?!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Take a step back and look at the overall picture.

Please list for me the exact sequence that you want to happen, in intricate detail.  Not just "the train passes, the lights flash, the boom closes", but exactly what you want each light to do, when you want the boom to start moving, stop moving etc, and all in chronological sequence.
Logged

Why not visit my eBay shop? http://stores.ebay.co.uk/Majenko-Technologies
Replacement for the Arduino IDE: UECIDE - Proper serial terminal, graphing facilities, plugins, overhauled internals.
Java isn't bad in itself, but it has enabled morons to write programs.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As I said I am still learning but here goes.

The train passes over the reed switch which activates the program
The Green active LED (which will be at the control board) comes on breifly and a tone is sounded
The boom gate lowers and the Crossing LEDs start flashing
The train passes over second switch which starts end sequence
Boom gate rises
Crossing lights stop flashing
RED inactive LED comes on and a tone is sounded for end of program



Looking over the sketch and writing it down i have found a few flaws with my sequence in the code but I've written it how I want it to run.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3969
Where is your SSCCE?!?!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The train passes over the reed switch which activates the program
The Green active LED (which will be at the control board) comes on breifly and a tone is sounded
The boom gate lowers and the Crossing LEDs start flashing
The train passes over second switch which starts end sequence
Boom gate rises
Crossing lights stop flashing
RED inactive LED comes on and a tone is sounded for end of program
Ok, let's see about categorizing this, so it's in a form that's easy to make a state machine from:

State: Idle.
Trigger: Train passes over reed switch
Transition: Light green LED, start tone, Set boom target angle to 0°, start flashing lights.
State: Waiting for time to pass
Trigger: Time has passed.
Transition: Turn off green LED, stop tone.
State: Waiting for train to pass second reed switch
Trigger: Train passes second reed switch
Transition: Set boom target angle to 45°
State: Waiting for boom to fully raise
Trigger: Boom has raised
Transition: Stop flashing lights, turn on red light, start making tone
State: Waiting for time to pass
Trigger: Time has passed
Transition: Stop making tone.  Turn off red light.  Go to idle state.

All the time: Move boom by 1° if not at target angle.
All the time: Flash lights if flashing is enabled.

You see how a trigger causes a transition to a new state?  Triggers are external influences - reed switch, value from millis(), etc.  States are static "waiting", where not much is happening until the next trigger.  Transitions are where the actual work is done - the turning on of lights, the setting of boom angles, etc.  The "All the time" functions happen always regardless of the state of the state machine, but can be controlled by the state machine by setting variables.  These are "asynchronous" actions, in that they have their own timing that is outside the scope of the state machine.
Logged

Why not visit my eBay shop? http://stores.ebay.co.uk/Majenko-Technologies
Replacement for the Arduino IDE: UECIDE - Proper serial terminal, graphing facilities, plugins, overhauled internals.
Java isn't bad in itself, but it has enabled morons to write programs.

Australia
Offline Offline
Newbie
*
Karma: 0
Posts: 20
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So basically I should build my sketch as an FSM?
Logged

London
Offline Offline
Edison Member
*
Karma: 23
Posts: 1062
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You basically need to have a variable in which you store the current angle of the boom.  Then you slowly (by comparing another variable to millis()) increase / decrease that variable until you have the desired final angle.  Every time you increase / decrease the angle, you do the servo.write call.

A little function such as (untested):
Code:
void moveTo(unsigned char angle)
{
  static unsigned char currentAngle = 0;
  if (currentAngle < angle) {
    currentAngle++;
    myservo.write(currentAngle);
    return;
  }
  if (currentAngle > angle) {
    currentAngle--;
    myservo.write(currentAngle);
    return;
  }
}

will only move the boom by one degree per call, if it needs to move it at all.  In your main loop, you can do something like:
Code:
static unsigned long boomMoveTime = millis(); // These are either local static variables, or global non-static variables.
static unsigned char desiredBoomAngle = 0;
...
if (millis() - boomMoveTime > 10) {
  boomMoveTime = millis();
  moveTo(desiredBoomAngle);
}
...
if (whatever) {
  desiredBoomAngle = 45;
}

So, every 10 milliseconds you make a call to get the boom closer to its target angle, if it's not already there.  At any time in your main loop, you can then set the variable desiredBoomAngle, and it will instantly start to move the boom slowly up or down, to whatever the desiredBoomAngle variable is set to.

Thanks for that Majenko.
I've been using delay with increments/decrements to get the motor on a model railway loco to accelerate/decelerate at a realistic rate. Your way looks easier and neater. I presume that it would be fairly easy to have the rate of change increase/decrease with time, ie not a straight line acceleration.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3969
Where is your SSCCE?!?!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, just change the > 10 in the function to compare with a variable, which sets the delay between increments.
Logged

Why not visit my eBay shop? http://stores.ebay.co.uk/Majenko-Technologies
Replacement for the Arduino IDE: UECIDE - Proper serial terminal, graphing facilities, plugins, overhauled internals.
Java isn't bad in itself, but it has enabled morons to write programs.

Pages: 1 [2]   Go Up
Jump to: