Monday, May 6, 2013

Back 'n Forth Shutttle Control

This project is an outgrowth of my clinic at the Streetsville Junction convention of the Niagara Frontier Region of the NMRA.

In this project a LaunchPad will control a train or locomotive going back and forth along a section of track.  The LaunchPad reads the track detection circuit (in the my diorama circuit I have an optical sensor, but other types can be used) and then it triggers dual SPDT relays wired as DPDT to reverse track voltage.  The design can be used with DC and dual-mode DCC locomotives.  As no deceleration is provided, DC locomotives should only be operated at low speed with this circuit.  Dual mode DCC decoders which provide momentum in DC mode (e.g ESU Loksound/Lokpilot) can be used at higher speeds.

This circuit is not the last word in a shuttle control. A circuit using PWM to control the motor and provide acceleration/deceleration would be better; but this circuit is a good start.

Bill of Materials:

(1) LaunchPad with MSP430G2553 processor (other types can be used as few pins are required)

(1) Dual relay module from e-bay 2 channel relay module (this link was valid at the time of publication)

 Dual Relay Module

(2) Optical sensor modules from a Chinese vendor IR Reflective Sensor (this link was valid at the time of publication

Optical Sensor - component side of board




Optical Sensor - emitter/detector side of board


Theory of Operation: 

Reflective optical sensors (or any other type of train detector) are placed in the track near the limits of the section of track that the train will shuttle back and forth. The sensors are connected to pins 11 and 13 of the LaunchPad. The sensors need not be at the extreme end of track as the software is able to allow the train to travel for a timed distance before reversing.  

Whatever train detector you use must make a connection to ground (called "active low") when a train is detected (the software could be modified to use a signal going high (active high)).  When a train is detected, the software in the LaunchPad causes both pins 6 and 7 to "toggle" (go from high to low or vice versa) essentially simultaneously.  This causes both relays to change state (from active to inactive or vice versa), reversing the train.  

The train then proceeds to the other end of the track and the sensor trips; the LaunchPad toggles the relays; the train reverses and heads back in the other direction.  On reaching the other sensor, the cycle repeats.

Circuit Diagram: 

Refer to the circuit diagram.  While the diagram looks complicated, hookup is actually reasonably simple.




The only complication comes in the fact that the relays and optical sensors require 5 VDC.  Remember that the LaunchPad runs on 3.3 VDC, so it cannot supply 5 VDC for the other modules. An external 5VDC source is wired to the relay module and to the optical sensors.  For the circuit to work with the LaunchPad running from (potentially) a different power supply, a common ground connection must be made between the 5 VDC supply and the LaunchPad and it's 3.3 VDC supply.  Run a wire from the GND pin on the LaunchPad to make a connection with the GND (-) wire from the 5 VDC supply.  The LaunchPad may be powered via it's USB port (as I did) or from an external 3.3 VDC supply.

The outputs from the optical sensors are wired to Pins 11 and 13 of the LaunchPad. It doesn't matter which end's sensor is wired to which pin, the circuit will work regardless.

The two input pins to the relay module are wired to pins 6 & 7 on the LaunchPad.  Again, it doesn't matter which input is wired to which pin.  The other end of the relay module has the contacts from the relays.  The relays lie side-by-side on the module.  The two outermost poles get the same polarity of track power; the two innermost poles get the other polarity of track power; the two center contacts go to the track.  This will wire the two SPDT relays as one DPDT relay.

I wired the sensors and the relays to the LaunchPad with wire-wrapping wire and the relays to track power and the track with 24 gauge wire.

The completed project

Software Concept of Operation: 

Conceptually, the software is very simple.  When one of the sensors goes low (i.e. to ground) both output pins connected to the relays are toggled, the train reverses and the cycle repeats.  There are just a couple of additions.  

You may want the train/loco to proceed a little way beyond the sensor before reversing.  So a timing loop is provided to allow the train to run for a selectable time beyond the sensor.  

If the sensor is not deactivated when the train runs over it, it would trip again and the train would reverse again.  The effect would be that the train would 'dither' back and forth across the same sensor at one end of the track.  So a second user-adjustable timing loop is provided after the train reverses (and after the first timing loop runs out) that prevents the sensor from reversing the train until it has passed back over the sensor and is on it's way to the other end of the track.

Finally I include code that toggles the on-board LEDs each time a sensor at the end of track is tripped. The pattern of the lights is a little cryptic.  Can you figure it out?  This part of the code does not provide any function - just makes the lights blink. 

Code Walkthrough:

In the section of the code that defines variables, two loop counters are defined.  At line 39 the variable "p" is defined.  "P" controls how long the loco will run after first tripping an end-of-track sensor.  The value of 10000 is enough to allow the On30 loco on my diorama to just get to the end of track.  This value was determined empirically.  You will have to determine the proper value for your set-up by trail and error.  The variable "p" should have some value, at least enough to allow the train/loco to go beyond and uncover the sensor in the case of an optical sensor.

At line 41 the variable "p2" is defined.  "P2" is used as a  timing loop variable to allow the reversed train to go past the sensor that it has just tripped so that the train does not get stuck going back and forth over the same sensor.  The value of 200000 was determined empirically on my diorama to allow the reversed loco to get beyond the end-of-track sensor it had just tripped.  You will have to determine the proper number for your set-up by trail and error.

To try new values for p and p2, enter them in lines 39 and 41 using CCS or a text editor.  Do not erase the semicolon (;) at the end of each line, it's necessary. Recompile (i.e. Build Project) and test.

The software sets up the input and output pins on the LaunchPad.  Pins 6 and 7 (ports 1.4 and 1.5) are set-up as outputs at lines 77 and 78 (in lines 75 and 76, the pins connected to the on-board LEDs are set-up as output).

The input pins are set-up in lines 80-87.  Unlike setting up the output pins which are a one-step process, input pins require 3 steps.  First the pins are defined as inputs. This is  done in lines 80-81 for pins 13 (Port 2, bit 5) and 11 (Port 2, bit 3).

Next, internal resistors must be connected to the newly defined input pins. Resistors prevent the pins from drifting if nothing is connected to them, they set the input pin to a known state in the absence of and external signal and they help assure clean switching between logic levels.  Lines 83-84 attaches internal resistors to pins 13 and 11 respectively.

Finally, the resistors are set to "pull-up", that is they bring the pins to logic "1" (high) in the absence of an external signal.  This is done because the sensors will pull the pins low (to logic "0") when a train is detected.  This is accomplished in lines 86-87.

The main part of the code begins with the ubiquitous infinite loop. Then an IF/ELSE IF structure tests pin 13 and then pin 11 to see if they have the value 0 indicating that those pins have been brought to ground. If one of these pins has been brought low, then the first timer is invoked and it counts up to the value in p.  This allows the train to continue past the sensor for a time.  At the conclusion of that timing loop, one of the on-board LEDs is toggled, then pins 6 & 7 are toggled to reverse the train by changing the state of the relays.  The toggling is accomplished by using the "Exclusive OR" function.

After the relays and LED have been toggled, a timing loop counting up to p2 is invoked.  This timing loop allows the now reversed train to get back past the sensor that it has just tripped, so that the train does not get stuck going back and forth over the same sensor.  This loop should be adjusted so that the train gets past the sensor, but it should time out before getting to the other sensor.  Some trial and error will be needed.

At the other end of the track, the cycle will be repeated except that the other leg of the IF/ELSE IF test will be taken

Video:

Here's a video of the project just after I got it into operation.  The "Professor" referred to in the video is "Professor" Klyzlr of the Model Rail Radio podcast who posed a challenge to design a similar system. While the simple back 'n forth action demonstrated in the video does not satisfy all of the Professor's criteria, it's a start. 
 















Code Listing:

As per usual, do not copy the code from this web page, embedded html will prevent it from compiling.  Get the code text file here: Back 'n Forth code 


////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                      ////
//                                                                                      ////
//    Back 'n Forth Shuttle                                                   ////
//                                                                                     ////
//    Provided under a Creative Commons Attribution,            ////

//    Non-Commercial, Share Alike,3.0 Unported License      ////
//                                                                                     ////
//        COPYRIGHT 2013 T. TERRANCE                            ////
//                                                                                    ////
//    TARGETED TO MSP430 LANUCHPAD                        ////

//    W/MSP430G2553 PROCESSOR                                ////
//                                                                                    ////
//                                                                                    ////
//////////////////////////////////////////////////////////////////////////////////////////












/*
 * main.c
 */
#include <msp430g2553.h>



    /////////////////////////////////////////////
    //  Define variables
    ////////////////////////////////////////////

    volatile long t=0;                //Define loop counter t and set it to 0
    volatile long p=10000;        //Define time for loco to reach end of track
    volatile long t2=0;              //Define loop counter t2 and set it to 0
    volatile long p2=200000;    //Define hold over period period variable P2

    short int detect;        //pseudo-logical for train detection









///////////////////////////////////////////////
//                      
//    BEGIN MAIN PROGRAM
//                     
////////////////////////////////////////////////


void main(void){








WDTCTL = WDTPW + WDTHOLD;  //Stop Watchdog Timer

    /////////////////////////////////////////////
    //  Set I/O pins for Relays & detectors
    ////////////////////////////////////////////

    P1DIR |= BIT0;  //sets pin 1.0 RED on-board LED for output and turns it on
    P1DIR |= BIT6;  //sets pin 1.6 Green on-board LED for output and turns it on
    P1DIR |= BIT4;  //sets pin 6 (port 1.4) for output and turns it on
    P1DIR |= BIT5;  //sets pin 7 (port 1.5) for output and turns it on

    P2DIR &= ~BIT5;    // sets Port 2, bit 5 to input for optical detector
    P2DIR &= ~BIT3;    // sets Port 2, bit 3 to input for optical detector

    P2REN |= BIT5;    // sets pull-up resistor on Port 2, bit 5 input pin
    P2REN |= BIT3;    // sets pull-up resistor on Port 2, bit 3 input pin

    P2OUT |= BIT5;    // sets pull-up resistor on Port 2, bit 5 to pull-up
    P2OUT |= BIT3;    // sets pull-up resistor on Port 2, bit 3 to pull-up

    detect=0;                //set detection variable to 0 (false)







while (1)    //begin infinite loop
{

    if ((P2IN & BIT5) == 0)
    {
        for (t; t<p; t++)  //timer 1
            {

                //timer loop to let critter get to  end of track

            }


            t=0;  //set t to zero

//      P1OUT ^= BIT0;   //toggle P1.0 the red LED
        P1OUT ^= BIT6;   //toggle P1.6 the green LED
        P1OUT ^= BIT4;   //toggle pin 6 (port 1.4)
        P1OUT ^= BIT5;   //toggle pin 7 (port 1.5)

        for (t2; t2<p2; t2++)  //timer 1
            {

                //timer 2 loop allows critter to reverse and get past the sensor that it tripped

            }

            t2 = 0;

    }

    else if ((P2IN & BIT3) == 0)
    {
        for (t; t<p; t++)  //timer 1
                {

                    //timer loop to let critter get to  end of track

                }


                    t=0;  //set t to zero

                P1OUT ^= BIT0;   //toggle P1.0 the red LED
//              P1OUT ^= BIT6;   //toggle P1.6 the green LED
                P1OUT ^= BIT4;   //toggle pin 6 (port 1.4)
                P1OUT ^= BIT5;   //toggle pin 7 (port 1.5)

        for (t2; t2<p2; t2++)  //timer 1
                {

                    //timer 2 loop allows critter to reverse and get past the sensor that it tripped

                }

                    t2 = 0;

    }


}

}  //end of main




No comments:

Post a Comment