Preloader image
   

Blog

Arduino Morse Code generator

First of all, you might want to know my motivation for this project, so here goes. MIT, Manipal – my engineering college, had offered to take classes for people wanting to own Amateur Radio licenses. This seems like a great opportunity to be one amongst about half a million around the world with special radio privileges. These people are actually hobbyists that get to legally play around with basic radio communication and they follow a certain convention – one of them being, you guessed it, Morse Code communication. And so, people who wish to apply for the general license need to know Morse Code; it is not necessary though – a restricted license could be obtained without this skill.

 

Morse Code, by itself, is not all that difficult to learn. What is difficult, however, is that after five minutes of practising, people get exasperated and tend to stop. It is not anyone’s fault actually; people do get tired when all they hear pulsations of sounds of a singular frequency. So, I decided to get a Morse code tutor that would reward me every time I recognised a letter correctly. The only way I could do it, without paying anyone, is by setting up one of my micro-controller boards such that it gives me a randomly chosen code anytime and I type in the letter. I decided to go the other way instead, and this is how I came up with the idea of the Morse code generator.

 

Let us familiarise ourselves with the concept of Morse Code, shall we?

 

As you can see above each letter is assigned a sequence of dots and dashes. These correspond to the length of the sound to be produced. The rules given below are followed, some official and some recommended by me:

1. Basic time unit: This is the duration of the shortest pulse in a Morse code transmission, i.e. duration of the sound of the ‘dot’. This is what decides the speed and universality of your code. How universality? Well, we do have slow readers in this world, so, even though you’re following a convention you’re making it difficult for others to follow if you’re too fast with your Morse coding.

2. Duration of a ‘dash’: This has been set to be equal to the duraton of three dots.

3. Duration of intraletter spacings: This is the time of silence(or relaxation time) between two consecutive pulses within a letter; it has to equal to the duration of a ‘dot’. (If you see the picture above, the spaces between dots and dashes are as much as a dot.)

4. Spacings between letters in a word: This should be equal to duration of three dots, kind of like a ‘dash of silence’.

5. Spacings between words: This is a bit ambiguous. Generally it is defined as 7 dots, but people, who have reached a peak in their transmission speeds, use 6 dots(or 2 dashes).

6. Nomenclature of the pulses based on sounds: The dots and dashes in Morse code have been named onomatopoeically to make it easier to learn by letting you speak the sounds out.

  • A ‘dot’ has to sound like “dit”.
  • A ‘dash’ has to sound like “dah”.
  • A ‘dot’, that is not the last dot in the sequence alloted to a letter, has to sound like “di”.

e.g. The letter ‘S’ in Morse code should sound like di-di-dit and ‘Q’ sounds like dah-dah-di-dah.

When you practice sounding the dots and dashes follow a fixed convention. As below,

_._ _          _ _ _          .._

dah-di-dah-dah     dah-dah-dah     di-di-dah

Now, let us discuss the layout of the circuit.

Things I’ve used in the making of the circuit:

  • An Arduino board(any Arduino board will do; I chose Uno, because it was ‘the one’ for me, literally) and the Arduino software.
  • A speaker(or a piezo).
  • Connecting wires.
  • A USB cable – male A to male B(for programming the Arduino and it’s serial communication with the PC).
  • Lots of patience.

Back to the project now. We start programming here.

 

Tip: Please note that this is just a guide to programming and we have not included downloadable codes for your own benefit.

This is how the Arduino IDE looks…

 

First, we need to define the duration of a dot.

You can assign it some arbitrary value, thus making changes by trial and error, or make it read an environment variable to decide the duration in realtime. To assign it a fixed value the syntax is…

#define dotPeriod 100

which sets the duration of a dot to 100 milliseconds.

However, if you’re feeling adventurous, you could attach a potentiometer to your project to make it decide read the duration in realtime from the analog signal fed from the potentiometer, say, connected at analog pin 2…

#define dotPeriod (analogRead(2))

Note that #define statements don’t end in a semi-colon.

Now, let us define dash length, relaxation time, letter-space time and word-space time. A good way to do this is individually define them by multiplying the right values to the value of dotPeriod defined. My way, the elegant way, is to define them as multiples of dotPeriod itself…
#define dashPeriod (dotPeriod*3)
#define relaxTime (dotPeriod)
#define letterSpace (dotPeriod*2)
#define wordSpace (dotPeriod*4)

It seems the definitions are way off, aren’t they? But, you’ll know how it actually works soon…

So let us set the frequency and the tone pin…
#define buzz 1000
#define tonePin 3

Now, if you’re me you’ll swap the buzz definition with the following…

#define buzz (analogRead(1)+50)

I added a potentiometer to analog pin 1 to dynamically set the tone frequency. Adding 200 to the analog input, sets a lower limit of 50Hz instead of 0Hz, because anything under than 20 Hz can cause damage to your controller; this way it can take an upper limit of 1073Hz…

Here is something I like to do a lot – making stuff modular. Even though the code gets a bit longer this way, it is a good thing to make a program you’ll understand like a decade from now.

So we get to defining what we call dits and dahs…
void dit()
{
tone(tonePin, buzz);
delay(dotPeriod);
noTone(tonePin);
delay(relaxtime);
}

Define dahs the same way; just change the delay to dashPeriod. Now, this is absolutely unnecessary, but you can define a function called di to make it more appealing.
void di()
{
di();
}

Now, let us define a function that makes it play the right letter in Morse code…
void playLetter(char x)
{
switch (x):
case ‘E’:
dit(); return;
case ‘T’:
dah(); return;
case ‘A’:
di();dah(); return;
case ‘O’:
dah();dah();dah(); return;
//Insert more alphabets here
case ‘ ‘:
delay(wordSpace);
/* We’ve inserted the wordSpace delay to make sure it relaxes when the letter is a space */
}

As seen above, I’ve not gone alphabetically to reduce compute load. The letter E is the most frequent letter, so we first check for E, and then T and then A and so on. You could look up Morse code for various special characters and add them to the function as well…

Now let us define the mandatory setup function.

void setup()
{
Serial.begin(9600);
/* Using the serial command I program the Arduino to communicate at a baud rate of 9600 bits per second. */
pinMode(tonePin, OUTPUT);
// This command sets the pin to act as output
}

Let us now define some global scope variables.
int Index=0, endofstring, i;
//This creates dummy variables to index letters
char Input[255];
//This is required to store the input data temporarily

Now let us define loop function. This one is also mandatory for an Arduino sketch to run…
void loop()
{
while(!Serial.available());
//This command makes it wait until the Serial data is sent
while(Serial.available())
{
Input[Index]=Serial.read();
//Stores the byte of data from the serial buffer
Serial.print(Input[Index]);
//Prints out the same data
if(Input[Index]>=97&&Input[Index]<=122)
{
Input[Index]=char(int(Input[Index])-32);
//Changes lowercase letters to uppercase
}
//This condition is used to uppercase all letters
}
//The loop runs until Serial data is completely transmitted
Serial.println();
//Creates a new line
endofstring=Index;
//Stores the address of the last byte of data
for(Index=0;Index<=endofstring;Index++)
{
playLetter(Input[Index]);
//Executes the playLetter function defined earlier
delay(letterSpace);
//Waits for 3 times unit duration between letters in words
}
Index=0;
//Sets index back to zero before the loop restarts
}

 

Now, lets understand what the code does. Steps as follows:

  1. It initialises the serial rate and sets tone pin as output.
  2. Waits for serial data.
  3. When the serial data becomes available, it grabs the data and stores them in an array; it also prints out the data as it enters and changes letters to uppercase.
  4. It plays the data, one letter at a time. The intraletter spacings are embedded in the dit and dah function itself. Spacing between letters are called after playing of the specific letter(space of 2 for letter and 1 for intraletter, giving 3 dot spaces. Word space is also defined in the letter playing function(4 for word space adds to 3 for the letterspaces, to give 7 spaces as intended).
  5. After all this is done, it goes back to step 3.

I cannot share the source code with you all, because it defeats the purpose of innovation. The code samples above are not directly from my code, so, you’re on your own if you wish to use this idea for your projects. I’m not the first one to make such a thing and there already have been people who made better ones; I still like mine better because I made it on my own…

 

Some things to try:

  1. The tone labeled Special in Nokia phones is actually Morse code for “SMS SMS“.
  2. The tone labeled Ascending spelles out “Connecting people“.
  3. The tone called Standard is just “M M” which probably is an initial for ‘message’.
  4. A very standard signal for help is SOS that sounds di-di-dit dah-dah-dah di-di-dit.
  5. Try using an audio jack instead of a speaker, analyse the audio and interct the message, for example the piece below shows a message I recorded in Audacity.

With the help of additional software, the waveforms can be studied and intercted.

This project can be extended to do a number of things like creating an automatic interpreter for Morse code.

The fun thing about taking up projects like this is to, at the very least, test your potential. Copy pasting gets you a lot initially but it is not respected by people except corporates(Hmmm!).

Of course, the occasional looking up information is allowed, since most of us, including me, are hobbyists; but believe me, engineering is fun only when you do it yourself.

You could visit my Facebook page RevRYL and if you’re my friend on Facebook, it’ll appear in my status. Follow me on @DenverDias. I promise there’ll be more interesting stuff coming soon. For more details and an earlier look at my recent work, do check outmy personal blog.

I’ll also be taking suggestions, for further project developments. Tutorials could be seen here on request, or you could ask for my personal advise on projects. Either way, I’ll be there…

Share this post on the following platforms easily:

1 Comment

  • eebest8

    Im thankful for the article.Thanks Again. Cool.

    Reply

Post A Comment

error: Context Menu disabled!