How to Display a String as Morse Code on an LED Using Arduino

morse_code_led_system

In this post. I’ll explain how to develop an application which executes on an Arduino and displays a user typed string, such as “Hello World”, as Morse code on an LED.

Named after Samuel F.B. Morse, the inventor of the telegraph, Morse code is a character encoding scheme that represents letters as long and short pulses of sound or light.

Requirements

The system that is developed must satisfy the following requirements:

  • It must execute on an Arduino. The Arduino version used was version 1.8.8.
  • It must display a user typed string, such as “Hello World”, as Morse code on an LED (or several LEDs), or an LCD.
    • A dash is three times as long as a dot.
    • The time between each dot or dash in the same letter is equal to the duration of one dot.
    • The time between two letters is the duration of one dash.
    • The time between two words is the same duration as seven dots.
  • It must use a Round Robin design where a loop:
    • Waits for a string
    • Displays the string in Morse code
    • Exits the loop only if a sentinel is entered (e.g. !)

Hardware Design

The following components are used for the Morse code LED system. You will need:

Here is the schematic:

Software Design

Here are the steps for the Morse code LED system:

  • Step 1. Prompt the user to enter a message on the Serial Monitor. The input for the message contains characters (letters and/or numbers).
  • Step 2. Read each character, one at a time.
  • Step 3. Convert each character into the equivalent Morse Code.
  • Step 4. Convert each Morse code sequence into the corresponding sequence of dots and dashes.
  • Step 5. Transmit the dots and dashes to the LED while transmitting the message to the Serial Monitor.
  • Step 6. Exit the loop if user enters the sentinel value of “!”

Implementation

Here is the source code that you will need to load to your Arduino:

/**
 * In this program, we develop an application which executes on an Arduino 
 * Uno and displays a user typed string, such as “Hello World”, as Morse 
 * code on an LED.   
 * 
 * @version 1.0 2019-01-31
 * @author Addison Sears-Collins
 */
 
// Assign a name to the digital pin 12
unsigned int led_pin = 12;

// Declare an array named letters that holds addresses of string literals 
// (i.e. an array of pointers to strings composed of dots and dashes) 
// Done to preserve memory because strings are not equal in size. A 2D array
// would be a waste of space.
char *letters[] = {
  // The letters A-Z in Morse code  
  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",    
  ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.",  
  "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."          
};

char *numbers[] = {
  // The numbers 0-9 in Morse code  
  "-----", ".----", "..---", "...--", "....-", ".....", "-....", 
  "--...", "---..", "----."
};

unsigned int dot_duration = 200;
bool done = false;

/**
 *  Function runs only once, after each powerup or reset of the Arduino
 */
void setup() {
  // Set the LED to output
  pinMode(led_pin, OUTPUT);
  
  // Open the serial port and set the data transmission rate to 9600 bits 
  // per second. 9600 is the default baud rate for Arduino.
  Serial.begin(9600); 
  
  // Show welcome message as human-readable ASCII text
  Serial.println("MORSE CODE LED PROGRAM");
  Serial.println("This program translates your message into Morse code");
  Serial.println("and flashes it on an LED.");
  Serial.println("Author: Addison Sears-Collins");
  Serial.println("");
  Serial.println("Enter your message(s) or ! to exit: ");
}

/**
 *  Main function that drives the system
 */
void loop() {
  char ch;
  
  // This loop waits for a string, displays it in Morse code, and only exits 
  // the loop if the sentinel is entered. 
  while (!done) {
  
    // Check to see if there are letters or numbers available to be read
    if (Serial.available()) {     
  
      // Read one letter or number at a time
      // Serial.read() returns the first (oldest) character in the buffer 
      // and removes that byte of data from the buffer
      ch = Serial.read();    
  
      // Check for uppercase letters
      if (ch >= 'A' &amp;&amp; ch <= 'Z') {
        Serial.println(ch);
        flash_morse_code(letters[ch - 'A']);        
      }
      // Check for lowercase letters
      else  if (ch >= 'a' &amp;&amp; ch <= 'z') {
        Serial.println(ch);
        flash_morse_code(letters[ch - 'a']);
      }
      // Check for numbers
      else if (ch >= '0' &amp;&amp; ch <= '9') {
        Serial.println(ch);
        flash_morse_code(numbers[ch - '0']);
      }
      // Check for space between words
      else if (ch == ' ') {
      
        // Put space between two words in a message...equal to seven dots
        delay(dot_duration * 7);       
      }
      // Check for sentinel value
      else if (ch == '!') {
        done = true;  
        Serial.println("Thank you! Your messages were sent successfully.");
        Serial.println("Goodbye.");
      }
    }     
  }  
  // Do nothing
  while(true) {}
}

/**
  *  Flashes the Morse code for the input letter or number
  *  @param morse_code pointer to the morse code
  */
void flash_morse_code(char *morse_code) {
   
  unsigned int i = 0;
   
  // Read the dots and dashes and flash accordingly
  while (morse_code[i] != NULL) {
    flash_dot_or_dash(morse_code[i]);
    i++;
  }
   
  // Space between two letters is equal to three dots
  delay(dot_duration * 3);    
}

/**
  *  Flashes the dot or dash in the Morse code
  *  @param dot_or_dash character that is a dot or a dash
  */
void flash_dot_or_dash(char dot_or_dash) {
  
  // Make the LED shine
  digitalWrite(led_pin, HIGH);
  
  if (dot_or_dash == '.') { // If it is a dot
    delay(dot_duration);           
  }
  else { // Has to be a dash...equal to three dots
    delay(dot_duration * 3);           
  }
  
  // Turn the LED off
  digitalWrite(led_pin, LOW);

  // Give space between parts of the same letter...equal to one dot
  delay(dot_duration); 
}

Video