Morse Code blinker

Well hello!

been a bit borded today so playing with arduino UNO and the onboard led so though hey ho lets make a morse code thingy??

anyways so proud of my terrible coding that i though i could share...

NOW IT WORKS! :~

/*

Steve's Morse Code sketch with arduino uno using pin 13 as led

*/

//globals
String text = "arduino rocks";

int small = 250;
int large = small * 3;

int space = large;
int spaceWord = small * 7;

int a[] = {small, large};
int b[] = {large, small, small, small};
int c[] = {large, small, large, small};
int d[] = {large, small, small};
int e[] = {small};
int f[] = {small, small, large, small};
int g[] = {large, large, small};
int h[] = {small, small, small, small};
int i[] = {small, small};
int j[] = {small, large, large, large};
int k[] = {large, small, large};
int l[] = {small, large, small, small};
int m[] = {large, large};
int n[] = {large, small};
int o[] = {large, large, large};
int p[] = {small, large, large, small};
int q[] = {large, large, small, large};
int r[] = {small, large, small};
int s[] = {small, small, small};
int t[] = {large};
int u[] = {small, small, large};
int v[] = {small, small, small, large};
int w[] = {small, large, large};
int x[] = {large, small, small, large};
int y[] = {large, small, large, large};
int z[] = {large, large, small, small};

void setup()
{
 pinMode(13, OUTPUT);
}

void loop()
{
  // get the first letter to flash
  for (int xp = 0; xp < (sizeof(text) / sizeof(char)); xp++)
  {    
    if (text[xp] == ' ')
    {
      delay(spaceWord);
    }
    else if(text[xp] == 'a')
    {
      flash(a,2);
    }
    else if(text[xp] == 'b')
    {
      flash(b,4);
    }
    else if(text[xp] == 'c')
    {
      flash(c,4);
    }
    else if(text[xp] == 'd')
    {
      flash(d,3);
    }
    else if(text[xp] == 'e')
    {
      flash(e,1);
    }
    else if(text[xp] == 'f')
    {
      flash(f,4);
    }
    else if(text[xp] == 'g')
    {
      flash(g,3);
    }
    else if(text[xp] == 'h')
    {
      flash(h,4);
    }
    else if(text[xp] == 'i')
    {
      flash(i,2);
    }
    else if(text[xp] == 'j')
    {
      flash(j,4);
    }
    else if(text[xp] == 'k')
    {
      flash(k,3);
    }
    else if(text[xp] == 'l')
    {
      flash(l,4);
    }
    else if(text[xp] == 'm')
    {
      flash(m,2);
    }
    else if(text[xp] == 'n')
    {
      flash(n,2);
    }
    else if(text[xp] == 'o')
    {
      Serial.println("flash o");
      flash(o,3);
    }
    else if(text[xp] == 'p')
    {
      flash(p,4);
    }
    else if(text[xp] == 'q')
    {
      flash(q,4);
    }
    else if(text[xp] == 'r')
    {
      flash(r,3);
    }
    else if(text[xp] == 's')
    {
      Serial.println("flash s");
      flash(s,3);
    }
    else if(text[xp] == 't')
    {
      flash(t,1);
    }
    else if(text[xp] == 'u')
    {
      flash(u,3);
    }
    else if(text[xp] == 'v')
    {
      flash(v,4);
    }
    else if(text[xp] == 'w')
    {
      flash(w,3);
    }
    else if(text[xp] == 'x')
    {
      flash(x,4);
    }
    else if(text[xp] == 'y')
    {
      flash(y,4);
    }
    else if(text[xp] == 'z')
    {
      flash(z,4);
    }
  }
  
  //delay before restarting loop
  delay(5000);
}

/*
  function flash the morse code for a letter then returns after letter spacing
*/
void flash(int letter[], int sizeLetter)
{
  for(int iz = 0; iz < sizeLetter; iz++)
  {
    digitalWrite(13, HIGH);
    delay(letter[iz]);
    digitalWrite(13, LOW);
    delay(small);
  }
  delay(space);
}

You didn't test it very well. It doesn't work.

Pete

well it worked for 'sos' for me hmmm...

yer forgot that arrays are passed to functions as pointers sooooo....... actually is there any benefit to using a switch block here instead of if else statements?

You'd be a lot better off using an array.

Pete

You obviously are not familiar with Morse code in practice (technically, not actually "Morse" code but ITU International Morse Code as it differs from the original by Samuel Morse) or instead of "small" and "large" you would have used the phonetic "dit" and "dah" - which are shorter and neaten up the code quite a bit, especially in those arrays. :smiley:

For this sort of coding, switch blocks are far more concise than "else if" sequences - and should code more concisely as you are not evaluation the "text[xp]" for each iteration (though the optimiser might just catch that). And for such tables, you do not need to separate each case into multiple lines, legibility is better on a single line. (Bet someone complains about this suggestion!)

Given that no plain alphabetic character is more than four symbols, an array should be much more concise code.

hmmm, been doing a little research I am not so bothered with the morse code side of things because I have no idea about it or any interest in learning it.

I think the project was more of a time killer and a bit of coding practise. I have been doing a bit of research and there seem to be mutiple views on if/else statements and switch blocks but there does not seem to be any performance benefit to using either or from what I have seen and more about code readability.

I think the main thing that I am trying to consider as a work around is how I could get past having if/else or a switch and how I could do it with an array..

pizzaboy150:
how I could get past having if/else or a switch and how I could do it with an array.

Seems to me to be dead easy (almost).

26 letters, each letter contains four symbols. You have two of the symbols defined, you need a third, blank one. The array is twenty-six rows of four symbols. You index the desired letter into the array and read out (in turn), four symbols and act on them.

You are doing the coding practice, I will leave it to you. :smiley:

hmmm that seems fun i will give it a try!

Sooooooo version 2 using an array the only way I can get it to work don't really see any benefit to doing it this way if I am honest but its another way and killed some time...

/*

  Steve's morse code thing v2

*/

//text to flash in International morse code
char text[] = "arduino rocks";

//timing variables
int dit = 250;
int dah = dit*3;
int space = dit;
int wordSpace = dit*7;

//array to hold information
char alpha[27][6] = {
                      {' ', 'n', 'n', 'n', 'n', 'n'},
                      {'a', 's', 'l', 'n', 'n', 'n'},
                      {'b', 'l', 's', 's', 's', 'n'},
                      {'c', 'l', 's', 'l', 's', 'n'},
                      {'d', 'l', 's', 's', 'n', 'n'},
                      {'e', 's', 'n', 'n', 'n', 'n'},
                      {'f', 's', 's', 'l', 's', 'n'},
                      {'g', 'l', 'l', 's', 'n', 'n'},
                      {'h', 's', 's', 's', 's', 'n'},
                      {'i', 's', 's', 'n', 'n', 'n'},
                      {'j', 's', 'l', 'l', 'l', 'n'},
                      {'k', 'l', 's', 'l', 'n', 'n'},
                      {'l', 's', 'l', 's', 's', 'n'},
                      {'m', 'l', 'l', 'n', 'n', 'n'},
                      {'n', 'l', 's', 'n', 'n', 'n'},
                      {'o', 'l', 'l', 'l', 'n', 'n'},
                      {'p', 's', 'l', 'l', 's', 'n'},
                      {'q', 'l', 'l', 's', 'l', 'n'},
                      {'r', 's', 'l', 's', 'n', 'n'},
                      {'s', 's', 's', 's', 'n', 'n'},
                      {'t', 'l', 'n', 'n', 'n', 'n'},
                      {'u', 's', 's', 'l', 'n', 'n'},
                      {'v', 's', 's', 's', 'l', 'n'},
                      {'w', 's', 'l', 'l', 'n', 'n'},
                      {'x', 'l', 's', 's', 'l', 'n'},
                      {'y', 'l', 's', 'l', 'l', 'n'},
                      {'z', 'l', 'l', 's', 's', 'n'},
                    };

//function to control led on/off
void flash(int time)
{
  digitalWrite(13, HIGH);
  delay(time);
  digitalWrite(13, LOW);
  delay(dit);
}

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  //loop through each character in the text string
  for(int i = 0; i < (sizeof(text) / sizeof(char)); i++)
  {
    //read the letter
    char letter = text[i];
    if(letter == ' ')
    {
      delay(wordSpace);
    }
    
    //loop through the array to find the letter
    for(int x = 0; x < 27; x++) {
      
      //Check character against array character
      if(alpha[x][0] == letter)
      {
        //loop through each letter code breaking at nil
        int t = 1;
        while(alpha[x][t] != 'n')
        {
          if(alpha[x][t] == 's')
          {
            flash(dit);
          }
          if(alpha[x][t] == 'l')
          {
            flash(dah);
          }        
          t += 1;
        }
        //spacing between letters
        delay(dah);
        
      }
    }
  }
  
  // Delay before restarting loop
  delay(10000);
}

Paul__B:
26 letters, each letter contains four symbols. You have two of the symbols defined, you need a third, blank one. The array is twenty-six rows of four symbols. You index the desired letter into the array and read out (in turn), four symbols and act on them.

Or maybe one more array position that stores either the number of non-blank characters or it stores the number of non-blank plus one . That could be used to shorten the transmission time by letting there be a single blank area between letters rather than several blanks in the instance of a single dih (E) or dah (T). A quicker transmission at the cost of a little bit more data storage.

Or, do it as an array of strings that represent the data patterns ("SL" for short-long [A]) and let the length of the string create the same result. Different ways to accomplish this task

ETA: numbers are 5 character entities, maybe a 2nd array if you want to not waste too much storage space. And to really complicate this, punctuation (period and question mark) are six characters long. :slight_smile:

Lyle

l_dowell:
Or maybe one more array position that stores either the number of non-blank characters or it stores the number of non-blank plus one . That could be used to shorten the transmission time by letting there be a single blank area between letters rather than several blanks in the instance of a single dih (E) or dah (T). A quicker transmission at the cost of a little bit more data storage.

You misunderstand - "blank" in this context really means blank - no output, no delay. Three blanks take just as long as one. :smiley:

For reference and discussion, here is an implementation of an Arduino Morse code generator that uses an array to specify the letter signatures:

The m() define is used to pack both the dit and dah elements (as 0 and 1) and the length of the character in elements into a single byte in the array.

Using three bits for the count leaves room for five Morse elements. This handles most cases, but because there are several Morse characters with six elements, there is also an overflow table (outliers) to define those characters.

-br