Thursday, July 25, 2013

Live and Learn

Several interesting things happened during the build-up to and the execution of the clinics that I gave at the NMRA national convention.

My work and travel schedule dictated that I had to postpone wiring the 3-color signals on the demonstration diorama until I was actually in Atlanta the day before my clinic.  As I started to wire the 3 additional LaunchPads that operate the signals to the 3 optical detectors, squirrely things started to happen.  Long story short (and I'm ashamed to say) that I had made an amateurish mistake in the electrical design and layout of the diorama.  I had too many signals hooked up to each optical detector.  This problem is called "fan-out" in electronics and I should have known better.  You are not likely to encounter a fan-out problem in routine working with the LaunchPad.  My problem arose because I was trying to fit too many effects into the one diorama that led to too many LaunchPads connected to each optical sensor. 

This led to another realization that I should have avoided.  The effects on the diorama were so interconnected that if anything failed it would prevent almost all of the effects from working.  This is called single-point failure and, as a long-time avionics system engineer, this is something I look for in my professional designs.  I just never applied it to my hobby pursuits.  

I could have fixed the problems; if I were at home and had access to my stock of electronics parts.  But seeing as I was in a hotel room in Atlanta, I decided that the best that I could do was not to hook up the signals.  However, single point failure was not done with me yet.

The diorama worked perfectly in the hotel Thursday and Friday in the morning before I went to do my first clinic.  After I set up in the clinic room almost nothing was working!  WTF?   After some abbreviated troubleshooting, I lifted up the diorama and saw that one of the optical sensor's LED was constantly illuminated indicating that the sensor was stuck in the "on" state.  Quickly going through a fault tree mentally, I realized that with the one sensor stuck "on", nothing but the crossing flasher would work; and I'd have to trigger that effect manually by putting my finger over one of the other sensors.  Single point failure had struck again!  So for my first clinic the diorama was a washout.

I thought that it was a simple matter of the sensitivity potentiometer being knocked out of adjustment by all of the travel.  So before my next clinic, which was that evening, I disassembled the diorama to adjust the screw, which I did.  When I powered it back up to my surprise all of the optical sensors were now stuck on!  At this point I was beginning to believe in demonic possession (especially since that had been a topic in the previous Sunday's sermon!).  Now I was really perplexed.

I wracked my brain for an answer.  In examining the diorama I turned it sideways - and all of the sensors turned off!   Then I had a flash of insight.  In a scene reminiscent of one from the movie "Aliens" I looked up towards the ceiling.  There was a hot incandescent spotlight directly overhead.  The incandescent bulb was emitting just enough infrared light to trigger the sensor.  I realized that I had never tested this sensor under incandescent light - it had always been used under the ubiquitous florescent lights.  I went to the clinic room's light switch and turned off the offending bank of lights.  Everything worked perfectly.

So the second clinic had a working diorama by the simple expedient of turning off the room light in the front of the clinic room - which also made the slides easier to see.

Fan-out, single point failure, inadequate testing - all things I should have known better. Duh!  Live and learn.



Jim Gifford's Quintet Optical Sensor

Here's a project from Jim Gifford (Hallet Cove Southern) from "Down Under" which illustrates the best of the open source paradigm.  Jim has taken parts of other projects posted here, merged them and re-purposed them to create a rather nifty project. This is what open source is about - reuse and innovation!

Jim has used a pair of LaunchPads, LEDs and optical detectors to detect the trains in his five-turn helix.  Here's Jim's description:


Quintet Optical Sensor


This project is to sense movement of a train through my helix.  The single track helix has a 33” radius and has approximately 5 ½ turns – HO scale 95 feet of track – so I have decided 10 detectors are required each having an output which stays on for around 10-12 seconds so that progression of a single railcar can be seen on a “row of LED’s” display.


In this project two LaunchPads will control the 10 LED display.  Each LaunchPad reads five of the optical sensors providing track occupancy and then illuminates respective LED’s for a predetermined time.  Please note that the “Block Occupied” indication comes from a “Block Watcher” detector to be used for signal logic.

Proposed Indicator Panel


Bill of Materials:

(1) 2 x LaunchPad with MSP430G2553IN20 processor.

(2) 10 x Optical sensor modules from a Chinese vendor IR Reflective Sensor (this link was valid at the time of publication) .
(3) 6 LED’s per LaunchPad.
(4) 5V regulated power supply to supply the optical sensors.


Optical Sensor - component side of board

Optical Sensor - emitter/detector side of board

Theory of Operation: 

Reflective optical sensors are placed adjacent to the track at predetermined locations on the helix. 





Each set of five sensors are connected to pins [Board (IC)] P1.0 (2), P1.3 (5), P1.4 (6), P1.5 (7), P1.6 (14)  and the respective indicator LED’s are connected to pins P2.0 (8), P2.1 (9), P2.2 (10), P2.3 (11), P2.4 (12) of the LaunchPad.


When a train is detected, the software in the LaunchPad causes the respective output to go high (turn on) and stay illuminated for a predetermined time.

This is achieved by using a simple counter for each Input/Output pair e.g. Input #1 P2.0 (input) and P1.0 (output) [Output_1_Timer].  The other pairs are P2.1/P1.3 [Output_2_Timer], P2.2/P1.4 [Output_3_Timer], P2.3/P1.5 [Output_4_Timer]  and P2.4/P1.6 [Output_5_Timer]. When an input is detected the respective counter is indexed by 1. If a long train is used it would be possible that all detectors are indexed at the same time. If the value of a counter is equal to 1 then the respective output is switched on. The program then checks to see if the counter exceeds the value of the variable max_time.  When the value of max_time is exceeded then the respective output in turned off and the respective counter reset to zero.  The final check is to index the respective counter for the next iteration of the while loop then the program keeps cycling at the chip operating frequency which depends on supply voltage as described on page 21 of the manual.

The Power on LED is connected to pin P2.5 (13) and illuminates when the LaunchPad is running the program.

Notes on setting the sensitivity of the detectors

  1. Turning the adjustment screw continuously clockwise increases the sensitivity eventually it detects nothing but activates (output goes low) make sure that the adjustment screw is backed off at least one turn or spurious activation results.
  2. The surface the “reflection” is sought from does matter good results where found with white, grey, orange, with varied results from dark brown & black.
  3. Direct sunlight will activate (output goes low) the sensor.

Circuit Diagram: 

Remember two of these circuits are required to illuminate the 10 LED’s.  While the diagram looks complicated, hookup is actually reasonably simple using wire wrap techniques.


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.



Demonstration of the Prototype

Link to Optical sensor testing – note detector 4 fails….

Link to testing with minimal time delay.

Link to see final configuration.


The Code

The code can be found here.

The code listing follows below.

/*
* Quintet Optical Sensor Version 1.1
* COPYRIGHT © 2013 Jim Gifford
* http://halletcovesouthern.blogspot.com.au
* Provided under a Creative Commons Attribution, Non-Commercial Share Alike,3.0 Unported License
*
* I wish to acknowledge code snippets initially written by:
* “Steve Hoffy Hofmeister”
* “Terry Terrance”
* that were adapted for use.
*
* Also thanks to Toni Ryan for his clarity advice
*
* TARGETED TO MSP430 LANUCHPAD W/MSP430G2553 PROCESSOR
*
* Design Notes:
*
* This code is designed to receive inputs from 5 Optical Sensors and light 5 independent indicator LEDS, hold them on for a predefined period of time (currently set to about 12 seconds), to signal that an object as been detected.
*
*This Project has been designed to be powered by the USB connection. Consult other available instructions on how to connect your MSP430 to external power sources before attempting.
*
*
* Circuit Pinout:
* PIN 1.0 = Anode of Indicator LED #1 \
* PIN 1.1 = UNASSIGNED - UART
* PIN 1.2 = UNASSIGNED - UART
* PIN 1.3 = Anode of Indicator LED #2 \
* PIN 1.4 = Anode of Indicator LED #3 \ Cathodes to ground
* PIN 1.5 = Anode of Indicator LED #4 /
* PIN 1.6 = Anode of Indicator LED #5 /
* PIN 1.7 = UNASSIGNED
* PIN 2.0 = Input for optical sensor 1
* PIN 2.1 = Input for optical sensor 2
* PIN 2.2 = Input for optical sensor 3
* PIN 2.3 = Input for optical sensor 4
* PIN 2.4 = Input for optical sensor 5
* PIN 2.5 = Circuit Power Indicator
* PINS 1.1, 1.2, 1.7 are left unused for integration into other projects.
*/

#include <msp430g2553.h>

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

                volatile long Output_1_Timer =0;       //Define Output_1_Timer & set to 0
                volatile long Output_2_Timer =0;       //Define Output_2_Timer & set to 0
                volatile long Output_3_Timer =0;       //Define Output_3_Timer & set to 0
                volatile long Output_4_Timer =0;       //Define Output_4_Timer & set to 0
                volatile long Output_5_Timer =0;       //Define Output_5_Timer & set to 0

                volatile long max_time=100000;  //Define time for outputs to stay on

void main(void) {

   WDTCTL = WDTPW + WDTHOLD;        // Stop watchdog timer

   P2DIR |= BIT5;  //  Circuit Power Indicator
   P2OUT |= BIT5;  //  Used to Trouble Shooting


//Configure Optical Sensors

    P2DIR &= ~BIT0; // sets Port 2, bit 0 to input for optical detector1
    P2DIR &= ~BIT1; // sets Port 2, bit 1 to input for optical detector2
    P2DIR &= ~BIT2; // sets Port 2, bit 2 to input for optical detector3
    P2DIR &= ~BIT3; // sets Port 2, bit 3 to input for optical detector4
    P2DIR &= ~BIT4; // sets Port 2, bit 4 to input for optical detector5

    P2REN |= BIT0;  // sets pull-up resistor on Port 2, bit 0 input pin
    P2REN |= BIT1;  // sets pull-up resistor on Port 2, bit 1 input pin
    P2REN |= BIT2;  // sets pull-up resistor on Port 2, bit 2 input pin
    P2REN |= BIT3;  // sets pull-up resistor on Port 2, bit 3 input pin
    P2REN |= BIT4;  // sets pull-up resistor on Port 2, bit 4 input pin

    P2OUT |= BIT0;  // sets pull-up resistor on Port 2, bit 0 to pull-up
    P2OUT |= BIT1;  // sets pull-up resistor on Port 2, bit 1 to pull-up
    P2OUT |= BIT2;  // sets pull-up resistor on Port 2, bit 2 to pull-up
    P2OUT |= BIT3;  // sets pull-up resistor on Port 2, bit 3 to pull-up
    P2OUT |= BIT4;  // sets pull-up resistor on Port 2, bit 4 to pull-up


//Configure Outputs

   P1DIR |= BIT0;                     // Port 1 P1.0 (Indicator #1) as output
   P1OUT &= ~BIT0;                // Port 1 P1.0 (Indicator #1) Set to off State

   P1DIR |= BIT3;                     // Port 1 P1.3 (Indicator #2) as output
   P1OUT &= ~BIT3;                // Port 1 P1.3 (Indicator #2) Set to off State

   P1DIR |= BIT4;                     // Port 1 P1.4 (Indicator #3) as output
   P1OUT &= ~BIT4;                // Port 1 P1.4 (Indicator #3) Set to off State

   P1DIR |= BIT5;                     // Port 1 P1.5 (Indicator #4) as output
   P1OUT &= ~BIT5;                // Port 1 P1.5 (Indicator #4) Set to off State

   P1DIR |= BIT6;                     // Port 1 P1.6 (Indicator #5) as output
   P1OUT &= ~BIT6;                // Port 1 P1.6 (Indicator #5) Set to off State

// Let's Get Down to Business

  while( 1 )              // begin infinite loop
   {

                //Detector #1
                if( (P2IN & BIT0) == 0)                                            // When IR Detector #1 activates by going low
                                Output_1_Timer ++;                                               //Index the counter
                if (Output_1_Timer ==1)                                        // First iteration when Detector #1 active
                                P1OUT |= BIT0;                                      // Set LED Indicator #1 to ON
                if (Output_1_Timer > max_time)           // Time up?
                                {
                                Output_1_Timer =0;                                               // Reset the counter
                                P1OUT &= ~BIT0;                                                   // Set LED Indicator #1 to OFF
                                }
                if (Output_1_Timer !=0)                                         // Output_1_Timer  is active
                                Output_1_Timer ++;                                               // Index the counter
                //END of Detector #1

                //Detector #2
                if( (P2IN & BIT1) == 0)                                            // When IR Detector #2 activates by going low
                                Output_2_Timer ++;                                               // Index the counter
                if (Output_2_Timer ==1)                                        // First iteration when Detector #2 active
                                P1OUT |= BIT3;                                                      // Set LED Indicator #2 to ON
                if (Output_2_Timer > max_time)           // Time up?
                                {
                                Output_2_Timer =0;                                               // Reset the counter
                                P1OUT &= ~BIT3 ;                                  // Set LED Indicator #2 to OFF
                                }
                if (Output_2_Timer !=0)                                         // Output_2_Timer  is active
                                Output_2_Timer ++;                                               // Index the counter
       //END of Detector #2

       //Detector #3
                if( (P2IN & BIT2) == 0)                                            // When IR Detector #3 activates by going low
                                Output_3_Timer ++;                                               // Index the counter
                if (Output_3_Timer ==1)                                        // First iteration when Detector #3 active
                                P1OUT |= BIT4;                                      // Set LED Indicator #3 to ON
                if (Output_3_Timer > max_time)           // Time up?
                                {
                                Output_3_Timer =0;                                               // Reset the counter
                                P1OUT &= ~BIT4;                                                   // Set LED Indicator #3 to OFF
                                }
                if (Output_3_Timer !=0)                                         // Output_3_Timer  is active
                                Output_3_Timer ++;                                               // Index the counter
                //END of Detector #3

                //Detector #4
                if( (P2IN & BIT3) == 0)                                            // When IR Detector #4 activates by going low
                                Output_4_Timer ++;                                               // Index the counter
                if (Output_4_Timer ==1)                                        // First iteration when Detector #4 active
                                P1OUT |= BIT5;                                      // Set LED Indicator #4 to ON
                if (Output_4_Timer > max_time)           // Time up?
                                {
                                Output_4_Timer =0;                                               // Reset the counter
                                P1OUT &= ~BIT5;                                                   // Set LED Indicator #4 to OFF
                                }
                if (Output_4_Timer !=0)                                         // Output_4_Timer  is active
                                Output_4_Timer ++;                                               // Index the counter
                //END of Detector #4

                //Detector #5
                if( (P2IN & BIT4) == 0)                                            // When IR Detector #5 activates by going low
                                Output_5_Timer ++;                                               // Index the counter
                if (Output_5_Timer ==1)                                        // First iteration when Detector #5 active
                                P1OUT |= BIT6;                                      // Set LED Indicator #5 to ON
                if (Output_5_Timer > max_time)           // Time up?
                                {
                                Output_5_Timer =0;                                               // Reset the counter
                                P1OUT &= ~BIT6;                                                   // Set LED Indicator #5 to OFF
                                }
                if (Output_5_Timer !=0)                                         // Output_5_Timer  is active
                                Output_5_Timer ++;                                               // Index the counter
                //END of Detector #5


   }            //End of While

}  // END OF MAIN