Laser Communications With Arduino Developed MPA Workshop Series

by SysOps

I’ve been giving a series of workshops for several months now. These workshops have been focused on understanding the basics of the underlying computer hardware. But much of that material can get rather technical and so we needed some hardware projects that didn’t involve building logic gates from transistors or designing CPU hardware in Logisim or Digital. We needed a fun project to break up the more technical material we’ve been covering. So, I discussed some ideas with the host and we came up with a simple Laser Communications System using the Arduino Nano. The project is simple enough to complete in  an evening. Exciting enough to gain interest. After all, what geek wouldn’t want to play with a laser? So I spend a bit of time developing this simple project and thought I’d share it here.

Before we begin, we’ll need a few supplies.  Tools, components and a computing device capable of running the Arduino IDE. Any laptop, table, or desktop machine should do. Some larger cellphones may even work. Check and see if you can install the Arduino IDE on your phone first, if you are intending to use your phone.

Since this is a communications system, you’ll need two systems so you have a transmitter and receiver. Each system actually functions as both so two way communications is possible. But you still need something to communicate with. The parts list is for a single unit. So, if you are building this by yourself you’ll need to build two. So let’s see what we’ll need:

  • A Solder-less Breadboard

An Arduino board with a Usb connector and headers. We used the Nano

  • Assorted jumper wires.
  • A 2n2222P NPN Transistor. T0-92 case preferred.
  • Two 39K or 47K through-hole, axial-lead 1/4 watt resistors.
  • A DTOL 10 X Mini Laser Dot Diode Module Head WL Red 650nm, 5v, 5mW. Can be found on Amazon and eBay. Part number: DTOL-SHUS1517
  • A Small Signal Photo Transistor in T-1 5mm Case. Must be sensitive to lights at 650nm. I used some clear 400nm to 1000nm Photo transistors from Amazon. They worked well.
  • A 220 or 330 ohm 1/4 watt through-hole, axial-lead resistor.

So, first let’s look at the schematic for the Laser. Here we can see a simple NPN2N2222P transistor being used in switching mode. The base of the transistor is connected to the Arduino board’s Digital Pin 2 (D2) through a 39K ohm resistor. The resistor limits the current to the base and ensures proper operation of the transistor. The current applied to the base of the transistor is multiplied by the transistor and the multiple is passed through the collector – emitter circuit. A typical 2N2222P should have a gain (multiplying effect) or around 200 or more. So what ever current we place on the base will be multiplied by ~200 and that amount of current will pass through the collector – emitter circuit. This all actually over simplified but it gives a basic understanding of the circuit. By using the transistor we can control much more current than the Arduino board’s output pins are capa

Laser Control Circuit

ble of supplying. If we were to connect the Laser to the Arduino directly we could cause damage to the Arduino. Since it’s possible that the transistor could pass more current than our Laser diode is capable of using, we could also cause damage to the laser if we did not limit the current flow through the laser with R2 a 330 Ohm resistor. The value of this resistor may be as low as 100 ohms or as high as 400 ohms. The lower the rating the more current will flow and the brighter the laser. However, the risk of damaging the laser or the surrounding circuit also increases as this number is lowered. I recommend you stick with values between 180 ohms and 330 ohms.

 

Let’s see how this sub-circuit looks on the breadboard. Note that we don’t yet have R4 connected to pin D2 of the Nano. We need the Nano for power at this time but we don’t want to connect our control circuit until we know it works as expected.

Wire up the board as shown. I recommend you use the same color wires if possible. Always use RED for positive power and BLACK for 0-Volts or ground. Make sure you use the 5-Volt pin on the Arduino board and not the 3.3-volt pin.

Laser Control Circuit

When placing the Laser on the board the long leg (Anode) should be placed so it connects to R2 the 330 ohm resistor. The short leg (on the side with the flat spot on the rim) is called the Cathode. The cathode should connect to the collector of the transistor.

When placing the transistor the pins out are as shown for most 2N2222 transistors. If your’s has a part number that begins with a “P” then the collector and emitter may be switched. But most will be exactly as shown. This should put the flat side of the transistor facing you if you wire the board as I did.

Transistor Pin Out

Once you have the transistor placed and the board wired as show, double check everything. If there is someone around who can double check your work for you, that is always helpful. Be particularly cautious of the connections to the Arduino board.

Now, first we will be a manual test of our sub-circuit to ensure it works as expected. Apply a jumper wire from the open (non connected) end of R4 to ground. Now plug the Arduino board into a USB port on your computer. The Laser should be off at this point.

Next, move the jumper wire to make a connection from the open end of R4 to the positive rail (5-volts). Now the Laser should turn on. If this works as expected you’re ready to write some test code. If not, then you need to double check everything. Make sure you have +5 volts to the positive (RED rail of the breadboard and 0-volts on the blue or black rail). Also, check that your Laser is placed with the long led connected to R2 and the other end of R2 is connected to +5 volts. Next, make sure your Transistor is placed properly and try turning it around if the part number begins with a “P”.  Have someone else check the circuit for you. A new set of eyes often sees more than the tired set that’s been looking at the same thing for hours.

Above showing R4 jumper to GND. Laser should be off. Arduino must be powered.

Above showing R4 jumper to Vcc +5 Volts. Laser should be on. Arduino must be powered.

 

Test The Laser Driver

OK, now that we have the laser working manually, it’s time to write some code. If you don’t already have Arduino IDE installed, go on over to www.arduino.cc go to the Software menu and select download. Follow their instructions for installing the IDE and getting your Arduino board up and running with the Blink example provided in the IDE. Once you have that done, or if you already have your IDE installed, move on to the next step.

Our first step will be to connect the open end of R4 to the D2 pin on the Arduino board. Next, open a new sketch in the Arduino IDE and enter the following code exactly as shown below:

Listing #1


/*
   LASER Blink
   BY: Randall Morgan

   Turns the LASER on for one second, then off for one second, repeatedly.

   We use D2 to drive the base of the switching transistor.
   D3 will be used later to read the Phototransistor.
   
   This example code is in the public domain.
   www.randallmorgan.me
   www.eastern-montana-tech.com

*/

int LASER_OUT = 2; // Laser control pin
int DELAY_MS = 1000; // 2000 ms (2 Seconds) cycle period

// the setup function runs once when you press reset or power the board
void setup() {
   // initialize digital pin 2 as an output.
   pinMode(LASER_OUT, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
   // Loop turning LASER on and off
   digitalWrite(LASER_OUT, HIGH); // turn the LED on (HIGH is the voltage level)
   delay(DELAY_MS); // wait for a second
   digitalWrite(LASER_OUT, LOW); // turn the LED off by making the voltage LOW
   delay(DELAY_MS); // wait for a second
}

Load and run this code by pressing the right facing triangle in the IDE. You should see the Laser Diode turning on and off. This should continue until you kill the power to the board.

 

Receiving Light Signals

OK, so now we have a way to send light pulses. What we need now is a way to receive light pulses. To do this we will use the Photo-transistor.  This is a transistor who’s base is exposed as a light sensitive element under the plastic package. Actually, all transistors are sensitive to light but a Photo-transistor is manufactured to take advantage of this phenomenon where other types of transistors are designed to minimize this phenomenon. Photo-transistors aren’t the only light sensitive devices we could use. Photo resistors are slower but work very well for sensing ambient light. Photo diodes work almost like Photo-transistors and can switch very fast for high speed communications.

In our project we chose the photo transistor as they are easy to work with and readily available. There is a three legged photo-transistor. The third leg is an exposed base. Basically, you can use the exposed base to adjust the sensitivity of the device. That’s a real nice feature but it complicates the design. So we chose not to use this type of photo transistor. If you purchased one of these it may work fine with the base left floating (unconnected). Sp give it a try before going out and purchasing the two legged type.

Complete Schematic

Looking at the schematic we can see that the photo transistor has it’s emitter tied to ground. The collector is connected to Vcc +5 volts through a 39K ohm resistor. This arrangement is known as a PULL-UP configuration. When the photo transistor is in the dark (or at least not receiving light on it’s base element), it is turned off and no current can flow through the transistor. This allows R1 to pull the input pin D3 on the Arduino to 5 volts. This creates a logic hi on the input. When the transistor receives light it turns on and pulls the collector down to near ground. This applies a logic lo or zero on pin D3. In this way we can sense the incoming light pulses.   Please ignore the dashed line. Fritzing kept replacing it after I removed or rerouted it. Very frustrating…

Photo Transistor Circuit Added

 

Now lets write some code to test this circuit. If you’re wondering why I’m not doing a manual test first, it’s because the circuit is very simple and about the only two things that may go wrong are that perhaps you put the photo transistor in backwards or you connect it to the wrong pin on the Arduino. If you have a multi-meter you can manually test the circuit by measuring the voltage on the collector of the photo-transistor. Cut a short piece of soda straw and place it over the photo-transistor. Then place the Laser Diode in the other end. SO that the laser shines on the end of the photo transistor. The voltage should drop on the collector to somewhere around 0.1-0.2 volts of less. If it does, you’re good to go. If it doesn’t, try turning the transistor around.

We’re going to write a little test code before we go all out and start sending messages to Mars and beyond. We use a little program to flash the laser on and off, one second in each state. During the middle of the state we’ll read the photo transistor on the digital input pin 3.

Now we need a way to communicate back to user just what the value read from the input is. We could setup an led and turn it on if the input is one or, we could just use the serial port to send the value back to the serial monitor in the Arduino IDE. I think this second approach is best and requires no additional hardware. So let’s see what this looks like:



/*
  LightReader
  By: Randall Morgan

  This test circuit simply toggles the laser connected
  to digital pin D3 on and off at a rate of 1/2 Hertz.
  After toggling the laser's state it then reads the
  input from the photo transistor on digital pin 2.

  To run this program you'll need an Arduino board
  with a laser diode connected via an npn switching
  transistor to digital pin 3.

  In addition you'll need a photo transistor connected
  to a resistor in a pull-down arrangment and the
  junction of the pull-up resistor and the photo
  transistor collector connected to digital pin 2 on
  the Arduino board.

  See the article at: http://www.randallmorgan.me/blog/
  Search for Arduino Laser Communications

  This code is placed in the public domain
*/

int LASER_OUT = 5; // Laser control pin
int PHOTOTRANS_IN = 3; // Photo transitor sense pin
int DELAY_MS = 1000; // 2000 ms (2 Seconds) cycle period
int val = 0; // input value
char buf[100];

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LASER_OUT, OUTPUT);
  pinMode(PHOTOTRANS_IN, INPUT);

  // Set up serial port
  Serial.begin(9600);
  // Wait for hardware serial to connect
  while(!Serial) {
    // wiating for connection....
  }
  Serial.print("Connected\n");
}

// the loop function runs over and over again forever
void loop() {
  // Turn on laser and read photo transistor
  digitalWrite(LASER_OUT, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(DELAY_MS/2); // wait for a second
  val = digitalRead(PHOTOTRANS_IN); // read the photo transistor
  sprintf(buf, " Val: %d \n", val);
  Serial.print(buf);
  delay(DELAY_MS/2);

  // turn off laser and read photo transistor
  digitalWrite(LASER_OUT, LOW); // turn the LED off by making the voltage LOW
  delay(DELAY_MS/2);
  val = digitalRead(PHOTOTRANS_IN);
  sprintf(buf, " Val: %d \n", val);
  Serial.print(buf);
  delay(DELAY_MS/2);
}


Reviewing the code we can see two interesting additions. First, we call Serial.begin() in the setup() function and pass it the baud rate we want to use. Since the default baud rate for the serial monitor in the IDE is 9600, we use that. Next we wait for the serial library to get a connection to the host computer. The while loop performs this wait for us and exits when Serial returns true. This occurs when the serial library has a connection to the host.

In the function loop() we added calls to SerialWrite() and pass in a buffer containing a string of characters to send to the host. We cheated a little and initialized a character array of 100 characters. Ideally, you’d want to safe guard against buffer overflow here. If you don’t know what that is, do a little googling and read up on it.

Before we can send the value read from the digital input pin to the host we must convert it to a string representation. What we read is actually a number not a character. So, we pass the buffer and the value to the C function sprintf() for formatting and conversion. You can find good information on many C and C++ functions and libraries that can be used with Arduino googling the “Standard C/C++ libraries”.

OK, so now we can control our laser and sense when a laser is on or off when pointed at out photo transistor. The only piece we are lacking now is the code to allow us to communicate with another unit. To accomplish this, we only need to setup a software serial port. Software serial ports work similar to hardware serial ports except they are just routines running to read and send bits on the I/O pins.

The serial library requires the use of interrupts. An interrupt is a signal to the processor to stop what it is doing and service another routine. Since the SoftwareSerial routine needs to be called regualrly so it doesn’t miss a bit, it requires inputs that are interrupt capable. Both D2 and D3 are interrupt capable pins but they are not the only ones on the Arduino. So if you used other pins, you’ll need to move your control signals to pins with interrupt support. The SoftwareSerial library is shipped with Arduino IDE so there is no need to download and install another library.

So, let’s talk about what we need to accomplish with our code. First, we need to send data on the laser. We can do this by setting the laser control pin as the software serial libraries transmit pin. In order to receive data we simple need to set the photo transistor’s sense pin as the software serial libraries receive pin. Then we simple use the hardware serial port to send anything received on the software serial port to the host. Anything we receive from the host on the hardware port can be sent on by the software serial port. So let’s see how we can implement this:


/*
   LightReader
   By: Randall Morgan

   This test circuit simply toggles the laser connected
   to digital pin D3 on and off at a rate of 1/2 Hertz. 
   After toggling the laser's state it then reads the 
   input from the photo transistor on digital pin 2.

   To run this program you'll need an Arduino board
   with a laser  diode connected via an npn switching 
   transistor to digital pin 3.

   In addition you'll need a photo transistor connected 
   to a resistor in a pull-down arrangment and the 
   junction of the pull-up resistor and the photo 
   transistor collector connected to digital pin 2 on
   the Arduino board.

   See the article at: http://www.randallmorgan.me/blog/
   Search for Arduino Laser Communications 

   This code is placed in the public domain
*/

// Tell the IDE we want to use 
// the SoftwareSerial library
#include 

int LASER_OUT = 2;      // Laser control pin
int PHOTOTRANS_IN = 3;  // Photo transitor sense pin
int DELAY_MS = 1000;    // 2000 ms (2 Seconds) cycle period
int val = 0;            // input value
char buf[100];


SoftwareSerial laserSerial(PHOTOTRANS_IN, LASER_OUT);

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LASER_OUT, OUTPUT);
  pinMode(PHOTOTRANS_IN, INPUT);  

  // Set up serial port
  Serial.begin(9600);
  // Wait for hardware serial to connect
  while(!Serial) {
    // wiating for connection....
  }

  Serial.print("Connected\n");

  // Setup Software Serial
  laserSerial.begin(57600);

  // Now we start sending data to 
  // allow the users to line up the
  // lasers and photo transistors.
  // Once the user hits a key, we 
  // stop and begin transceiving 
  // data on the serial ports.
  while(!Serial.available()){ 
    laserSerial.write("Light is beautiful!...");  
  }
  
}


// the loop function runs over and over again forever
void loop() {
  // If the photo transistor has received 
  // and data, send it to the host
  if(laserSerial.available()) {
    Serial.write(laserSerial.read());
  }

  if(Serial.available()) {
    laserSerial.write(Serial.read());
  }
}


Now enter the code above into the Arduino IDE and upload it to your Arduino board. The system should begin sending the phrase “Light is beautiful!…” immediately. Use this phrase data to line up your laser with the second unit’s photo transistor. Once the alignment is complete, hit a key on the keyboard and the transmission should stop. The system is now in transceiver mode. Anything you type into the serial monitor will be sent to the second unit. Anything the second unit sends will be sent to the serial monitor for display.

Congratulations, you now have completed the project. But this is only the beginning. There are many improvements to both the code and the circuit that can be made. Take the circuit presented here and make changes to it. Share those changes with others and let’s see what you come up with.

Until next time, Happy Hacking!