Thirteen members joined us on today's Cumbria Zoom meeting where Tony Hoath demonstrated and explained his Arduino based shuttle layout which he uses for bedding in new OO scale locos.
The basic Pocket Money shuttle Kit suffers from the sudden stop when the track break is detected and the sudden start when the relay is reversed. The affect can be minimised if slow speed is selected.
Tony uses a simple Light Dependent Resistor to detect the presence of a loco and then gradually decelerates and finally stops on reaching a second sensor.
The circuit is shown below. As the relay is only switched when no power is being supplied to the track, a much smaller relay can be used to change direction.
As the locomotive returns it ramps up to a set speed so the rather unrealistic stop / start is avoided.
Tony's sketch is available below.
//00 test track
//1 loco to run back and forth
//2 LDR,s to determine train postion.
//2 push buttons. Green starts and stops operation. The stop is registered and completes at the end of the cycle.
//Red stops operation immediately in a controlled manner.
//The cycle is acceleration and coasting until LDR 2 is found followed by a controlled stop,
//followed by acceleration and coasting in the opposite direction until LDR1 is found
//followed by a controlled stop.
//ldr inputs
int ldr1 = A4;
int ldr1base = 320;
int ldr1mult = 12;
int ldr2 = A2;
int ldr2base = 320;
int ldr2mult = 12;
//train drive
const byte trainout = 6;
byte dir = 2;
//Button inputs
const byte red = 5;
const byte green = 4;
//train parameters
int trnmax1 = 255;
int trn1min1 = 15;
int trnspeedbase1 = 0;
int trnacc = 300;
int trnbrakerate = 35;
int fastbrakerate =4;
int trnspeed =0;
//general purpose
int grnflg = 0;
int redflg = 0;
int var1 = 0;
//LED output
const int led = 7;
void setup()
{
Serial.begin(115200);
//declare the pins
pinMode (dir, OUTPUT);
pinMode (led, OUTPUT);
pinMode (red, INPUT_PULLUP);
pinMode (green, INPUT_PULLUP);
pinMode (ldr1, INPUT_PULLUP);
pinMode (ldr2, INPUT_PULLUP);
analogWrite(trainout, 0); //set train speed to zero
}
//////////////////////////////////////////////////////////
//Main loop
void loop()
{
Serial.print(analogRead(ldr2));
Serial.print(" ");
//digitalWrite(ledrr,LOW);
delay(500); redflg = 0;
grnflg = 1;
while (digitalRead(red)==LOW)
{
digitalWrite(led, HIGH);
delay (500);
digitalWrite(led, LOW);
delay (500);
}
//cycle shuttle mode until green button is pushed.
//if red button is pushed stop train and set reflg to 1.
if (digitalRead(green)==LOW)
// wait until button released
{
while (digitalRead(green)==LOW)
{
grnflg = 0;
digitalWrite(led, HIGH);
delay (150);
digitalWrite(led, LOW);
delay (150);
}
trnspeed = trnspeedbase1;
while ((grnflg == 0) && (redflg == 0))
{
digitalWrite(dir, HIGH);
ldr2base = analogRead(ldr2) * ldr2mult/10;
// accelerate and coast to LDR2
while ((trnspeed < trnmax1) && (redflg == 0) && (analogRead(ldr2) < (ldr2base)))
{
analogWrite(trainout, trnspeed);
trnspeed = trnspeed + 1;
var1 = trnacc;
spdelay();
}
//coast to LDR2
while ((redflg == 0) && (analogRead(ldr2) < (ldr2base)))
{
analogWrite(trainout, trnspeed);
if (digitalRead(green)==LOW)
{
grnflg = 1;
}
if (digitalRead(red)==LOW)
{
redflg = 1;
faststop();
}
}
//brake to zero before return
while ((trnspeed > trn1min1) && (redflg == 0))
{
analogWrite(trainout, trnspeed);
trnspeed = trnspeed - 1;
var1 = trnbrakerate;
spdelay();
}
analogWrite(trainout, 0);
delay(500);
//go the other
digitalWrite(dir, LOW);
ldr1base = analogRead(ldr1) * ldr1mult/10;
// accelerate and coast to LDR1
while ((trnspeed < trnmax1) && (redflg == 0) && (analogRead(ldr1) < (ldr1base)))
{
analogWrite(trainout, trnspeed);
trnspeed = trnspeed + 1;
var1 = trnacc;
spdelay();
}
//coast to LDR1
while ((redflg == 0) && (analogRead(ldr1) < (ldr1base)))
{
analogWrite(trainout, trnspeed);
if (digitalRead(green)==LOW)
{
grnflg = 1;
}
if (digitalRead(red)==LOW)
{
redflg = 1;
faststop();
}
}
//brake to zero before return
while ((trnspeed > trn1min1) && (redflg == 0))
{
analogWrite(trainout, trnspeed);
trnspeed = trnspeed - 1;
var1 = trnbrakerate;
spdelay();
}
analogWrite(trainout, 0);
delay(500);
}
}
}
//Functions
//delays speed change by var1 whilst checking red and green buttons not pushed
void spdelay()
{
while ((var1 > 0) && (redflg == 0))
{
delayMicroseconds(100);
var1 = var1 - 1;
if (digitalRead(green)==LOW)
{
grnflg = 1;
}
if (digitalRead(red)==LOW)
{
redflg = 1;
faststop();
}
}
}
//reduce speed to zero quickly
void faststop()
{
while (trnspeed > 0)
{
analogWrite(trainout, trnspeed);
trnspeed = trnspeed - 1;
delay(fastbrakerate);
}
analogWrite(trainout, 0);
}
/*Serial.print(analogRead(ldr3));
Serial.print(" ");
digitalWrite(ledrr,LOW);
delay(100);
digitalWrite(led, HIGH);
*/
Comments
Post a Comment