Arduino-Based DSP Morse Decoder & Trainer For Ham Radio CW Operators


After you finish reading this article, please also read the sequel:


This real-time Morse decoder uses the Goertzel algorithm to detect a CW tone of 708 Hz. In order to better isolate the useful signal, the program introduces comparing the magnitudes for three frequency bins – the central one and two adjacent ones on both sides.

The program then analyzes the detected tone patterns in order to recognize and decode Morse characters.

The decoding is flawless if the input signal is itself flawless in every aspect. The speed can exceed 50 standard words per minute (wpm). However, on the always noisy HF bands the decoder is clearly inferior to a trained human ear. Still, at any given time one will find real CW transmissions that can be decoded with some success, although the results may vary from a few clear words in a pile of gibberish – to 100% accurate text. Unusual sending styles also confuse the decoder.

The purpose of this Morse decoder is not to discourage operators from learning Morse code but, on the contrary, to stoke their curiosity and give them a fun learning experience.

The decoder automatically adjusts to the transmission speed. When there is a sharp change, it will take a few characters to determine the new wpm, but that is not an issue. The internal speaker outputs a 708 Hz tone repeating the detection pattern, i.e. Morse characters, if all goes well.

The program provides three levels of simple filtering. High speeds require filter level 0, i.e. no filtering at all. Filter level 1 is mild and should be used for speeds up to 36 or so wpm. Filter level 2 should be good for speeds below 25 wpm (the numbers are only approximate). A wrong choice of filter level will mess up decoding.

The W1AW bulletin comes through perfect.
The filter is on ‘1’ while the speed is over 40 wpm, my mistake. Still not terrible.
The leading procession of E’s and T’s was produced by atmospheric noise.
Straight key again. Not bad.
During these two contest QSOs the speed was 40-42 wpm, but afterwards it wandered off to 52 due to noise. It comes back easily though.
A random real-world example: a modest signal, some QSB. There are around 70 characters on the display, and three decoding errors. Two of them are caused by short sudden drops in the signal level. The third one is a stray ‘E’ added by QRN crackle. But all in all, this was good copy. Here is the audio-recording, just the second CQ call for reference. Arduino program version: 1.0.
The first DIT of the letter ‘Z’ is 12 dB weaker than the first DAH of the same letter, due to QSB.
On the other hand, the letter ‘F’ made it, barely.

The tone detection algorithm is very sensitive to any frequency offset. The detection will work for a range of frequencies, but it will perform best when the tone is exactly right. The green LED flickers when it is close, but that indicator is not nearly good enough. The RIT/RX Clarifier on the radio should be used at all times, tweaking the frequency for that sweet spot and the best result.

The input signal level should also be adjusted for optimum performance. The red LED shows when audio peaks are getting pretty high, close to clipping (but not necessarily there). Currently this LED lights up at around 4 Vp-p. By the way, in this specific implementation (the second schematic below) the analog input A1 is protected against overvoltage.

THE TRAINER: If you plug in a CW/Morse key, the device will switch from the ‘AUDIO’ mode to the ‘KEY’ mode which lets you practice sending Morse characters. The decoder will decode and display what you are sending in real time, provided that the shapes of characters are correct. Still, it is not too harsh on the beginner.

The basic schematic.
The detection works best if the input signal’s amplitude is large enough so that the (almost) full DC range of the ADC can be used.
A more developed/fancy variant, close to what is in the ugly box shown in the photos.
On the rear panel there are two 1/8″ jacks in parallel (phones and audio input), the power switch and the DC connector.

There is still a lot of experimenting and tweaking to be done.

Download the Arduino program: GOERTZEL_ZZ_v1_0.ino

LiquidCrystalFast.h: https://www.pjrc.com/teensy/arduino_libraries/LiquidCrystalFast_1.1.zip

You can also download version 1.1 that has been shown to perform marginally better in certain situations involving weaker signals and QSB. For example, it can salvage the lost letter ‘Z’ from the audio snippet shown above. It is in the tinkering phase and may be updated sporadically.

Please read the follow-up article.

The initial idea for the decoder came from here:
http://www.oz1jhm.dk/content/very-simpel-cw-decoder-easy-build
I studied the original program but ended up writing essentially a new one. The hardware setup is also different. Anyway, big thanks to OZ1JHM/OZ8CW.

2 thoughts on “Arduino-Based DSP Morse Decoder & Trainer For Ham Radio CW Operators

  1. Pingback: Arduino-Based DSP Morse Decoder and Trainer, on a Custom PCB | YU2ZZ ····· Elektronika. Radio. Hobi.

  2. Pingback: Arduino-Based DSP Morse Decoder and Trainer, on a Custom PCB - YU2ZZ ····· Elektronika. Radio. Hobi.

Leave a Reply