Daily Archives: 11/14/2009

Another try at an Arduino Based Morse Beacon

Back in 2008, I blogged about a stupid program I wrote to implement a Morse Beacon on the Arduino. I couldn’t find that code, and it was stupid anyway, so I went ahead and implemented a new version, with an added improvement: it doesn’t hardcode dots and dashes, it has a built in table. Right now, the message is hardcoded into the program, but in the future, I’ll probably work up a trivial command language so you can change the message and speed, and store the message in the on-chip eprom. On the other hand, doing it by modifying the program source code isn’t really very much harder than getting a terminal to talk to your Arduino (it might even be easier) so this still might be the best way.

Basically, this just puts a logic high state on output pin #13 whenever the keydown should occur, and low when it is released. My Arduino is one of the older ones, so I needed to put an LED in myself, but I understand more modern ones have a built in LED. You could use whatever output pin you like though, with the obvious modification. To turn it into a full fledged keyer, you just need a transistor to handle the switching. On this model of Arduino, pin 13 has a 1K resistor in series to current limit, so you should just be able to put in any NPN transistor (base in pin 13, emitter to ground) and then use the collector/emitter to key the transmitter (I might also think about using an optoisolator, just to be safe).

This is overkill in a lot of ways: the program, sloppily as it is written only takes about 1/7 of the memory on my Arduino, and modern ones have double the space. We could do the same with a very small Atmel. But Arduinos are available and versatile, and have considerable potential. Worth playing with.

//
// Simple Arduino Morse Beacon
// Written by Mark VandeWettering K6HX
// Email: k6hx@arrl.net
// 
// This code is so trivial that I'm releasing it completely without 
// restrictions.  If you find it useful, it would be nice if you dropped
// me an email, maybe plugged my blog @ https://brainwagon.org or included
// a brief acknowledgement in whatever derivative you create, but that's
// just a courtesy.  Feel free to do whatever.
//


struct t_mtab { char c, pat; } ;

struct t_mtab morsetab[] = {
  	{'.', 106},
	{',', 115},
	{'?', 76},
	{'/', 41},
	{'A', 6},
	{'B', 17},
	{'C', 21},
	{'D', 9},
	{'E', 2},
	{'F', 20},
	{'G', 11},
	{'H', 16},
	{'I', 4},
	{'J', 30},
	{'K', 13},
	{'L', 18},
	{'M', 7},
	{'N', 5},
	{'O', 15},
	{'P', 22},
	{'Q', 27},
	{'R', 10},
	{'S', 8},
	{'T', 3},
	{'U', 12},
	{'V', 24},
	{'W', 14},
	{'X', 25},
	{'Y', 29},
	{'Z', 19},
	{'1', 62},
	{'2', 60},
	{'3', 56},
	{'4', 48},
	{'5', 32},
	{'6', 33},
	{'7', 35},
	{'8', 39},
	{'9', 47},
	{'0', 63}
} ;

#define N_MORSE  (sizeof(morsetab)/sizeof(morsetab[0]))

#define SPEED  (12)
#define DOTLEN  (1200/SPEED)
#define DASHLEN  (3*(1200/SPEED))

int LEDpin = 13 ;

void
dash()
{
  digitalWrite(LEDpin, HIGH) ;
  delay(DASHLEN);
  digitalWrite(LEDpin, LOW) ;
  delay(DOTLEN) ;
}

void
dit()
{
  digitalWrite(LEDpin, HIGH) ;
  delay(DOTLEN);
  digitalWrite(LEDpin, LOW) ;
  delay(DOTLEN);
}

void
send(char c)
{
  int i ;
  if (c == ' ') {
    Serial.print(c) ;
    delay(7*DOTLEN) ;
    return ;
  }
  for (i=0; i<N_MORSE; i++) {
    if (morsetab[i].c == c) {
      unsigned char p = morsetab[i].pat ;
      Serial.print(morsetab[i].c) ;

      while (p != 1) {
          if (p & 1)
            dash() ;
          else
            dit() ;
          p = p / 2 ;
      }
      delay(2*DOTLEN) ;
      return ;
    }
  }
  /* if we drop off the end, then we send a space */
  Serial.print("?") ;
}

void
sendmsg(char *str)
{
  while (*str)
    send(*str++) ;
  Serial.println("");
}

void setup() {
  pinMode(LEDpin, OUTPUT) ;
  Serial.begin(9600) ;
  Serial.println("Simple Arduino Morse Beacon v0.0") ;
  Serial.println("Written by Mark VandeWettering <k6hx@arrl.net>") ;
  Serial.println("Check out my blog @ https://brainwagon.org") ;
  Serial.println("") ;
}

void loop() {
  sendmsg("K6HX/B CM87") ;
  delay(3000) ;
}

Addendum:


Addendum2:

Josh asked me how the morse code table works. It’s a little bit clever (a very little bit) but I guess it does require some explanation. Morse code characters are all length six or less, and each element is either a dot or a dash, so it would seem that we can store the pattern in six bits. Let’s say that dits are zero and dahs are one. Lets store them so the first element gets stored in the least significant bit, and the next in the second most, and so on. The only trick is knowing when there are no elements left, because otherwise we can’t tell (for example) K (-.-) from C (-.-.) To do that, we store a single extra one after all the other elements are taken care of. Then, when we are looping, we do the following. If the pattern is equal to one, we are done (that’s our guard bit). If not, we look at the least significant digit. If it is a zero, we have a dit, if we have a one, it’s a dah. We then get rid of that element (by dividing by two, or shifting right if that floats your boat) and repeat. Voila. Each character takes only a single byte to store its pattern, and decoding is just done in a few instructions.

Hope that helps.

Addendum3: Well, I couldn’t leave that alone, witness this…


There are many examples that people use to output sound, most of which seem to bang an output pin high or low, call delay to wait a given number of microseconds, then change its state. This seems odd to me, because the Arduino has some pretty good pulse width modulation. This can be used to make higher quality sound, but for me, it also proved to be easier. I just configured pin 9 to be an output pin, and then used analogWrite(9, 128) to turn on the sound, and analogWrite(9, 0) to turn the sound off. That’s it! You get about a 500hz tone, and it works really well.

Click here for the source code.