Mirko Pavleski
Published © GPL3+

DIY Arduino Morse code Decoder and Trainer

This device is especially useful for HAM radio beginners, and also SW listeners who can monitor CW communications without knowing Morse cod

BeginnerFull instructions provided2 hours1,648
DIY Arduino Morse code Decoder and Trainer

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
LCD 128x64 with ST7565 driver
×1
1N4148 – General Purpose Fast Switching
1N4148 – General Purpose Fast Switching
×1
Resistor 10k ohm
Resistor 10k ohm
×1
Pushbutton Switch, Momentary
Pushbutton Switch, Momentary
×1
Capacitor 470 µF
Capacitor 470 µF
×1
capacitor 470 nF
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Schematics

schematic

...

Code

Code

C/C++
...
/* 
 *  Morse code receiver
 */

#include <U8g2lib.h>
#include <TimerOne.h>

U8G2_ST7565_ERC12864_1_4W_SW_SPI u8g2 ( U8G2_R0, /* scl=*/  13 , /* si=*/  11 , /* cs=*/  10 , /* rs=*/  9 , /* rse=*/  8 ) ;

byte inPin1 = 0;                  //analog input to telegraph key or radio output
byte P1, P2;                      //button states
int readPin1;                     //telegraph key or radio output variableradia
int k, i;                         //iloop index
int kropka;                       //dot length
int z, s;                         //character pulses
int p, r;                         //break pulses
int wpm;                          //word per minute
String znak_M;
String litera_M;                  
char S_str[6];
char P_str[6];
char wpm_str[2];
char* znak;
char* wiersz[12];                                 //char workline*
char* wiersz1[12];                                //top line char*


const byte index_key = 48;                        //number of characters in the array 48
const char* Z_char[index_key] = {
"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",
"0","1","2","3","4","5","6","7","8","9",
"!","(",")","+",",","-",".","/","=","?","_"};

const String Morse[index_key] = {                 //Morse code
".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--",
"-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..",
"-----",".----","..---","...--","....-",".....","-....","--...","---..","----.", 
"-.-.--","-.--.","-.--.-",".-.-.","--..--","-....-",".-.-.-","-..-.","-...-","..--..","..--.-"};
/*
' (single apostrophe) • — — — — •
" (quote) • — • • — •
: (colon) — — — • • •
; (semicolon) — • — • — •
@ (monkey or at)  • — — • — •
*/

void setup() {
  
  Serial.begin(9600);
  u8g2.begin();
  u8g2.setContrast(210);
  Timer1.initialize(1000);
  Timer1.attachInterrupt(Zliczaj);
}

void loop() {
  //Serial.println(s);
  //delay(100); 
  Display(); 
}

void Display() {
  //sprintf(S_str,"%d", s);
  //sprintf(P_str,"%d", r);
  u8g2.setFontMode(1);
  u8g2.setFont(u8g2_font_10x20_tr);
  u8g2.firstPage();
  do {
     u8g2.drawStr(0, 15, "Morse"); 
     u8g2.drawStr(75, 15, wpm_str); 
     u8g2.drawStr(98, 15, "w/m");
     //u8g2.drawStr(75, 30, S_str);
     //u8g2.drawStr(105, 30, P_str);
     for (k = 0; k < 12; k++){  
       u8g2.drawStr(k*10, 40, wiersz1[k] );   //top line
       u8g2.drawStr(k*10, 60, wiersz[k] );    //workline
     }
  } while ( u8g2.nextPage() );
  delay(10);
}
  
void Zliczaj(){
  readPin1 = analogRead(inPin1);
  if (readPin1 > 10 ) {             //key is pressed
    z++;
    if (z == 1){
      r = p;
      //Display();                    //Displays the length of the last pause
      //delay(5);
      p = 0;
    }
  }
  if (readPin1 <= 10) {             //key released
    p++;
    if (p == 1) {
      s = z;
      if ( kropka == 0){
         kropka = s ;
         //wpm = 1200/s;
         //sprintf(wpm_str,"%d", wpm);
      }
      if ( z > 5 && z < 1.5 * kropka){ znak_M = "."; kropka = z ;}
      if ( z > 2 * kropka ){ znak_M = "-";}
      if ( r < 2 * kropka){ litera_M += znak_M;}
      if ( litera_M.length() == 0 ) {litera_M = znak_M;}
      z = 0;
    }
    if (p == 2 * kropka) {
      wpm = 1200/kropka;
      if (wpm > 90) {wpm = 0 ; z = 0;}
      sprintf(wpm_str,"%d", wpm);
      if ( litera_M.length() > 0 ) {
        ZnajdzZnak();
        i++;
        wiersz[i-1] = znak;
        if (i > 11) {
          for (int k = 0; k < 12; k++) {
            wiersz1[k] = " ";                        //delete the top line
            wiersz1[k] = wiersz[k];                  //rewriting characters from the working line to the top line
            wiersz[k] = " ";                         //delete work line    
          }
          i = 0;
        } 
      }   
      Display();                                   //displays the read characters
   }
    if (p == 100 * kropka && i > 0) {
       for (int k = 0; k < 12; k++) {
          wiersz1[k] = " ";                        //rewriting characters from the working line to the top line
          wiersz1[k] = wiersz[k];                  //rewriting characters from the working line to the top line
          wiersz[k] = " ";                         //delete work line    
        }
        i = 0;
        Display();                                //Displays the characters read
    }
  }
}

void ZnajdzZnak(){
  znak = "";
  for (k = 0; k <= index_key; k++){
     if (Morse[k] == litera_M) {
        znak = Z_char[k];            //converting the key code to a letter
        break;
     }
  }
  k = 0;
  litera_M = "";
}

Credits

Mirko Pavleski

Mirko Pavleski

150 projects • 1283 followers

Comments