Hackster is hosting Impact Spotlights highlighting smart energy storage. Start streaming on Thursday!Stream Impact Spotlights on Thursday!
donbuckley
Published © GPL3+

Laser Pager / Morse Code Transceiver

Send texts with lasers in Morse code!

AdvancedFull instructions provided1,034
Laser Pager / Morse Code Transceiver

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×2
Breadboard (generic)
Breadboard (generic)
×2
Laser Diode, 655 nm
Laser Diode, 655 nm
×2
Photo resistor
Photo resistor
×2
Resistor 10k ohm
Resistor 10k ohm
×2
Jumper wires (generic)
Jumper wires (generic)
×2

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Circuit Diagram

The basic circuit.

Code

Laser Pager Code

Arduino
Copy and paste to both computers. When you run it, put Serial in fullscreen and don't start texting until a username is entered on both ends.
//stuff for laser and photoresistor
const int laserPin = 2;
const int photoPin = A0;
const int lightLimit = 800;
int photoVal; 

//stuff for intro
String myName = "";
boolean introEnd = false;

//stuff for transmitting texts
String myText;
String myMorse;
String myMorseChar;
int myTextNum = 0;

//stuff for receiving texts
String theirMorse;
boolean messEnd = false;
int spaces = 0;
int spaceIndex;
String theirMorseChar;
String theirText;
String theirName;
int theirTextNum = 0;

//time values for laser pulses
const int dot = 30;
const int dash = dot * 2;
const int undscr = dot * 3;
const int elemSpace = dot;
const int charSpace = dot;
const int messSpace = dot * 2;

//array of Morse values in order of corresponding ascii characters starting with space (decimal 32)
const char* asciiArray[] = {
  
// space to /
".", "-", "_", "..", ".-", "._", "-.", "--", "-_", "_.", "_-", "__", "...", "..-", ".._", ".-.", 
// 0 to 9
".--", ".-_", "._.", "._-", ".__", "-..", "-.-", "-._", "--.", "---",
// : to @
"--_", "-_.", "-_-", "-__", "_..", "_.-", "_._", 
// A to M
"_-.", "_--", "_-_", "__.", "__-", "___", "....", "...-", "..._", "..-.", "..--", "..-_", ".._.", 
// N to Z
".._-", "..__", ".-..", ".-.-", ".-._", ".--.", ".---", ".--_", ".-_.", ".-_-", ".-__", "._..", "._.-", 
// [ to `
"._._", "._-.", "._--", "._-_", ".__.", ".__-",
// a to m
".___", "-...", "-..-", "-.._", "-.-.", "-.--", "-.-_", "-._.", "-._-", "-.__", "--..", "--.-", "--._", 
// n to z
"---.", "----", "---_", "--_.", "--_-", "--__", "-_..", "-_.-", "-_._", "-_-.", "-_--", "-_-_", "-__.", 
// { to ~
"-__-", "-___", "_...", "_..-" 
};

void setup() {
  //initialize and turn on laser 
  pinMode(laserPin, OUTPUT);
  digitalWrite(laserPin, HIGH);

  //set Serial and print instructions
  Serial.begin(9600);
  Serial.println(F("Align the laser and sensor with another user's, then enter a username."));
}

void loop() {
  //intro keeps laser on until username input
  while(introEnd == false) {
    
    //when user sends something to Serial
    if(Serial.available()>0) {
      
      //new myName from Serial has leading and trailing whitespace removed
      myName = Serial.readString();
      myName.trim();
    }
    
    //when myName value has changed
    if(myName != "") { 
      
      //turn off laser and allow next while loop
      digitalWrite(laserPin, LOW);
      introEnd = true;
      
      //intro message with separating line
      Serial.print(F("Hi, "));
      Serial.print(myName);
      Serial.println(F("! Message away."));
      Serial.print(F("─────────────────────────────────────────────────────────"));
      Serial.println(F("────────────────────────────────────────────────────────"));
    }
  }
  
  //the meat and potatoes if yknow what I mean
  while(introEnd == true) {
      
    //transmitter loop starting when Serial gets something
    while(Serial.available() > 0) {
      
      //prints text sent to Serial for self
      myText = Serial.readString();
      myText.trim();
      Serial.print(F("Me: "));
      Serial.println(myText);
      Serial.println();

      //turns myName into sending format
      myName += ": ";
    
      //only sends username in first message, shortens time for subsequent messages
      if(myTextNum == 0) {
        myText = myName + myText;
      }
      
      //loop for constructing Morse code from myText
      for(int i=0; i < myText.length(); i++) {
       
        //subtract ascii value of each char in myMorseName by 32 for place in array and adds thus Morse to myMorse separated by spaces
        myMorseChar = asciiArray[myText.charAt(i) - 32];
        myMorse += myMorseChar + " ";
      }
    
      //converts Morse characters to laser pulses
      for(int i=0; i < myMorse.length(); i++) {
        
        //repurposes myMorseChar for individual Morse elements
        myMorseChar = myMorse.charAt(i);
        
        //if character is a dot
        if(myMorseChar == ".") {
          digitalWrite(laserPin, HIGH);
          delay(dot);
        }
        //if character is a dash
        else if(myMorseChar == "-") {
          digitalWrite(laserPin, HIGH);
          delay(dash);
        }
        //if character is an underscore
        else if(myMorseChar == "_") {
          digitalWrite(laserPin, HIGH);
          delay(undscr);
        }
        //if character is a space
        else if(myMorseChar == " ") {
          delay(charSpace);
        }
        //space between elements
        digitalWrite(laserPin, LOW);
        delay(elemSpace);
      }

      //clear myMorse, add 1 to sent message total and delay before next message
      myMorse = "";
      myTextNum++;
      delay(messSpace);
    }
    
    //receiver loop starting when laser brightness detected
    while(analogRead(photoPin) > lightLimit) {

      //reset boolean for ending Morse retrieval loop and delay by dot length + 5
      messEnd = false;
      delay(dot + 5);
      
      //loop for getting Morse characters, starts when dot would end and ends when time off is longer than space pause
      while(messEnd == false) {
    
        //delay for dot time and add dot if laser is off by then, otherwise go to dash/undscr
        if(analogRead(photoPin) < lightLimit) {
          theirMorse += ".";
        }
        //delay for additional dot, add dash if off by then, otherwise add undscr and delay for another dot
        else {
          delay(dash - dot);
          if(analogRead(photoPin) < lightLimit) {
            theirMorse += "-";
          }
          else {
            theirMorse += "_";
            delay(undscr - dash);
          }
        }
        //delay by element space for next element
        delay(elemSpace);

        //if laser is not back on after element space, delay and add dash space
        if(analogRead(photoPin) < lightLimit) {
          delay(charSpace + elemSpace);
          theirMorse += " ";
          
          //delay by dot if laser is back on, otherwise end loop
          if(analogRead(photoPin) < lightLimit) {
            delay(dot);
          }
          else {
            messEnd = true;
          }
        }
        //if laser is back on after element space, delay and restart loop
        else {
          delay(dot);
        }
      }
       
      //count spaces in theirMorse to make size of spaceIndexArray
      for(int i=0; i <= 95; i++) {
        if(theirMorse[i] == ' ') {
          spaces++;
        }
      }
      int spaceIndexArray[spaces];
      
      //find positions of spaces in theirMorse and add to spaceIndexArray
      for(int i=0; i <= spaces; i++) {
        if(i == 0) {
          spaceIndexArray[i] = theirMorse.indexOf(' ');
        }
        else {
          spaceIndexArray[i] = theirMorse.indexOf(' ', spaceIndexArray[i - 1] + 1);
        }
      }

      //extract Morse chars with substrings starting after previous space and ending on current space
      for(int i=0; i <= spaces; i++) {
        if(i == 0) {
          theirMorseChar = theirMorse.substring(0, spaceIndexArray[i]);
        }
        else {
          theirMorseChar = theirMorse.substring(spaceIndexArray[i - 1] + 1, spaceIndexArray[i]);
        }

        //find theirMorseChar in asciiArray and add corresponding char to theirText
        for(int j=0; j <= 95; j++) {
          if(theirMorseChar == asciiArray[j]) {
            theirText += char (j + 32);
          }
        }
      }

      //trim theirText and only register message if it is not blank
      theirText.trim();
      if(theirText.length() > 0) {
        
        //if this is the first received message, print text normally
        if(theirTextNum == 0) {
          Serial.println(theirText);
          Serial.println();

          //extract username with substring ending after first colon
          theirName = theirText.substring(0, theirText.indexOf(": ") + 2);
        }

        //after first message, print name and new text
        else {
          Serial.print(theirName);
          Serial.println(theirText);
          Serial.println();
        }

        //add 1 to received message total
        theirTextNum++;
      }
      
      //reset theirMorse, spaces and theirText
      theirMorse = "";
      spaces = 0;
      theirText = "";
    }
  }
}

Credits

donbuckley

donbuckley

0 projects • 3 followers

Comments