Laser Communication

If anyone is interested in communicating over a laser, here is some code I wrote to achieve communication from one photon to another.
It uses a modified version of RS232 and a 38KHz carrier frequency.
It works pretty well, although there is no error correction or acknowledgement.
Hope it’s useful to others.

Sorry - every time I put code in a code block it spills out and goes everywhere… :

    //  TRANSMITTER CODE
/*
Code written by Lindsay Fowler

This project will be in two parts:
*A Transmitter Tx (this code is for the Transmitter)
*A Reciever Rx

It will transmit a signal with a RS232 protocol.
Using special PWM feature of AnalogWrite function, the RS232 is modulated onto a 38KHz carrier (kicks in when applied to digital pins) to achieve 38KHz
This way we can use an off the shelf IR receiver, and red laser.

Tx Circuit:

-------|
       |                        5V
Phton  |                        |
       |                        |
       |         10K Ohms     ||D-   
    D0 |---------/\/\/\/\---G||     Laser Diode Module (1mW)
       |                     ||S----|>|------          
-------|                                    |                   
                           2N7000           |
                           MOSFET           |
                                            |
                                            |
                                           GND


Protocol:
Basically RS232 Except l have a normally low Idle,
with an active high start bit, high 1s, low 0s, then high stop bit:

IDLE  start 0   1   2   3   4   5   6   7  stop (rising edge on pulseWidth*10)   
      |---|---|---|       |---|---|   |---|---|
------|   | 1 | 1 | 0  0  | 1 | 1 | 0 | 1 |   |-----------

*/

byte byteToSend = 0xAC;
int pulseWidth = 5;//pulse width in milliseconds

void setup() {


    pinMode(D0, OUTPUT); //Connected to Laser
    
    pinMode(D7, OUTPUT); //Blue transmission indicator LED
    
    pinMode(D1, OUTPUT);// debug - to mark the start of transmission
    
    Serial.begin(9600); //turn on the serial monitor

}

void loop() {
    //wait a second
    delay(pulseWidth*15);
    sendByte(byteToSend); //Send byte
    byteToSend+=1; 
    //delay(pulseWidth*15);
    //sendByte(0x55); //Send byte
}


void sendByte(byte dataByte){

    Serial.println("sending 0x"+String(dataByte, BIN)); //debug

    //send start bit
    analogWrite(D0,128,38000);//Switch on the 38KHz to IR LED
    digitalWrite(D7,HIGH);//Switch on the Blue Indicator LED
    delay(pulseWidth); //wait until stop bit is over.

    for (int bitNumber=0;bitNumber<=7;bitNumber++){
        if(dataByte & (1 << bitNumber)){
            analogWrite(D0,128,38000);//Switch on the 38KHz to IR LED
            digitalWrite(D7,HIGH);//Switch on the Blue Indicator LED
            //Serial.println(String("bitPos:") + String(bitNumber) + "  Data: 1"); //debug
            
        }else{
            analogWrite(D0,0,38000);//Switch off the 38KHz to IR LED
            digitalWrite(D7,LOW);//Switch off the Blue Indicator LED
            //Serial.println(String("bitPos:") + String(bitNumber) + "  Data: 0"); //debug

        }// end if
        delay(pulseWidth); //wait to send the next bit
        

    }// end for loop

    analogWrite(D0,128,38000);//Switch on the 38KHz to IR LED
    digitalWrite(D7,HIGH);//Switch on the Blue Indicator LED
    delay(pulseWidth); //wait until stop bit is over.
    
    analogWrite(D0,0,38000);//Switch off the 38KHz to IR LED
    digitalWrite(D7,LOW);//Switch off the Blue Indicator LED

}// end sendByte
//RECEIVER CODE

/*
Code written by Lindsay Fowler

This project will be in two parts:

  • A Transmitter (Tx)
  • A Receiver (Rx) This is the receiver

It will monitor the laser receiver photo diode
Use RS232-like protocol
1 Start bit
8 Data bits
1 Stop bit

Protocol:
Basically RS232 Except l have a normally low Idle,
with an active high start bit, high 1s, low 0s, then high stop bit:

IDLE start 0 1 2 3 4 5 6 7 stop
|—|---|—| |—|---| |—|---|
------| | 1 | 1 | 0 0 | 1 | 1 | 0 | 1 | |-------------

Receiver Circuit for connection to Particle Photon:

IR Detector (front)
 ____________
|    ____    |
|   /    \   |
|  |      |  |
|   \____/   |
|            |
|Out GND VCC |
 -------------
 |     |    |
 |     |    |
 |     |    |
 D0   D1    D2

*/

//pin constants
const int powerPin = D2;
const int gndPin = D1;
const int dataIn = D0;
int debugPin = D3; // pin to highlight the reading time

int value_recieved;
int pulseWidth = 5; //milliseconds

void setup() {
Serial.begin(19200); //turn on the serial monitor
Serial.println(“Setting up Receiver. Expected pulse width is “+ String(pulseWidth)+“ms.”);
Serial.println(””);

pinMode(gndPin, OUTPUT);  //make a ground for detector
digitalWrite(gndPin, LOW);

pinMode(powerPin, OUTPUT); //make a supply for detector
digitalWrite(powerPin, HIGH);

pinMode(D7, OUTPUT); //turn on indicator LED
digitalWrite(D7,HIGH);

pinMode(debugPin, OUTPUT); //turn on indicator LED
digitalWrite(debugPin,LOW);

pinMode(dataIn, INPUT);

}

void loop() {
//wait for start bit (rising edge)
if(digitalRead(dataIn)==0){//the IR detector is active low.
//Serial.println(“Start bit detected”); //debug
Serial.println("Byte received: " + String(receiveByte()));//blocking function, hopefully
}
}

byte receiveByte (){
byte data = 0x00;
byte bitPos = 0x01;

//delay half of pulse width because rising edge detected and we should be in the middle of next pulse
//Serial.println("Waiting 1.5 pulse widths"); //debug
delay(pulseWidth*1.5);

for (int bitPos=0;bitPos<=7;bitPos++){
    //debugPulse();//send a debug pulse to see when the bit value reading is occuring
    if(digitalRead(dataIn)==0){ //the IR detector is active low.
        data = data | (1 << bitPos); // "|" is bitwise Or; data|00000001 sets bit 0
        //Serial.println("bitPos:" + String(bitPos) + "  Data: 1"); //debug
    }else{
        //Serial.println("bitPos:" + String(bitPos) + "  Data: 0"); //debug
        data = data & ~(1 << bitPos); // "|" is bitwise Or; "~" is a bitwise not: data|11110111 clears bit 3  
    }
    delay(pulseWidth); //wait to read the next bit


}
delay(pulseWidth/2); //wait until stop bit is over.

return data;

}

void debugPulse(){
digitalWrite(debugPin,HIGH);
delay(0.9);
digitalWrite(debugPin,LOW);
}

3 Likes

@Lindsay, that code was a snot but I think I got it right :wink:

2 Likes