Skip to main content

Arduino controlled shuttle

 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

Popular posts from this blog

Train sequence / timetable using Arduino

                              Following discussions in a MERG Zoom meeting about potential projects for the Cumbria virtual area group I have started this blog to share my ideas for building a train sequence / timetable system based on an Arduino UNO. The trigger for this project was Andy Robb's article in the MERG journal (June 2020 edition). In it Andy describes using an UNO with a OLED display to produce an electronic station display board.  Having tried out Andy's version I started thinking about expanding the idea and have come up the following list of possibilities: 1. Replace my card index train sequence with an electronic version. 2. Have the train sequence synchronised with the on platform displays. 3. Display an analogue clock on the station display and have it display the train times. 4. Store the position reached in the sequence so that it starts where it left off on power up.  To mak...

3D Printing Presentation

Sunday's Zoom meeting had our largest audience so far with 19 members attending from various parts of the country. Alan Geekie gave us an excellent and well received presentation on 3D printing that included FDM (Fused Deposition Modeling) and SLA (Stereolithography apparatus) types He first showed how we can source "things to print" using sites like Thingiverse. His own filament printer was the Prusa i3 Mk 3S which is available either as a kit (£699) or pre-assembled (£899) and features a self leveling bed. It also benefited from an additional multi material upgrade kit and he demonstrated the start up sequence of leveling, homing, clearing remaining filament from the hot end and then beginning the print.  The process of slicing where a 3d object drawing file (.stl) is broken up into the x,y,z drawing coordinates for each individual layer was also explained. Alan then moved on to resin printers using another Prusa model, the SL1 and its associated curing and washing mach...

Mimic Points in Visual Basic

For this project, I wanted to create a moving graphic to mimic a set of points moving from one position to the other.  This Blog shows all that is needed. The first Picture shows the 6 lines needed.                                 This Picture shows the Line Properties.    The tracks are shown with 5 lines, though only the middle ones in red are involved.  The other line shown below the others is the one that actually "moves".  It is shown below the other lines for clarity only.  At the start of the Program running, it is positioned over the lower red line. In VB, each Line has properties and these are shown above.  To get a line to appear to move, all that needs to be done is to gradually change the X2 and Y2 co-ordinates of the line. This is the code for the program. The first 6 lines create a pause Function in the program, by using the Computers internal C...