Machine Recognition of hand-sent Morse Code

Two easy to build microcontroller projects.

Back to main page

First publication of page, 2016-03-20

Although not an active CW operator, I enjoy listening to the lower end of the HF bands from time to time.

Recently I wanted to demonstrate Morse code, and in particular how to use a Morse Key (who uses those anymore? J). To do this, I rigged up an Arduino Uno with an LCD, hooked it up to the Morse Key and tested a few Arduino sketches for Morse Decode:

It was a disaster – it turns out that most Morse code decoding software relies on the transmission being very accurately timed and with little or no jitter. - Definitely not me when pumping away using a hand Key.

Some Googling around turned up a document with the title:

"MACHINE RECOGNITION OF HAND-SENT MORSE CODE USING THE PDP-12 COMPUTER",

by Joel Arthur Guenther, Air Force Institute of Technology, Wright-Patterson Air Force Base, Ohio, December 1973

available here: https://apps.dtic.mil/sti/pdfs/AD0786492.pdf

Mildly put, I am not adept at reading the PDP-12 instruction set. However this project is very well documented with diagrams, flowcharts and equations – so it was not hard to reproduce the methodology using an Arduino Uno as a platform. The big surprise though, was the realization how very capable the Arduino is in relation to a 1970’s style minicomputer.

PDP-12

The two Morse Decode projects side by side. Disclaimer: The size of picture below is not to scale with the size of the picture above J

Take One, an Arduino Uno sketch

To make a long story short: All the algorithms described in Mr. Guenther's paper were implemented, including a 200 microsecond interrupt function for signal sampling, error correction algorithms and other good stuff – and with some improvements of my own here and there. Works beautifully, the only snag being that it takes the reception of up to 20 characters to accurately sample the timing pattern. But nothing is lost while doing so; everything is buffered until ready to decode.

The Arduino sketch at the bottom of this webpage, while written for an Arduino Uno, should work with just about any Arduino derivative – together with a HD44780 compatible 16x2 or 20x4 LCD. In addition to printing the decoded data to the LCD, the sketch also sends the data to the (USB) serial port.

Two inputs are provided – one digital input, to directly connect a Morse Key or similar – and another analog input, for direct audio hookup to the speaker output of the Radio.

The analog input relies on a lightweight but impressive Audio Tone Processing method by the name of “Goertzel Algorithm”. In fact, the Goertzel code I use is a direct swipe from another Arduino Morse Decode sketch written by Hjalmar Skovholm Hansen OZ1JHM (http://skovholm.com/cwdecoder). Hjalmar, thanks for making your code publicly available.

Connections diagram, Arduino version:

The speed-reset toggle switch is not really necessary. The morse key input and the audio input are equivalent, if one input is not in use – then it doesn’t bother the other one. The speaker output is not necessary, but gives a useful indication when adjusting the receive tone and signal level from the receiver. If you want to use a 20x4 Display, then modify the relevant #defines in CWReceiveArduino.h.

Take two, Fast Fourier Transform and Colour Graphics

The Teensy 3.2 Sketch at the bottom of this webpage, is a further elaboration on the above theme. It uses a standard Adafruit (ST7735) 160x128 pixel TFT LCD and the Teensy Audio Shield.

FFT1024 or FFT256 is used to filter the tone and then some additional noise cancel methods can be used to further clean up the signal before passing it to the decode functions.

The received signal is visualized using a Waterfall-type display. Using the visual queues, one can adjust the volume, signal level threshold and peak tone frequency of the desired signal – using three trimpot resistors.

Connections diagram, Teensy 3.2 and Audio Shield version:

The 3.5mm audio output connector on the Audio Shield, not shown on the schematic, reproduces the filtered CW signal, useful for adjusting optimal reception.

Like the first sketch, this one also prints the decoded Morse Code to both LCD and (USB) serial port.

The time it takes for a Fast Fourier Transform to make new measurements available is directly related to the length of the FFT (number of points). An audio stream sampled at 44.1 kHz (Teensy Audio Shield) by a 1024 FFT, will provide 512 bins of signal strength measurements – each of them 43 Hz wide (these are also used to draw the Waterfall display), 86 times per second, or once every 11.6 milliseconds. This limits the timing rate at which the Morse code transmission can be measured accurately. If the rate of the Morse code transmission is 20 words per minute, then this is roughly equivalent to 5 time ticks per “dit”. It turns out that 20WPM is slightly below the observed highest readable speed without noticeable amount of errors, when using a 1024 FFT.

To be able to decode at higher speeds, a 256 FFT can also be selected – running at four times the speed of the 1024 FFT, the penalty being much worse frequency resolution of desired vs. undesired signals, so much stronger “desired” signals are required.

The 256 FFT should work beyond 40WPM, depending on which post-filters (defined in the CWReceive.h file) are selected.

Enough said.

Compiling the Arduino Sketches

Both sketches contain a number of files. Unpack the zip files, but make sure not to rename the folders - the Arduino GUI won’t like that.

The Arduino sketch needs the standard Arduino GUI, available at http://Arduino.cc. If not installed by default, then the TimerOne library needs to be installed (sketch -> include library -> manage libraries, type “timerone” in search window).

To compile the Teensy sketch, in addition to the Ardino GUI you will also need to install Teensyduino, available here: http://www.pjrc.com/teensy/teensyduino.html

When installing Teensyduino, you will be offered the option of selecting certain Libraries for install. Select all.

When opening the sketches, the second tab in the Arduino GUI is a .h file with a number of user customizable #define’s. Have fun.

Source code for firmware available below: