Morse Code Decoder and Encoder

by danielcaliskan9 in Circuits > Arduino

300 Views, 0 Favorites, 0 Comments

Morse Code Decoder and Encoder

IMG_0552.jpg
IMG_0550.jpg
IMG_0551.jpg
IMG_0553.jpg

For the final project of our ECET 380 course at Purdue. Our project centered on creating a Morse Code decoding device, leveraging hardware to transmit signals translated into words displayed on a serial monitor. The project aligns with budget constraints and utilizes a microcontrollers, wires, LEDs, a buzzer, and push buttons. The central focus remains the conversion of Morse Code into practical forms of information. We contemplated whether the original concept or alternative directions with new hardware components should serve as our foundational framework. The core idea involved LEDs, a control device, and a monitor to display converted letters. We aimed to incorporate additional functionality, including sending Morse Code via LEDs and triggering events based on specific words. We successfully met these standards and now have a successful functioning project.


Budget, timeline, testing, and professionalism were critical considerations. Our documentation has adhered to high standards, recording responses and lessons learned through trial and error. Possible enhancements included an encoder for a more user-friendly experience, involving a keypad and LCD for input and output. These enhancements were added. The addition of a small speaker producing Morse Code sounds and synchronized LED flashes enhances the device's accessibility. Instead of a speaker, a buzzer was substituted and met the exact same function. Ambitious functionalities such as integrating a camera for computer vision were considered, contingent on overcoming challenges.


Connecting the encoder to a brighter light for use as a signal light expanded the device's utility. Machine learning algorithms, though beyond the project's scope, offered promise for streamlining encoding, decoding, and interpretation processes. Exploring rudimentary algorithms could’ve enhanced the user experience and device reliability. In conclusion, the project aimed to push technical boundaries, offering a unique and learning experience. The Morse Code decoding device aspires to be genuinely interesting and useful, reflecting our passion for Morse Code exploration and real-world applications.


Supplies

Screenshot 2023-12-11 221544.png
Screenshot 2023-12-11 221729.png

Supplies required for this project

  • Sunfounder UNO $16.99 (Any UNO works as long as the
  • Resistors, Switches, & Buzzer $0.47, $1.00, $0.78
  • Wire Kit & Breadboard $10.00

Total Cost $29.24

Setup Circuit

For the first step, make sure to build the circuit based on the schematic and provided pictures. The wires will be connected as such:

  • 5V and GND are indicated on the board.
  • The buzzer is going to have Digital PWM pin 7 on the positive terminal with a seperate ground on the negative.
  • Pusbuttons 1 and 2 are connected to Digital PWM 11, and 10.
  • LEDs (Green and Red, colors are interchangeable not much importance), are on Digital PWM pin 9 and 8.

Make sure to test each component is working seperately by itself ahead of time. For the LEDs simply check if they light up when 5V with a resistor is connected. For the buzzer send a sample PWM signal and check that a correct sound is outputted. For the pushbuttons, debug with the Arduino IDE, and check for pin status in the pin status window.

Upload Code

The code provided within this project is credited to bluejay701 who had the original idea, with minor changes in the code on our end. Use the attached code in order to debug and test to make sure that there are no errors and that it compiles. Once that is done, move on to uploading the code via the correct port.


int RedLED = 8;
int BlueLED = 9;
int dotPin = 11;
int dashPin = 10;
int buzzPin = 7;

int ditLength;
int dahLength;
int spaceLength;
int toneVal = 1;

String input_string = "";
String morseInput = "";
String message = "";

int letterGap = 500;
int wordGap = 1000;
long lastInputTime = 0;

void setSpeed(char);
void translateLetter(char);
void buzzerSound(int);
char translateCode(String);


void setup() {
 Serial.begin(9600);
 pinMode(dotPin, INPUT_PULLUP);
 pinMode(dashPin, INPUT_PULLUP);
 pinMode(RedLED, OUTPUT);
 pinMode(BlueLED, OUTPUT);
 pinMode(buzzPin, OUTPUT);
}

void loop() {
 while (true) {
  Serial.println("Choose a mode: ");
  char mode_choice = getMenuChoice();
  Serial.println(mode_choice);

  if (mode_choice == 'A') {
   while (true) {
    MorseCodeGeneration();
    if (Serial.available() > 0 && Serial.read() == 'Q') {
     // Press 'Q' to exit the loop
     break;
    }
   }
  } 
  else if (mode_choice == 'B') {
   while (true) {
    MorseCodeTranslation();
    if (Serial.available() > 0 && Serial.read() == 'Q') {
     // Press 'Q' to exit the loop
     break;
    }
   }
  }
 }
}

char getMenuChoice() {
 Serial.println("A. Morse Code Generation B. Morse Code Translation");
 while (Serial.available() == 0) {
 }
 char choice = Serial.read();
 return choice;
}

void MorseCodeGeneration() {
 setSpeed('C');

 Serial.println("Enter a Word or Phrase: ");
 while (Serial.available() == 0) {
 }

 input_string = Serial.readString();
 int str_len = input_string.length() + 1;

 char buf[30];
 input_string.toCharArray(buf, str_len);
 Serial.println(buf);

 for (int x = 0; x < str_len - 1; x++) {
  char letter = tolower(buf[x]);
  Serial.println(letter);
  translateLetter(letter);

  delay(800);
 }
}

void MorseCodeTranslation() {
 ditLength=40;
 dahLength=120;
 int dotButtonState, dashButtonState;
 long currentTime = millis();

 dotButtonState = digitalRead(dotPin);
 dashButtonState = digitalRead(dashPin);

 if (dotButtonState == LOW || dashButtonState == LOW) {
  if (currentTime - lastInputTime > wordGap) {
   message += " ";
  }
  lastInputTime = currentTime;

  if (dotButtonState == LOW) {
   digitalWrite(RedLED, HIGH);
   delay(ditLength);
   digitalWrite(RedLED, LOW);

   buzzerSound(ditLength);
   while (digitalRead(dotPin) == LOW) {
   }
   morseInput += ".";
  }

  if (dashButtonState == LOW) {
   digitalWrite(BlueLED, HIGH);
   delay(dahLength);
   digitalWrite(BlueLED, LOW);

   buzzerSound(dahLength);
   while (digitalRead(dashPin) == LOW) {
   }
   morseInput += "-";
  }
 }

 if (currentTime - lastInputTime > letterGap && morseInput != "") {
  char letter = translateCode(morseInput);
  message += letter;
  morseInput = "";
 }

 if (message != "") {
  Serial.print(message);
  message = "";
 }
}

void setSpeed(char c){
 switch(c){
  case 'A':
   ditLength=60;
   break;
  case 'B':
   ditLength=34;
   break;
  case 'C':
   ditLength=24;
   break;
 }
 dahLength=ditLength*3;
 spaceLength=ditLength*7;
}

void translateLetter(char l){
 switch(l){
    case 'a':
     ditSound(1); //The dit sound last for a set number of milliseconds,
     dahSound(1); //the dah sound lasts for 3 times as long as a dit
     break;    //LED blinks are of same duration and simultaneous as the dit and dah sounds
    case 'b':
     dahSound(1);
     ditSound(3);
     break;
    case 'c':
     dahSound(1);
     ditSound(1);
     dahSound(1);
     ditSound(1);
     break;
    case 'd':
     dahSound(1);
     ditSound(2);
     break;
    case 'e':
     ditSound(1);
     break;
    case 'f':
     ditSound(2);
     dahSound(1);
     ditSound(1);
     break;
    case 'g':
     dahSound(2);
     ditSound(1);
     break;
    case 'h':
     ditSound(4);
     break;
    case 'i':
     ditSound(2);
     break;
    case 'j':
     ditSound(1);
     dahSound(3);
     break;
    case 'k':
     dahSound(1);
     ditSound(1);
     dahSound(1);
     break;
    case 'l':
     ditSound(1);
     dahSound(1);
     ditSound(2);
     break;
    case 'm':
     dahSound(2);
     break;
    case 'n':
     dahSound(1);
     ditSound(1);
     break;
    case 'o':
     dahSound(3);
     break;
    case 'p':
     ditSound(1);
     dahSound(2);
     ditSound(1);
     break;
    case 'q':
     dahSound(2);
     ditSound(1);
     dahSound(1);
     break;
    case 'r':
     ditSound(1);
     dahSound(1);
     ditSound(1);
     break;
    case 's':
     ditSound(3);
     break;
    case 't':
     dahSound(1);
     break;
    case 'u':
     ditSound(2);
     dahSound(1);
     break;
    case 'v':
     ditSound(3);
     dahSound(1);
     break;
    case 'w':
     ditSound(1);
     dahSound(2);
     break;
    case 'x':
     dahSound(1);
     ditSound(2);
     dahSound(1);
     break;
    case 'y':
     dahSound(1);
     ditSound(1);
     dahSound(2);
     break;
    case 'z':
     dahSound(2);
     ditSound(2);
     break;
    case '1':
     ditSound(1);
     dahSound(4);
     break;
    case '2':
     ditSound(2);
     dahSound(3);
     break;
    case '3':
     ditSound(3);
     dahSound(2);
     break;
    case '4':
     ditSound(4);
     dahSound(1);
     break;
    case '5':
     ditSound(5);
     break;
    case '6':
     dahSound(1);
     ditSound(4);
     break;
    case '7':
     dahSound(2);
     ditSound(3);
     break;
    case '8':
     dahSound(3);
     ditSound(2);
     break;
    case '9':
     dahSound(4);
     ditSound(1);
     break;
    case '0':
     dahSound(5);
     break;
    case ' ':
     delay(spaceLength);
     break;
    default:
     Serial.println("Invalid Letter");
     break;
   }
}

void ditSound(int times){
 for(int k=0; k<times; k++){
  digitalWrite(RedLED,HIGH);
  delay(ditLength);
  for(int x=0; x<ditLength; x++){
   digitalWrite(buzzPin,HIGH);
   delay(toneVal);
   digitalWrite(buzzPin,LOW);
   delay(toneVal);
   }
  digitalWrite(RedLED,LOW);
 delay(dahLength);
 }
}

//a dah sound should be 3 times longer than the duration of a dit
void dahSound(int times){
 for(int k=0; k<times; k++){
  digitalWrite(BlueLED,HIGH);
  delay(dahLength);
  for(int x=0; x<dahLength; x++){
   digitalWrite(buzzPin,HIGH);
   delay(toneVal);
   digitalWrite(buzzPin,LOW);
   delay(toneVal);
   }
  digitalWrite(BlueLED,LOW);
 delay(dahLength);
 }
}

char translateCode(String code) {

 const char* morseCode[] = {
  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
  "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
  "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.",
  ".-.-.-"};


 const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.";

 for (int i = 0; i < 37; i++) { 
  if (code == morseCode[i]) {
   return alphabet[i];
  }
 }
}

void buzzerSound(int buzzT){
 for (int x=0; x<buzzT; x++){
  digitalWrite(buzzPin,HIGH);
  delay(toneVal);
  digitalWrite(buzzPin,LOW);
  delay(toneVal);
 }
}

Downloads

Test Device

International_Morse_Code.svg.png

Once the code uploads correctly, go on to testing the device from Mode A which encodes ASCII inputs and plays them in Morse Code. A good test word is simply TEST. The morse code output should be - . ... - . In order to test Mode B, simply type in mode B to the terminal and as a test word send S-O-S through the pushbuttons which should be ... ---- ... .