Arduino morse transmitter and decoder

Hi!
I have just started using Arduinos, and I have a school project where I’m going to make a morse transmitter and a decoder, with two Arduinos connected to each other. The code may not be optimized, and maybe slow, but that’s not the point.

OK, so here is my problem:
I’ve made a morsecode transmitter connected to a PS/2 keyboard (and an Arduino Uno), and the transmitter works well. It transmit morse with 0v and 5v on pin 9 (if that’s relevant). The other Arduino (Duemillanove w/ atmega328p) will recieve this code, decode it and print it out on the serial monitor or simular. Since I’m a new to C++/Processing, I don’t know how to convert the input signal to letters.
Can anyone help?

Greetings
Hansibull

Schematic:

The project files are attached :slight_smile:

PS2Keyboard.h (7.15 KB)

how to convert the input signal to letters

You can use a two dimensional array as a look up table.

Each letter has the Morse value you receive and the ASCII character in it.
You search through the array looking for a match with your Morse value, when you find it the other element in the same array contains the ASCII value to print out.

I assume you must be using a lookup table to convert letters into dots and dashes for the transmitter. Can you not simply do the reverse for the decoder?

Decoding is a much more difficult task then encoding morse code. When sending you choose what CW output speed you will send at, but when receiving you can't assume that and the decoder must be able to analyze the incoming dots and dashes to figure out what speed the code is being sent at before attempting to decode it.

Lefty

Many years ago there was a Morse decode program written for the TRS-80 that assigned numeric values to the dots and dashes. If I recall anywhere near correctly - the first dot was 2 and the first dash was a 4, the value was shifted and the next dot or dash was decoded and a dot was a 1 and a dash was a 2 and that was added to the previous value, this proceded until the long space was recieved that indicated the end of the character.

You might do some searches for Morse Code Decode.

My system, pre TRS80 days was to start off with the value of 1.
Then with each incoming character I shifted it one place to the right and made the least significant bit 0 for a dot and 1 for a dash. That gave a unique bit pattern for all the letters and numbers and they all fitted in one byte.

I've red a little about arrays on Arduino, but how would the code look like?

the transmitted morse code functions look like this:

void lang() //long
{
   digitalWrite (9, HIGH);
   delay (100);
   digitalWrite (9, LOW);
   delay (33);
}


void kort() //Short
{
   digitalWrite (9, HIGH);
   delay (25);
   digitalWrite (9, LOW);
   delay (33);
}

void pause()
{
  delay(100);
}

                void a() //a
                {
                kort();
                lang();
                pause(); 
               }
                
                void b() //b
                {
                lang();
                kort();
                kort(); 
                kort();
                pause();
                }
                
                 void c() //c
                {
                lang();
                kort();
                lang(); 
                kort();
                pause();
                }
                
                
                 void d() //d
                {
                lang();
                kort();
                kort();
                pause(); 
                }
                
                 void e() //e
                {
                kort();
                pause();
                }
                
                 void f() //f
                {
                kort();
                kort();
                lang();
                kort();
                pause();
                }

[code]

[/code]

but how would the code look like?

This is a school assignment. You have to do some work. We can help but not do it for you.

The code would look like the code you posted, consisting of statements.
A two dimensional variable would look like
table[num][0] = // the value you are going to find
table[num][1] = // the value of the ASCII character

the transmitted morse code functions look like this:

Yes but what does your receive function look like?

ok but I needed Morse Code transmitter for my flight simulator it takes input from a database and it chucks it out… easy
so here it is::: 8)

The following function gets the next callsign segment from CallSign and sets it up as a string of Morse Code timer durations in Morse:

// t = ptr to Tx Data structure of stn currently being keyed
SetUpCallSign(struct TxData t){
/
Array letters of the Morse Code alphabet where
the code for each letter is expressed as timer
durations: dot=1, dash = 3 */

char *MorseCode = {
“\3\1”, “\3\1\1\3”, “\3\1\3\1”, “\3\1\1”,
“\1”, “\1\1\3\1”, “\3\3\1”, “\1\1\1\1”,
“\1\1”, “\1\3\3\3”, “\3\1\3”, “\1\3\1\1”,
“\3\3”, “\3\1”, “\3\3\3”, “\1\3\3\1”, “\3\3\1\3”,
“\1\3\1”, “\1\1\1”, “\3”, “\1\1\3”, “\1\1\1\3”,
“\1\3\3”, “\3\1\1\3”, “\3\1\3\3”, “\3\3\1\1”};
char MC, //Morse Code element (dot/dash/gap)
*pMC, //ptr to Morse element in MorseCode
*pC = t->pCallSign, //ptr to start of next callsign segment
*pM = t->pMorse; //ptr to start of stn’s Morse string

if(*pC == ‘\0’) //if we’ve reached end of callsign data
pC = t->CallSign; //reset ptr to start of callsign data

t->Pitch = (int)*pC++; //audio frequency of keying tone
t->Repeat = (int)*pC++; //Nº of times it is to be repeated

if((int delay = (int)*pC++) < 0) //if the delay is negative{
t->Key = TRUE; //set morse key to the on state
delay = -delay; //reverse its sign (make it positive)}
else //if delay is zero or positive
t->Key = FALSE; //set morse key to the off state

/While the next call sign character is not a semicolon
get pointer to next character’s Morse sequence string
/

while((char Letter = *pC) != ‘;’) {
pMC = MorseCode + Letter - 65;

//For each Morse element (dot or dash) of the character

while((MC = *pMC++) > ‘\0’) {
*pM++ = MC; //store duration of this Morse element
*pM++ = ‘\1’; //store duration of inter-element pause
}
*–pM = ‘\3’; //overwrite with an inter-letter pause
pC++; //advance to next letter to be translated
}
*pM++ = delay; //overwrite with delay at end of callsign
*pM = ‘\0’; //terminating null for Morse Buffer
t->pCallSign = ++pC; //start of next segment of callsign
}

The timing of your morse code transmission isn't very good. The unit of time for morse code is based on the length of the "dit". From that, a dah is 3*dit and the silence between them is also one dit long. Between letters there's another space that is 3 dits long and the word space is 7 dits long.
So, your code should be more like this:

#define DIT_LENGTH 100
void lang() //long
{
   digitalWrite (9, HIGH);
   delay (3*DIT_LENGTH);
   digitalWrite (9, LOW);
   delay (DIT_LENGTH);
}


void kort() //Short
{
   digitalWrite (9, HIGH);
   delay (DIT_LENGTH);
   digitalWrite (9, LOW);
   delay (DIT_LENGTH);
}

FYI the way to convert a morse code speed in words per minute (WPM) into the length of a dit in milliseconds is simply:
dit length (ms) = 1200/WPM
So the dit length of 100ms is 12 WPM.

I wouldn't use a separate function to send each letter, but it's your project and you have to do something yourself.

Decoding is whole different problem, but if you get the transmission timing right and set up the decoder properly you can increase or decrease the transmission speed and still have the decoder figure it out. The way that you have the sender and receiver hooked together means you don't have to worry too much about noise on the incoming signal.
I wrote a decoder (not for Arduino though) that used, in effect, a linked list of character values and it works really well but I think the method Grumpy_Mike has described is easier to understand for someone who's just starting to program.

Pete

Were you even able to get the Rx/Tx project to work?