Sunday, March 31, 2013

An Arduino Laser Tripwire

A few weeks ago I was sitting at home sick and a friend called me to ask if I wanted to come over and hack on electronics.  Needless to say, I was instantly well enough to go play with his new Raspberry Pi and Arduinos.

He decided he liked the Raspberry Pi better, so he gave me one of the Arduinos to take home and fiddle with.  I wanted to put together a simple laser tripwire which will serve as a component of another, larger project that I am planning.  This project is designed to be a black-box component of anything that needs to rapidly trigger when an object crosses a beam.  You can imagine sending the "trip" signal to an floodlight, an alarm, or some mechanical device that just needs to do something when an object is deposited at this position.

Setting up the Arduino Uno was trivial--it connects to my PC through a USB port and takes a 9VDC power adapter.   I have a small project board that it screws into, so the whole setup looks pretty nice.  If you wanted something more permanent, there are cute project enclosures for all types of Arduino available.
The Arduino Uno connected to power and USB, and attached to my project board.
Next I wanted to make a Hello World program for my Arduino--or maybe more appropriately, Hello LED.  The IDE is actually not too intrusive and is easy to use, so the next step was to

sudo apt-get install arduino

Entering the Hello LED program into the IDE and uploading gave me a sample program to start with and an Arduino with a blinking LED.

The Arduino Uno with the blinking LED program from the Arduino Tutorials installed and running.  
Naturally, the USB no longer needs to be plugged in for my Arduino to continue its once-per-second LED toggle--the code has been uploaded to the Arduino board and it will continue blinking until I remove it from its power source!

Next I put together my laser tripwire.  I want it to trigger fast, so I bought a some phototransistors.  I also wanted it to be resilient to changing light conditions in its environment, so initially I thought I'd have to rapidly switch the laser beam on and off and look for the moment when the phototransistor didn't detect the change.  In fact, this turned out to be unnecessary.  The laser is so bright compared to everything else (including daylight) that it works great if I just look for the moment that the phototransistor detects a 10% drop in brightness.
Schematics made in the open-source schematics suite KiCad for the tripwire circuit.  Depending on what hardware you have, you may have to vary the resistances.
Next I needed to upload some code to the Arduino to give it the desired behavior.  Here is the source code I compiled and uploaded using the arduino package IDE.

int ledPort = 13; 
int laserPort = 12; 
int tripPort = 11; 

int timerToggle = 1000; 
int timerCount = 0; 
boolean timerState = false; 

int onLevel = -1; 
int offLevel = -1; 
boolean tripped = false; 

void setup() { 
  pinMode(ledPort, OUTPUT); 
  pinMode(laserPort, OUTPUT); 
  pinMode(tripPort, OUTPUT); 
  digitalWrite(tripPort, LOW); 

  // Check the state of the phototransistor with the laser on 
  // and off.  I delay a bit because the rise time on the 
  // pins appears to be between 1/10 and 1/100 of a second.
  digitalWrite(laserPort, LOW); 
  delay(1000);  
  offLevel = analogRead(A0); 

  digitalWrite(laserPort, HIGH); 
  delay(1000); 
  onLevel = analogRead(A0); 


// An alive signal that appears on the arduino, 
// just to let me know the program is running. 
void timer() { 
  timerCount++; 
  if (timerCount == timerToggle) {
    timerCount = 0; 

    timerState = !(timerState); 
    if (timerState) { 
      digitalWrite(ledPort, HIGH); 
    } else { 
      digitalWrite(ledPort, LOW); 
    } 
  }


void loop() { 
  delay(1); 
  timer(); 
  // The device just lights the trip light if it is triggered. 
  // It must be reset by pressing the reset button afterwards. 
  if (!(tripped)) { 
    currentLevel = analogRead(A0); 
    // Trip if the light level drops below 90% of on vs. ambient. 
    if (currentLevel < onLevel - (onLevel - offlevel) / 10) { 
      tripped = true; 
      digitalWrite(tripPort, HIGH); 
    } 
  } 
}

Finally, I started it up and gave it a whirl!  To illustrate how it works, I've made a YouTube video that you should check out:



Here's a picture of the completed device:

The completed laser tripwire.  I used LEDs as resistors, because I didn't have any within an order of magnitude of the resistance I needed!