Thursday, November 7, 2013

Interactive Town Play Mat Complete

Here is a video featuring all three parts of the Interactive Town Play Mat.

Arduino Interactive Play Mat from Kendalf on Vimeo.

Sunday, November 3, 2013

Train Crossing Signal with Ultrasonic Trigger


After several design iterations I finally completed the Train Crossing Signal for the Interactive Town Play Mat project. This portion of the project uses an ultrasonic sensor to trigger two model train signal lights that I found on eBay. The sensor sends out ultrasonic sound pulses, and then listens for the echo. The Arduino sketch includes a calculation that takes the time that it takes for the echo to return to calculate the range of the reflecting object.

In my sketch, when the sensor detects an object at close range (about 3 cm) it triggers the light flashing function. By placing the breadboard with the sensor right beside the track, the crossing signal will be triggered by a passing train. The function then performs a check to keep the lights flashing for the designated time interval, enough to allow the train to pass the crossing.

The breadboard circuit is diagrammed below. The crossing signal lights require a 12V power supply, so like the city street lights portion of the play mat, I had to incorporate transistors in the circuit.
This video shows an earlier version of the crossing signal, before I added the code that caused the signal to continue flashing even if the train was no longer in front of the ultrasonic sensor.

Train Crossing Flashing with Ultrasonic Sensor.mp4 from Kendalf on Vimeo.


The Sketch:

/* Train Crossing Signal with Light Sensor
 by: Ken Yeh
 */

/* Pin Definitions */
int trigPin = 2;  // set Ultrasonic trigger pin
int echoPin = 3;  // set Ultrasonic echo detect pin
int ledPin1 = 5;  // LED 1
int ledPin2 = 6;  // LED 2
int buzzerP = 7;
int buzzerN = 12;

/* Global variables */
boolean ledState = false; //boolean variable used to store the current LED state
long previousMillis = 0; //stores the last time LED was updated
long interval = 350;  //time interval (in ms) between LED flash
long duration, distance; // Duration used to calculate distance
long signalDuration = 5000; // Time duration for signal to stay on after triggered
long startTime = -signalDuration; // stores when signal is triggered, set to a value to initially keep signal off

void setup()
{
  pinMode(ledPin1, OUTPUT);  // set LED pin as output
  pinMode(ledPin2, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT); // set Echo pin as input

  //Buzzer
  pinMode(buzzerP, OUTPUT);  // set both buzzer pins as outputs
  pinMode(buzzerN, OUTPUT);

  Serial.begin(9600);  // We'll output some information over serial
}

void loop()
{
  // Ultrasonic Sensor
  /* The following trigPin/echoPin cycle is used to determine the
     distance of the nearest object by bouncing soundwaves off of it. */
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);

  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);

  // Calculate the distance (in cm) based on the speed of sound.
  distance = duration / 58.2;

  Serial.print("Range= ");
  Serial.println(distance);

  // Test if Signal should be activated
  if(distance < 5 && distance != 0)  //detects if train is within a certain range
  {
    startTime = millis(); // sets time for when the signal is triggered
    flashSignal();  // call the Signal Flashing function
  }
  else    // else turn signal off when no train is in range
  {
    digitalWrite(ledPin1, false);
    digitalWrite(ledPin2, false);
  }
}

// Signal Flashing Function
void flashSignal()
{
  while(millis() - startTime < signalDuration) // Keeps signals flashing for the set time duration
  {
    unsigned long currentMillis = millis();
    // Loop that causes the signal lights to flash alternatively at the set time interval
    if(currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;    // save the last time you blinked the LED
      ledState = !ledState;   // toggle ledState
      digitalWrite(ledPin1, ledState);  // give LEDs opposite states
      digitalWrite(ledPin2, !ledState);
      // tone(7, 750, 100);    // need to test this for crossing signal sound
    }
  }
}