Nibbles and Bits
The Care and Feeding of My Pet Arduino


by Budd Churchward - WB7FHC - NIBBLES AND BITS LIBRARY


Teaching Arduino to Copy Morse Code

« 1 2 3 4 5 6 7 8 9 10 11 12 13  14  15 16 17 18 19 »

Section 14

Here you go! If you didn't want to figure the remaining letters out yourself, or if things got botched up while you tried, here is what the final string of characters looks like. You can copy it from here, or from the sketch below, and paste it into your project.

  char mySet[] ="##TEMNAIOGKDWRUS##QZYCXBJP#L#FVH09#8###7#######61#######2###3#45";

Notice that we have cleaned this up. Not all of the positions in the string are needed because there are some combinations of dits and dahs that don't represent ANY character. For example: ••-- means nothing in Morse Code. If he hears it, Arduino is going to create the bit stream 00011100, in decimal the number: 28. Well, the letter L is 27 and the letter F is 29. Look at our character set. Right between the L and the F we have inserted a '#'. We have put this symbol in all the places that don't match up with actual characters in Morse Code. If the sender makes a mistake or you are listening to a marginal signal on your receiver, Arduino will print these guys when he can't match the code with the correct letter.

Notice how we see more and more '#####'s strung together as we reach the end of our character set. We have chosen to cut off the set at the number 5. Arduino's bit stream for the '5' would be: 00111111, in decimal the number: 63. We stop there and ignore the punctuation marks. If we continued to use this strategy for them, our character set would be almost twice as long and contain mostly long strings of '#####'s.

To handle the punctuation marks we will check to see if the value of myNum is greater than 63. If it is, we will use a short little proceedure, printPunctuation(), containing half a dozen If statements to match the code to a character and then print it.

Copy and paste the highlighted sections and give it a try. You should end up with a fairly complete set of characters and our project is nearly finished. In the next section, we will add spaces and figure out when to start new lines on our display. Then we will move on to getting our sketch to automatically adjust to the speed of the sender. Until then, Arduino might make a lot of errors copying your code. You can change the value of FullWait to see if you can improve it. Anything as low as 1500 might work for you. When we get to the auto adjusting routines, he will home in on your speed quite quickly.

Next Section »

International Morse Code
   A •-
   B -•••
   C --•
   D -••
   E •
   F ••-•
   G --•
   H ••••
   I ••
   J •---
   K --
   L •-••
   M --
   N -•
   O ---
   P •--•
   Q ---
   R •-•
   S •••
   T -
   U ••-
   V •••-
   W •--
   X -••-
   Y ---
   Z --••
   
   1 •----
   2 ••---
   3 •••--
   4 ••••-
   5 •••••
   6 -••••
   7 --•••
   8 ---••
   9 ----•
   0 -----
   
   . •--- [period]
   , --••-- [comma]
   ? ••--•• [question mark]
   ! ---- [exclamation mark]
   @ •---• [at sign]
   - -••••- [hyphen]
   : ---••• [colon]
 

int myKey=14;    // We are borrowing Analog Pin 0 and using it as digital
int speaker=11;  // Speaker will be hooked between pin 11 and ground

int val=0;       // A value for key up and down
int myTone=440;  // Freq. of our tone

boolean ditOrDah=true;
int dit=100;

boolean characterDone=true;
int myBounce=2;
int downTime=0;

long FullWait=10000;
long WaitWait=FullWait;

int myNum=0;

char mySet[] ="##TEMNAIOGKDWRUS##QZYCXBJP#L#FVH09#8###7#######61#######2###3#45";

void setup() {
  pinMode(myKey, INPUT);
  pinMode(speaker,OUTPUT);
  // initialize the serial communication:
  Serial.begin(9600);
}



 void loop() {
   val=digitalRead(myKey);
   if (val) keyIsDown();
   if (!val) keyIsUp();
 }
 
 void keyIsDown() {
   tone(speaker,myTone);
   WaitWait=FullWait;
   downTime++;   //Count how long the key is down
 
  if (myNum==0) {
      myNum=1;  // This is our start bit
    }
   characterDone=false;
   ditOrDah=false;
   delay(myBounce);
 }

 void keyIsUp() {
   noTone(speaker);
   if (!ditOrDah) {
       shiftBits();
   }
  if (!characterDone) {
      WaitWait--;  //We are counting down
      if (WaitWait==0) {

        printCharacter();
        
        characterDone=true;
        myNum=0;
      }

      downTime=0;
    }
}

void printCharacter() {
  if (myNum>63) {
    printPunctuation();
    return; // Go back to the main loop(), we're done here.
  }

  Serial.print(mySet[myNum]);
}

void printPunctuation() {
  byte pMark='#'; // Just in case nothing matches
  if (myNum==71) pMark=':';
  if (myNum==76) pMark=',';
  if (myNum==84) pMark='!';
  if (myNum==94) pMark='-';
  if (myNum==101) pMark='@';
  if (myNum==106) pMark='.';
  if (myNum==115) pMark='?';
  Serial.print(pMark);
}

void shiftBits() {
  WaitWait=FullWait;
  ditOrDah=true;
  if (downTime<dit) {
    // We got a dit
    myNum = myNum << 1;  //shift bits left
    myNum++;
  }
  else {
    // We got a dah
    myNum = myNum << 1; // shift bits left
  }
}