Morse Code Generator

Lets Beef-Up the ‘Blink’ Program

A blinking circuit may be useful as a signal to warn others of dangerous situations or to draw people’s attention. Another use for a blinking light is to communicate with someone over a distance. The following program makes use of the blinking light circuit to implement a Morse code generator.

Around 1837, the American Samuel F. B. Morse invented an early version of what was to become Morse code. Morse code is a method of transmitting information as a series of on-off tones, lights, or clicks. Basically, letters, numbers, and punctuation marks are translated to a variable length collection of dots and dashes, of shorter and longer bursts of sound or light. The duration of the dot, the short burst, is the unit of time by which all other elements of Morse code are defined. A dash, the long burst, is a signal whose duration is three times that of the dot. The time between dots and dashes within an encoded character is one unit of time. the time between characters is three units of time and the time between words is seven units of time.

International Morse code is thus composed of five elements:

  • short mark, dot or ‘dit’: one time unit long
  • longer mark, dash or ‘dah’: three time units long
  • gap between the dots and dashes within a character: one time unit long
  • gap between letters of a word: three time units long
  • gap between words: seven time units long

Following, is the international Morse code equivalent, in dot (.) and dash (-) notation for each alphabetical and numerical character:

315px-International_Morse_Code.svg

For instance, if we are to show the character sequence “PARIS” in Morse code, we can represent it in text as “.–.  .-  .-.  ..  …” and if we want to represent it as a series of on and off signals, arbitrarily represented by an equal sign “=” and an underscore “_” respectively, each one time unit in duration and we follow the rules stated above, we get the following signal:

___=_===_===_=___=_===___=_===_=___=_=___=_=_=___

The following program, written in “C” for the Arduino, converts a character string of alphabetical characters into a series of short and long blinking LED signals corresponding to their morse code equivalent. You can reconstruct the program in the Arduino IDE (Integrated Development Environment) by copying the code from this post and pasting it in sequence, as it appears in this text, in the text editing pane of the IDE.

The Program Header

The program header, a few paragraphs down, contains a comment describing the nature and purpose of the program as well as a copyright notice. I am the author of the code and I have put it in the public domain. Comments are character sequences ignored by the program interpreter or compiler. Comments can be formatted as any text between a slash-asterisk, ‘/*‘, and asterisk-slash, ‘*/‘, character sequences. This is the original way to enter comments in the ‘C’ language. Text enclosed between these two-character sequences can span several lines and are ignored. Comments can also be entered after a double-slash, ‘//‘, character sequence. All text after the double-slash character sequence, until the end of line, is considered a comment and is ignored by the program interpreter or compiler.

We define the digital output PORT as LED_BUILTIN, the digital output port corresponding to the Arduino’s built-in LED. The UNIT_TIME value corresponds to the time in milliseconds of the ‘on’ duration of the dot. The #define statement allows programmers to associate text to a name. When the program is compiled, the text replaces the name whenever it appears in the program. At compile time, PORT is replaced by the Arduino LED_BUILTIN  constant and UNIT_TIME is replaced by the integer value 100. Note that LED_BUILTIN is also a definition and it gets substituted by the appropriate integer value depending on the target Arduino board.

The characters String variable and codedCharacters String array variable work in tandem as the list of supported characters and their corresponding Morse code equivalent. The Morse code equivalent is encoded as a character string containing a series of period (‘.‘) and dashes (‘‘) representing the short and long bursts of Morse code. Each string in the codedCharacters array corresponds to the character at the same index in the characters string variable.

/* Morse Code Generator
   Blink an LED connected to pin LED_BUILTIN to display morse
   code corresponding to text entered. Repeats forever.
   This sketch was written by Michel Lagacé, 2018-09-02
   This code is in the public domain */

// Output port to display morse code
#define PORT LED_BUILTIN

// unit time length of the morse encoding
#define UNIT_TIME 100

// Characters to be encoded
static String characters = "abcdefghijklmnopqrstuvwxyz";

// Morse code sequences for each character
static String codedCharacters[] = { 
    ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
    "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.",
    "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-",
    "-.--", "--.." };

In ‘C++‘, an array is a collection of elements accessible through the use of an index. A String is a specialized array for collections of characters. Thus, each character in a String and each element of an array can be accessed through the use of an index. An index is an integer value enclosed in square brackets ([ ]) right after the variable name. The first character of a string or element in an array has index 0. The second character or element has index 1 and each successive character or element’s index is one more than the preceding index.

In the code above, character ‘c’ is at index 2 in the characters String. The corresponding Morse code sequence, “-.-.”, is a String at index 2 in the codeCharacters String array. The characters variable is declared as static meaning that the variable’s memory is allocated once at the start of the program and remains for the duration of the program. Non-static variables in functions are allocated in memory only for the duration of the execution of the function, then released back to the pool of memory a program can use. This is very useful for very large programs as only the necessary memory is used at any time. The characters String is initialized with the character string “abcdefghijklmnopqrstuvwxyz”. codedCharacters is also declared as a static String, but the variable name is followed by square brackets. These square brackets indicate that the variable is an array. The size of the array is set to the number of elements it is initialized with. In this case, 26 elements. If an uninitialized array is to be created, the size can be specified as a value within the square brackets.

Digital Output Setup

The setup of the digital output to blink an LED is identical to the setup in the ‘BLINK’ circuit demonstration. We set the pin mode to OUTPUT.

// Setup the board. Digital port LED_BUILTIN in output mode
void setup() {
    pinMode(PORT, OUTPUT);
}

Outputting Dots and Dashes

Code can be, and should be, segregated into functions that provide specific well-defined functionality to a program. Functions, also called subroutines, are sequences of code that can be called by name. In the ‘C’ language, functions must be defined before they are used and thus must appear in the code before any code that uses them. The simplest functions have the following structure:

void functionName() {
    // Sequence of code the function performs when called
}

The void reserved word specifies that the function does not return any value. The we have the function name, followed by a sequence of code enclosed in curly braces, ‘{‘ and ‘}‘. Elsewhere in the program, if we want to call up the sequence of code contained i the function, we simply use the function name, followed by parentheses and a semicolon:

    functionName();

In the Morse code program, we first define two functions, one to output a dot, put the LED on for one time unit, then off for one time unit; and the other to output a dash, put the LED on for three time units, then off for one time unit. In the following code, you will find both functions. They are very similar to the code found in the original ‘BLINK’ program: lights on, lights off.

/* Function to output a dot: one unit on, one unit off */
void outputDot() {
    digitalWrite(PORT,HIGH);
    delay(UNIT_TIME);
    digitalWrite(PORT,LOW);
    delay(UNIT_TIME);
}

/* Function to output a dash: three units on, one unit off */
void outputDash() {
    digitalWrite(PORT,HIGH);
    delay(UNIT_TIME*3);
    digitalWrite(PORT,LOW);
    delay(UNIT_TIME);
}

Encoding a Character in Morse Code

Next, we have a function that outputs a character as a series of dots and dashes. Before having a look at this function, let’s go through a few concepts that will help people unfamiliar with ‘C++’ understand the code better.

‘C++’ Classes

In ‘C++’, functions can be attached to data structures called classes. I will not delve on classes, but suffices to say that these functions are called methods. The String data type is actually a class called String. Variables created with a class are usually called objects. In the case of the String class, because it is used as a data type, I will still call them variables. The String class has several methods associated with it. in the following function, we use the indexOf() and length() methods. The indexOf() method returns the index of the first occurrence of the character passed as an argument in the String. The length() method returns the number of characters in the String. To use a method associated to a variable, use the variable name followed by a period, followed by the method name, parentheses, and any parameter required by the method. It is like calling a function, but preceded by the variable name. Thus, to get the index of the position of letter ‘f’ within the characters String and initialize the index variable with it, use the following code:

    int index = characters.indexOf('f');

index will be initialized with the value 5, the index of the letter ‘f’ in the String characters.

The outputCharacter function introduces us to two fundamental programming structures. The for-loop, and the if-then-else structures.

if-then-else Control Structure

The if-then-else control structure allows a program to conditionally execute a portion of a program. It has the following structure:

    if (condition) {
        // Code to execute if condition is true
    }
    else if (other condition) {
        // Code to execute if other condition is true
    }
    else {
        // Code to execute if all preceding conditions are false
    }

Only the first if block is mandatory; the else if and else blocks are optional. The execution flow is as follows: if the condition specified within parenthesis after the first if is true, then the code within the curly braces following the if statement is executed; if the condition within the first if statement is false then the condition in the else if statement is checked; if the condition in the else if statement is true, then the code within the curly braces following the else if statement is executed; if the condition in the else if statement is false, then the code contained within the curly braces after the else statement is executed. There can be several else if statements, each testing a different condition.

for-loop Control Structure

The for-loop control structure allows the program to iterate through code several times until a condition is met. It has the following structure:

    for (initialization; condition; post-processing {
        // Code to execute until condition is met
    }

where initialization is a statement executed just before entering the loop; condition is a test performed at the beginning of the loop, if true, code within the for-loop curly braces is executed, if false, execution continues after the loop; and post-processing, is a statement executed after each iteration through the code within the curly brackets. For instance, in the following for-loop control structure:

    for (int i = 0; i < 10; i++) {
        // Code executed 10 times
    }

Variable i is initialized to 0 before entering the loop; i is tested if smaller than 10, since it is, the code within the curly braces is executed and i is available for use within this code; after the code within the curly braces is executed, the variable i is incremented by 1. A second iteration of the loop then starts and i is tested if smaller than 10. The loop continues until the condition i < 10 is false. The loop executes 10 times with values of i from 0 to 9.

outputCharacter Function

Looking at the function header, we find that it is similar to the previous functions, but has a parameter within the parentheses: char c. This defines a single character parameter to the function. Parameters allows the calling program to pass values to the function. In this case, the character to be output as Morse code. Within the outputCharacter function, variable index is set to the index of character c in the characters String. If the character is found, that is if index is greater or equal to 0, then we output the Morse code. To do so, we get the Morse code associated with the character using index to retrieve the Morse code string from codedCharacters. We then iterate through each character of the Morse code and output a dash, if the character is a hyphen or a dot otherwise using the outputDash() and outputDot() functions respectively. At the end of the character output, we wait an extra 2 units of time, totaling the 3 units of time required at the end of a Morse code character. The wait totals 3 units of time since we already introduced a single unit of time delay at the end of the dash or dot.

/* Function to output a single character */
void outputCharacter(char c) {

    // Find index of character to encode
    int index = characters.indexOf(c);
 
    // Ignore unencodable characters
    if (index >= 0) {

        // Encode Morse code and output it
        String code = codedCharacters[index];
        for (int i = 0; i < code.length(); i++) {
            if (code[i] == '-') {
                outputDash();
            }
            else { // if not '-', must be '.'
                outputDot();
            }
        }

        // wait 3 units at the end of the letter
        // (2 units assuming previous dot or dash)
        delay(UNIT_TIME*2);
    }
}

Encoding Text into Morse Code

The sentence function’s purpose is to output text as Morse code. It accepts the single String parameter: text. First, the function gets the length of the text and stores it in the len variable. It then iterates through the whole text String using i as the index in a for-loop structure from 0 until len – 1. It gets the character indexed by i and turns it to lowercase using the tolower() built-in function. If the character is not a space, it is output using outputCharacter(). If the character is a space, we wait an extra 4 units of time, totaling the 7 units of time required at the end of a word. The wait amounts to 7 units of time since we already added 3 units of time at the end of the previous Morse code character output.

// Function to encode a whole string
void sentence (String text) {
    // Compute length of character string
    int len = text.length();

    // Output each character in turn
    for (int i = 0; i < len; i++) {

        // Only lower case characters are encoded
        char c = tolower(text[i]);
        if (c != ' ') {
            outputCharacter(c);
        }
 
        // Spaces are encoded as 7 units,
        // (4 units assuming a previous character)
        else {
            delay(UNIT_TIME*4);
        }
    }
}

The Main Loop

Finally, this is the main loop(). This code is repeated over and over. It outputs the text “Mikes Electro Shack” in Morse code, then waits 28 units of time corresponding to 4 spaces between words. The delay is actually specified as 25 units of time since the last character output already added a 3 units of time delay. You can of course replace the text by any text you see fit.

void loop() {
    sentence("Mikes Electro Shack");
    delay(UNIT_TIME*25); // Wait 4 spaces at the end
}

What Next?

Through the implementation of this fairly simple program, we have seen two extremely important control structures, the if-then-else control structure and the for-loop control structure. We have seen that the String data type is implemented as a class and that there are methods associated with it. We also have seen a few String methods such as indexOf() and length().

This program can be put to use to learn Morse code, which is required to get one’s ham radio (amateur radio) license. Complete the list of characters to include numbers and punctuation marks and their equivalent Morse code to complete the experience.

Arduino’s Blink

The very first project everybody makes in any Arduino starter kit is the blinking LED project, “Blink.” In this post, we will have a look at the theory behind this simple circuit and program.

The Circuit

This circuit is very simple and contains only two components. An LED’s anode is connected to a current limiting resistor, which is connected to the Arduino’s digital output pin 13. The LED’s cathode is connected to the Arduino’s ground as in the following circuit:

Blink Circuit

When the Arduino’s digital output pin is set to HIGH or 5 volts, current flows through the resistor and LED making the LED emit light. When the Arduino’s digital output pin is set to LOW or 0 volt, current stops flowing and the LED does not emit light.

Each component will be described later in the post. The value of the resistor may vary from one kit to another. I will explain how to compute its value later in the post.

Breadboarding

The following picture depicts how to connect the different parts using a solderless breadboard, jumper wires, an LED and a 330Ω resistor.

Arduinos Blink_bb

The Program

We start with the simple blinker program found in most if not all Arduino kits. If it is not included in your kit, you can always download a copy of Blink on the Arduino site. The following is an excerpt from the actual listing, some comments have been removed for clarity.

/* Blink: turns an LED on for one second, then off for one second,
   repeatedly.
   This example code is in the public domain.
   http://www.arduino.cc/en/Tutorial/Blink  */
 
 // the setup function runs once when you press reset
 void setup() {
   // initialize digital pin LED_BUILTIN as an output.
   pinMode(LED_BUILTIN, OUTPUT);
 }
 
 // the loop function runs over and over again forever
 void loop() {
   // turn the LED on by making the voltage HIGH, wait a second
   digitalWrite(LED_BUILTIN, HIGH);
   delay(1000);
   // turn the LED off by making the voltage LOW, wait a second
   digitalWrite(LED_BUILTIN, LOW);
   delay(1000);
 }

The language used within the Arduino IDE (Integrated Development Environment) is actual C++. The major difference is that the Arduino system does not call a main( ) function like it does under normal Windows or Linux console applications. instead, the system expect the programmer to define two ‘C’ functions:

void setup();

and

void loop();

The setup( ) function (or method) is called once the first time the program is downloaded, once after the Arduino board reset button has been depressed, or once the Arduino board has been powered up. The loop( ) function is called repeatedly and indefinitely after setup( ) has been called once.

The Arduino system also comes with a set of predefined function libraries. In our first example, two functions are used to access the digital output pin to make the LED blink. The first function’s signature (this is how we call a function’s description) is

void pinMode ( int pin, int mode );

Where pin is an integer specifying the digital pin to be setup and mode is an integer specifying the mode this pin will be used in. In the program above, the pin number used is LED_BUILTIN which corresponds to the pin number connected to the built-in Arduino board LED, pin 13 on the Arduino UNO. The mode can have one of three values: INPUT, OUTPUT, or INPUT_PULLUP, all constant values that can be used as the digital I/O pin mode. In the program, we use OUTPUT, allowing us to use the pin as a digital output. The pinMode( ) function is used as part of the setup( ) function body to prepare the LED_BUILTIN digital I/O pin to be outputted to.

The second function signature is

void digitalWrite ( int pin, int value );

Where pin is an integer specifying the digital pin we are outputting to, while value is an integer whose value can be 0 or 1, LOW or HIGH. digitalWrite( ) can only be used if the pin mode was previously set to OUTPUT.

The last function signature used within our simple piece of code is

void delay( int value )

where value is an integer specifying the amount of time in milliseconds (thousandths of a second) the program is to wait and do nothing. In the program above it waits twice for a full second each time, leaving the LED on for a full second then turning it off for a full second.

Components

Two electronic components are used within this circuit, a resistor and an LED. We will describe each in turn in the following paragraphs

Resistors

Resistors are electronic devices that restrict current flow according to Ohm’s law. Ohm’s law states that the current through a conductor between two points is directly proportional to the voltage across the two points. In mathematical terms, Ohm’s law can be restated

I = V / R

Where I is the current in amperes (A), V is the voltage across the conductor in volts (V) and R is the resistance of the conductor in ohms (Ω). Hence, a 330Ω resistor with 5V across its leads will let a current flow of 5V / 330Ω, 0.01515A, or 15.15mA.

Resistors
Two 1/4 watt carbon film resistors

Resistors restrict current by dissipating energy in the form of heat. This is an important factor as resistors have to be selected not only in terms of their resistance, but also for their capacity to dissipate heat, or power rating. The energy dissipated per second by a resistor, the electrical power, is expressed in watts (W). In mathematical terms, Power can be computed as

P = VI

Where P is the power in watts (W), V is the voltage across the resistor in volts (V) and I is the current, in amperes (A) flowing through the resistor. in the previous example, the power dissipated by the 330Ω resistor is 5V • 0.01515A, 0.07575W, or 75.75mW. The resistors supplied with most kits have a power rating of 1/4W (250mW). A 1/4W power rating is sufficient for our current example and most Arduino circuits you will encounter.

LED

LEDs are semiconductor devices that emit light when current flows through them. as its name suggests, an LED only allows current to flow in one direction, from anode to cathode, in the direction of the arrow of the diode symbol. Unlike resistors, an LEDs voltage across it leads is not linearly proportional to the current through the device and we have to look at its specification sheet to determine how the LED will perform within a circuit.

Red LED
A standard 20 mA red LED

Here is a sample datasheet for a standard 20mA LED:

YSL-R531R3D-D2

As can be seen from the data sheet, the forward voltage across the LED, that is the voltage across the LED when 20mA of current is flowing from the anode to the cathode, is between 1.8 and 2.2 volts. Also, it is suggested to limit the current between 16 to 18 mA in normal operation.

Computing the Resistor Value

Apart from Ohm’s law and the power rating formula, we need a bit more information to find a resistor value that will limit the current flow within the LED to a value not exceeding 18mA. Kirchkoff’s Voltage Law states that the sum of voltages around a closed circuit loop is 0V. Current goes in the counter-clockwise direction in this circuit, from the positive end of the power source to the negative end and the voltage drop around the power source is negative since voltage does not drop but increases around it. Redrawing our LED circuit when the digital output pin is HIGH and replacing the pin by a 5V source we get:

Kirchkoff

The sum of all voltages around the circuit is:

-5V + 1.8V + VR1 = 0V

Solving for VR1, we get

VR1 = 5V – 1.8V = 3.2V

Thus, we know that we want 18mA to flow through both LED and resistor and that the voltage across the resistor is 3.2V. Going back to Ohm’s law we know that

R1 = VR1 / I = 3.2V / 0.018A = 177Ω

This is the smallest resistor value to obtain the maximum optimal amount of current through the circuit. Resistors don’t come in all possible values. The most common values are the following values multiplied by powers of 10: 10, 15, 22, 33, 47, 68. The value just higher than 177Ω is 220Ω. Using this new value, we get

I = VR1 / R1 = 3.2V / 220Ω = 14.5mA

A value close to the optimal value suggested by the LED manufacturer. The value shown in the first circuit, 330Ω is the value used in the SparkFun kit I used for this experiment. This value limits the current to a value of 9.7mA which does allow the LED to emit light, but at a dimmer intensity.

There is Beauty in Geeky Things!

Welcome to my blog about sharing my life long passion with electronics, software design and my newfound passion with micro-controllers and their open hardware and software platforms. This blog is a series of tutorials and experiments to allow hobbyists understand the basics of electronic design and software programming and be able to reproduce the experiments, add to them and create their own circuits and programs.

Experiments in this blog make use of the Arduino Uno, a micro-controller, and a few electronic components that come with starter kits that can be found on the Internet. Experiments were tested using SparkFun Inventor’s Kit. The kit comes with a SparkFun RedBoard, a version of the Arduino Uno micro-controller, a solderless breadboard, jumper wires and electronic components such as LEDs (Light Emitting Diodes), resistors, light and temperature sensors, and more.

I recommend to the beginning enthusiast to procure a kit, whether from Sparkfun or other suppliers as they contain instructions on how to setup the Arduino, on how to get necessary software from the Internet, and how to use the software to program the micro-controller and make it work. Here is a non-exhaustive list of starter kits found on the Internet in no particular order.

Once equipped with a kit, we will embark on a series of circuits and programs that will complement and further your starter kit experience with explanations, tips and ideas.

Progress lies not in enhancing what is, but in advancing toward what will be. — Khalil Gibran

Place_Jacques-Cartier_Jan_2006