> | | | > Laser Setup and Detection

Laser Setup and Detection

Posted on Wednesday, 21 November 2012 | 2 Comments

Laser Setup

TESTING LASER SWITCHES ON

Firstly, the laser needed to be tested to see if it would work. On the TTL laser, there is a polarized 4-pin connector with the following connections:

  • Red wire:5-12 V DC input
  • Black wire: GND
  • Green wire: 10k pull-down (aka GND)
  • White wire: active low TTL input (3.3 V or 5 V logic)

The laser was tested by firstly just turning the laser ON and leaving it on. This was done by connecting the red wire to a power source, the black wire to GND, the white wire to GND and leaving the green wire unconnected. This successfully turned the laser on. 


TESTING LASER WORKS WITH ARDUINO

The laser was then tested with the Arduino. The white wire was connected to a TTL output on the Arduino (Port 13), the red wire was connected to 5V and the black wire was connected to Gnd as shown in the diagram below. Again, the green wire was left unconnected. 
Arduino Laser Connections

The Arduino was given power and the basic sketch "Blink" was downloaded to the board. Once downloaded, the laser successfully started blinking in accordance with the sketch. This shows that the laser can easily work with the Arduino. 

The testing for this laser was found at this site.

Laser Detection

LDR

To detect a laser, a light dependent resistor (LDR) is needed. An LDR is a device which has a resistance that varies according to the amount of light falling on its surface. A typical LDR can be seen pictured below, along with its circuit diagram symbol.
LDR and circuit symbol
The LDR that was chosen to go with the TTL Laser Module was the Mini Photocell, as this was suggested from the manufacturer. The photocell can be seen below. 
Mini Photocell

DETECTION CIRCUIT

An LDR can be set up in two ways:
  1. The LDR is activated by darkness
  2. The LDR is activated by light
For LaserBots, a laser is fired and the LDR is meant to detect when the laser hits it. Therefore, the LDR needs to be activated by light. The circuit for this can be seen below:
LDR circuit
When light hits the LDR, the LED will light up. The variable resistor is used to fine tune the amount of light needed to activate the LDR. 

A similar circuit to the one pictured above (resistor values were different) was built on a breadboard and the variable resistor was used to tune the LDR so that only the high intensity laser beam activated the LED and not the background light from the room. The circuit was powered by connecting it to an Arduino, along with a laser. A video of this circuit working can be seen below. 


As can be seen, when the laser moves over and hits the LDR, it switches the transistor and turns the LED on. 

ARDUINO CODE

SIMPLE LASER DETECTION

Now that the laser and detection circuit has been tested to see that both work, the next stage is to get the Arduino involved. The Arduino should be able to turn the laser on and off. Firstly, the pin that the laser is connected to can be given a name, for example, laser. This pin can then be set as an output, which will tell the laser to go either high or low depending on which command the Arduino writes to it. For this first simple set up of code, the laser is set to be low. The pin that the LDR is connected to is set up in the same way. It is given a name (LDR) and is assigned a pin mode (this time it is set to input, as data will be received from the LDR). For this circuit, the laser is connected to pin 8 and the LDR is connected to pin 7, but any pin could have been chosen. The code can be seen below. 

/*
int LDR = 7; //LDR attached to pin 7
int laser = 8; //Laser attached to pin 8

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the LDR's pin an input:
  pinMode(LDR, INPUT);
  //make the laser's pin an output:
  pinMode(laser, OUTPUT);
  
  digitalWrite(laser, LOW);//turn laser on 
}
Now that the pins have been set up, code can be written to interact with the detector circuit that has been built. When the LDR is hit with the laser, the output changes from high to low. This change can be picked up by the Arduino by doing a digital read of the pin. A digital read reads the value from a specified digital pin, either HIGH or LOW. If the value read is LOW, the Arduino can state that it has been hit, else if it is HIGH it won't do anything, as can be seen in the following code.
// the loop routine runs over and over again forever:
void loop() {
  // read the input pin:
  int hitState = digitalRead(LDR);

  //LDR goes low when it has been hit
  if (hitState == 0)
  {
    Serial.println("HIT");
    delay(2000);        // delay in between reads for stability
  }
This code can now be put together and uploaded onto the Arduino. The Arduino and detector circuit should be set up as follows.
INSERT PIC
Once everything is set up, the Arduino was kept connected to the computer and a Serial monitor was opened. When the laser hit the LDR, on the Serial monitor "HIT" was printed. The Arduino successfully works with the laser detection circuit.


USING INTERRUPTS

If the robot was only detecting whether or not it had been hit, the code shown above would be fine. However, the robot is going to be processing lots of other code (controlling servos, motors, lasers etc) and so the above code is not sufficient, as it only checks if it has been hit once every turn of the loop. This could cause the robot to miss detecting that it has been hit.

To overcome this problem, interrupts can be used. An interrupt is a signal to the processor emitted by hardware or software indicating an event that needs immediate attention, which in this case is the LDR stating that it has been hit. There are only two external interrupt pins on the Arduino Uno, INT0 and INT1, and they are mapped to Arduino pins 2 and 3. The interrupts can be set to trigger on RISING or FALLING signal edges, or on low level. It was decided that the interrupt should occur on the FALLING signal edge rather than on low level. This is because it means that the user will have to move the laser off the LDR before they can hit the robot again, making the game slightly harder. Otherwise, the user could just leave the laser pointing on the LDR and get a huge score. 

The code was changed to use interrupts instead of a digital read. For interrupts to work, the interrupt library needs to be included in the code, therefore at the top of the program before anything else this line of code was added:
 #include "avr/interrupt.h"
Firstly, the pin that the LDR was on was changed from 7 to 2 (as pin 2 has an interrupt attached to it). In the setup method, the following code was added to enable the interrupt and set the interrupt to trigger on a falling edge. 
  sei(); //Enable global interrupts
  EIMSK |= (1 << INT0); //Enable external interrupt INT0
  EICRA |= (1 << ISC01); //Trigger INT0 on falling edge
An interrupt service routine (ISR) then needs to be written. An ISR is the code that is run when the interrupt is triggered. For the moment, the Arduino will just print out that it has been hit.
//interrupt service routine for when the LDR is hit
ISR(INT0_vect)
{
    Serial.println("HIT INTERRUPT");
}
In the main loop of the program, the digital read is removed, as that is no longer needed. To get the program to still do something for the interrupt to interrupt, the Arduino will just print out that it is waiting for the interrupt. The whole code now looks like this:
int LDR = 2; //LDR attached to pin 2 (as pin 2 has an interrupt on it)
int laser = 8; //Laser attached to pin 8

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the LDR's pin an input:
  pinMode(LDR, INPUT);
  //make the laser's pin an output:
  pinMode(laser, OUTPUT);
  
  sei(); //Enable global interrupts
  EIMSK |= (1 << INT0); //Enable external interrupt INT0
  EICRA |= (1 << ISC01); //Trigger INT0 on falling edge
  
  digitalWrite(laser, HIGH);//turn laser on 
}

// the loop routine runs over and over again forever:
void loop() {
  //print something so program has something to do
  Serial.println("Waiting for interrupt");
  delay(1000); //wait one second
}

//interrupt service routine for when the LDR is hit
ISR(INT0_vect)
{
    Serial.println("HIT INTERRUPT");
}
Running the code and watching on a serial monitor, the program outputs "Waiting for interrupt" every second until the interrupt is called, in which case it prints "HIT INTERRUPT".


UPDATING SCORES AND USING MILLIS

Now that the code works with interrupts, more functionality can be added. A score can be added into the code, so that every time the robot is hit, a score is incremented. To stop a user from continually hitting the robot and gaining a large score very quickly, an interval can be included to stop incrementing the score until 5 seconds has passed between hits. Finally, rather than using delays in the code which hold the whole program up, a function called millis() can be used. It is a command that returns the number of milliseconds since the Arduino board started running its current program. An example of using millis() is given in the Arduino examples, callled "Blink without Delay". 

Combining all of the above, the final code looks like the following:
 #include "avr/interrupt.h"

int LDR = 2; //LDR attached to pin 2 (as pin 2 has an interrupt on it)
int laser = 8; //Laser attached to pin 8
int score = 0; //score of the robot
int scoreFront = 10; //score of hitting the LDR
//introduce 5 second interval after hit before another hit can occur
int interval = 5000; 
long lastBlinkTime = 0; //variable used with millis

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the LDR's pin an input:
  pinMode(LDR, INPUT);
  //make the laser's pin an output:
  pinMode(laser, OUTPUT);
  
  sei(); //Enable global interrupts
  EIMSK |= (1 << INT0); //Enable external interrupt INT0
  EICRA |= (1 << ISC01); //Trigger INT0 on falling edge
  
  digitalWrite(laser, HIGH); 
}

// the loop routine runs over and over again forever:
void loop() {
  //make program do something
  digitalWrite(laser, HIGH);  
}

//interrupt service routine for when the LDR is hit
ISR(INT0_vect)
{
  unsigned long hitMillis = millis();
  
  //if there has been more than 5 seconds since the last hit
  if ((hitMillis - lastBlinkTime) > interval)
  {
    lastBlinkTime = hitMillis;
    
    //increment score
    score = score + scoreFront;
    
    Serial.println("Hit Interrupt");
    Serial.println(score);
  }
}
Running this code, when the LDR is hit, the ISR is called and "Hit Interrupt" along with a score is printed, for example 10 for the first hit. When the user tries to hit the LDR again, nothing happens until 5 seconds has passed. The user hits the LDR again and now the Arduino prints out "Hit Interrupt" with a score, now equal to 20. This concludes the code that is needed for laser detection.

Comments:2

  1. I DO HAVE SOME THINGS TO HELP WITH THIS KIND OF PROJECT
    http://www.ebay.com/itm/140930389517?ssPageName=STRK:MESELX:IT&_trksid=p3984.m1555.l2649

    http://www.ebay.com/itm/140928107140?ssPageName=STRK:MESELX:IT&_trksid=p3984.m1555.l2649

    http://www.ebay.com/itm/140930389517?ssPageName=STRK:MESELX:IT&_trksid=p3984.m1555.l2649

    ReplyDelete
  2. Please provide circuit diagram

    ReplyDelete

Theme MXS. Powered by Blogger.