Morse Code for Kids.

8.4K4515

Intro: Morse Code for Kids.

Morse code unit for kids. Variable speed and different levels.

My son goes to CUBS and has a special event coming up. This event is all about communicating with other Scouts/Cubs from around the world? Via radio, also over the weekend there will be other activities including Morse code. So this little project is just a little demonstration of Morse code.

This is the current specification:

Variable timing from about 100ms to 1100ms

Red Green Blue led for different effects

12 different 3 letter words

1000mAh lipo power with built in charger.

Sound with on/off switch.

Arduino Nano.

So Firstly I need to give credit to Simon Monk and his book “Programming Arduino” which I bought a while ago when I first started looking at the Arduino boards. His program is the bases of this program.

So what is Morse code???

Well before I started this project I didn’t have a clue apart from knowing SOS. So a quick goggle and there is loads of information out there. Thankfully all of the information I found stated the same rules which are as follows.

A DOT is one time period.

A DASH is three time periods.

Between each DOT OR DASH of a letter is a one period space.

Between each letter is a three period gap

And lastly between each word is a seven period gap.

STEP 1: Marking Out and Drilling.

Sorry if I am pointing out the obvious but the easiest way to mark out and drill plastic boxes is to cover the box with masking tape, this serves two purposes firstly you can easily mark out onto the tape and secondly the tape stops the drill wondering.

Marking out should be done with care and consideration to every item you need to fit in the box, and don't do as I did and forget the battery! You can see in one of the picture how I have bent over the legs of the rotary switch this was to stop the legs fowling with the LED pcb.

I have a small pedestal drill which makes drilling easy, but the best tool by far is the stepped drill bit.

With the selector switch you have a location pin which should have another hole drill for it. I find the best way to mark this out is to put a fresh bit of masking tape near where the hole needs to go and then put the switch into the main hole and push the switch down onto the tape to leave an imprint.

STEP 2: Fitting Out the Box and Wiring Together

So i have used a couple of nice tricks here to try and keep things nice and neat, the first trick is to try and common 5 volt and 0 volt connections. so if you look at the picture which shows the variable resistor and selector switch you will see i have commoned the supplies to both, what this means is that the lid will only have 4 wires coming from it.

Next choose you arduino pin's wisely! the neatest way to wire up the full colour LED was to put the three wires together, however i decided to choose pins 9,10 and 11 which are all PWM pins and will allow for future programs to vary the colours.

Another choice i made was to put the power supplies to the pot the wrong way round, which means with the pot adjusted full Anti clockwise the speed is the slowest (longest time delay 1123 ms, 5 volts) and with the pot turned fully clockwise its the fastest (shortest time delay 100ms, 0 volts)

STEP 3: The Program

So the start of this project was Simon Monk’s program which takes characters from the serial port and flashes out the Morse code, however I wanted to expand on this. It was very obvious to me that the original program which had a time period of 200ms was much too quick, so the first change was to add a variable resistor and make the timing period adjustable. Next I wanted to flash various codes and not use the serial monitor so I added a 12 position switch and assigned each switch position a 3 letter animal. For a nice effect I also added a sounder so not only can you see the code but also hear it (and added a switch to turn it off!) Lastly I added a few extra features to make it easier to use, these extra features are selected by holding down the button when you turn on the power and selecting the option with the rotary switch.

STEP 4: Lipo Battery, Dc-dc Converter and Lipo Charger.

This is the one bit i didn't get right! i didn't really decide on what power supply to use for this project. When you are programming the nano board it is simple the power comes from the USB. but once disconnected from the computer i then had to find another power source. At first i decided a 9V (smoke alarm battery) however this was not going to fit. so at the time i decided to put a hole in the bottom and put the 9 volt battery outside.

I was not happy with this solution so had a look at what else i had. and came across a 1000mAh lipo which just fitted in the case (i had to bend the sounder legs over) However this solution has its own problem and that is a lipo doesn't generate 5 volts. Now i could have got away with only 4.2 volts but as the battery drains the voltage will drop and if i was using the blue LED it would spot flashing. so i decided to use a DC-DC converter. These converts are very small so was easy to fit under one of the side switches. Lastly i then had to add a charger so that i cold charge the lipo without having to remove the battery from the case.The simple solution was to use a USB charger module.

To connect this lot up to the ON/OFF switch i decided to connect the lipo to the center pins then in the "ON" direction the lipo would connect to the DC-DC converter and power the Nano (via the 5 volt pin) and in the OFF position the lipo would be connected to the charger.

Have a look at the drawing and photo which might make it a bit clearer!

STEP 5: Operation and Options

As explained the 12 position selector switch is used to select the animal and the following are currently programmed.

  1. HHH (demonstration of what a DOT sounds like, H is DOT DOT DOT DOT)
  2. OOO (demonstration of what a DASH sounds like, O is DASH DASH DASH)
  3. CAT (Example of different letters have a different number of dots and dashes depending on commonness)
  4. DOG
  5. ANT
  6. FLY
  7. RAT
  8. OWL
  9. PIG
  10. HEN
  11. FOX
  12. EMU

AND the options you can select by pressing the button whilst the unit is turning on are as follows.

  1. Red LED
  2. Blue LED
  3. Green LED
  4. Green/Blue LED's
  5. Red/Green LED's
  6. Red/Blue LED's
  7. Red/Blue/Green LED's
  8. Red DOT and Green Dash.
  9. Change colour every word.
  10. Change colour every letter.

STEP 6: Arduino Program

int dotDelay = 200;
int ledPinRed = 11;//red
int ledPinBlue = 10;//blue
int ledPinGreen = 9;//green
int oldAI = 15;
int pat;
int i = 1;
int j = 0;
bool toggle = false;
int button = 8;
int buzzer = 7;
int flag = 1;
int selectWord;
int animal = 1;
int potValue = 0;
int maxVoltageBits = 1023;
int dividedBits = maxVoltageBits/22;
const int pot = A4;
const int rotaryInput = A5;
char ch;

char* letters[] = {
  ".-","-...","-.-.","-..",".","..-.","--.","....","..",
  ".---","-.-",".-..","--","-.","---",".--.","--.-",".-.",
  "...","-","..-","...-",".--","-..-","-.--","--.."};

char* numbers[] = {
  "-----",".----","..---","...--","....-",
  ".....","-....","--...","---..","----."};

char *animals3 = "hhhooocatdogantflyratowlpighenfoxemu";

void setup()
{
  pinMode(ledPinBlue, OUTPUT);
  pinMode(ledPinRed, OUTPUT);
  pinMode(ledPinGreen, OUTPUT);
  pinMode(pot, INPUT);
  pinMode(rotaryInput, INPUT);
  pinMode(button, INPUT);
  pinMode(buzzer, OUTPUT);
  digitalWrite(ledPinRed, HIGH);
  digitalWrite(ledPinBlue, HIGH);
  digitalWrite(ledPinGreen, HIGH);
  digitalWrite(ledPinRed, LOW);
  delay(500);
  digitalWrite(ledPinRed, HIGH);
  delay(100);
  digitalWrite(ledPinBlue, LOW);
  delay(500);
  digitalWrite(ledPinBlue, HIGH);
  delay(100);
  digitalWrite(ledPinGreen, LOW);
  delay(500);
  digitalWrite(ledPinGreen, HIGH);
  delay(100);
  digitalWrite(buzzer, HIGH);
  delay(100);
  digitalWrite(buzzer, LOW);  
  int buttonValue = digitalRead(button);
  if (buttonValue == 1)
  {
    selectWord = analogRead(rotaryInput);
    selectorSwitch1(selectWord);
  }
  else
  {
    flag = 1;
  }
}

void loop()
{
  wait_for_enter();
  selectWord = analogRead(rotaryInput);
  selectorSwitch(selectWord);
  potValue = analogRead(pot);
  dotDelay = potValue + 100;
  i = (animal *3)-3;
  while (j < 3)
  {
    ch = animals3[i];
    if (ch >= 'a' && ch <= 'z')
    {
      flashSequence(letters[ch - 'a']);
    }
    else if (ch >= '0' && ch <= '9')
    {
      flashSequence(letters[ch - '0']);
    }
    else if (ch == ' ')
    {
      delay(dotDelay * 7);
    }
    i = i + 1;
    j = j + 1;
  }
  delay(dotDelay * 7);
  //toggle = !toggle; //toggle colour every word (not needed) 
  j = 0;
}
void wait_for_enter()
{
  int buttonValue = digitalRead(button);
  while (buttonValue == 0)
  {
    buttonValue = digitalRead(button);
  }
}

void flashSequence(char* sequence)
{
  int k = 0;
  while (sequence[k] != '\0')
  {
    flashDotOrDash(sequence[k]);
    k=k+1;
  }
  //Serial.print("   ");
  delay(dotDelay * 3);
  toggle = !toggle;// toggle colour beween letters
}

void flashDotOrDash(char dotOrDash)
{
  if (dotOrDash == '.')
  {
    if (flag == 1)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
    }
    else if(flag == 2)
    {
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinBlue, HIGH);
    }
    else if(flag == 3)
    {
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 4)
    {
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinGreen, HIGH);
      digitalWrite(ledPinBlue, HIGH);
    }
    else if(flag == 5)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 6)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
      digitalWrite(ledPinBlue, HIGH);
    }
    else if(flag == 7)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
      digitalWrite(ledPinBlue, HIGH);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 8)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
    }
    else if(flag == 9)
    {
      if (toggle != 0)
      {
        digitalWrite(ledPinRed, LOW);
        digitalWrite(buzzer, HIGH);
        delay(dotDelay);
        digitalWrite(buzzer, LOW);
        digitalWrite(ledPinRed, HIGH);
      }
      else 
      {
        digitalWrite(ledPinBlue, LOW);
        digitalWrite(buzzer, HIGH);
        delay(dotDelay);
        digitalWrite(buzzer, LOW);
        digitalWrite(ledPinBlue, HIGH);
      }
    }
  }
  else
  {
    if (flag == 1)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
    }
    else if(flag == 2)
    {
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay* 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinBlue, HIGH);
    }
    else if(flag == 3)
    {
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 4)
    {
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinGreen, HIGH);
      digitalWrite(ledPinBlue, HIGH);
    }
    else if(flag == 5)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 6)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
      digitalWrite(ledPinBlue, HIGH);
    }
    else if(flag == 7)
    {
      digitalWrite(ledPinRed, LOW);
      digitalWrite(ledPinBlue, LOW);
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinRed, HIGH);
      digitalWrite(ledPinBlue, HIGH);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 8)
    {
      digitalWrite(ledPinGreen, LOW);
      digitalWrite(buzzer, HIGH);
      delay(dotDelay * 3);
      digitalWrite(buzzer, LOW);
      digitalWrite(ledPinGreen, HIGH);
    }
    else if(flag == 9)
    {
      if (toggle != 0)
      {
        digitalWrite(ledPinRed, LOW);
        digitalWrite(buzzer, HIGH);
        delay(dotDelay * 3);
        digitalWrite(buzzer, LOW);
        digitalWrite(ledPinRed, HIGH);
      }
      else 
      {
        digitalWrite(ledPinBlue, LOW);
        digitalWrite(buzzer, HIGH);
        delay(dotDelay * 3);
        digitalWrite(buzzer, LOW);
        digitalWrite(ledPinBlue, HIGH);
        
      }
    }
    
  }
  delay(dotDelay);//between letters
  //toggle = !toggle;//toggle between caractors
}
void selectorSwitch1(int AI)
{
  if ((AI > (oldAI + 10)) || (AI < (oldAI - 10)))// see if the value has changed?
  {
    if (AI > 11*dividedBits)// must be 7,8,9,10,11,12.
    {
      if (AI > 17*dividedBits)// must be 10,11,12.
      {
        if (AI > 21*dividedBits)// must be 12.
        {
          flag = 12;
        }
        else//must be either 10,11.
        {
          if (AI > 19*dividedBits)// must be 11.
          {
            flag = 11;
          }
          else// must be 10.
          {
           flag = 10;
          }
        }
      }
      else // must be 7,8,9.
      {
        if (AI > 15*dividedBits)// must be 9.
        {
          flag = 9;
        }
        else// must be 7,8.
        {
          if (AI > 13*dividedBits)// must be 8.
          {
            flag = 8;
          }
          else// must be 7.
          {
            flag = 7;
          }
        }
      }
    }
    else// must be 1,2,3,4,5,6.
    {
      if (AI > 5*dividedBits)// must be 4,5,6.
      {
        if (AI > 9*dividedBits)// must be 6.
        {
          flag = 6;
        }
        else// must be 4,5.
        {
          if (AI > 7*dividedBits)// must be 5
          {
            flag = 5;
          }
          else// must be 4.
          {
            flag = 4;
          }
        }
      }
      else// must be 1,2,3.
      {
        if (AI > 3*dividedBits)// must be 3.
        {
          flag = 3;
        }
        else// must be 1,2.
        {
          if (AI > dividedBits)// must be 2.
          {
            flag = 2;

          }
          else// must be 1.
          {
            flag = 1;
          }
        }
      }
    }
  }
  oldAI = AI;
  //delay(500);
  //Serial.println();
}
void selectorSwitch(int AI)
{
  if ((AI > (oldAI + 10)) || (AI < (oldAI - 10)))// see if the value has changed?
  {
    if (AI > 11*dividedBits)// must be 7,8,9,10,11,12.
    {
      if (AI > 17*dividedBits)// must be 10,11,12.
      {
        if (AI > 21*dividedBits)// must be 12.
        {
          animal = 12;
        }
        else//must be either 10,11.
        {
          if (AI > 19*dividedBits)// must be 11.
          {
            animal = 11;
          }
          else// must be 10.
          {
           animal = 10;
          }
        }
      }
      else // must be 7,8,9.
      {
        if (AI > 15*dividedBits)// must be 9.
        {
          animal = 9;
        }
        else// must be 7,8.
        {
          if (AI > 13*dividedBits)// must be 8.
          {
            animal = 8;
          }
          else// must be 7.
          {
            animal = 7;
          }
        }
      }
    }
    else// must be 1,2,3,4,5,6.
    {
      if (AI > 5*dividedBits)// must be 4,5,6.
      {
        if (AI > 9*dividedBits)// must be 6.
        {
          animal = 6;
        }
        else// must be 4,5.
        {
          if (AI > 7*dividedBits)// must be 5
          {
            animal = 5;
          }
          else// must be 4.
          {
            animal = 4;
          }
        }
      }
      else// must be 1,2,3.
      {
        if (AI > 3*dividedBits)// must be 3.
        {
          animal = 3;
        }
        else// must be 1,2.
        {
          if (AI > dividedBits)// must be 2.
          {
            animal = 2;

          }
          else// must be 1.
          {
            animal = 1;
          }
        }
      }
    }
  }
  oldAI = AI;
  //delay(500);
  //Serial.println();
}

13 Comments

simple and excellent!
Hi,
great little project well presented but a suppliers list for those of us who do not have an extensive "spares" box would be a neat addition.
Hi thanks for your comment, and yes i am guilty of having a extensive spares box! i tend to look what else a supplier has when i order from eBay and then end up buying loads! i have put the list of items below, in most cases you can cut and paste the discription into eBay and you should be able to find the part.
1 * 10MM RGB LED Module £1.00
1 * Arduino Nano v3.0 £3.00
2 * DPDT slide switch £0.50?
1 * 1 pole 12 way rotary switch £2.00
1 * 4k7 16mm linear omeg £3.00
1 * red push button spst push to make £3.00
1 * 5 volt buzzer £1.00
1 * lipo charger tp4056 £1.75
1 * dc-dc step up 5v phone £1.00
1 * 1000mAh 503450 battery £3.50
12 * 1Kohm resistor 1/8 watt
1 * 10Kohm resistor 1/8 watt
Mr_FID,
Thank you for the additional info, now to get busy.
As to your "addiction" I "suffer" from the same symptoms but with hand tools :-)
S & F
Geo.
So, for some reason this project resonates with me. I've always wanted to master Morse Code, but ever since they dropped it from the HAM licensing requirements in the US. Well, I can say I have never truly "learned" it.

The project is simple enough, but I think with just a couple tweaks and very minor cost reallocation's you can expand the training possibilities enormously. By going to a rotary encoder instead of the 12 position switch. And adding an I2C connected display, either 4 Digit 7 segment or a 20 character type display. You could expand the number of selectable words and display what those selections were as you jogged through them. You should have sufficient GPIO and I2C left on your NANO to pull this off.

The rotary encoder will probably be significantly cheaper than a 12 position switch as well, possibly totally offsetting the cost of the display. Tie it all up with an STL file for a 3D printed enclosure.

Your project got my brain going this afternoon. Thanks for that!
I had so many ideas when i was thinking of this project, two stations and a battleships game? but 3 letter words was hard enough!
It sounds like you have set yourself a nice challenge!!
Good luck!
Hi Mr Fid
Nice project, but am I not seeing part of the instructible ? I don't see any diagram showing which pins are connected to where. I can possibly work it out from the code, but mistakes can be made. If you don't have one perhaps "Fritzing" might be an option.
Otherwise thanks for a great idea.
HI
thanks for your comment, i have added a wiring diagram.
Hello Mr Fid,
Very nice project! I've been a ham radio operator for years and mostly use morse code only to communicate around the world. I use only 1 watt of power and communicate over the entire world using Morse Code!
I wrote an iPhone Morse Code app over 2 years ago as a teaching aid. It's inactive now because I haven't renewed my Apple Developer Contract. Maybe I'll renew it again.

I just noticed that your arduino code for your numbers array is incorrect for the numbers 2 and 7.
The numeral 2 should be: di-di-dah-dah-dah or . . _ _ _
seven 7 should be: dah-dah-di-di-dit or _ _ . . .

Keep on making these great creative projects!

dah di-di-di-dit di-dah dah-dit dah-di-dah di-di-dit
_ /.... /._ /_. /_._ /... (forward slashes are used to separate characters)

Gary K2DG
PS
So, instead of using "Dot" for the short sound . and "Dash" for the long sound _
use "Dit" for the short sound . and "Dah" for the long sound _
"Dit" and "Dah" represent more closely of what audible morse code sounds like.
When you have multiple "Dits" drop the "t"s on the "dit" unless it's
the last sound for that character.
Example: the letter "V": di-di-di-dah
the letter "K": dah-di-dah
the letter "B": dah-di-di-dit
Hello
Thanks for you comments.
I have to be honest i really didn't know much about the world of ham radio, but the event (Jamboree On The Air) was really good.
I will correct the numbers, but i didn't get around to using them. Maybe when i program some longer words and sentences then i could add grid references!! It would make an interesting challenge for the SCOUTS.
This is a cool project.
In actual practice, the code is almost entirely used by ear, not flashing lights (via radio)
The speed of Morse code is measured in WPM (Words Per Minute) http://www.kent-engineers.com/codespeed.htm

Learning a few 3 letter words is a start, but how about programming your box to work like this no-longer-in-production device for learning all the code: http://www.kent-engineers.com/TUTORinfo.htm

A popular method of learning to recognize the code by ear is the Koch method, where letters are always sent at a typical real-world speed of 15-20 WPM, but the spacing/gaps between letters is greatly increased to slow things down to something like 5-12 WPM. This allows you to learn the regularly experienced real-world rhythmic sound of a letter, but have time to recognize and write it down while learning. Usually you start learning just two letters, then add another letter whenever your accuracy is good enough with that set - until you have learned all the letters, numbers and punctuation. Here's a great article on learning code and how not to learn it.
https://www.qsl.net/n1irz/finley.morse.html


Hello and thanks for your kind comments!
when i researched this project i did read all about WPM and how quick competitors used to be when there were competitions!
Initially this project was going to be a send and receive project using only light with each station across a field! but when i tried out just the basic 3 letter words it was clear it was much to hard for 8 year olds!
I will add a few more options including sentences but for the event (Jamboree On The Air) the 3 letter words were perfect. The Kent Morse code unit would be really easy to copy, but i will let someone else do that!!