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 15

In this section we are going to get our project to put spaces between the words. We have already been keeping track of how long the key is silent in order to know when the sender has finished a character. Now we are going to watch for an even longer period to know when the sender has paused between words. To do this we are going to declare a new variable:

          long newWord=0; 

Like some of our others, we are going to use this as a counter. Even though we initialize it with the value 0, when we use it we are going to count down, not up. We want a space when the sender takes a long pause, but we only want ONE space. Look at these two lines that we are inserting right after Arduino has told us the key has come up:

          if (newWord>0) newWord--;     
          if (newWord==1) printSpace(); 
When we start the program, newWord equals 0 so neither of these if statements will pass muster, nothing happens. As soon as the key is pressed, we slam a big ol' number into newWord. Like 5 times our FullWait! And everytime Arduino finds that key down, we slam that number right back in there:
          newWord=FullWait*5; 

Now when the key goes back up, the first of our If statements is going to be TRUE and we start counting down. If the sender doesn't start another letter, our value will eventually hit 1 and we will head off to print a space. In the very next pass our value drops from 1 to 0, so we're back where we started. No more counting down and no more printing spaces. As soon as the key is pressed again. we're good to go one more time.

For now, our new printSpace() procedure is fairly vanilla. In the next section we will trick it up so Arduino will know how to start a new line between words.

Copy and paste the highlighted sections below and give the sketch a try. Experiment with different values for FullWait to find one that matches your speed. Don't worry too much if you are not always getting spaces where you think they should be. Soon we will be teaching Arduino to adjust to your speed automatically.

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;
long newWord=0;

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 (newWord>0) newWord--;
  if (newWord==1) printSpace();

   if (!ditOrDah) {
       shiftBits();
   }
  if (!characterDone) {
      WaitWait--;  //We are counting down
      if (WaitWait==0) {
        printCharacter();
        
        characterDone=true;
        myNum=0;
      }

      downTime=0;
    }
}

void printSpace() {
  Serial.print(' ');
}


void printCharacter() {
  newWord=FullWait*5;
  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
  }
}