Morse Code Translator with Arduino

You write in your computer, sends a message thought USB and Arduino translates it into a Morse code.

Just a Arduino board with a buzzer connected at the digital output 12 (one wire in the ground and the other in the 12).

Arduino

I tried to make the code as general as possible so you can easily adapt it for anthers ways of transmitting a Morse code. To do that you just need to rewrite a few functions.

                                                  +-------------------+
                                                  | 3) Interpretation |
                                                  +-------------------+
                                                  |   2) Translation  |
+-------------------+                             +-------------------+
|     Computer      |<========USB (Serial)=======>|     1) Reading    |
+-------------------+                             +-------------------+

  1. Reads a character from Serial. Main function loop().
  2. Translate a ascii char into a Morse code using a reference table. A letter ‘K’ becomes a string word “-.-“. Function say_char().
  3. Interpret the Morse word as light and sound. Mostly at function say_morse_word(). The Interpretation needs 5 functions to say all Morse words, dot(), dash(), shortgap(), mediumgap() and intragap().

For a more details on Morse code I strongly recommend the English Wikipedia article on it.

int led = 13;                   // LED connected to digital pin 13
int buzzer = 12;                // buzzer connected to digital pin 12
int unit = 50;                  // duration of a pulse
 
char * morsecode[] = {
    "-----",  // 0
    ".----",  // 1
    "..---",  // 2
    "...--",  // 3
    "....-",  // 4
    ".....",  // 5
    "-....",  // 6 
    "--...",  // 7
    "---..",  // 8
    "----.",  // 9
    "---...", // :
    "-.-.-.", // ;
    "",       // < (there's no morse for this simbol)
    "-...-",  // =
    "",       // > (there's no morse for this simbol)
    "..--..", // ?
    ".--._.", // @
    ".-",     // A
    "-...",   // B
    "-.-.",   // C
    "-..",    // D
    ".",      // E
    "..-.",   // F
    "--.",    // G
    "....",   // H
    "..",     // I
    ".---",   // J
    "-.-",    // K
    ".-..",   // L
    "--",     // M
    "-.",     // N
    "---",    // O
    ".--.",   // P
    "--.-",   // Q
    ".-.",    // R
    "...",    // S
    "-",      // T
    "..-",    // U
    "...-",   // V
    ".--",    // W
    "-..-",   // X
    "-.--",   // Y
    "--.."    // Z
};
 
void setup() {
  pinMode(led, OUTPUT);
  pinMode(buzzer, OUTPUT);
  Serial.begin(9600);
}
 
void say_morse_word(char * msg){
  int index = 0;
  while(msg[index]!='\0'){
    // say a dash
    if(msg[index]=='-'){
      dash();
    }
    // say a dot
    if(msg[index]=='.'){
      dot();
    }
    // gap beetween simbols
    intragap();
    index++;
  }
}
 
// beep
void beep(int time){
  int i;
  int t = 100; // period of the wav. bigger means lower pitch.
  int beepduration = (int)((float)time/t*1800);
  digitalWrite(led, HIGH);
  for(i=0;i<beepduration;i++){
    digitalWrite(buzzer, HIGH);
    delayMicroseconds(t);
    digitalWrite(buzzer, LOW);
    delayMicroseconds(t);
  }
  delay(time);
}
 
// silence
void silence(int time){
  digitalWrite(led, LOW);
  delay(time);
}
 
// general procedure for .
void dot() {
  beep(unit);
}
 
// general procedure for -
void dash() {
  beep(unit*3);
}
 
// gap between dots and dashes
void intragap() {
  silence(unit);
}
 
// gap between letters
void shortgap() {
  silence(3*unit);
}
 
// gap be  tween words
void mediumgap() {
  silence(7*unit);
}
 
void say_char(char letter){
  if((letter>='0')&&(letter<='Z')&&(letter!='<')&&(letter!='>')){
    Serial.print(morsecode[letter-'0']);
    Serial.print(' ');
    say_morse_word(morsecode[letter-'0']);
    shortgap();
  } else {
    if(letter==' '){
      Serial.print(" \\ ");
      mediumgap();
    }else{
      Serial.print("X");
    }
  }
}
 
void loop(){
  if(Serial.available()){
    say_char((char)Serial.read());
  }
}

Additionally you can put another function to say entire strings, like say_string(“HELLO WORLD”)

void say_string(char * asciimsg){
  int index = 0;
  char charac;  
  charac = asciimsg[index];
  while(charac!='\0'){
    say_char(morsecode[charac-'0']);
    Serial.println(morsecode[charac-'0']);
    charac = asciimsg[++index];
    shortgap();
  }
}

You can use the Arduino IDE itself or any other program that talks with the serial port USB.

arduino interface

15 thoughts on “Morse Code Translator with Arduino

  1. @Greg: I will start to work on such a project in the coming weeks. An Arduino will be connected to an LCD display that displays the translation from morse input. Way to input morse will be non standard. Project is to be used as a communication tool for a person with severe physical disabilities.

  2. I’m just starting on my arduino and want to know how to go about decoding morse and display to an LCD my self thanks!!!

    Nice work

    Chad

  3. Hi There. Really nice project you have there. I was interested in implementing morse code in arduino, however I did i the other way around – user flashes the flashligh or other source of light near the photo diode, and arduino board translates it into letters, works pretty well :)

    Btw. How did you configure your IDE to have serial monitor directly below the code in the same window (it’s pretty annoying to open serial monitor every time from the menu, and the Keyboard shotcuts always puts empy line in the code…).

  4. Hi! I wonder if you ever made the morse code decoder – if so, could you send me the sourcecode for it ?
    I am making a project which I could share with you later on.. :)

  5. Hi all

    I’m working on an art piece at the moment which will decode morse but the difference is that the morse will be sent by human operated morse key so will obviously have to account for slightly variable timings. I have made some code in processing – the idea being that i will use analog in from arduino and send that by serial to processing. I’m happy to post the code if anyone is interested? at the moment it jsut works with a key press.

  6. if anyone needs a “passive” version of this (i.e no delays) so the rest of your code runs without delay … I’m just blinking the LED & printing to Serial, but it can easily be modified for sound, or even LCD display:

    const char * morsecode[] = {
    “—–“, // 0
    “.—-“, // 1
    “..—“, // 2
    “…–“, // 3
    “….-“, // 4
    “…..”, // 5
    “-….”, // 6
    “–…”, // 7
    “—..”, // 8
    “—-.”, // 9
    “—…”, // :
    “-.-.-.”, // ;
    “”, // (there’s no morse for this symbol)
    “..–..”, // ?
    “.–._.”, // @
    “.-“, // A
    “-…”, // B
    “-.-.”, // C
    “-..”, // D
    “.”, // E
    “..-.”, // F
    “–.”, // G
    “….”, // H
    “..”, // I
    “.—“, // J
    “-.-“, // K
    “.-..”, // L
    “–“, // M
    “-.”, // N
    “—“, // O
    “.–.”, // P
    “–.-“, // Q
    “.-.”, // R
    “…”, // S
    “-“, // T
    “..-“, // U
    “…-“, // V
    “.–“, // W
    “-..-“, // X
    “-.–“, // Y
    “–..” // Z
    };

    int count_Morse = 1;
    int word_index = 0;
    int morse_index = 0;
    unsigned long LED_current_time = millis();
    unsigned long LED_time_unit_CONST = 0;

    #define LED_PIN 13

    void setup() {
    Serial.begin(9600);
    pinMode(LED_PIN, OUTPUT);
    Serial.println();
    }

    void loop() {
    LED_blink_morse(200,1023,”Hello World!”);
    }

    void LED_blink_morse(int LED_blink_time_unit, int LED_ON_strength, String MORSE_CODE_string) {
    LED_ON_strength = constrain(LED_ON_strength,100,1023);
    LED_blink_time_unit = constrain(LED_blink_time_unit, 100,1000);

    char charac = toUpperCase(MORSE_CODE_string.charAt(word_index));

    if(charac!=’\0′){
    if((charac>=’0′)&&(charac<='Z')&&(charac!='’)){
    String morse_word = morsecode[charac-‘0′];

    if(morse_word[morse_index]!=’\0′){

    if(morse_word[morse_index]==’-‘ && !digitalRead(LED_PIN) && (millis() – LED_current_time >= LED_time_unit_CONST)){
    Serial.print(“-|”);
    LED_time_unit_CONST = LED_blink_time_unit * 3;
    digitalWrite(LED_PIN, LED_ON_strength); //turn ON LED
    //Serial.print(digitalRead(LED_PIN));
    LED_current_time = millis();
    count_Morse = 1;
    }

    if(morse_word[morse_index]==’.’ && !digitalRead(LED_PIN) && (millis() – LED_current_time >= LED_time_unit_CONST)){
    Serial.print(“.|”);
    LED_time_unit_CONST = LED_blink_time_unit;
    digitalWrite(LED_PIN, LED_ON_strength); //turn ON LED
    //Serial.print(digitalRead(LED_PIN));
    LED_current_time = millis();
    count_Morse = 1;
    }

    if (digitalRead(LED_PIN) && millis() – LED_current_time >= LED_time_unit_CONST) { //===== intergap
    Serial.print(” |”);
    LED_time_unit_CONST = LED_blink_time_unit;
    digitalWrite(LED_PIN, 0);
    //Serial.print(digitalRead(LED_PIN));
    morse_index++;
    LED_current_time = millis();
    count_Morse = 1;
    }

    if (!digitalRead(LED_PIN) && millis() – LED_current_time >= LED_blink_time_unit*count_Morse && count_Morse = LED_blink_time_unit*count_Morse && count_Morse < LED_time_unit_CONST/LED_blink_time_unit) { //===== intergap
    Serial.print("-|");
    count_Morse++;
    }

    } else if(morse_word[morse_index]=='\0'){
    LED_time_unit_CONST = LED_blink_time_unit * 3; //====================================== space between letters
    morse_index = 0;
    word_index++;
    LED_current_time = millis();
    }

    } else if(charac==' '){
    LED_time_unit_CONST = LED_blink_time_unit * 7; //======================================== space between words
    morse_index = 0;
    word_index++;
    LED_current_time = millis();

    } else {
    Serial.println("MORSE: not a character ");
    word_index++;
    }

    } else if(charac=='\0'){
    word_index = 0;
    morse_index = 0;
    LED_time_unit_CONST = LED_blink_time_unit * 7; //======================================== space between words
    LED_current_time = millis();

    } else {
    Serial.println("MORSE: 404:Failed ");
    word_index++;
    }

    }

Leave a Reply

Your email address will not be published. Required fields are marked *