Introduction: Arduino Controlled Morse Code Key and Transmitter

About: I am an American teaching English at Shangluo University, Shaanxi. I like making machines that do interesting but fairly useless things - I call them Quixotic Machines.

This is kind of a mashup of different projects: an arduino to control a servo that controls a homemade Morse code key that controls a simple 4 to 7 component cw transmitter. I will just show some pictures of the various parts and a few comments about each. Please note that operating a cw transmitter generally requires a ham radio license unless you terminate the transmitter with a dummy load resistor to keep from propagating a signal outside of your house. A license is a pretty easy prospect these days since proficiency with Morse code is no longer required.

Why do this project?

1. It is entertaining to watch the arduino control the key with a servo.

2. It is a good practice oscillator for listening to Morse code.

3. It can operate your key and transmitter while you go outside the house and check reception.

Have fun - de ke8bsh

PS: Try out my online Bible Verse Morse Code Generator here: Bible Morse Code Generator

Step 1: Homemade Key and Servo

Please see my Instructable about how to make a Morse code key here: https://www.instructables.com/id/Morse-Code-Keyer-...

The key is just a steak knife clamped to a piece of wood with a clip binder. In a second block of wood a screw serves as the contact point against the steak knife. Pretty simple and effective sideswipe key.

I just mounted a servo next to the steak knife and the servo arm pushes on the knife.

Step 2: CW Transmitter

This is probably the simplest cw transmitter you can build and it only needs a few components. I have had it working with just the resistor, the choke which is made with 150 winds of magnetic wire over a 150 ohm resistor, a crystal and a 2N2222 transistor. Here is a link to a schematic and build instructions for the transmitter.

Ten Minute Transmitter

Step 3: Arduino and Code

The arduino controls the servo and you don't even need a separate power supply for the servo as the arduino can handle one micro servo. The servo signal wire goes to digital pin 5, the power goes to 5 volt and ground to ground.

I originally copied the code from another instructable but then modified it quite a bit. Note the code needs more entries for additional punctuation if you use it.

#include servo.h
//**************************************************/

/ Type the String to Convert to Morse Code Here /

/**************************************************//

char stringToMorseCode[] = "cq cq de xxxx";

/* from Morse Code Project

Set the speed of your morse code

Adjust the 'dotlen' length to speed up or slow down your morse code

(all of the other lengths are based on the dotlen)

Here are the ratios code elements:

Dash length = Dot length x 3

Pause between elements = Dot length

(pause between dots and dashes within the character)

Pause between characters = Dot length x 3

Pause between words = Dot length x 7

http://www.nu-ware.com/NuCode%20Help/index.html?m...

*/

int dotLen = 150; // length of the morse code 'dot'

int dashLen = dotLen * 3; // length of the morse code 'dash'

int elemPause = dotLen; // length of the pause between elements of a character

int Spaces = dotLen * 3; // length of the spaces between characters

int wordPause = dotLen * 7; // length of the pause between words

Servo myservo1,myservo2,myservo3; // create servo object to control a servo

int potpin = 0; // analog pin used to connect the potentiometer

int val; // variable to read the value from the analog pin

void setup() {

Serial.begin(9600);

myservo1.attach(5); // attaches the servo on pin 5 to the servo object

myservo1.write(90);

}

void dit()

{

myservo1.write(125);

delay(dotLen); // hold in this position

charPause(elemPause);

}

void dah()

{

myservo1.write(125);

delay(dashLen); // hold in this position

charPause(elemPause);

}

// move servo to neutral postion

void charPause(int delayTime)

{

myservo1.write(110); // move servo back to neutral position

delay(delayTime); // hold in this position

}

void tx(char morseCode[]) {

for (int i = 0; i < 7; i++)

{

// Get the character in the current position

char tmpChar = morseCode[i];

Serial.print("tmpChar= ");Serial.print(sizeof(morseCode));Serial.println(tmpChar);

switch (tmpChar) {

case '.': dit(); break;

case '-': dah(); break;

case '/': return;

case ' ': return;

} // end switch

} // end for

delay(Spaces); // pause between characters

} // end function

// *** Characters to Morse Code Conversion *** //

void GetChar(char tmpChar)

{

// Take the passed character and use a switch case to find the morse code for that characters

// NOTE: have to terminate parameter with space (or just slash if you want - I uses spaces for readabilty)-

// for function tx to work. Something about cannot read length of string in passed argument to functions. Stupid.

switch (tmpChar) {

case 'a': tx(".- "); break;

case 'b': tx("-... "); break;

case 'c': tx("-.-. "); break;

case 'd': tx("-.. "); break;

case 'e': tx(". "); break;

case 'f': tx("..-. "); break;

case 'g': tx("--. "); break;

case 'h': tx(".... "); break;

case 'i': tx(".. "); break;

case 'j': tx(".--- "); break;

case 'k': tx("-.- "); break;

case 'l': tx(".-.. "); break;

case 'm': tx("-- "); break;

case 'n': tx("-. "); break;

case 'o': tx("--- "); break;

case 'p': tx(".--. "); break;

case 'q': tx("--.- "); break;

case 'r': tx(".-. "); break;

case 's': tx("... "); break;

case 't': tx("- "); break;

case 'u': tx("..- "); break;

case 'v': tx("...- "); break;

case 'w': tx(".-- "); break;

case 'x': tx("-..- "); break;

case 'y': tx("-.-- "); break;

case 'z': tx("--.. "); break;

case '.': tx(".-.-.- "); break;

case '1': tx(".---- "); break;

case '2': tx("..--- "); break;

case '3': tx("...-- "); break;

case '4': tx("....- "); break;

case '5': tx("..... "); break;

case '6': tx("_.... "); break;

case '7': tx("--... "); break;

case '8': tx("---.. "); break;

case '9': tx("----. "); break;

case '0': tx("----- "); break;

default:

// If a matching character was not found it will default to space between words

charPause(wordPause);

}

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////

/ Create a loop of the letters/words you want to output in morse code (defined in string at top of code)

void loop()

{

// Loop through the string and get each character one at a time until the end is reached

for (int i = 0; i < sizeof(stringToMorseCode) - 1; i++)

{

// Get the character in the current position

char tmpChar = stringToMorseCode[i];

// Set the case to lower case

tmpChar = toLowerCase(tmpChar);

// Call the subroutine to get the morse code equivalent for this character

GetChar(tmpChar);

delay(Spaces); // pause between characters

}

// At the end of the string long pause before looping and starting again

delay(2000);

}

Step 4: Receiver

You must have a short wave radio capable of receiving Morse code CW and about the cheapest one available is the Tecsun Pl600. I have had the PL600 and the PL660 and they are both great radios. If you have a shortwave radio without the SSB capability you will not be able to hear the side-tone.

Tune the radio near the crystal's frequency, in my case it was 7.159 Mhz. You can buy crystals on ebay.